using System;
using System.IO;
using System.Data;
using System.Data.SqlClient;
using System.Collections;
using System.Collections.Generic;
using System.Security.Cryptography;
using System.Text;
using System.Net;
using LumiSoft.Net;
using LumiSoft.Net.AUTH;
using LumiSoft.Net.IMAP.Server;
using LumiSoft.Net.IMAP;
using LumiSoft.Net.Mime;
namespace LumiSoft.MailServer
{
/// <summary>
/// Lumisoft Mail Server MSSQL API.
/// </summary>
public class mssql_API : IMailServerApi
{
private string m_ConStr = "";
/// <summary>
/// Default constructor.
/// </summary>
/// <param name="intitString"></param>
public mssql_API(string intitString)
{
// connectionstring=
string[] parameters = intitString.Replace("\r\n","\n").Split('\n');
foreach(string param in parameters){
if(param.ToLower().IndexOf("connectionstring=") > -1){
m_ConStr = param.Substring(17);
}
}
SqlConnectionStringBuilder b = new SqlConnectionStringBuilder(m_ConStr);
string database = b.InitialCatalog;
b.InitialCatalog = "";
using(SqlConnection con = new SqlConnection(b.ToString())){
con.Open();
// See if database exists
try{
con.ChangeDatabase(database);
}
catch{
// Database don't exist, try to create it
try{
SqlCommand cmd = new SqlCommand();
cmd.Connection = con;
cmd.CommandType = CommandType.Text;
cmd.CommandText = "create database \"" + database + "\"";
cmd.ExecuteNonQuery();
con.ChangeDatabase(database);
// Create tables
cmd.CommandText = ResManager.GetText("tables.sql",System.Text.Encoding.Default);
cmd.ExecuteNonQuery();
// Create procedures
using(System.IO.StringReader r = new System.IO.StringReader(ResManager.GetText("procedures.sql",System.Text.Encoding.UTF8))){
string line = r.ReadLine().Trim();
StringBuilder command = new StringBuilder();
while(line != null){
line = line.TrimEnd();
if(line.ToLower() == "go"){
cmd.CommandText = command.ToString();
cmd.ExecuteNonQuery();
command = new StringBuilder();
}
else{
command.Append(line + "\r\n");
}
line = r.ReadLine();
}
// No ending GO, exec last statement block
if(command.ToString().Trim() != ""){
cmd.CommandText = command.ToString();
cmd.ExecuteNonQuery();
}
}
}
catch(Exception x){
throw new Exception("Database '" + database + "' doesn''t exist ! Create failed, specified user doesn't have enough permisssions to create database ! Create database manually.");
}
}
}
}
#region Domain related
#region method GetDomains
/// <summary>
/// Gets domain list.
/// </summary>
/// <returns></returns>
public DataView GetDomains()
{
using(WSqlCommand sqlCmd = new WSqlCommand(m_ConStr,"lspr_GetDomains")){
DataSet ds = sqlCmd.Execute();
ds.Tables[0].TableName = "Domains";
return ds.Tables["Domains"].DefaultView;
}
}
#endregion
#region method AddDomain
/// <summary>
/// Adds new domain.
/// </summary>
/// <param name="domainID">Domain ID. Suggested value is Guid.NewGuid() .</param>
/// <param name="domainName">Domain name. Eg. yourDomain.com .</param>
/// <param name="description">Domain description.</param>
/// <remarks>Throws exception if specified domain already exists.</remarks>
public void AddDomain(string domainID,string domainName,string description)
{
if(domainID.Length == 0){
throw new Exception("You must specify domainID");
}
ArgsValidator.ValidateDomainName(domainName);
using(WSqlCommand sqlCmd = new WSqlCommand(m_ConStr,"lspr_AddDomain")){
sqlCmd.AddParameter("@DomainID" ,SqlDbType.NVarChar,domainID);
sqlCmd.AddParameter("@DomainName" ,SqlDbType.NVarChar,domainName);
sqlCmd.AddParameter("@Description",SqlDbType.NVarChar,description);
DataSet ds = sqlCmd.Execute();
ds.Tables[0].TableName = "Domains";
if(ds.Tables["Domains"].Rows.Count > 0 && ds.Tables["Domains"].Rows[0]["ErrorText"].ToString().Length > 0){
throw new Exception(ds.Tables["Domains"].Rows[0]["ErrorText"].ToString());
}
}
}
#endregion
#region function DeleteDomain
/// <summary>
/// Deletes specified domain.
/// </summary>
/// <param name="domainID">Domain ID. Use <see cref="IMailServerApi.GetDomains">GetDomains()</see> to get valid values.</param>
/// <remarks>Deletes specified domain and all domain related data (users,mailing lists,routes).</remarks>
public void DeleteDomain(string domainID)
{
using(WSqlCommand sqlCmd = new WSqlCommand(m_ConStr,"lspr_DeleteDomain")){
sqlCmd.AddParameter("@DomainID" ,SqlDbType.NVarChar,domainID);
DataSet ds = sqlCmd.Execute();
}
}
#endregion
#region method UpdateDomain
/// <summary>
/// Updates specified domain data.
/// </summary>
/// <param name="domainID">Domain ID which to update.</param>
/// <param name="domainName">Domain name.</param>
/// <param name="description">Domain description.</param>
public void UpdateDomain(string domainID,string domainName,string description)
{
if(domainID.Length == 0){
throw new Exception("You must specify domainID");
}
ArgsValidator.ValidateDomainName(domainName);
using(WSqlCommand sqlCmd = new WSqlCommand(m_ConStr,"lspr_UpdateDomain")){
sqlCmd.AddParameter("@DomainID" ,SqlDbType.NVarChar,domainID);
sqlCmd.AddParameter("@DomainName" ,SqlDbType.NVarChar,domainName);
sqlCmd.AddParameter("@Description",SqlDbType.NVarChar,description);
DataSet ds = sqlCmd.Execute();
ds.Tables[0].TableName = "Domains";
if(ds.Tables["Domains"].Rows.Count > 0 && ds.Tables["Domains"].Rows[0]["ErrorText"].ToString().Length > 0){
throw new Exception(ds.Tables["Domains"].Rows[0]["ErrorText"].ToString());
}
}
}
#endregion
#region function DomainExists
/// <summary>
/// Checks if specified domain exists.
/// </summary>
/// <param name="source">Domain name or email address.</param>
/// <returns>Returns true if domain exists.</returns>
public bool DomainExists(string source)
{
// Source is Emails
if(source.IndexOf("@") > -1){
source = source.Substring(source.IndexOf("@") + 1);
}
using(WSqlCommand sqlCmd = new WSqlCommand(m_ConStr,"lspr_DomainExists")){
sqlCmd.AddParameter("@DomainName",SqlDbType.NVarChar,source);
DataSet ds = sqlCmd.Execute();
ds.Tables[0].TableName = "Domains";
if(ds.Tables["Domains"].Rows.Count > 0){
return true;
}
}
return false;
}
#endregion
#endregion
#region User and Groups related
#region function GetUsers
/// <summary>
/// Gets user list in specified domain.
/// </summary>
/// <param name="domainName">Domain which user list to retrieve.To get all use value 'ALL'.</param>
/// <returns></returns>
public DataView GetUsers(string domainName)
{
using(WSqlCommand sqlCmd = new WSqlCommand(m_ConStr,"lspr_GetUsers")){
if(domainName != "ALL"){
sqlCmd.AddParameter("@DomainName",SqlDbType.NVarChar,domainName);
}
DataSet ds = sqlCmd.Execute();
ds.Tables[0].TableName = "Users";
return ds.Tables["Users"].DefaultView;
}
}
#endregion
#region method GetUserID
/// <summary>
/// Gets user ID from user name. Returns null if user doesn't exist.
/// </summary>
/// <param name="userName">User name.</param>
/// <returns>Returns user ID or null if user doesn't exist.</returns>
public string GetUserID(string userName)
{
using(WSqlCommand sqlCmd = new WSqlCommand(m_ConStr,"select UserID from lsUsers where (UserName = '" + userName + "')")){
sqlCmd.CommandType = CommandType.Text;
DataSet ds = sqlCmd.Execute();
ds.Tables[0].TableName = "Users";
if(ds.Tables["Users"].Rows.Count > 0){
return ds.Tables["Users"].Rows[0]["UserID"].ToString();
}
}
return null;
}
#endregion
#region function AddUser
/// <summary>
/// Adds new user to specified domain.
/// </summary>
/// <param name="userID">User ID. Suggested value is Guid.NewGuid() .</param>
/// <param name="userName">User login name.</param>
/// <param name="fullName">User full name.</param>
/// <param name="password">User login password.</param>
/// <param name="description">User description.</param>
/// <param name="domainName">Domain where to add user. Use <see cref="IMailServerApi.GetDomains">GetDomains()</see> to get valid values.</param>
/// <param name="mailboxSize">Maximum mailbox size.</param>
/// <param name="enabled">Sepcifies if user is enabled.</param>
/// <param name="permissions">Specifies user permissions.</param>
/// <remarks>Throws exception if specified user already exists.</remarks>
public void AddUser(string userID,string userName,string fullName,string password,string description,string domainName,int mailboxSize,bool enabled,UserPermissions_enum permissions)
{
if(userID.Length == 0){
throw new Exception("You must specify userID");
}
if(userName.Length == 0){
throw new Exception("You must specify userName");
}
using(WSqlCommand sqlCmd = new WSqlCommand(m_ConStr,"lspr_AddUser")){
sqlCmd.AddParameter("@UserID" ,SqlDbType.NVarChar,userID);
sqlCmd.AddParameter("@FullName" ,SqlDbType.NVarChar,fullName);
sqlCmd.AddParameter("@UserName" ,SqlDbType.NVarChar,userName);
sqlCmd.AddParameter("@Password" ,SqlDbType.NVarChar,password);
sqlCmd.AddParameter("@Description" ,SqlDbType.NVarChar,description);
sqlCmd.AddParameter("@DomainName" ,SqlDbType.NVarChar,domainName);
sqlCmd.AddParameter("@MailboxSize" ,SqlDbType.NVarChar,mailboxSize);
sqlCmd.AddParameter("@Enabled" ,SqlDbType.Bit,enabled);
sqlCmd.AddParameter("@permissions" ,SqlDbType.Int,permissions);
DataSet ds = sqlCmd.Execute();
ds.Tables[0].TableName = "Users";
if(ds.Tables["Users"].Rows.Count > 0 && ds.Tables["Users"].Rows[0]["ErrorText"].ToString().Length > 0){
throw new Exception(ds.Tables["Users"].Rows[0]["ErrorText"].ToString());
}
}
}
#endregion
#region function DeleteUser
/// <summary>
/// Deletes user.
/// </summary>
/// <param name="userID">User id of the user which to delete. Use <see cref="IMailServerApi.GetUsers">>GetUsers()</see> to get valid values.</param>
public void DeleteUser(string userID)
{
using(WSqlCommand sqlCmd = new WSqlCommand(m_ConStr,"lspr_DeleteUser")){
sqlCmd.AddParameter("@UserID" ,SqlDbType.NVarChar,userID);
DataSet ds = sqlCmd.Execute();
}
}
#endregion
#region function UpdateUser
/// <summary>
/// Updates new user to specified domain.
/// </summary>
/// <param name="userID">User id of the user which to update. Use <see cref="IMailServerApi.GetUsers">>GetUsers()</see> to get valid values.</param>
/// <param name="userName">User login name.</param>
/// <param name="fullName">User full name.</param>
/// <param name="password">User login password.</param>
/// <param name="description">User description.</param>
/// <param name="domainName">Domain where to add user. Use <see cref="IMailServerApi.GetDomains">>GetDomains()</see> to get valid values.</param>
/// <param name="mailboxSize">Maximum mailbox size.</param>
/// <param name="enabled">Sepcifies if user is enabled.</param>
/// <param name="permissions">Specifies user permissions.</param>
public void UpdateUser(string userID,string userName,string fullName,string password,string description,string domainName,int mailboxSize,bool enabled,UserPermissions_enum permissions)
{
if(userName.Length == 0){
throw new Exception("You must specify userName");
}
using(WSqlCommand sqlCmd = new WSqlCommand(m_ConStr,"lspr_UpdateUser")){
sqlCmd.AddParameter("@UserID" ,SqlDbType.NVarChar,userID);
sqlCmd.AddParameter("@UserName" ,SqlDbType.NVarChar,userName);
sqlCmd.AddParameter("@FullName" ,SqlDbType.NVarChar,fullName);
sqlCmd.AddParameter("@Password" ,SqlDbType.NVarChar,password);
sqlCmd.AddParameter("@Description" ,SqlDbType.NVarChar,description);
sqlCmd.AddParameter("@DomainName" ,SqlDbType.NVarChar,domainName);
sqlCmd.AddParameter("@MailboxSize" ,SqlDbType.NVarChar,mailboxSize);
sqlCmd.AddParameter("@Enabled" ,SqlDbType.Bit,enabled);
sqlCmd.AddParameter("@permissions" ,SqlDbType.Int,permissions);
DataSet ds = sqlCmd.Execute();
ds.Tables[0].TableName = "Users";
if(ds.Tables["Users"].Rows.Count > 0 && ds.Tables["Users"].Rows[0]["ErrorText"].ToString().Length > 0){
throw new Exception(ds.Tables["Users"].Rows[0]["ErrorText"].ToString());
}
}
}
#endregion
#region function AddUserAddress
/// <summary>
/// Add new email address to user.
/// </summary>
/// <param name="userName">User name. Use <see cref="IMailServerApi.GetUsers">>GetUsers()</see> to get valid values.</param>
/// <param name="emailAddress">Email address to add.</param>
/// <remarks>Throws exception if specified user email address exists.</remarks>
public void AddUserAddress(string userName,string emailAddress)
{
if(userName.Length == 0){
throw new Exception("You must specify userName");
}
if(emailAddress.Length == 0){
throw new Exception("You must specify address");
}
using(WSqlCommand sqlCmd = new WSqlCommand(m_ConStr,"lspr_AddUserAddress")){
sqlCmd.AddParameter("@UserName",SqlDbType.NVarChar,userName);
sqlCmd.AddParameter("@Address" ,SqlDbType.NVarChar,emailAddress);
DataSet ds = sqlCmd.Execute();
ds.Tables[0].TableName = "UserAddresses";
if(ds.Tables["UserAddresses"].Rows.Count > 0 && ds.Tables["UserAddresses"].Rows[0]["ErrorText"].ToString().Length > 0){
throw new Exception(ds.Tables["UserAddresses"].Rows[0]["ErrorText"].ToString());
}
}
}
#endregion
#region function DeleteUserAddress
/// <summary>
/// Deletes specified email address from user.
/// </summary>
/// <param name="emailAddress">Email address to add.</param>
public void DeleteUserAddress(string emailAddress)
{
using(WSqlCommand sqlCmd = new WSqlCommand(m_ConStr,"lspr_DeleteUserAddress")){
sqlCmd.AddParameter("@emailAddress" ,SqlDbType.VarChar,emailAddress);
DataSet ds = sqlCmd.Execute();
}
}
#endregion
#region function GetUserAddresses
/// <summary>
/// Gets user email addresses.
/// </summary>
/// <param name="userName"> Use <see cref="IMailServerApi.GetUsers">GetUsers()</see> to get valid values.</param>
public DataView GetUserAddresses(string userName)
{
using(WSqlCommand sqlCmd = new WSqlCommand(m_ConStr,"lspr_GetUserAddresses")){
if(userName.Length > 0){
sqlCmd.AddParameter("@UserName",SqlDbType.NVarChar,userName);
}
DataSet ds = sqlCmd.Execute();
ds.Tables[0].TableName = "UserAddresses";
return ds.Tables["UserAddresses"].DefaultView;
}
}
#endregion
#region function UserExists
/// <summary>
/// Checks if user exists.
/// </summary>
/// <param name="userName">User name.</param>
/// <returns>Returns true if user exists.</returns>
public bool UserExists(string userName)
{
using(WSqlCommand sqlCmd = new WSqlCommand(m_ConStr,"lspr_GetUserProperties")){
sqlCmd.AddParameter("@UserName",SqlDbType.NVarChar,userName);
DataSet ds = sqlCmd.Execute();
ds.Tables[0].TableName = "Users";
if(ds.Tables["Users"].Rows.Count > 0){
return true;
}
}
return false;
}
#endregion
#region function MapUser
/// <summary>
/// Maps email address to mailbox.
/// </summary>
/// <param name="emailAddress"></param>
/// <returns>Returns mailbox or null if such email address won't exist.</returns>
public string MapUser(string emailAddress)
{
using(WSqlCommand sqlCmd = new WSqlCommand(m_ConStr,"lspr_MapUser")){
sqlCmd.AddParameter("@EmailAddress",SqlDbType.NVarChar,emailAddress);
DataSet ds = sqlCmd.Execute();
ds.Tables[0].TableName = "UserAddresses";
if(ds.Tables["UserAddresses"].Rows.Count > 0){
return ds.Tables["UserAddresses"].Rows[0]["UserName"].ToString();
}
}
return null;
}
#endregion
#region function ValidateMailboxSize
/// <summary>
/// Checks if specified mailbox size is exceeded.
/// </summary>
/// <param name="userName">User name. Use <see cref="IMailServerApi.GetUsers">GetUsers()</see> to get valid values.</param>
/// <returns>Returns true if exceeded.</returns>
public bool ValidateMailboxSize(string userName)
{
using(WSqlCommand sqlCmd = new WSqlCommand(m_ConStr,"lspr_ValidateMailboxSize")){
sqlCmd.AddParameter("@UserName",SqlDbType.NVarChar,userName);
DataSet ds = sqlCmd.Execute();
ds.Tables[0].TableName = "Detail";
if(ds.Tables["Detail"].Rows.Count > 0){
return !Convert.ToBoolean(ds.Tables["Detail"].Rows[0]["Validated"]);
}
}
return false;
}
#endregion
#region method GetUserPermissions
/// <summary>
/// Gets specified user permissions.
/// </summary>
/// <param name="userName">User name.</param>
/// <returns></returns>
public UserPermissions_enum GetUserPermissions(string userName)
{
using(WSqlCommand sqlCmd = new WSqlCommand(m_ConStr,"lspr_GetUserProperties")){
sqlCmd.AddParameter("@UserName",SqlDbType.NVarChar,userName);
DataSet ds = sqlCmd.Execute();
ds.Tables[0].TableName = "Users";
if(ds.Tables["Users"].Rows.Count > 0){
return (UserPermissions_enum)Convert.ToInt32(ds.Tables["Users"].Rows[0]["Permissions"]);
}
}
return UserPermissions_enum.None;
}
#endregion
#region method GetUserLastLoginTime
/// <summary>
/// Gets user last login time.
/// </summary>
/// <param name="userName">User name who's last login time to get.</param>
/// <returns>User last login time.</returns>
public DateTime GetUserLastLoginTime(string userName)
{
using(WSqlCommand sqlCmd = new WSqlCommand(m_ConStr,"lspr_GetUserProperties")){
sqlCmd.AddParameter("@userName",SqlDbType.NVarChar,userName);
DataSet ds = sqlCmd.Execute();
ds.Tables[0].TableName = "Users";
if(ds.Tables["Users"].Rows.Count > 0){
return Convert.ToDateTime(ds.Tables["Users"].Rows[0]["LastLoginTime"]);
}
return DateTime.Now;
}
}
#endregion
#region method UpdateUserLastLoginTime
/// <summary>
/// Updates user last login time.
/// </summary>
/// <param name="userName">User name who's last login time to update.</param>
public void UpdateUserLastLoginTime(string userName)
{
using(WSqlCommand sqlCmd = new WSqlCommand(m_ConStr,"lspr_UpdateUserLastLoginTime")){
sqlCmd.AddParameter("@userName",SqlDbType.NVarChar,userName);
DataSet ds = sqlCmd.Execute();
}
}
#endregion
#region function GetUserRemoteServers
/// <summary>
/// Gets user pop3 remote accounts.
/// </summary>
/// <param name="userName">User name. Use <see cref="IMailServerApi.GetUsers">GetUsers()</see> to get valid values.</param>
/// <returns></returns>
public DataView GetUserRemoteServers(string userName)
{
using(WSqlCommand sqlCmd = new WSqlCommand(m_ConStr,"lspr_GetUserRemoteServers")){
if(userName.Length > 0){
sqlCmd.AddParameter("@UserName",SqlDbType.NVarChar,userName);
}
DataSet ds = sqlCmd.Execute();
ds.Tables[0].TableName = "UserRemoteServers";
return ds.Tables["UserRemoteServers"].DefaultView;
}
}
#endregion
#region function AddUserRemoteServer
/// <summary>
/// AAdds new remote pop3 server to user.
/// </summary>
/// <param name="serverID">Server ID. Suggested value is Guid.NewGuid() .</param>
/// <param name="userName">User name. Use <see cref="IMailServerApi.GetUsers">GetUsers()</see> to get valid values.</param>
/// <param name="description">Remote server description.</param>
/// <param name="remoteServer">Remote server name.</param>
/// <param name="remotePort">Remote server port.</param>
/// <param name="remoteUser">Remote server user name.</param>
/// <param name="remotePassword">Remote server password.</param>
/// <param name="useSSL">Specifies if SSL must be used to connect to remote server.</param>
/// <param name="enabled">Specifies if remote server is enabled.</param>
/// <remarks>Throws exception if specified user remote server already exists.</remarks>
public void AddUserRemoteServer(string serverID,string userName,string description,string remoteServer,int remotePort,string remoteUser,string remotePassword,bool useSSL,bool enabled)
{
if(serverID.Length == 0){
throw new Exception("You must specify serverID");
}
if(userName.Length == 0){
throw new Exception("You must specify userName");
}
using(WSqlCommand sqlCmd = new WSqlCommand(m_ConStr,"lspr_AddUserRemoteServer")){
sqlCmd.AddParameter("@ServerID" ,SqlDbType.NVarChar,serverID);
sqlCmd.AddParameter("@UserName" ,SqlDbType.NVarChar,userName);
sqlCmd.AddParameter("@Description" ,SqlDbType.NVarChar,description);
sqlCmd.AddParameter("@RemoteServer" ,SqlDbType.NVarChar,remoteServer);
sqlCmd.AddParameter("@RemotePort" ,SqlDbType.Int ,remotePort);
sqlCmd.AddParameter("@RemoteUserName" ,SqlDbType.NVarChar,remoteUser);
sqlCmd.AddParameter("@RemotePassword" ,SqlDbType.NVarChar,remotePassword);
sqlCmd.AddParameter("@UseSSL" ,SqlDbType.Bit ,useSSL);
sqlCmd.AddParameter("@Enabled" ,SqlDbType.Bit ,enabled);
DataSet ds = sqlCmd.Execute();
ds.Tables[0].TableName = "Result";
if(ds.Tables["Result"].Rows.Count > 0 && ds.Tables["Result"].Rows[0]["ErrorText"].ToString().Length > 0){
throw new Exception(ds.Tables["Result"].Rows[0]["ErrorText"].ToString());
}
}
}
#endregion
#region function DeleteUserRemoteServer
/// <summary>
/// Deletes specified pop3 remote account from user.
/// </summary>
/// <param name="serverID">Remote server ID. Use <see cref="IMailServerApi.GetUserRemoteServers">GetUserRemoteServers()</see> to get valid values.</param>
public void DeleteUserRemoteServer(string serverID)
{
using(WSqlCommand sqlCmd = new WSqlCommand(m_ConStr,"lspr_DeleteUserRemoteServer")){
sqlCmd.AddParameter("@ServerID" ,SqlDbType.UniqueIdentifier,serverID);
DataSet ds = sqlCmd.Execute();
}
}
#endregion
#region mehtod UpdateUserRemoteServer
/// <summary>
/// Updates user remote pop3 server.
/// </summary>
/// <param name="serverID">Server ID. Suggested value is Guid.NewGuid() .</param>
/// <param name="userName">User name. Use <see cref="IMailServerApi.GetUsers">GetUsers()</see> to get valid values.</param>
/// <param name="description">Remote server description.</param>
/// <param name="remoteServer">Remote server name.</param>
/// <param name="remotePort">Remote server port.</param>
/// <param name="remoteUser">Remote server user name.</param>
/// <param name="remotePassword">Remote server password.</param>
/// <param name="useSSL">Specifies if SSL must be used to connect to remote server.</param>
/// <param name="enabled">Specifies if remote server is enabled.</param>
/// <remarks>Throws exception if specified user remote server already exists.</remarks>
public void UpdateUserRemoteServer(string serverID,string userName,string description,string remoteServer,int remotePort,string remoteUser,string remotePassword,bool useSSL,bool enabled)
{
if(serverID.Length == 0){
throw new Exception("You must specify serverID");
}
if(userName.Length == 0){
throw new Exception("You must specify userName");
}
using(WSqlCommand sqlCmd = new WSqlCommand(m_ConStr,"lspr_UpdateUserRemoteServer")){
sqlCmd.AddParameter("@ServerID" ,SqlDbType.NVarChar,serverID);
sqlCmd.AddParameter("@UserName" ,SqlDbType.NVarChar,userName);
sqlCmd.AddParameter("@Description" ,SqlDbType.NVarChar,description);
sqlCmd.AddParameter("@RemoteServer" ,SqlDbType.NVarChar,remoteServer);
sqlCmd.AddParameter("@RemotePort" ,SqlDbType.Int ,remotePort);
sqlCmd.AddParameter("@RemoteUserName" ,SqlDbType.NVarChar,remoteUser);
sqlCmd.AddParameter("@RemotePassword" ,SqlDbType.NVarChar,remotePassword);
sqlCmd.AddParameter("@UseSSL" ,SqlDbType.Bit ,useSSL);
sqlCmd.AddParameter("@Enabled" ,SqlDbType.Bit ,enabled);
DataSet ds = sqlCmd.Execute();
ds.Tables[0].TableName = "Result";
if(ds.Tables["Result"].Rows.Count > 0 && ds.Tables["Result"].Rows[0]["ErrorText"].ToString().Length > 0){
throw new Exception(ds.Tables["Result"].Rows[0]["ErrorText"].ToString());
}
}
}
#endregion
#region method GetUserMessageRules
/// <summary>
/// Gets user message rules.
/// </summary>
/// <param name="userName">User name.</param>
/// <returns></returns>
public DataView GetUserMessageRules(string userName)
{
using(WSqlCommand sqlCmd = new WSqlCommand(m_ConStr,"lspr_GetUserMessageRules")){
if(userName.Length > 0){
sqlCmd.AddParameter("@UserName",SqlDbType.NVarChar,userName);
}
DataSet ds = sqlCmd.Execute();
ds.Tables[0].TableName = "UserMessageRules";
// We need to convert MatchExpression to string.
// MSSQL won't allow strings bigger than 400 chars, because of it we store it as Image.
ds.Tables[0].Columns["MatchExpression"].ColumnName = "MatchExpressionOld";
ds.Tables[0].Columns.Add("MatchExpression",typeof(string));
foreach(DataRow dr in ds.Tables[0].Rows){
dr["MatchExpression"] = System.Text.Encoding.Default.GetString((byte[])dr["MatchExpressionOld"]);
}
ds.Tables[0].Columns.Remove("MatchExpressionOld");
return ds.Tables["UserMessageRules"].DefaultView;
}
}
#endregion
#region method AddUserMessageRule
/// <summary>
/// Adds new user message rule.
/// </summary>
/// <param name="userID">User who owns specified rule.</param>
/// <param name="ruleID">Rule ID. Guid.NewID().ToString() is suggested.</param>
/// <param name="cost">Cost specifies in what order rules are processed. Costs with lower values are processed first.</param>
/// <param name="enabled">Specifies if rule is enabled.</param>
/// <param name="checkNextRule">Specifies when next rule is checked.</param>
/// <param name="description">Rule description.</param>
/// <param name="matchExpression">Rule match expression.</param>
public void AddUserMessageRule(string userID,string ruleID,long cost,bool enabled,GlobalMessageRule_CheckNextRule_enum checkNextRule,string description,string matchExpression)
{
if(userID == null || userID == ""){
throw new Exception("Invalid userID value, userID can't be '' or null !");
}
if(ruleID == null || ruleID == ""){
throw new Exception("Invalid ruleID value, ruleID can't be '' or null !");
}
using(WSqlCommand sqlCmd = new WSqlCommand(m_ConStr,"lspr_AddUserMessageRule")){
sqlCmd.AddParameter("@userID" ,SqlDbType.NVarChar,userID);
sqlCmd.AddParameter("@ruleID" ,SqlDbType.NVarChar,ruleID);
sqlCmd.AddParameter("@cost" ,SqlDbType.BigInt ,cost);
sqlCmd.AddParameter("@enabled" ,SqlDbType.Bit ,enabled);
sqlCmd.AddParameter("@checkNextRule" ,SqlDbType.Int ,checkNextRule);
sqlCmd.AddParameter("@description" ,SqlDbType.NVarChar,description);
sqlCmd.AddParameter("@matchExpression" ,SqlDbType.Image ,System.Text.Encoding.Default.GetBytes(matchExpression));
DataSet ds = sqlCmd.Execute();
ds.Tables[0].TableName = "UserMessageRules";
if(ds.Tables["UserMessageRules"].Rows.Count > 0 && ds.Tables["UserMessageRules"].Rows[0]["ErrorText"].ToString().Length > 0){
throw new Exception(ds.Tables["UserMessageRules"].Rows[0]["ErrorText"].ToString());
}
}
}
#endregion
#region method DeleteUserMessageRule
/// <summary>
/// Deletes specified user message rule.
/// </summary>
/// <param name="userID">User who owns specified rule.</param>
/// <param name="ruleID">Rule ID.</param>
public void DeleteUserMessageRule(string userID,string ruleID)
{
if(userID == null || userID == ""){
throw new Exception("Invalid userID value, userID can't be '' or null !");
}
if(ruleID == null || ruleID == ""){
throw new Exception("Invalid ruleID value, ruleID can't be '' or null !");
}
using(WSqlCommand sqlCmd = new WSqlCommand(m_ConStr,"lspr_DeleteUserMessageRule")){
sqlCmd.AddParameter("@userID" ,SqlDbType.NVarChar,userID);
sqlCmd.AddParameter("@ruleID" ,SqlDbType.NVarChar,ruleID);
DataSet ds = sqlCmd.Execute();
}
}
#endregion
#region method UpdateUserMessageRule
/// <summary>
/// Updates specified user message rule.
/// </summary>
/// <param name="userID">User who owns specified rule.</param>
/// <param name="ruleID">Rule ID.</param>
/// <param name="cost">Cost specifies in what order rules are processed. Costs with lower values are processed first.</param>
/// <param name="enabled">Specifies if rule is enabled.</param>
/// <param name="checkNextRule">Specifies when next rule is checked.</param>
/// <param name="description">Rule description.</param>
/// <param name="matchExpression">Rule match expression.</param>
public void UpdateUserMessageRule(string userID,string ruleID,long cost,bool enabled,GlobalMessageRule_CheckNextRule_enum checkNextRule,string description,string matchExpression)
{
if(userID == null || userID == ""){
throw new Exception("Invalid userID value, userID can't be '' or null !");
}
if(ruleID == null || ruleID == ""){
throw new Exception("Invalid ruleID value, ruleID can't be '' or null !");
}
using(WSqlCommand sqlCmd = new WSqlCommand(m_ConStr,"lspr_UpdateUserMessageRule")){
sqlCmd.AddParameter("@userID" ,SqlDbType.NVarChar,userID);
sqlCmd.AddParameter("@ruleID" ,SqlDbType.NVarChar,ruleID);
sqlCmd.AddParameter("@cost" ,SqlDbType.BigInt ,cost);
sqlCmd.AddParameter("@enabled" ,SqlDbType.Bit ,enabled);
sqlCmd.AddParameter("@checkNextRule" ,SqlDbType.Int ,checkNextRule);
sqlCmd.AddParameter("@description" ,SqlDbType.NVarChar,description);
sqlCmd.AddParameter("@matchExpression" ,SqlDbType.Image ,System.Text.Encoding.Default.GetBytes(matchExpression));
DataSet ds = sqlCmd.Execute();
ds.Tables[0].TableName = "UserMessageRules";
if(ds.Tables["UserMessageRules"].Rows.Count > 0 && ds.Tables["UserMessageRules"].Rows[0]["ErrorText"].ToString().Length > 0){
throw new Exception(ds.Tables["UserMessageRules"].Rows[0]["ErrorText"].ToString());
}
}
}
#endregion
#region method GetUserMessageRuleActions
/// <summary>
/// Gets specified user message rule actions.
/// </summary>
/// <param name="userID">User who owns specified rule.</param>
/// <param name="ruleID">Rule ID of rule which actions to get.</param>
public DataView GetUserMessageRuleActions(string userID,string ruleID)
{
if(userID == null || userID == ""){
throw new Exception("Invalid userID value, userID can't be '' or null !");
}
if(ruleID == null || ruleID == ""){
throw new Exception("Invalid ruleID value, ruleID can't be '' or null !");
}
using(WSqlCommand sqlCmd = new WSqlCommand(m_ConStr,"lspr_GetUserMessageRuleActions")){
sqlCmd.AddParameter("@userID",SqlDbType.NVarChar,userID);
sqlCmd.AddParameter("@ruleID",SqlDbType.NVarChar,ruleID);
DataSet ds = sqlCmd.Execute();
ds.Tables[0].TableName = "UserMessageRuleActions";
return ds.Tables["UserMessageRuleActions"].DefaultView;
}
}
#endregion
#region method AddUserMessageRuleAction
/// <summary>
/// Adds action to specified user message rule.
/// </summary>
/// <param name="userID">User who owns specified rule.</param>
/// <param name="ruleID">Rule ID to which to add this action.</param>
/// <param name="actionID">Action ID. Guid.NewID().ToString() is suggested.</param>
/// <param name="description">Action description.</param>
/// <param name="actionType">Action type.</param>
/// <param name="actionData">Action data. Data structure depends on action type.</param>
public void AddUserMessageRuleAction(string userID,string ruleID,string actionID,string description,GlobalMessageRuleAction_enum actionType,byte[] actionData)
{
if(userID == null || userID == ""){
throw new Exception("Invalid userID value, userID can't be '' or null !");
}
if(ruleID == null || ruleID == ""){
throw new Exception("Invalid ruleID value, ruleID can't be '' or null !");
}
if(actionID == null || actionID == ""){
throw new Exception("Invalid actionID value, actionID can't be '' or null !");
}
using(WSqlCommand sqlCmd = new WSqlCommand(m_ConStr,"lspr_AddUserMessageRuleAction")){
sqlCmd.AddParameter("@userID" ,SqlDbType.NVarChar,userID);
sqlCmd.AddParameter("@ruleID" ,SqlDbType.NVarChar,ruleID);
sqlCmd.AddParameter("@actionID" ,SqlDbType.NVarChar,actionID);
sqlCmd.AddParameter("@description" ,SqlDbType.NVarChar,description);
sqlCmd.AddParameter("@actionType" ,SqlDbType.Int ,(int)actionType);
sqlCmd.AddParameter("@actionData" ,SqlDbType.Image ,actionData);
DataSet ds = sqlCmd.Execute();
ds.Tables[0].TableName = "UserMessageRuleActions";
if(ds.Tables["UserMessageRuleActions"].Rows.Count > 0 && ds.Tables["UserMessageRuleActions"].Rows[0]["ErrorText"].ToString().Length > 0){
throw new Exception(ds.Tables["UserMessageRuleActions"].Rows[0]["ErrorText"].ToString());
}
}
}
#endregion
#region method DeleteUserMessageRuleAction
/// <summary>
/// Deletes specified action from specified user message rule.
/// </summary>
/// <param name="userID">User who owns specified rule.</param>
/// <param name="ruleID">Rule ID which action to delete.</param>
/// <param name="actionID">Action ID of action which to delete.</param>
public void DeleteUserMessageRuleAction(string userID,string ruleID,string actionID)
{
if(userID == null || userID == ""){
throw new Exception("Invalid userID value, userID can't be '' or null !");
}
if(ruleID == null || ruleID == ""){
throw new Exception("Invalid ruleID value, ruleID can't be '' or null !");
}
if(actionID == null || actionID == ""){
throw new Exception("Invalid actionID value, actionID can't be '' or null !");
}
using(WSqlCommand sqlCmd = new WSqlCommand(m_ConStr,"lspr_DeleteUserMessageRuleAction")){
sqlCmd.AddParameter("@userID" ,SqlDbType.NVarChar,userID);
sqlCmd.AddParameter("@ruleID" ,SqlDbType.NVarChar,ruleID);
sqlCmd.AddParameter("@actionID" ,SqlDbType.NVarChar,actionID);
DataSet ds = sqlCmd.Execute();
}
}
#endregion
#region method UpdateUserMessageRuleAction
/// <summary>
/// Updates specified rule action.
/// </summary>
/// <param name="userID">User who owns specified rule.</param>
/// <param name="ruleID">Rule ID which action to update.</param>
/// <param name="actionID">Action ID of action which to update.</param>
/// <param name="description">Action description.</param>
/// <param name="actionType">Action type.</param>
/// <param name="actionData">Action data. Data structure depends on action type.</param>
public void UpdateUserMessageRuleAction(string userID,string ruleID,string actionID,string description,GlobalMessageRuleAction_enum actionType,byte[] actionData)
{
if(userID == null || userID == ""){
throw new Exception("Invalid userID value, userID can't be '' or null !");
}
if(ruleID == null || ruleID == ""){
throw new Exception("Invalid ruleID value, ruleID can't be '' or null !");
}
if(actionID == null || actionID == ""){
throw new Exception("Invalid actionID value, actionID can't be '' or null !");
}
using(WSqlCommand sqlCmd = new WSqlCommand(m_ConStr,"lspr_UpdateUserMessageRuleAction")){
sqlCmd.AddParameter("@userID" ,SqlDbType.NVarChar,userID);
sqlCmd.AddParameter("@ruleID" ,SqlDbType.NVarChar,ruleID);
sqlCmd.AddParameter("@actionID" ,SqlDbType.NVarChar,actionID);
sqlCmd.AddParameter("@description" ,SqlDbType.NVarChar,description);
sqlCmd.AddParameter("@actionType" ,SqlDbType.Int ,(int)actionType);
sqlCmd.AddParameter("@actionData" ,SqlDbType.Image ,actionData);
DataSet ds = sqlCmd.Execute();
ds.Tables[0].TableName = "UserMessageRuleActions";
if(ds.Tables["UserMessageRuleActions"].Rows.Count > 0 && ds.Tables["UserMessageRuleActions"].Rows[0]["ErrorText"].ToString().Length > 0){
throw new Exception(ds.Tables["UserMessageRuleActions"].Rows[0]["ErrorText"].ToString());
}
}
}
#endregion
#region function AuthUser
/// <summary>
/// Authenticates user.
/// </summary>
/// <param name="userName">User name.</param>
/// <param name="passwData">Password data.</param>
/// <param name="authData">Authentication specific data(as tag).</param>
/// <param name="authType">Authentication type.</param>
/// <returns></returns>
public DataSet AuthUser(string userName,string passwData,string authData,AuthType authType)
{
DataSet retVal = new DataSet();
DataTable dt = retVal.Tables.Add("Result");
dt.Columns.Add("Result");
dt.Columns.Add("ReturnData");
DataRow drx = dt.NewRow();
drx["Result"] = "false";
drx["ReturnData"] = "";
dt.Rows.Add(drx);
using(WSqlCommand sqlCmd = new WSqlCommand(m_ConStr,"lspr_GetUserProperties")){
sqlCmd.AddParameter("@UserName",SqlDbType.NVarChar,userName);
DataSet ds = sqlCmd.Execute();
ds.Tables[0].TableName = "Users";
if(ds.Tables["Users"].Rows.Count > 0){
string password = ds.Tables["Users"].Rows[0]["PASSWORD"].ToString().ToLower();
switch(authType)
{
case AuthType.APOP:
if(AuthHelper.Apop(password,authData) == passwData){
drx["Result"] = "true";
return retVal;
}
break;
case AuthType.CRAM_MD5:
if(AuthHelper.Cram_Md5(password,authData) == passwData){
drx["Result"] = "true";
return retVal;
}
break;
case AuthType.DIGEST_MD5:
string realm = "";
string nonce = "";
string cnonce = "";
string digest_uri = "";
foreach(string clntRespParam in authData.Split(',')){
if(clntRespParam.StartsWith("realm=")){
realm = clntRespParam.Split(new char[]{'='},2)[1].Replace("\"","");
}
else if(clntRespParam.StartsWith("nonce=")){
nonce = clntRespParam.Split(new char[]{'='},2)[1].Replace("\"","");
}
else if(clntRespParam.StartsWith("cnonce=")){
cnonce = clntRespParam.Split(new char[]{'='},2)[1].Replace("\"","");
}
else if(clntRespParam.StartsWith("digest-uri=")){
digest_uri = clntRespParam.Split(new char[]{'='},2)[1].Replace("\"","");
}
}
if(passwData == AuthHelper.Digest_Md5(true,realm,userName,password,nonce,cnonce,digest_uri)){
string returnData = AuthHelper.Digest_Md5(false,realm,userName,password,nonce,cnonce,digest_uri);
drx["Result"] = "true";
drx["ReturnData"] = returnData;
return retVal;
}
break;
case AuthType.Plain:
if(password == passwData.ToLower()){
drx["Result"] = "true";
return retVal;
}
break;
}
}
}
return retVal;
}
#endregion
#region method GroupExists
/// <summary>
/// Gets if specified user group exists.
/// </summary>
/// <param name="groupName">Group name.</param>
/// <returns>Returns true, if user group exists.</returns>
public bool GroupExists(string groupName)
{
/* Implementation notes:
*) Validate values. Throw ArgumnetExcetion if invalid values.
*) Check if group exists.
*/
//--- Validate values --------------------//
ArgsValidator.ValidateUserName(groupName);
//----------------------------------------//
using(WSqlCommand sqlCmd = new WSqlCommand(m_ConStr,"lspr_GroupExists")){
sqlCmd.AddParameter("@groupName",SqlDbType.NVarChar,groupName);
DataSet ds = sqlCmd.Execute();
ds.Tables[0].TableName = "Result";
if(ds.Tables["Result"].Rows.Count > 0){
return true;
}
}
return false;
}
#endregion
#region method GetGroups
/// <summary>
/// Gets user groups.
/// </summary>
/// <returns></returns>
public DataView GetGroups()
{
/* Implementation notes:
*) Get groups.
*/
using(WSqlCommand sqlCmd = new WSqlCommand(m_ConStr,"lspr_GetGroups")){
DataSet ds = sqlCmd.Execute();
ds.Tables[0].TableName = "Groups";
return ds.Tables["Groups"].DefaultView;
}
}
#endregion
#region method AddGroup
/// <summary>
/// Adds new user group.
/// </summary>
/// <param name="groupID">Group ID. Guid.NewGuid().ToString() is suggested.</param>
/// <param name="groupName">Group name.</param>
/// <param name="description">Group description.</param>
/// <param name="enabled">Specifies if group is enabled.</param>
public void AddGroup(string groupID,string groupName,string description,bool enabled)
{
/* Implementation notes:
*) Validate values. Throw ArgumnetExcetion if invalid values.
*) Ensure that group ID won't exist already. Throw Exception if does.
*) Ensure that group or user with specified name doesn't exist. Throw Exception if does.
*) Add group.
*/
//--- Validate values --------------------//
if(groupID == null || groupID == ""){
throw new Exception("Invalid groupID value, groupID can't be '' or null !");
}
ArgsValidator.ValidateUserName(groupName);
ArgsValidator.ValidateNotNull(description);
//----------------------------------------//
/* We handle these is SQL, sql returns these errors in ErrorText
*) Ensure that group ID won't exist already. Throw Exception if does.
*) Ensure that group or user with specified name doesn't exist. Throw Exception if does.
*/
// Insert group
using(WSqlCommand sqlCmd = new WSqlCommand(m_ConStr,"lspr_AddGroup")){
sqlCmd.AddParameter("@groupID" ,SqlDbType.NVarChar,groupID);
sqlCmd.AddParameter("@groupName" ,SqlDbType.NVarChar,groupName);
sqlCmd.AddParameter("@description" ,SqlDbType.NVarChar,description);
sqlCmd.AddParameter("@enabled" ,SqlDbType.Bit ,enabled);
DataSet ds = sqlCmd.Execute();
ds.Tables[0].TableName = "Groups";
// Proccess adding errors
if(ds.Tables["Groups"].Rows.Count > 0 && ds.Tables["Groups"].Rows[0]["ErrorText"].ToString().Length > 0){
throw new Exception(ds.Tables["Groups"].Rows[0]["ErrorText"].ToString());
}
}
}
#endregion
#region method DeleteGroup
/// <summary>
/// Deletes specified user group.
/// </summary>
/// <param name="groupID">Group ID.</param>
public void DeleteGroup(string groupID)
{
/* Implementation notes:
*) Validate values. Throw ArgumnetExcetion if invalid values.
*) Ensure that group does exist. Throw Exception if doesn't.
*) Delete group members.
*) Delete group.
*/
//--- Validate values --------------------//
if(groupID == null || groupID == ""){
throw new Exception("Invalid groupID value, groupID can't be '' or null !");
}
//----------------------------------------//
/* We handle these is SQL, sql returns these errors in ErrorText
*) Ensure that group does exist.
*) Delete group members.
*/
// Delete group and it's emebres
using(WSqlCommand sqlCmd = new WSqlCommand(m_ConStr,"lspr_DeleteGroup")){
sqlCmd.AddParameter("@groupID" ,SqlDbType.NVarChar,groupID);
DataSet ds = sqlCmd.Execute();
ds.Tables[0].TableName = "Groups";
// Proccess errors
if(ds.Tables["Groups"].Rows.Count > 0 && ds.Tables["Groups"].Rows[0]["ErrorText"].ToString().Length > 0){
throw new Exception(ds.Tables["Groups"].Rows[0]["ErrorText"].ToString());
}
}
}
#endregion
#region method UpdateGroup
/// <summary>
/// Updates user group info.
/// </summary>
/// <param name="groupID">Group ID.</param>
/// <param name="groupName">Group name.</param>
/// <param name="description">Group description.</param>
/// <param name="enabled">Specifies if group is enabled.</param>
public void UpdateGroup(string groupID,string groupName,string description,bool enabled)
{
/* Implementation notes:
*) Validate values. Throw ArgumnetExcetion if invalid values.
*) Ensure that group with specified ID does exist. Throw Exception if doesn't.
*) If group name is changed, ensure that new group name won't conflict
any other group or user name. Throw Exception if does.
*) Udpate group.
*/
//--- Validate values --------------------//
if(groupID == null || groupID == ""){
throw new Exception("Invalid groupID value, groupID can't be '' or null !");
}
ArgsValidator.ValidateUserName(groupName);
ArgsValidator.ValidateNotNull(description);
//----------------------------------------//
/* We handle these is SQL, sql returns these errors in ErrorText
*) Ensure that group with specified ID does exist. Throw Exception if doesn't.
*) If group name is changed, ensure that new group name won't conflict
any other group or user name. Throw Exception if does.
*/
// Update group
using(WSqlCommand sqlCmd = new WSqlCommand(m_ConStr,"lspr_UpdateGroup")){
sqlCmd.AddParameter("@groupID" ,SqlDbType.NVarChar,groupID);
sqlCmd.AddParameter("@groupName" ,SqlDbType.NVarChar,groupName);
sqlCmd.AddParameter("@description" ,SqlDbType.NVarChar,description);
sqlCmd.AddParameter("@enabled" ,SqlDbType.Bit ,enabled);
DataSet ds = sqlCmd.Execute();
ds.Tables[0].TableName = "Groups";
// Proccess adding errors
if(ds.Tables["Groups"].Rows.Count > 0 && ds.Tables["Groups"].Rows[0]["ErrorText"].ToString().Length > 0){
throw new Exception(ds.Tables["Groups"].Rows[0]["ErrorText"].ToString());
}
}
}
#endregion
#region method GroupMemberExists
/// <summary>
/// Gets if specified group member exists in specified user group members list.
/// </summary>
/// <param name="groupName">Group name</param>
/// <param name="userOrGroup">User or group.</param>
/// <returns></returns>
public bool GroupMemberExists(string groupName,string userOrGroup)
{
/* Implementation notes:
*) Validate values. Throw ArgumnetExcetion if invalid values.
*) Ensure that group exists. Throw Exception if doesn't.
*) Check if group member exists.
*/
//--- Validate values --------------------//
ArgsValidator.ValidateUserName(groupName);
ArgsValidator.ValidateUserName(userOrGroup);
//----------------------------------------//
// Ensure that group exists. Throw Exception if doesn't.
if(!GroupExists(groupName)){
throw new Exception("Invalid group name, specified group '" + groupName + "' doesn't exist !");
}
using(WSqlCommand sqlCmd = new WSqlCommand(m_ConStr,"lspr_GroupMemberExists")){
sqlCmd.AddParameter("@groupName" ,SqlDbType.NVarChar,groupName);
sqlCmd.AddParameter("@userOrGroup",SqlDbType.NVarChar,userOrGroup);
DataSet ds = sqlCmd.Execute();
ds.Tables[0].TableName = "Result";
if(ds.Tables["Result"].Rows.Count > 0){
return true;
}
}
return false;
}
#endregion
#region method GetGroupMembers
/// <summary>
/// Gets useer group members who belong to specified group.
/// </summary>
/// <param name="groupName">Group name.</param>
/// <returns></returns>
public string[] GetGroupMembers(string groupName)
{
/* Implementation notes:
*) Validate values. Throw ArgumnetExcetion if invalid values.
*) Ensure that group exists. Throw Exception if doesn't.
*) Get members.
*/
//--- Validate values --------------------//
if(groupName == null || groupName == ""){
throw new Exception("Invalid groupName value, groupName can't be '' or null !");
}
//----------------------------------------//
// Ensure that group exists.
if(!GroupExists(groupName)){
throw new Exception("Invalid group name, specified group name '" + groupName + "' doesn't exist !");
}
using(WSqlCommand sqlCmd = new WSqlCommand(m_ConStr,"lspr_GetGroupMembers")){
sqlCmd.AddParameter("@groupName" ,SqlDbType.NVarChar,groupName);
DataSet ds = sqlCmd.Execute();
ds.Tables[0].TableName = "Groups";
List<string> members = new List<string>();
foreach(DataRow dr in ds.Tables["Groups"].Rows){
members.Add(dr["UserOrGroup"].ToString());
}
return members.ToArray();
}
}
#endregion
#region method AddGroupMember
/// <summary>
/// Add specified user or group to specified goup members list.
/// </summary>
/// <param name="groupName">Group name.</param>
/// <param name="userOrGroup">User or group.</param>
public void AddGroupMember(string groupName,string userOrGroup)
{
/* Implementation notes:
*) Validate values. Throw ArgumnetExcetion if invalid values.
*) Ensure that group exists. Throw Exception if doesn't.
*) Don't allow to add same group as group member.
*) Ensure that group member doesn't exist. Throw Exception if does.
*) Add group member.
*/
//--- Validate values --------------------//
ArgsValidator.ValidateUserName(groupName);
ArgsValidator.ValidateUserName(userOrGroup);
//----------------------------------------//
/* We handle these is SQL, sql returns these errors in ErrorText
*) Ensure that group exists. Throw Exception if doesn't.
*) Don't allow to add same group as group member.
*) Ensure that group member doesn't exist. Throw Exception if does.
*/
// Add group member
using(WSqlCommand sqlCmd = new WSqlCommand(m_ConStr,"lspr_AddGroupMember")){
sqlCmd.AddParameter("@groupName" ,SqlDbType.NVarChar,groupName);
sqlCmd.AddParameter("@userOrGroup" ,SqlDbType.NVarChar,userOrGroup);
DataSet ds = sqlCmd.Execute();
ds.Tables[0].TableName = "Result";
// Proccess errors
if(ds.Tables["Result"].Rows.Count > 0 && ds.Tables["Result"].Rows[0]["ErrorText"].ToString().Length > 0){
throw new Exception(ds.Tables["Result"].Rows[0]["ErrorText"].ToString());
}
}
}
#endregion
#region method DeleteGroupMember
/// <summary>
/// Deletes specified user or group from specified group members list.
/// </summary>
/// <param name="groupName">Group name.</param>
/// <param name="userOrGroup">User or group.</param>
public void DeleteGroupMember(string groupName,string userOrGroup)
{
/* Implementation notes:
*) Validate values. Throw ArgumnetExcetion if invalid values.
*) Ensure that group exists. Throw Exception if doesn't.
*) Ensure that group member does exist. Throw Exception if doesn't.
*) Delete group member.
*/
//--- Validate values --------------------//
ArgsValidator.ValidateUserName(groupName);
ArgsValidator.ValidateUserName(userOrGroup);
//----------------------------------------//
/* We handle these is SQL, sql returns these errors in ErrorText
*) Ensure that group exists. Throw Exception if doesn't.
*) Ensure that group member does exist. Throw Exception if doesn't.
*/
// Delete group and it's emebres
using(WSqlCommand sqlCmd = new WSqlCommand(m_ConStr,"lspr_DeleteGroupMember")){
sqlCmd.AddParameter("@groupName" ,SqlDbType.NVarChar,groupName);
sqlCmd.AddParameter("@userOrGroup" ,SqlDbType.NVarChar,userOrGroup);
DataSet ds = sqlCmd.Execute();
ds.Tables[0].TableName = "Result";
// Proccess errors
if(ds.Tables["Result"].Rows.Count > 0 && ds.Tables["Result"].Rows[0]["ErrorText"].ToString().Length > 0){
throw new Exception(ds.Tables["Result"].Rows[0]["ErrorText"].ToString());
}
}
}
#endregion
#region method GetGroupUsers
/// <summary>
/// Gets specified group users. All nested group members are replaced by actual users.
/// </summary>
/// <param name="groupName">Group name.</param>
/// <returns></returns>
public string[] GetGroupUsers(string groupName)
{
List<string> users = new List<string>();
List<string> proccessedGroups = new List<string>();
Queue<string> membersQueue = new Queue<string>();
string[] members = GetGroupMembers(groupName);
foreach(string member in members){
membersQueue.Enqueue(member);
}
while(membersQueue.Count > 0){
string member = membersQueue.Dequeue();
// Nested group
DataRow drGroup = GetGroup(member);
if(drGroup != null){
// Don't proccess poroccessed groups any more, causes infinite loop
if(!proccessedGroups.Contains(member.ToLower())){
// Skip disabled groups
if(Convert.ToBoolean(drGroup["Enabled"])){
members = GetGroupMembers(member);
foreach(string m in members){
membersQueue.Enqueue(m);
}
}
proccessedGroups.Add(member.ToLower());
}
}
// User
else{
if(!users.Contains(member)){
users.Add(member);
}
}
}
return users.ToArray();
}
#endregion
#endregion
#region MailingList related
#region function GetMailingLists
/// <summary>
/// Gets mailing lists.
/// </summary>
/// <param name="domainName">Domain name. Use <see cref="IMailServerApi.GetDomains">GetDomains()</see> to get valid values.</param>
/// <returns></returns>
public DataView GetMailingLists(string domainName)
{
using(WSqlCommand sqlCmd = new WSqlCommand(m_ConStr,"lspr_GetMailingLists")){
if(domainName != "ALL"){
sqlCmd.AddParameter("@DomainName",SqlDbType.NVarChar,domainName);
}
DataSet ds = sqlCmd.Execute();
ds.Tables[0].TableName = "MailingLists";
return ds.Tables["MailingLists"].DefaultView;
}
}
#endregion
#region function AddMailingList
/// <summary>
/// Adds new mailing list.
/// </summary>
/// <param name="mailingListID">Mailing list ID. Suggested value is Guid.NewGuid() .</param>
/// <param name="mailingListName">Mailing list name name. Eg. all@lumisoft.ee .</param>
/// <param name="description">Mailing list description.</param>
/// <param name="domainName">Domain name. Use <see cref="IMailServerApi.GetDomains">GetDomains()</see> to get valid values.</param>
/// <param name="enabled">Specifies if mailing list is enabled.</param>
/// <remarks>Throws exception if specified mailing list already exists.</remarks>
public void AddMailingList(string mailingListID,string mailingListName,string description,string domainName,bool enabled)
{
if(mailingListID.Length == 0){
throw new Exception("You must specify mailingListID");
}
if(mailingListName.Length == 0){
throw new Exception("You must specify mailingListName");
}
using(WSqlCommand sqlCmd = new WSqlCommand(m_ConStr,"lspr_AddMailingList")){
sqlCmd.AddParameter("@MailingListID" ,SqlDbType.NVarChar,mailingListID);
sqlCmd.AddParameter("@MailingListName" ,SqlDbType.NVarChar,mailingListName);
sqlCmd.AddParameter("@Description" ,SqlDbType.NVarChar,description);
sqlCmd.AddParameter("@DomainName" ,SqlDbType.NVarChar,domainName);
sqlCmd.AddParameter("@enabled" ,SqlDbType.Bit ,enabled);
DataSet ds = sqlCmd.Execute();
ds.Tables[0].TableName = "MailingLists";
if(ds.Tables["MailingLists"].Rows.Count > 0 && ds.Tables["MailingLists"].Rows[0]["ErrorText"].ToString().Length > 0){
throw new Exception(ds.Tables["MailingLists"].Rows[0]["ErrorText"].ToString());
}
}
}
#endregion
#region function DeleteMailingList
/// <summary>
/// Deletes specified mailing list.
/// </summary>
/// <param name="mailingListID"> Use <see cref="IMailServerApi.GetMailingLists">GetMailingLists()</see> to get valid values.</param>
/// <returns></returns>
public void DeleteMailingList(string mailingListID)
{
using(WSqlCommand sqlCmd = new WSqlCommand(m_ConStr,"lspr_DeleteMailingList")){
sqlCmd.AddParameter("@MailingListID" ,SqlDbType.NVarChar,mailingListID);
DataSet ds = sqlCmd.Execute();
}
}
#endregion
#region function UpdateMailingList
/// <summary>
/// Updates specified mailing list.
/// </summary>
/// <param name="mailingListID">Mailing list ID.</param>
/// <param name="mailingListName">Mailing list name name. Use <see cref="IMailServerApi.GetMailingLists">GetMailingLists()</see> to get valid values.</param>
/// <param name="description">Mailing list description.</param>
/// <param name="domainName">Domain name. Use <see cref="IMailServerApi.GetDomains">>GetUsers()</see> to get valid values.</param>
/// <param name="enabled">Specifies if mailing list is enabled.</param>
public void UpdateMailingList(string mailingListID,string mailingListName,string description,string domainName,bool enabled)
{
if(mailingListName.Length == 0){
throw new Exception("You must specify mailingListName");
}
using(WSqlCommand sqlCmd = new WSqlCommand(m_ConStr,"lspr_UpdateMailingList")){
sqlCmd.AddParameter("@MailingListID" ,SqlDbType.NVarChar,mailingListID);
sqlCmd.AddParameter("@MailingListName" ,SqlDbType.NVarChar,mailingListName);
sqlCmd.AddParameter("@Description" ,SqlDbType.NVarChar,description);
sqlCmd.AddParameter("@DomainName" ,SqlDbType.NVarChar,domainName);
sqlCmd.AddParameter("@enabled" ,SqlDbType.Bit ,enabled);
DataSet ds = sqlCmd.Execute();
ds.Tables[0].TableName = "MailingLists";
if(ds.Tables["MailingLists"].Rows.Count > 0 && ds.Tables["MailingLists"].Rows[0]["ErrorText"].ToString().Length > 0){
throw new Exception(ds.Tables["MailingLists"].Rows[0]["ErrorText"].ToString());
}
}
}
#endregion
#region function AddMailingListAddress
/// <summary>
/// Add new email address to specified mailing list.
/// </summary>
/// <param name="addressID">Address ID. Suggested value is Guid.NewGuid() .</param>
/// <param name="mailingListName">Mailing list name name. Use <see cref="IMailServerApi.GetMailingLists">GetMailingLists()</see> to get valid values.</param>
/// <param name="address">Mailing list member address.</param>
/// <remarks>Throws exception if specified mailing list member already exists.</remarks>
public void AddMailingListAddress(string addressID,string mailingListName,string address)
{
if(addressID.Length == 0){
throw new Exception("You must specify addressID");
}
if(mailingListName.Length == 0){
throw new Exception("You must specify mailingListName");
}
if(address.Length == 0){
throw new Exception("You must specify address");
}
using(WSqlCommand sqlCmd = new WSqlCommand(m_ConStr,"lspr_AddMailingListAddress")){
sqlCmd.AddParameter("@AddressID" ,SqlDbType.NVarChar,addressID);
sqlCmd.AddParameter("@MailingListName" ,SqlDbType.NVarChar,mailingListName);
sqlCmd.AddParameter("@Address" ,SqlDbType.NVarChar,address);
DataSet ds = sqlCmd.Execute();
ds.Tables[0].TableName = "MailingListAddresses";
if(ds.Tables["MailingListAddresses"].Rows.Count > 0 && ds.Tables["MailingListAddresses"].Rows[0]["ErrorText"].ToString().Length > 0){
throw new Exception(ds.Tables["MailingListAddresses"].Rows[0]["ErrorText"].ToString());
}
}
}
#endregion
#region function DeleteMailingListAddress
/// <summary>
/// Deletes specified email address from mailing list.
/// </summary>
/// <param name="addressID">Mailing list member address ID. Use <see cref="IMailServerApi.GetMailingListAddresses">GetMailingListMembers()</see> to get valid values.</param>
public void DeleteMailingListAddress(string addressID)
{
using(WSqlCommand sqlCmd = new WSqlCommand(m_ConStr,"lspr_DeleteMailingListAddress")){
sqlCmd.AddParameter("@AddressID" ,SqlDbType.UniqueIdentifier,addressID);
DataSet ds = sqlCmd.Execute();
}
}
#endregion
#region function GetMailingListAddresses
/// <summary>
/// Gets mailing list members.
/// </summary>
/// <param name="mailingListName">Mailing list name name. Use <see cref="IMailServerApi.GetMailingLists">GetMailingLists()</see> to get valid values.</param>
public DataView GetMailingListAddresses(string mailingListName)
{
using(WSqlCommand sqlCmd = new WSqlCommand(m_ConStr,"lspr_GetMailingListAddresses")){
if(mailingListName.Length > 0){
sqlCmd.AddParameter("@MailingListName",SqlDbType.NVarChar,mailingListName);
}
DataSet ds = sqlCmd.Execute();
ds.Tables[0].TableName = "MailingListAddresses";
return ds.Tables["MailingListAddresses"].DefaultView;
}
}
#endregion
#region method GetMailingListACL
/// <summary>
/// Gets mailing list ACL list.
/// </summary>
/// <param name="mailingListName">Mailing list name.</param>
public DataView GetMailingListACL(string mailingListName)
{
/* Implementation notes:
*) Get mailing list ACL list.
*/
// Get mailing list ACL list
using(WSqlCommand sqlCmd = new WSqlCommand(m_ConStr,"lspr_GetMailingListACL")){
sqlCmd.AddParameter("@MailingListName" ,SqlDbType.NVarChar,mailingListName);
DataSet ds = sqlCmd.Execute();
ds.Tables[0].TableName = "ACL";
return ds.Tables["ACL"].DefaultView;
}
}
#endregion
#region method AddMailingListACL
/// <summary>
/// Adds specified user or group to mailing list ACL list (specified user can send messages to the specified mailing list).
/// </summary>
/// <param name="mailingListName">Mailing list name.</param>
/// <param name="userOrGroup">User or group name.</param>
public void AddMailingListACL(string mailingListName,string userOrGroup)
{
/* Implementation notes:
*) Ensure that mailing list exists.
*) Ensure that user or group already doesn't exist in list.
*) Add ACL entry.
*/
/* We handle these is SQL, sql returns these errors in ErrorText
*) Ensure that mailing list exists.
*) Ensure that user or group already doesn't exist in list.
*/
// Add ACL entry
using(WSqlCommand sqlCmd = new WSqlCommand(m_ConStr,"lspr_AddMailingListACL")){
sqlCmd.AddParameter("@mailingListName" ,SqlDbType.NVarChar,mailingListName);
sqlCmd.AddParameter("@userOrGroup" ,SqlDbType.NVarChar,userOrGroup);
DataSet ds = sqlCmd.Execute();
ds.Tables[0].TableName = "Result";
// Proccess errors
if(ds.Tables["Result"].Rows.Count > 0 && ds.Tables["Result"].Rows[0]["ErrorText"].ToString().Length > 0){
throw new Exception(ds.Tables["Result"].Rows[0]["ErrorText"].ToString());
}
}
}
#endregion
#region method DeleteMailingListACL
/// <summary>
/// Deletes specified user or group from mailing list ACL list.
/// </summary>
/// <param name="mailingListName">Mailing list name.</param>
/// <param name="userOrGroup">User or group name.</param>
public void DeleteMailingListACL(string mailingListName,string userOrGroup)
{
/* Implementation notes:
*) Ensure that mailing list exists.
*) Delete ACL entry.
*/
/* We handle these is SQL, sql returns these errors in ErrorText
*) Ensure that mailing list exists.
*/
// Delete group and it's emebres
using(WSqlCommand sqlCmd = new WSqlCommand(m_ConStr,"lspr_DeleteMailingListACL")){
sqlCmd.AddParameter("@mailingListName" ,SqlDbType.NVarChar,mailingListName);
sqlCmd.AddParameter("@userOrGroup" ,SqlDbType.NVarChar,userOrGroup);
DataSet ds = sqlCmd.Execute();
ds.Tables[0].TableName = "Result";
// Proccess errors
if(ds.Tables["Result"].Rows.Count > 0 && ds.Tables["Result"].Rows[0]["ErrorText"].ToString().Length > 0){
throw new Exception(ds.Tables["Result"].Rows[0]["ErrorText"].ToString());
}
}
}
#endregion
#region method CanAccessMailingList
/// <summary>
/// Checks if specified user can access specified mailing list.
/// There is one built-in user anyone, that represent all users (including anonymous).
/// </summary>
/// <param name="mailingListName">Mailing list name.</param>
/// <param name="user">User name.</param>
/// <returns></returns>
public bool CanAccessMailingList(string mailingListName,string user)
{
/* Implementation notes:
*) Ensure that mailing list exists.
*) Check access.
*/
// Ensure that mailing list exists
// Get mailing list ID
string mailingListID = null;
foreach(DataRowView drV in GetMailingLists("ALL")){
if(drV["MailingListName"].ToString().ToLower() == mailingListName.ToLower()){
mailingListID = drV["MailingListID"].ToString();
break;
}
}
if(mailingListID == null){
throw new Exception("Invalid mailing list name, specified mailing list '" + mailingListName + "' doesn't exist !");
}
// Check access
WSqlCommand cmd = new WSqlCommand(m_ConStr,"select * from lsMailingListACL");
cmd.CommandType = CommandType.Text;
DataSet dsMailingListACL = cmd.Execute();
dsMailingListACL.Tables[0].TableName = "ACL";
foreach(DataRow dr in dsMailingListACL.Tables["ACL"].Rows){
if(dr["MailingListID"].ToString() == mailingListID){
// Built-in anyone
if(dr["UserOrGroup"].ToString().ToLower() == "anyone"){
return true;
}
// Built-in "authenticated users"
else if(dr["UserOrGroup"].ToString().ToLower() == "authenticated users"){
return UserExists(user);
}
// User or group
else{
if(GroupExists(dr["UserOrGroup"].ToString())){
return IsUserGroupMember(dr["UserOrGroup"].ToString(),user);
}
else{
return UserExists(user);
}
}
}
}
return false;
}
#endregion
#region function MailingListExists
/// <summary>
/// Checks if user exists.
/// </summary>
/// <param name="mailingListName">Mailing list name.</param>
/// <returns>Returns true if mailing list exists.</returns>
public bool MailingListExists(string mailingListName)
{
using(WSqlCommand sqlCmd = new WSqlCommand(m_ConStr,"lspr_GetMailingListProperties")){
sqlCmd.AddParameter("@MailingListName",SqlDbType.NVarChar,mailingListName);
DataSet ds = sqlCmd.Execute();
ds.Tables[0].TableName = "MailingLists";
if(ds.Tables["MailingLists"].Rows.Count > 0){
return true;
}
}
return false;
}
#endregion
#endregion
#region Rules
#region method GetGlobalMessageRules
/// <summary>
/// Gets global message rules.
/// </summary>
/// <returns></returns>
public DataView GetGlobalMessageRules()
{
using(WSqlCommand sqlCmd = new WSqlCommand(m_ConStr,"lspr_GetGlobalMessageRules")){
DataSet ds = sqlCmd.Execute();
ds.Tables[0].TableName = "GlobalMessageRules";
// We need to convert MatchExpression to string.
// MSSQL won't allow strings bigger than 400 chars, because of it we store it as Image.
ds.Tables[0].Columns["MatchExpression"].ColumnName = "MatchExpressionOld";
ds.Tables[0].Columns.Add("MatchExpression",typeof(string));
foreach(DataRow dr in ds.Tables[0].Rows){
dr["MatchExpression"] = System.Text.Encoding.Default.GetString((byte[])dr["MatchExpressionOld"]);
}
ds.Tables[0].Columns.Remove("MatchExpressionOld");
return ds.Tables["GlobalMessageRules"].DefaultView;
}
}
#endregion
#region method AddGlobalMessageRule
/// <summary>
/// Adds new global message rule.
/// </summary>
/// <param name="ruleID">Rule ID. Guid.NewID().ToString() is suggested.</param>
/// <param name="cost">Cost specifies in what order rules are processed. Costs with lower values are processed first.</param>
/// <param name="enabled">Specifies if rule is enabled.</param>
/// <param name="checkNextRule">Specifies when next rule is checked.</param>
/// <param name="description">Rule description.</param>
/// <param name="matchExpression">Rule match expression.</param>
public void AddGlobalMessageRule(string ruleID,long cost,bool enabled,GlobalMessageRule_CheckNextRule_enum checkNextRule,string description,string matchExpression)
{
if(ruleID == null || ruleID == ""){
throw new Exception("Invalid ruleID value, ruleID can't be '' or null !");
}
using(WSqlCommand sqlCmd = new WSqlCommand(m_ConStr,"lspr_AddGlobalMessageRule")){
sqlCmd.AddParameter("@ruleID" ,SqlDbType.NVarChar,ruleID);
sqlCmd.AddParameter("@cost" ,SqlDbType.BigInt ,cost);
sqlCmd.AddParameter("@enabled" ,SqlDbType.Bit ,enabled);
sqlCmd.AddParameter("@checkNextRule" ,SqlDbType.Int ,checkNextRule);
sqlCmd.AddParameter("@description" ,SqlDbType.NVarChar,description);
sqlCmd.AddParameter("@matchExpression" ,SqlDbType.Image ,System.Text.Encoding.Default.GetBytes(matchExpression));
DataSet ds = sqlCmd.Execute();
ds.Tables[0].TableName = "GlobalMessageRules";
if(ds.Tables["GlobalMessageRules"].Rows.Count > 0 && ds.Tables["GlobalMessageRules"].Rows[0]["ErrorText"].ToString().Length > 0){
throw new Exception(ds.Tables["GlobalMessageRules"].Rows[0]["ErrorText"].ToString());
}
}
}
#endregion
#region method DeleteGlobalMessageRule
/// <summary>
/// Deletes specified global message rule.
/// </summary>
/// <param name="ruleID">Rule ID of rule which to delete.</param>
public void DeleteGlobalMessageRule(string ruleID)
{
if(ruleID == null || ruleID == ""){
throw new Exception("Invalid ruleID value, ruleID can't be '' or null !");
}
using(WSqlCommand sqlCmd = new WSqlCommand(m_ConStr,"lspr_DeleteGlobalMessageRule")){
sqlCmd.AddParameter("@ruleID" ,SqlDbType.NVarChar,ruleID);
DataSet ds = sqlCmd.Execute();
}
}
#endregion
#region method UpdateGlobalMessageRule
/// <summary>
/// Updates specified global message rule.
/// </summary>
/// <param name="ruleID">Rule ID.</param>
/// <param name="cost">Cost specifies in what order rules are processed. Costs with lower values are processed first.</param>
/// <param name="enabled">Specifies if rule is enabled.</param>
/// <param name="checkNextRule">Specifies when next rule is checked.</param>
/// <param name="description">Rule description.</param>
/// <param name="matchExpression">Rule match expression.</param>
public void UpdateGlobalMessageRule(string ruleID,long cost,bool enabled,GlobalMessageRule_CheckNextRule_enum checkNextRule,string description,string matchExpression)
{
if(ruleID == null || ruleID == ""){
throw new Exception("Invalid ruleID value, ruleID can't be '' or null !");
}
using(WSqlCommand sqlCmd = new WSqlCommand(m_ConStr,"lspr_UpdateGlobalMessageRule")){
sqlCmd.AddParameter("@ruleID" ,SqlDbType.NVarChar,ruleID);
sqlCmd.AddParameter("@cost" ,SqlDbType.BigInt ,cost);
sqlCmd.AddParameter("@enabled" ,SqlDbType.Bit ,enabled);
sqlCmd.AddParameter("@checkNextRule" ,SqlDbType.Int ,checkNextRule);
sqlCmd.AddParameter("@description" ,SqlDbType.NVarChar,description);
sqlCmd.AddParameter("@matchExpression" ,SqlDbType.Image ,System.Text.Encoding.Default.GetBytes(matchExpression));
DataSet ds = sqlCmd.Execute();
ds.Tables[0].TableName = "GlobalMessageRules";
if(ds.Tables["GlobalMessageRules"].Rows.Count > 0 && ds.Tables["GlobalMessageRules"].Rows[0]["ErrorText"].ToString().Length > 0){
throw new Exception(ds.Tables["GlobalMessageRules"].Rows[0]["ErrorText"].ToString());
}
}
}
#endregion
#region method GetGlobalMessageRuleActions
/// <summary>
/// Gets specified global message rule actions.
/// </summary>
/// <param name="ruleID">Rule ID of rule which actions to get.</param>
public DataView GetGlobalMessageRuleActions(string ruleID)
{
if(ruleID == null || ruleID == ""){
throw new Exception("Invalid ruleID value, ruleID can't be '' or null !");
}
using(WSqlCommand sqlCmd = new WSqlCommand(m_ConStr,"lspr_GetGlobalMessageRuleActions")){
sqlCmd.AddParameter("@ruleID",SqlDbType.NVarChar,ruleID);
DataSet ds = sqlCmd.Execute();
ds.Tables[0].TableName = "GlobalMessageRuleActions";
return ds.Tables["GlobalMessageRuleActions"].DefaultView;
}
}
#endregion
#region method AddGlobalMessageRuleAction
/// <summary>
/// Adds action to specified global message rule.
/// </summary>
/// <param name="ruleID">Rule ID to which to add this action.</param>
/// <param name="actionID">Action ID. Guid.NewID().ToString() is suggested.</param>
/// <param name="description">Action description.</param>
/// <param name="actionType">Action type.</param>
/// <param name="actionData">Action data. Data structure depends on action type.</param>
public void AddGlobalMessageRuleAction(string ruleID,string actionID,string description,GlobalMessageRuleAction_enum actionType,byte[] actionData)
{
if(ruleID == null || ruleID == ""){
throw new Exception("Invalid ruleID value, ruleID can't be '' or null !");
}
if(actionID == null || actionID == ""){
throw new Exception("Invalid actionID value, actionID can't be '' or null !");
}
using(WSqlCommand sqlCmd = new WSqlCommand(m_ConStr,"lspr_AddGlobalMessageRuleAction")){
sqlCmd.AddParameter("@ruleID" ,SqlDbType.NVarChar,ruleID);
sqlCmd.AddParameter("@actionID" ,SqlDbType.NVarChar,actionID);
sqlCmd.AddParameter("@description" ,SqlDbType.NVarChar,description);
sqlCmd.AddParameter("@actionType" ,SqlDbType.Int ,(int)actionType);
sqlCmd.AddParameter("@actionData" ,SqlDbType.Image ,actionData);
DataSet ds = sqlCmd.Execute();
ds.Tables[0].TableName = "GlobalMessageRuleActions";
if(ds.Tables["GlobalMessageRuleActions"].Rows.Count > 0 && ds.Tables["GlobalMessageRuleActions"].Rows[0]["ErrorText"].ToString().Length > 0){
throw new Exception(ds.Tables["GlobalMessageRuleActions"].Rows[0]["ErrorText"].ToString());
}
}
}
#endregion
#region method DeleteGlobalMessageRuleAction
/// <summary>
/// Deletes specified action from specified global message rule.
/// </summary>
/// <param name="ruleID">Rule ID which action to delete.</param>
/// <param name="actionID">Action ID of action which to delete.</param>
public void DeleteGlobalMessageRuleAction(string ruleID,string actionID)
{
if(ruleID == null || ruleID == ""){
throw new Exception("Invalid ruleID value, ruleID can't be '' or null !");
}
if(actionID == null || actionID == ""){
throw new Exception("Invalid actionID value, actionID can't be '' or null !");
}
using(WSqlCommand sqlCmd = new WSqlCommand(m_ConStr,"lspr_DeleteGlobalMessageRuleAction")){
sqlCmd.AddParameter("@ruleID" ,SqlDbType.NVarChar,ruleID);
sqlCmd.AddParameter("@actionID" ,SqlDbType.NVarChar,actionID);
DataSet ds = sqlCmd.Execute();
}
}
#endregion
#region method UpdateGlobalMessageRuleAction
/// <summary>
/// Updates specified rule action.
/// </summary>
/// <param name="ruleID">Rule ID which action to update.</param>
/// <param name="actionID">Action ID of action which to update.</param>
/// <param name="description">Action description.</param>
/// <param name="actionType">Action type.</param>
/// <param name="actionData">Action data. Data structure depends on action type.</param>
public void UpdateGlobalMessageRuleAction(string ruleID,string actionID,string description,GlobalMessageRuleAction_enum actionType,byte[] actionData)
{
if(ruleID == null || ruleID == ""){
throw new Exception("Invalid ruleID value, ruleID can't be '' or null !");
}
if(actionID == null || actionID == ""){
throw new Exception("Invalid actionID value, actionID can't be '' or null !");
}
using(WSqlCommand sqlCmd = new WSqlCommand(m_ConStr,"lspr_UpdateGlobalMessageRuleAction")){
sqlCmd.AddParameter("@ruleID" ,SqlDbType.NVarChar,ruleID);
sqlCmd.AddParameter("@actionID" ,SqlDbType.NVarChar,actionID);
sqlCmd.AddParameter("@description" ,SqlDbType.NVarChar,description);
sqlCmd.AddParameter("@actionType" ,SqlDbType.Int ,(int)actionType);
sqlCmd.AddParameter("@actionData" ,SqlDbType.Image ,actionData);
DataSet ds = sqlCmd.Execute();
ds.Tables[0].TableName = "GlobalMessageRuleActions";
if(ds.Tables["GlobalMessageRuleActions"].Rows.Count > 0 && ds.Tables["GlobalMessageRuleActions"].Rows[0]["ErrorText"].ToString().Length > 0){
throw new Exception(ds.Tables["GlobalMessageRuleActions"].Rows[0]["ErrorText"].ToString());
}
}
}
#endregion
#endregion
#region Routing related
#region function GetRoutes
/// <summary>
/// Gets email address routes.
/// </summary>
/// <returns></returns>
public DataView GetRoutes()
{
using(WSqlCommand sqlCmd = new WSqlCommand(m_ConStr,"lspr_GetRoutes")){
DataSet ds = sqlCmd.Execute();
ds.Tables[0].TableName = "Routing";
return ds.Tables["Routing"].DefaultView;
}
}
#endregion
#region function AddRoute
/// <summary>
/// Adds new route.
/// </summary>
/// <param name="routeID">Route ID.</param>
/// <param name="cost">Cost specifies in what order roues are processed. Costs with lower values are processed first.</param>
/// <param name="enabled">Specifies if route is enabled.</param>
/// <param name="description">Route description text.</param>
/// <param name="pattern">Match pattern. For example: *,*@domain.com,*sales@domain.com.</param>
/// <param name="action">Specifies route action.</param>
/// <param name="actionData">Route action data.</param>
public void AddRoute(string routeID,long cost,bool enabled,string description,string pattern,RouteAction_enum action,byte[] actionData)
{
if(routeID.Length == 0){
throw new Exception("You must specify routeID");
}
if(pattern.Length == 0){
throw new Exception("You must specify pattern");
}
using(WSqlCommand sqlCmd = new WSqlCommand(m_ConStr,"lspr_AddRoute")){
sqlCmd.AddParameter("@routeID" ,SqlDbType.NVarChar,routeID);
sqlCmd.AddParameter("@cost" ,SqlDbType.BigInt ,cost);
sqlCmd.AddParameter("@enabled" ,SqlDbType.Bit ,enabled);
sqlCmd.AddParameter("@description" ,SqlDbType.NVarChar,description);
sqlCmd.AddParameter("@pattern" ,SqlDbType.NVarChar,pattern);
sqlCmd.AddParameter("@action" ,SqlDbType.Int ,action);
sqlCmd.AddParameter("@actionData" ,SqlDbType.Image ,actionData);
DataSet ds = sqlCmd.Execute();
ds.Tables[0].TableName = "Routing";
if(ds.Tables["Routing"].Rows.Count > 0 && ds.Tables["Routing"].Rows[0]["ErrorText"].ToString().Length > 0){
throw new Exception(ds.Tables["Routing"].Rows[0]["ErrorText"].ToString());
}
}
}
#endregion
#region function DeleteRoute
/// <summary>
/// Deletes route.
/// </summary>
/// <param name="routeID">Route ID.</param>
public void DeleteRoute(string routeID)
{
using(WSqlCommand sqlCmd = new WSqlCommand(m_ConStr,"lspr_DeleteRoute")){
sqlCmd.AddParameter("@RouteID" ,SqlDbType.NVarChar,routeID);
DataSet ds = sqlCmd.Execute();
}
}
#endregion
#region function UpdateRoute
/// <summary>
/// Updates route.
/// </summary>
/// <param name="routeID">Route ID.</param>
/// <param name="cost">Cost specifies in what order roues are processed. Costs with lower values are processed first.</param>
/// <param name="enabled">Specifies if route is enabled.</param>
/// <param name="description">Route description text.</param>
/// <param name="pattern">Match pattern. For example: *,*@domain.com,*sales@domain.com.</param>
/// <param name="action">Specifies route action.</param>
/// <param name="actionData">Route action data.</param>
public void UpdateRoute(string routeID,long cost,bool enabled,string description,string pattern,RouteAction_enum action,byte[] actionData)
{
if(pattern.Length == 0){
throw new Exception("You must specify pattern");
}
using(WSqlCommand sqlCmd = new WSqlCommand(m_ConStr,"lspr_UpdateRoute")){
sqlCmd.AddParameter("@routeID" ,SqlDbType.NVarChar,routeID);
sqlCmd.AddParameter("@cost" ,SqlDbType.BigInt ,cost);
sqlCmd.AddParameter("@enabled" ,SqlDbType.Bit ,enabled);
sqlCmd.AddParameter("@description" ,SqlDbType.NVarChar,description);
sqlCmd.AddParameter("@pattern" ,SqlDbType.NVarChar,pattern);
sqlCmd.AddParameter("@action" ,SqlDbType.Int ,action);
sqlCmd.AddParameter("@actionData" ,SqlDbType.Image ,actionData);
DataSet ds = sqlCmd.Execute();
ds.Tables[0].TableName = "Routing";
if(ds.Tables["Routing"].Rows.Count > 0 && ds.Tables["Routing"].Rows[0]["ErrorText"].ToString().Length > 0){
throw new Exception(ds.Tables["Routing"].Rows[0]["ErrorText"].ToString());
}
}
}
#endregion
#endregion
#region MailStore related
#region function GetMessagesInfo
/// <summary>
/// Gets specified IMAP folder messages info.
/// </summary>
/// <param name="accessingUser">User who accesses this method.
/// User needs r permission to call this method or Exception is thrown.
/// There is special user 'system' for which permission check is skipped.</param>
/// <param name="folderOwnerUser">User who's folder it is.</param>
/// <param name="folder">Folder what messages info to get. For example: Inbox,Public Folders/Documnets .</param>
/// <param name="messages">IMAP_Messages collection where to store folder messages info.</param>
public void GetMessagesInfo(string accessingUser,string folderOwnerUser,string folder,IMAP_MessageCollection messages)
{
/* Implementation notes:
*) Validate values. Throw ArgumnetExcetion if invalid values.
*) Ensure that user exists.
*) Normalize folder. Remove '/' from folder start and end, ... .
*) Do Shared Folders mapping.
*) Ensure that folder exists. Throw Exception if don't.
*) See if user has sufficient permissions. User requires 'r' permission.
There is builtin user system, skip ACL for it.
*) Fill messages info.
*/
//--- Validate values -------------------//
ArgsValidator.ValidateUserName(folderOwnerUser);
ArgsValidator.ValidateFolder(folder);
ArgsValidator.ValidateNotNull(messages);
//---------------------------------------//
// Ensure that user exists.
if(!UserExists(folderOwnerUser)){
throw new Exception("User '" + folderOwnerUser + "' doesn't exist !");
}
// Normalize folder. Remove '/' from folder start and end.
folder = API_Utlis.NormalizeFolder(folder);
// Do Shared Folders mapping.
string originalFolder = folder;
SharedFolderMapInfo mappedFolder = MapSharedFolder(originalFolder);
if(mappedFolder.IsSharedFolder){
folderOwnerUser = mappedFolder.FolderOnwer;
folder = mappedFolder.Folder;
if(folderOwnerUser == "" || folder == ""){
throw new ArgumentException("Specified root folder '" + originalFolder + "' isn't accessible !");
}
}
// Ensure that folder exists. Throw Exception if don't.
if(!FolderExists(folderOwnerUser + "/" + folder)){
throw new Exception("Folder '" + folder + "' doesn't exist !");
}
// See if user has sufficient permissions. User requires 'r' permission.
// There is builtin user system, skip ACL for it.
if(accessingUser.ToLower() != "system"){
IMAP_ACL_Flags acl = GetUserACL(folderOwnerUser,folder,accessingUser);
if((acl & IMAP_ACL_Flags.r) == 0){
throw new InsufficientPermissionsException("Insufficient permissions for folder '" + accessingUser + "/" + folder + "' !");
}
}
//--- Fill messages info
using(WSqlCommand sqlCmd = new WSqlCommand(m_ConStr,"lspr_GetMessageInfo")){
sqlCmd.AddParameter("@Mailbox",SqlDbType.NVarChar,folderOwnerUser);
sqlCmd.AddParameter("@Folder" ,SqlDbType.NVarChar,folder);
DataSet ds = sqlCmd.Execute();
ds.Tables[0].TableName = "lsMailStore";
foreach(DataRow dr in ds.Tables["lsMailStore"].Rows){
string messageID = dr["MessageID"].ToString();
int size = Convert.ToInt32(dr["Size"]);
DateTime date = Convert.ToDateTime(dr["Date"]);
int flags = Convert.ToInt32(dr["MessageFlags"]);
int uid = Convert.ToInt32(dr["UID"]);
messages.Add(
messageID,
uid,
date,
size,
(IMAP_MessageFlags)flags
);
}
}
}
#endregion
#region function StoreMessage
/// <summary>
/// Stores message to specified folder.
/// </summary>
/// <param name="accessingUser">User who accesses this method.
/// User needs r permission to call this method or Exception is thrown.
/// There is special user 'system' for which permission check is skipped.</param>
/// <param name="folderOwnerUser">User who's folder it is.</param>
/// <param name="folder">Folder where to store message. For example: Inbox,Public Folders/Documnets .</param>
/// <param name="msgStream">Stream where message has stored. Stream position must be at the beginning of the message.</param>
/// <param name="date">Recieve date.</param>
/// <param name="flags">Message flags.</param>
public void StoreMessage(string accessingUser,string folderOwnerUser,string folder,Stream msgStream,DateTime date,IMAP_MessageFlags flags)
{
/* Implementation notes:
*) Validate values. Throw ArgumnetExcetion if invalid values.
*) Ensure that user exists.
*) Normalize folder. Remove '/' from folder start and end, ... .
*) Do Shared Folders mapping.
*) Ensure that folder exists. Throw Exception if don't.
*) See if user has sufficient permissions. User requires 'p' or 'i' permission.
There is builtin user system, skip ACL for it.
*) Store message.
*/
//--- Validate values -------------------//
ArgsValidator.ValidateUserName(folderOwnerUser);
ArgsValidator.ValidateFolder(folder);
ArgsValidator.ValidateNotNull(msgStream);
//---------------------------------------//
// Ensure that user exists.
if(!UserExists(folderOwnerUser)){
throw new Exception("User '" + folderOwnerUser + "' doesn't exist !");
}
// Normalize folder. Remove '/' from folder start and end.
folder = API_Utlis.NormalizeFolder(folder);
// Do Shared Folders mapping.
string originalFolder = folder;
SharedFolderMapInfo mappedFolder = MapSharedFolder(originalFolder);
if(mappedFolder.IsSharedFolder){
folderOwnerUser = mappedFolder.FolderOnwer;
folder = mappedFolder.Folder;
if(folderOwnerUser == "" || folder == ""){
throw new ArgumentException("Specified root folder '" + originalFolder + "' isn't accessible !");
}
}
// Ensure that folder exists. Throw Exception if don't.
if(!FolderExists(folderOwnerUser + "/" + folder)){
throw new Exception("Folder '" + folder + "' doesn't exist !");
}
// See if user has sufficient permissions. User requires 'p' or 'i' permission.
// There is builtin user system, skip ACL for it.
if(accessingUser.ToLower() != "system"){
IMAP_ACL_Flags acl = GetUserACL(folderOwnerUser,folder,accessingUser);
if((acl & IMAP_ACL_Flags.p) == 0 && (acl & IMAP_ACL_Flags.i) == 0){
throw new InsufficientPermissionsException("Insufficient permissions for folder '" + accessingUser + "/" + folder + "' !");
}
}
//--- Store message
byte[] topLines = GetTopLines(msgStream,50);
msgStream.Position = 0;
byte[] messageData = new byte[msgStream.Length];
msgStream.Read(messageData,0,messageData.Length);
using(WSqlCommand sqlCmd = new WSqlCommand(m_ConStr,"lspr_StoreMessage")){
sqlCmd.AddParameter("@MailBox" ,SqlDbType.NVarChar ,folderOwnerUser);
sqlCmd.AddParameter("@Folder" ,SqlDbType.NVarChar ,folder);
sqlCmd.AddParameter("@Data" ,SqlDbType.Image ,messageData);
sqlCmd.AddParameter("@Size" ,SqlDbType.BigInt ,msgStream.Length);
sqlCmd.AddParameter("@TopLines" ,SqlDbType.Image ,topLines);
sqlCmd.AddParameter("@Date" ,SqlDbType.DateTime ,date);
sqlCmd.AddParameter("@MessageFlags" ,SqlDbType.Int ,(int)flags);
DataSet ds = sqlCmd.Execute();
if(ds.Tables.Count > 0 && ds.Tables[0].Rows.Count > 0){
throw new Exception(ds.Tables[0].Rows[0]["ErrorText"].ToString());
}
}
}
#endregion
#region function StoreMessageFlags
/// <summary>
/// Stores IMAP message flags (\seen,\draft, ...).
/// </summary>
/// <param name="accessingUser">User who accesses this method.
/// User needs r permission to call this method or Exception is thrown.
/// There is special user 'system' for which permission check is skipped.</param>
/// <param name="folderOwnerUser">User who's folder it is.</param>
/// <param name="folder">Folder which message flags to store. For example: Inbox,Public Folders/Documnets .</param>
/// <param name="message">Fix ME: ???</param>
/// <param name="msgFlags">Message flags to store.</param>
public void StoreMessageFlags(string accessingUser,string folderOwnerUser,string folder,LumiSoft.Net.IMAP.Server.IMAP_Message message,IMAP_MessageFlags msgFlags)
{
/* Implementation notes:
*) Validate values. Throw ArgumnetExcetion if invalid values.
*) Ensure that user exists.
*) Normalize folder. Remove '/' from folder start and end, ... .
*) Do Shared Folders mapping.
*) Ensure that folder exists. Throw Exception if don't.
*) Remove all message flags which permissions user doesn't have.
*) Store message.
*/
//--- Validate values -------------------//
ArgsValidator.ValidateUserName(folderOwnerUser);
ArgsValidator.ValidateFolder(folder);
ArgsValidator.ValidateNotNull(message);
//---------------------------------------//
// Ensure that user exists.
if(!UserExists(folderOwnerUser)){
throw new Exception("User '" + folderOwnerUser + "' doesn't exist !");
}
// Normalize folder. Remove '/' from folder start and end.
folder = API_Utlis.NormalizeFolder(folder);
// Do Shared Folders mapping.
string originalFolder = folder;
SharedFolderMapInfo mappedFolder = MapSharedFolder(originalFolder);
if(mappedFolder.IsSharedFolder){
folderOwnerUser = mappedFolder.FolderOnwer;
folder = mappedFolder.Folder;
if(folderOwnerUser == "" || folder == ""){
throw new ArgumentException("Specified root folder '" + originalFolder + "' isn't accessible !");
}
}
// Ensure that folder exists. Throw Exception if don't.
if(!FolderExists(folderOwnerUser + "/" + folder)){
throw new Exception("Folder '" + folder + "' doesn't exist !");
}
// Remove all message flags which permissions user doesn't have.
if(accessingUser != "system"){
IMAP_ACL_Flags userACL = GetUserACL(folderOwnerUser,folder,accessingUser);
if((userACL & IMAP_ACL_Flags.s) == 0){
msgFlags &= ~IMAP_MessageFlags.Seen;
}
else if((userACL & IMAP_ACL_Flags.d) == 0){
msgFlags &= ~IMAP_MessageFlags.Deleted;
}
else if((userACL & IMAP_ACL_Flags.s) == 0){
msgFlags &= (~IMAP_MessageFlags.Answered | ~IMAP_MessageFlags.Draft | ~IMAP_MessageFlags.Flagged);
}
}
//--- Store message flags
using(WSqlCommand sqlCmd = new WSqlCommand(m_ConStr,"lspr_StoreMessageFlags")){
sqlCmd.AddParameter("@MessageID" ,SqlDbType.NVarChar,message.ID);
sqlCmd.AddParameter("@Mailbox" ,SqlDbType.NVarChar,folderOwnerUser);
sqlCmd.AddParameter("@Folder" ,SqlDbType.NVarChar,folder);
sqlCmd.AddParameter("@MessageFalgs" ,SqlDbType.Int ,(int)message.Flags);
DataSet ds = sqlCmd.Execute();
}
}
#endregion
#region method DeleteMessage
/// <summary>
/// Deletes message from mailbox.
/// </summary>
/// <param name="accessingUser">User who accesses this method.
/// User needs r permission to call this method or Exception is thrown.
/// There is special user 'system' for which permission check is skipped.</param>
/// <param name="folderOwnerUser">User who's folder it is.</param>
/// <param name="folder">Folder what message to delete. For example: Inbox,Public Folders/Documnets .</param>
/// <param name="messageID">Message ID.</param>
/// <param name="uid">Message UID value.</param>
public void DeleteMessage(string accessingUser,string folderOwnerUser,string folder,string messageID,int uid)
{
/* Implementation notes:
*) Validate values. Throw ArgumnetExcetion if invalid values.
*) Ensure that user exists.
*) Normalize folder. Remove '/' from folder start and end, ... .
*) Do Shared Folders mapping.
*) Ensure that folder exists. Throw Exception if don't.
*) See if user has sufficient permissions. User requires 'd' permission.
There is builtin user system, skip ACL for it.
*) Fill messages info.
*/
//--- Validate values -------------------//
ArgsValidator.ValidateUserName(folderOwnerUser);
ArgsValidator.ValidateFolder(folder);
ArgsValidator.ValidateNotNull(messageID);
//---------------------------------------//
// Ensure that user exists.
if(!UserExists(folderOwnerUser)){
throw new Exception("User '" + folderOwnerUser + "' doesn't exist !");
}
// Normalize folder. Remove '/' from folder start and end.
folder = API_Utlis.NormalizeFolder(folder);
// Do Shared Folders mapping.
string originalFolder = folder;
SharedFolderMapInfo mappedFolder = MapSharedFolder(originalFolder);
if(mappedFolder.IsSharedFolder){
folderOwnerUser = mappedFolder.FolderOnwer;
folder = mappedFolder.Folder;
if(folderOwnerUser == "" || folder == ""){
throw new ArgumentException("Specified root folder '" + originalFolder + "' isn't accessible !");
}
}
// Ensure that folder exists. Throw Exception if don't.
if(!FolderExists(folderOwnerUser + "/" + folder)){
throw new Exception("Folder '" + folder + "' doesn't exist !");
}
// See if user has sufficient permissions. User requires 'd' permission.
// There is builtin user system, skip ACL for it.
if(accessingUser.ToLower() != "system"){
IMAP_ACL_Flags acl = GetUserACL(folderOwnerUser,folder,accessingUser);
if((acl & IMAP_ACL_Flags.d) == 0){
throw new InsufficientPermissionsException("Insufficient permissions for folder '" + accessingUser + "/" + folder + "' !");
}
}
//--- Recycle bin handling ----------------------------------------------------------------------//
if(Convert.ToBoolean(GetRecycleBinSettings().Rows[0]["DeleteToRecycleBin"])){
EmailMessageItems msgItems = new EmailMessageItems(messageID,IMAP_MessageItems_enum.Message | IMAP_MessageItems_enum.Envelope);
GetMessageItems("system",folderOwnerUser,folder,msgItems);
if(msgItems.MessageExists){
byte[] data = new byte[msgItems.MessageStream.Length];
msgItems.MessageStream.Read(data,0,data.Length);
using(WSqlCommand sqlCmd = new WSqlCommand(m_ConStr,"lspr_StoreRecycleBinMessage")){
sqlCmd.AddParameter("@messageID" ,SqlDbType.NVarChar,Guid.NewGuid().ToString());
sqlCmd.AddParameter("@user" ,SqlDbType.NVarChar,folderOwnerUser);
sqlCmd.AddParameter("@folder" ,SqlDbType.NVarChar,folder);
sqlCmd.AddParameter("@size" ,SqlDbType.BigInt ,data.Length);
sqlCmd.AddParameter("@envelope" ,SqlDbType.NVarChar,msgItems.Envelope);
sqlCmd.AddParameter("@data" ,SqlDbType.Image ,data);
DataSet ds = sqlCmd.Execute();
}
}
}
//----------------------------------------------------------------------------------------------//
//--- Delete message
using(WSqlCommand sqlCmd = new WSqlCommand(m_ConStr,"lspr_DeleteMessage")){
sqlCmd.AddParameter("@MessageID" ,SqlDbType.NVarChar,messageID);
sqlCmd.AddParameter("@Mailbox" ,SqlDbType.NVarChar,folderOwnerUser);
sqlCmd.AddParameter("@Folder" ,SqlDbType.NVarChar,folder);
DataSet ds = sqlCmd.Execute();
}
}
#endregion
#region method GetMessageItems
/// <summary>
/// Gets specified message specified items.
/// </summary>
/// <param name="accessingUser">User who accesses this method.
/// User needs r permission to call this method or Exception is thrown.
/// There is special user 'system' for which permission check is skipped.</param>
/// <param name="folderOwnerUser">User who's folder it is.</param>
/// <param name="folder">Folder what message to delete. For example: Inbox,Public Folders/Documnets .</param>
/// <param name="e">MessageItems info.</param>
public void GetMessageItems(string accessingUser,string folderOwnerUser,string folder,EmailMessageItems e)
{
/* Implementation notes:
*) Validate values. Throw ArgumnetExcetion if invalid values.
*) Ensure that user exists.
*) Normalize folder. Remove '/' from folder start and end, ... .
*) Do Shared Folders mapping.
*) Ensure that folder exists. Throw Exception if don't.
*) See if user has sufficient permissions. User requires 'r' permission.
There is builtin user system, skip ACL for it.
*) Store message.
*/
//--- Validate values -------------------//
ArgsValidator.ValidateUserName(folderOwnerUser);
ArgsValidator.ValidateFolder(folder);
ArgsValidator.ValidateNotNull(e);
//---------------------------------------//
// Ensure that user exists.
if(!UserExists(folderOwnerUser)){
throw new Exception("User '" + folderOwnerUser + "' doesn't exist !");
}
// Normalize folder. Remove '/' from folder start and end.
folder = API_Utlis.NormalizeFolder(folder);
// Do Shared Folders mapping.
string originalFolder = folder;
SharedFolderMapInfo mappedFolder = MapSharedFolder(originalFolder);
if(mappedFolder.IsSharedFolder){
folderOwnerUser = mappedFolder.FolderOnwer;
folder = mappedFolder.Folder;
if(folderOwnerUser == "" || folder == ""){
throw new ArgumentException("Specified root folder '" + originalFolder + "' isn't accessible !");
}
}
// Ensure that folder exists. Throw Exception if don't.
if(!FolderExists(folderOwnerUser + "/" + folder)){
throw new Exception("Folder '" + folder + "' doesn't exist !");
}
// See if user has sufficient permissions. User requires 'r' permission.
// There is builtin user system, skip ACL for it.
if(accessingUser.ToLower() != "system"){
IMAP_ACL_Flags acl = GetUserACL(folderOwnerUser,folder,accessingUser);
if((acl & IMAP_ACL_Flags.r) == 0){
throw new InsufficientPermissionsException("Insufficient permissions for folder '" + accessingUser + "/" + folder + "' !");
}
}
//--- Get message
using(WSqlCommand sqlCmd = new WSqlCommand(m_ConStr,"lspr_GetMessage")){
sqlCmd.AddParameter("@MessageID" ,SqlDbType.NVarChar,e.MessageID);
sqlCmd.AddParameter("@Mailbox" ,SqlDbType.NVarChar,folderOwnerUser);
sqlCmd.AddParameter("@Folder" ,SqlDbType.NVarChar,folder);
DataSet ds = sqlCmd.Execute();
ds.Tables[0].TableName = "lsMailStore";
byte[] data = (byte[])ds.Tables["lsMailStore"].Rows[0]["Data"];
Mime m = null;
if((e.MessageItems & IMAP_MessageItems_enum.BodyStructure) != 0 || (e.MessageItems & IMAP_MessageItems_enum.Envelope) != 0){
try{
m = Mime.Parse(data);
}
catch(Exception x){
m = LumiSoft.Net.Mime.Mime.CreateSimple(new AddressList(),new AddressList(),"[BAD MESSAGE] Bad message, message parsing failed !","NOTE: Bad message, message parsing failed !\r\n\r\n" + x.Message,"");
}
}
if((e.MessageItems & IMAP_MessageItems_enum.BodyStructure) != 0){
e.BodyStructure = IMAP_BODY.ConstructBodyStructure(m,false).Substring(5);
}
if((e.MessageItems & IMAP_MessageItems_enum.Envelope) != 0){
e.Envelope = IMAP_Envelope.ConstructEnvelope(m.MainEntity);
}
if((e.MessageItems & IMAP_MessageItems_enum.Header) != 0){
e.Header = GetTopLines(new MemoryStream(data),0);
}
if((e.MessageItems & IMAP_MessageItems_enum.Message) != 0){
e.MessageStream = new MemoryStream(data);
}
}
}
#endregion
#region function GetMessageTopLines
/// <summary>
/// Gets message header + number of specified lines.
/// </summary>
/// <param name="accessingUser">User who accesses this method.
/// User needs r permission to call this method or Exception is thrown.
/// There is special user 'system' for which permission check is skipped.</param>
/// <param name="folderOwnerUser">User who's folder it is.</param>
/// <param name="folder">Folder what message top lines to get. For example: Inbox,Public Folders/Documnets .</param>
/// <param name="msgID">MessageID.</param>
/// <param name="nrLines">Number of lines to retrieve. NOTE: line counting starts at the end of header.</param>
/// <returns>Returns message header + number of specified lines.</returns>
public byte[] GetMessageTopLines(string accessingUser,string folderOwnerUser,string folder,string msgID,int nrLines)
{
/* Implementation notes:
*) Validate values. Throw ArgumnetExcetion if invalid values.
*) Ensure that user exists.
*) Normalize folder. Remove '/' from folder start and end, ... .
*) Do Shared Folders mapping.
*) Ensure that folder exists. Throw Exception if don't.
*) See if user has sufficient permissions. User requires 'r' permission.
There is builtin user system, skip ACL for it.
*) Get message top lines.
*/
//--- Validate values -------------------//
ArgsValidator.ValidateUserName(folderOwnerUser);
ArgsValidator.ValidateFolder(folder);
ArgsValidator.ValidateNotNull(msgID);
//---------------------------------------//
// Ensure that user exists.
if(!UserExists(folderOwnerUser)){
throw new Exception("User '" + folderOwnerUser + "' doesn't exist !");
}
// Normalize folder. Remove '/' from folder start and end.
folder = API_Utlis.NormalizeFolder(folder);
// Do Shared Folders mapping.
string originalFolder = folder;
SharedFolderMapInfo mappedFolder = MapSharedFolder(originalFolder);
if(mappedFolder.IsSharedFolder){
folderOwnerUser = mappedFolder.FolderOnwer;
folder = mappedFolder.Folder;
if(folderOwnerUser == "" || folder == ""){
throw new ArgumentException("Specified root folder '" + originalFolder + "' isn't accessible !");
}
}
// Ensure that folder exists. Throw Exception if don't.
if(!FolderExists(folderOwnerUser + "/" + folder)){
throw new Exception("Folder '" + folder + "' doesn't exist !");
}
// See if user has sufficient permissions. User requires 'r' permission.
// There is builtin user system, skip ACL for it.
if(accessingUser.ToLower() != "system"){
IMAP_ACL_Flags acl = GetUserACL(folderOwnerUser,folder,accessingUser);
if((acl & IMAP_ACL_Flags.r) == 0){
throw new InsufficientPermissionsException("Insufficient permissions for folder '" + accessingUser + "/" + folder + "' !");
}
}
//--- Get message top lines
if(nrLines < 50){
using(WSqlCommand sqlCmd = new WSqlCommand(m_ConStr,"lspr_GetMessageTopLines")){
sqlCmd.AddParameter("@MessageID" ,SqlDbType.NVarChar,msgID);
sqlCmd.AddParameter("@Mailbox" ,SqlDbType.NVarChar,folderOwnerUser);
sqlCmd.AddParameter("@Folder" ,SqlDbType.NVarChar,folder);
DataSet ds = sqlCmd.Execute();
ds.Tables[0].TableName = "lsMailStore";
return GetTopLines(new MemoryStream((byte[])ds.Tables["lsMailStore"].Rows[0]["TopLines"]),nrLines);
}
}
else{
EmailMessageItems msgItems = new EmailMessageItems(msgID,IMAP_MessageItems_enum.Message);
GetMessageItems(accessingUser,folderOwnerUser,folder,msgItems);
byte[] topLines = GetTopLines(msgItems.MessageStream,nrLines);
msgItems.MessageStream.Dispose();
return topLines;
}
}
#endregion
#region function CopyMessage
/// <summary>
/// Creates copy of message to destination IMAP folder.
/// </summary>
/// <param name="accessingUser">User who accesses this method.
/// User needs r permission to call this method or Exception is thrown.
/// There is special user 'system' for which permission check is skipped.</param>
/// <param name="folderOwnerUser">User who's folder it is.</param>
/// <param name="folder">Folder what contains message to copy. For example: Inbox,Public Folders/Documnets .</param>
/// <param name="destFolderUser">Destination IMAP folder owner user name.</param>
/// <param name="destFolder">Destination IMAP folder name.</param>
/// <param name="message">IMAP message which to copy.</param>
public void CopyMessage(string accessingUser,string folderOwnerUser,string folder,string destFolderUser,string destFolder,LumiSoft.Net.IMAP.Server.IMAP_Message message)
{
/* Implementation notes:
*) Validate values. Throw ArgumnetExcetion if invalid values.
*) We don't need to map shared folder, check security, it done by GetMessage and StoreMessage methods.
*) Copy message.
*/
//--- Validate values -------------------//
ArgsValidator.ValidateUserName(folderOwnerUser);
ArgsValidator.ValidateFolder(folder);
ArgsValidator.ValidateUserName(destFolderUser);
ArgsValidator.ValidateFolder(destFolder);
ArgsValidator.ValidateNotNull(message);
//---------------------------------------//
//--- Copy message
EmailMessageItems msgItems = new EmailMessageItems(message.ID,IMAP_MessageItems_enum.Message);
GetMessageItems(accessingUser,folderOwnerUser,folder,msgItems);
StoreMessage("system",destFolderUser,destFolder,msgItems.MessageStream,message.InternalDate,message.Flags);
msgItems.MessageStream.Dispose();
}
#endregion
#region function GetFolders
/// <summary>
/// Gets all available IMAP folders.
/// </summary>
/// <param name="userName">User name who's folders to get.</param>
/// <param name="includeSharedFolders">If true, shared folders are included.</param>
public string[] GetFolders(string userName,bool includeSharedFolders)
{
/* Implementation notes:
*) Validate values. Throw ArgumnetExcetion if invalid values.
*) Ensure that user exists. Throw Exception if don't.
*) See if user has sufficient permissions. User requires 'l' permission.
*) Append all visible(Forlders on what user has 'r' right) user mailbox folders.
*) Append all visible(Forlders on what user has 'r' right) public folders to folders list !
*/
//--- Validate values -------------------//
ArgsValidator.ValidateUserName(userName);
//---------------------------------------//
// Ensure that user exists.
if(!UserExists(userName)){
throw new Exception("User '" + userName + "' desn't exist !");
}
DataSet dsFolders = null;
using(WSqlCommand sqlCmd = new WSqlCommand(m_ConStr,"lspr_GetFolders")){
sqlCmd.AddParameter("@UserName",SqlDbType.NVarChar,userName);
dsFolders = sqlCmd.Execute();
dsFolders.Tables[0].TableName = "Folders";
}
// Append all visible(Forlders on what user has 'r' right) user mailbox folders.
List<string> userFolders = new List<string>();
for(int i=0;i<dsFolders.Tables["Folders"].Rows.Count;i++){
string folder = dsFolders.Tables["Folders"].Rows[i]["FolderName"].ToString();
// Show folders what user has 'r' right
if((GetUserACL(userName,folder,userName) & IMAP_ACL_Flags.r) != 0){
userFolders.Add(folder);
}
}
// Append all visible(Forlders on what user has 'r' right) shared folders to folders list
if(includeSharedFolders){
SharedFolderRoot[] sharedFolderRoots = GetSharedFolderRoots();
foreach(SharedFolderRoot sharedFolderRoot in sharedFolderRoots){
// Skip disabled roots
if(!sharedFolderRoot.Enabled){
continue;
}
// Root is bounded folder
if(sharedFolderRoot.RootType == SharedFolderRootType_enum.BoundedRootFolder){
// Get root child folders
string[] boundedFolders = GetFolders(sharedFolderRoot.BoundedUser,false);
foreach(string boundedFolder in boundedFolders){
// We want folders what will be BoundedFolder child folders, others just skip
if(boundedFolder.ToLower().StartsWith(sharedFolderRoot.BoundedFolder.ToLower())){
// Show only folder what user has 'lr' right
if((GetUserACL(sharedFolderRoot.BoundedUser,boundedFolder,userName) & IMAP_ACL_Flags.r) != 0){
// We must cut of boundedFolder part. For example root name = 'Public'and
// boundedFolder = 'inbox', then it must be visible as Public/inboxChildFolders,
// not Public/inbox/inboxChildFolders.
userFolders.Add(sharedFolderRoot.FolderName + boundedFolder.Substring(sharedFolderRoot.BoundedFolder.Length));
}
}
}
}
// Root is Users Shared Folders namespace
else{
// Get shared user on which accessing user has access rights
List<string> sharingUsers = new List<string>();
foreach(DataRow dr in GetACL().Tables["ACL"].Rows){
string userOrGroup = dr["User"].ToString().ToLower();
string sharingUserName = dr["Folder"].ToString().Split(new char[]{'/'},2)[0];
// anyone access, so we have access to that folder
if(userOrGroup == "anyone"){
if(!sharingUsers.Contains(sharingUserName)){
sharingUsers.Add(sharingUserName);
}
}
// accessing user has access to that folder
else if(userOrGroup == userName.ToLower()){
if(!sharingUsers.Contains(sharingUserName)){
sharingUsers.Add(sharingUserName);
}
}
else{
// If group ACL set, see if accessing user is member of that group
DataRow drGroup = GetGroup(userOrGroup);
if(drGroup != null && IsUserGroupMember(drGroup["GroupName"].ToString(),userName)){
if(!sharingUsers.Contains(sharingUserName)){
sharingUsers.Add(sharingUserName);
}
}
}
}
//--- Show folders on what user has enough ACL
foreach(string sharingUser in sharingUsers){
string[] sharingUserFolders = GetFolders(sharingUser,false);
foreach(string sharingUserFolder in sharingUserFolders){
// Show only folder what user has 'lr' right
if((GetUserACL(sharingUser,sharingUserFolder,userName) & IMAP_ACL_Flags.r) != 0){
userFolders.Add(sharedFolderRoot.FolderName + "/" + sharingUser + "/" + sharingUserFolder);
}
}
}
}
}
}
return userFolders.ToArray();
}
#endregion
#region function GetSubscribedFolders
/// <summary>
/// Gets subscribed IMAP folders.
/// </summary>
/// <param name="userName"></param>
public string[] GetSubscribedFolders(string userName)
{
using(WSqlCommand sqlCmd = new WSqlCommand(m_ConStr,"lspr_GetSubscribedFolders")){
sqlCmd.AddParameter("@UserName",SqlDbType.NVarChar,userName);
DataSet ds = sqlCmd.Execute();
ds.Tables[0].TableName = "Folders";
string[] retVal = new string[ds.Tables["Folders"].Rows.Count];
int i = 0;
foreach(DataRow dr in ds.Tables["Folders"].Rows){
retVal[i] = dr["FolderName"].ToString();
i++;
}
return retVal;
}
}
#endregion
#region function SubscribeFolder
/// <summary>
/// Subscribes new IMAP folder.
/// </summary>
/// <param name="userName"></param>
/// <param name="folder"></param>
public void SubscribeFolder(string userName,string folder)
{
using(WSqlCommand sqlCmd = new WSqlCommand(m_ConStr,"lspr_SubscribeFolder")){
sqlCmd.AddParameter("@UserName",SqlDbType.NVarChar,userName);
sqlCmd.AddParameter("@Folder" ,SqlDbType.NVarChar,folder);
DataSet ds = sqlCmd.Execute();
}
}
#endregion
#region function UnSubscribeFolder
/// <summary>
/// UnSubscribes IMAP folder.
/// </summary>
/// <param name="userName"></param>
/// <param name="folder"></param>
public void UnSubscribeFolder(string userName,string folder)
{
using(WSqlCommand sqlCmd = new WSqlCommand(m_ConStr,"lspr_UnSubscribeFolder")){
sqlCmd.AddParameter("@UserName",SqlDbType.NVarChar,userName);
sqlCmd.AddParameter("@Folder" ,SqlDbType.NVarChar,folder);
DataSet ds = sqlCmd.Execute();
}
}
#endregion
#region function CreateFolder
/// <summary>
/// Creates new IMAP folder.
/// </summary>
/// <param name="accessingUser">User who accesses this method.
/// User needs r permission to call this method or Exception is thrown.
/// There is special user 'system' for which permission check is skipped.</param>
/// <param name="folderOwnerUser">User who's folder it is.</param>
/// <param name="folder">Folder what contains message to copy. For example: Inbox,Public Folders/Documnets .</param>
public void CreateFolder(string accessingUser,string folderOwnerUser,string folder)
{
/* Implementation notes:
*) Validate values. Throw ArgumnetExcetion if invalid values.
*) Ensure that user exists.
*) Normalize folder. Remove '/' from folder start and end, ... .
*) Do Shared Folders mapping.
*) Ensure that folder doesn't exists. Throw Exception if don't.
*) See if user has sufficient permissions. User requires 'c' permission.
There is builtin user system, skip ACL for it.
*) Create folder.
*/
//--- Validate values -------------------//
ArgsValidator.ValidateUserName(folderOwnerUser);
ArgsValidator.ValidateFolder(folder);
//---------------------------------------//
// Ensure that user exists.
if(!UserExists(folderOwnerUser)){
throw new Exception("User '" + folderOwnerUser + "' doesn't exist !");
}
// Normalize folder. Remove '/' from folder start and end.
folder = API_Utlis.NormalizeFolder(folder);
// Do Shared Folders mapping.
string originalFolder = folder;
SharedFolderMapInfo mappedFolder = MapSharedFolder(originalFolder);
if(mappedFolder.IsSharedFolder){
folderOwnerUser = mappedFolder.FolderOnwer;
folder = mappedFolder.Folder;
if(folderOwnerUser == "" || folder == ""){
throw new ArgumentException("Specified root folder '" + originalFolder + "' isn't accessible !");
}
}
// Ensure that folder doesn't exists. Throw Exception if don't.
if(FolderExists(folderOwnerUser + "/" + folder)){
throw new Exception("Folder '" + folder + "' already exist !");
}
// See if user has sufficient permissions. User requires 'c' permission.
// There is builtin user system, skip ACL for it.
if(accessingUser.ToLower() != "system"){
IMAP_ACL_Flags acl = GetUserACL(folderOwnerUser,folder,accessingUser);
if((acl & IMAP_ACL_Flags.c) == 0){
throw new InsufficientPermissionsException("Insufficient permissions for folder '" + accessingUser + "/" + folder + "' !");
}
}
//--- Create folder
using(WSqlCommand sqlCmd = new WSqlCommand(m_ConStr,"lspr_CreateFolder")){
sqlCmd.AddParameter("@UserName",SqlDbType.NVarChar,folderOwnerUser);
sqlCmd.AddParameter("@Folder" ,SqlDbType.NVarChar,folder);
DataSet ds = sqlCmd.Execute();
if(ds.Tables.Count > 0 && ds.Tables[0].Rows.Count > 0){
throw new Exception(ds.Tables[0].Rows[0]["ErrorText"].ToString());
}
}
}
#endregion
#region method DeleteFolder
/// <summary>
/// Deletes IMAP folder.
/// </summary>
/// <param name="accessingUser">User who accesses this method.
/// User needs r permission to call this method or Exception is thrown.
/// There is special user 'system' for which permission check is skipped.</param>
/// <param name="folderOwnerUser">User who's folder it is.</param>
/// <param name="folder">Folder what to delete. For example: Inbox,Public Folders/Documnets .</param>
public void DeleteFolder(string accessingUser,string folderOwnerUser,string folder)
{
/* Implementation notes:
*) Validate values. Throw ArgumnetExcetion if invalid values.
*) Ensure that user exists.
*) Normalize folder. Remove '/' from folder start and end, ... .
*) Do Shared Folders mapping.
*) Don't allow to delete shared folders root folder.
For BoundedUser root don't allow root folder only,
for UsersShared root don't allow root + user name.
*) Ensure that folder exists. Throw Exception if don't.
*) See if user has sufficient permissions. User requires 'c' permission.
There is builtin user system, skip ACL for it.
*) Create folder.
*/
// Don't allow to delete inbox
if(folder.ToLower() == "inbox"){
throw new Exception("Can't delete inbox");
}
//--- Validate values -------------------//
ArgsValidator.ValidateUserName(folderOwnerUser);
ArgsValidator.ValidateFolder(folder);
//---------------------------------------//
// Ensure that user exists.
if(!UserExists(folderOwnerUser)){
throw new Exception("User '" + folderOwnerUser + "' doesn't exist !");
}
// Normalize folder. Remove '/' from folder start and end.
folder = API_Utlis.NormalizeFolder(folder);
// Do Shared Folders mapping.
string originalFolder = folder;
SharedFolderMapInfo mappedFolder = MapSharedFolder(originalFolder);
if(mappedFolder.IsSharedFolder){
folderOwnerUser = mappedFolder.FolderOnwer;
folder = mappedFolder.Folder;
/* Don't allow to delete shared folders root folder.
For BoundedUser root don't allow root folder only,
for UsersShared root don't allow root + user name.
*/
// Main shared folder root.
if(mappedFolder.SharedRootName.ToLower() == originalFolder.ToLower()){
throw new ArgumentException("Can't delete shared root folder '" + originalFolder + "' !");
}
// Users shared folder: root/username -> no folder
if(folder == ""){
throw new ArgumentException("Can't delete shared root folder '" + originalFolder + "' !");
}
if(folderOwnerUser == "" || folder == ""){
throw new ArgumentException("Specified root folder '" + originalFolder + "' isn't accessible !");
}
}
// Ensure that folder doesn't exists. Throw Exception if don't.
if(!FolderExists(folderOwnerUser + "/" + folder)){
throw new Exception("Folder '" + folder + "' doesn't exist !");
}
// See if user has sufficient permissions. User requires 'c' permission.
// There is builtin user system, skip ACL for it.
if(accessingUser.ToLower() != "system"){
IMAP_ACL_Flags acl = GetUserACL(folderOwnerUser,folder,accessingUser);
if((acl & IMAP_ACL_Flags.c) == 0){
throw new InsufficientPermissionsException("Insufficient permissions for folder '" + accessingUser + "/" + folder + "' !");
}
}
//--- Recycle bin handling ----------------------------------------------------------------------//
if(Convert.ToBoolean(GetRecycleBinSettings().Rows[0]["DeleteToRecycleBin"])){
IMAP_MessageCollection messages = new IMAP_MessageCollection();
GetMessagesInfo("system",folderOwnerUser,folder,messages);
foreach(IMAP_Message message in messages){
EmailMessageItems msgItems = new EmailMessageItems(message.ID,IMAP_MessageItems_enum.Message);
GetMessageItems("system",folderOwnerUser,folder,msgItems);
if(msgItems.MessageExists){
string subject = "<none>";
try{
subject = MimeUtils.ParseHeaderField("Subject:",msgItems.MessageStream);
subject = subject.Replace("\r","");
subject = subject.Replace("\n","");
}
catch{
}
msgItems.MessageStream.Position = 0;
byte[] data = new byte[msgItems.MessageStream.Length];
msgItems.MessageStream.Read(data,0,data.Length);
using(WSqlCommand sqlCmd = new WSqlCommand(m_ConStr,"lspr_StoreRecycleBinMessage")){
sqlCmd.AddParameter("@messageID" ,SqlDbType.NVarChar,Guid.NewGuid().ToString());
sqlCmd.AddParameter("@user" ,SqlDbType.NVarChar,folderOwnerUser);
sqlCmd.AddParameter("@folder" ,SqlDbType.NVarChar,folder);
sqlCmd.AddParameter("@subject" ,SqlDbType.NVarChar,subject);
sqlCmd.AddParameter("@data" ,SqlDbType.Image ,data);
DataSet ds = sqlCmd.Execute();
}
}
}
}
//----------------------------------------------------------------------------------------------//
//--- Delete folder
using(WSqlCommand sqlCmd = new WSqlCommand(m_ConStr,"lspr_DeleteFolder")){
sqlCmd.AddParameter("@UserName",SqlDbType.NVarChar,folderOwnerUser);
sqlCmd.AddParameter("@Folder" ,SqlDbType.NVarChar,folder);
DataSet ds = sqlCmd.Execute();
if(ds.Tables.Count > 0 && ds.Tables[0].Rows.Count > 0){
throw new Exception(ds.Tables[0].Rows[0]["ErrorText"].ToString());
}
}
}
#endregion
#region function RenameFolder
/// <summary>
/// Renames IMAP folder.
/// </summary>
/// <param name="accessingUser">User who accesses this method.
/// User needs r permission to call this method or Exception is thrown.
/// There is special user 'system' for which permission check is skipped.</param>
/// <param name="folderOwnerUser">User who's folder it is.</param>
/// <param name="folder">Folder what to delete. For example: Trash,Public Folders/Documnets .</param>
/// <param name="newFolder">New folder name.</param>
public void RenameFolder(string accessingUser,string folderOwnerUser,string folder,string newFolder)
{
/* Implementation notes:
*) Validate values. Throw ArgumnetExcetion if invalid values.
*) Ensure that user exists.
*) Normalize folders. Remove '/' from folder start and end, ... .
*) Do Shared Folders mapping.
*) Don't allow to rename shared folders root folder.
For BoundedUser root don't allow root folder only,
for UsersShared root don't allow root + user name.
*) Ensure that source folder exists. Throw Exception if don't.
*) Ensure that destinaton folder doesn't exists. Throw Exception if does.
*) See if user has sufficient permissions. User requires 'c' permission.
There is builtin user system, skip ACL for it.
*) Rename folder.
*/
// Don't allow to rename inbox
if(folder.ToLower() == "inbox"){
throw new Exception("Can't rename inbox");
}
//--- Validate values -------------------//
ArgsValidator.ValidateUserName(folderOwnerUser);
ArgsValidator.ValidateFolder(folder);
ArgsValidator.ValidateFolder(newFolder);
//---------------------------------------//
// Ensure that user exists.
if(!UserExists(folderOwnerUser)){
throw new Exception("User '" + folderOwnerUser + "' doesn't exist !");
}
// Normalize folder. Remove '/' from folder start and end.
folder = API_Utlis.NormalizeFolder(folder);
// Do Shared Folders mapping.
string originalFolder = folder;
SharedFolderMapInfo mappedFolder = MapSharedFolder(originalFolder);
if(mappedFolder.IsSharedFolder){
folderOwnerUser = mappedFolder.FolderOnwer;
folder = mappedFolder.Folder;
if(originalFolder.ToLower() == mappedFolder.SharedRootName.ToLower() || folderOwnerUser == "" || folder == ""){
throw new Exception("Can't rename shared root folder '" + originalFolder + "' !");
}
}
// Normalize folder. Remove '/' from folder start and end.
newFolder = API_Utlis.NormalizeFolder(newFolder);
// Do Shared Folders mapping.
string originalNewFolder = newFolder;
string destinationFolderOwner = folderOwnerUser;
SharedFolderMapInfo mappedNewFolder = MapSharedFolder(originalNewFolder);
if(mappedNewFolder.IsSharedFolder){
destinationFolderOwner = mappedNewFolder.FolderOnwer;
newFolder = mappedNewFolder.Folder;
if(originalNewFolder.ToLower() == mappedNewFolder.SharedRootName.ToLower() || destinationFolderOwner == "" || newFolder == ""){
throw new Exception("Invalid destination folder value, folder '" + originalNewFolder + "' alreay exists !");
}
}
// Don't allow shared folder to change root folder
// For example: "Public Folder/aaa" can't be renamed to "Public Folder New/aaa"
if(mappedFolder.SharedRootName.ToLower() != mappedNewFolder.SharedRootName.ToLower() || mappedFolder.FolderOnwer.ToLower() != mappedNewFolder.FolderOnwer.ToLower()){
throw new ArgumentException("Shared folder can't change root folder !");
}
// Ensure that folder does exist. Throw Exception if don't.
if(!FolderExists(folderOwnerUser + "/" + folder)){
throw new Exception("Folder '" + folder + "' doesn't exist !");
}
// Ensure that folder doesn't exists. Throw Exception if does.
if(FolderExists(folderOwnerUser + "/" + newFolder)){
throw new Exception("Folder '" + newFolder + "' doesn't exist !");
}
// See if user has sufficient permissions. User requires 'c' permission.
// There is builtin user system, skip ACL for it.
if(accessingUser.ToLower() != "system"){
IMAP_ACL_Flags acl = GetUserACL(folderOwnerUser,folder,accessingUser);
if((acl & IMAP_ACL_Flags.c) == 0){
throw new InsufficientPermissionsException("Insufficient permissions for folder '" + accessingUser + "/" + folder + "' !");
}
}
//--- Rename folder
using(WSqlCommand sqlCmd = new WSqlCommand(m_ConStr,"lspr_RenameFolder")){
sqlCmd.AddParameter("@UserName" ,SqlDbType.NVarChar,folderOwnerUser);
sqlCmd.AddParameter("@Folder" ,SqlDbType.NVarChar,folder);
sqlCmd.AddParameter("@NewFolder" ,SqlDbType.NVarChar,newFolder);
DataSet ds = sqlCmd.Execute();
if(ds.Tables.Count > 0 && ds.Tables[0].Rows.Count > 0){
throw new Exception(ds.Tables[0].Rows[0]["ErrorText"].ToString());
}
}
}
#endregion
//**
#region method FolderExists
/// <summary>
/// Gets if specified folder exists.
/// </summary>
/// <param name="folderName">Folder name which to check. Eg. UserName/Inbox,UserName/Inbox/subfolder.</param>
/// <returns>Returns true if folder exists, otherwise false.</returns>
public bool FolderExists(string folderName)
{
string[] user_folder = folderName.Split(new char[]{'/'},2);
string userName = user_folder[0];
if(user_folder.Length == 2){
folderName = user_folder[1];
}
using(WSqlCommand sqlCmd = new WSqlCommand(m_ConStr,"lspr_FolderExists")){
sqlCmd.AddParameter("@FolderName",SqlDbType.NVarChar,folderName);
sqlCmd.AddParameter("@UserName" ,SqlDbType.NVarChar,userName);
DataSet ds = sqlCmd.Execute();
if(ds.Tables.Count > 0 && ds.Tables[0].Rows.Count > 0){
return true;
}
}
return false;
}
#endregion
#region method FolderCreationTime
/// <summary>
/// Gets time when specified folder was created.
/// </summary>
/// <param name="folderOwnerUser">User who's folder it is.</param>
/// <param name="folder">Folder what creation time to get. For example: Inbox,Public Folders/Documnets .</param>
public DateTime FolderCreationTime(string folderOwnerUser,string folder)
{
using(WSqlCommand sqlCmd = new WSqlCommand(m_ConStr,"lspr_FolderExists")){
sqlCmd.AddParameter("@userName" ,SqlDbType.NVarChar,folderOwnerUser);
sqlCmd.AddParameter("@folderName",SqlDbType.NVarChar,folder);
DataSet ds = sqlCmd.Execute();
if(ds.Tables.Count > 0 && ds.Tables[0].Rows.Count > 0){
return (DateTime)ds.Tables[0].Rows[0]["CreationTime"];
}
else{
throw new Exception("Folder '" + folderOwnerUser + "/" + folder + "' doesn't exist !");
}
}
}
#endregion
#region method GetSharedFolderRoots
/// <summary>
/// Gets shared folder root folders.
/// </summary>
/// <returns></returns>
public SharedFolderRoot[] GetSharedFolderRoots()
{
/* Implementation notes:
*) Get shared folder roots.
*/
using(WSqlCommand sqlCmd = new WSqlCommand(m_ConStr,"lspr_GetSharedFolderRoots")){
DataSet dsSharedFolderRoots = sqlCmd.Execute();
dsSharedFolderRoots.Tables[0].TableName = "SharedFoldersRoots";
List<SharedFolderRoot> roots = new List<SharedFolderRoot>();
foreach(DataRow dr in dsSharedFolderRoots.Tables["SharedFoldersRoots"].Rows){
roots.Add(new SharedFolderRoot(
dr["RootID"].ToString(),
Convert.ToBoolean(dr["Enabled"]),
dr["Folder"].ToString(),
dr["Description"].ToString(),
(SharedFolderRootType_enum)Convert.ToInt32(dr["RootType"]),
dr["BoundedUser"].ToString(),
dr["BoundedFolder"].ToString()
));
}
return roots.ToArray();
}
}
#endregion
#region method AddSharedFolderRoot
/// <summary>
/// Add shared folder root.
/// </summary>
/// <param name="rootID">Root folder ID. Guid.NewID().ToString() is suggested.</param>
/// <param name="enabled">Specifies if root folder is enabled.</param>
/// <param name="folder">Folder name which will be visible to public.</param>
/// <param name="description">Description text.</param>
/// <param name="rootType">Specifies what type root folder is.</param>
/// <param name="boundedUser">User which to bound root folder.</param>
/// <param name="boundedFolder">Folder which to bound to public folder.</param>
public void AddSharedFolderRoot(string rootID,bool enabled,string folder,string description,SharedFolderRootType_enum rootType,string boundedUser,string boundedFolder)
{
/* Implementation notes:
*) Validate values. Throw ArgumnetExcetion if invalid values.
*) Ensure that root ID doesn't exists.
*) Ensure that root doesn't exists.
*) Add root folder.
*/
if(rootID == null || rootID == ""){
throw new Exception("Invalid rootID value, rootID can't be '' or null !");
}
//--- Validate values -------------------------------------//
ArgsValidator.ValidateNotNull(rootID);
ArgsValidator.ValidateSharedFolderRoot(folder);
ArgsValidator.ValidateNotNull(description);
if(rootType == SharedFolderRootType_enum.BoundedRootFolder){
ArgsValidator.ValidateUserName(boundedUser);
ArgsValidator.ValidateFolder(boundedFolder);
}
//---------------------------------------------------------//
/* We handle these is SQL, sql returns these errors in ErrorText
*) Ensure that root ID doesn't exists.
*) Ensure that root doesn't exists.
*/
// Insert group
using(WSqlCommand sqlCmd = new WSqlCommand(m_ConStr,"lspr_AddSharedFolderRoot")){
sqlCmd.AddParameter("@rootID" ,SqlDbType.NVarChar ,rootID);
sqlCmd.AddParameter("@enabled" ,SqlDbType.Bit ,enabled);
sqlCmd.AddParameter("@folder" ,SqlDbType.NVarChar ,folder);
sqlCmd.AddParameter("@description" ,SqlDbType.NVarChar ,description);
sqlCmd.AddParameter("@rootType" ,SqlDbType.Int ,rootType);
sqlCmd.AddParameter("@boundedUser" ,SqlDbType.NVarChar ,boundedUser);
sqlCmd.AddParameter("@boundedFolder" ,SqlDbType.NVarChar ,boundedFolder);
DataSet ds = sqlCmd.Execute();
ds.Tables[0].TableName = "Result";
// Proccess adding errors
if(ds.Tables["Result"].Rows.Count > 0 && ds.Tables["Result"].Rows[0]["ErrorText"].ToString().Length > 0){
throw new Exception(ds.Tables["Result"].Rows[0]["ErrorText"].ToString());
}
}
}
#endregion
#region method DeleteSharedFolderRoot
/// <summary>
/// Deletes shard folders root folder.
/// </summary>
/// <param name="rootID">Root folder ID which to delete.</param>
public void DeleteSharedFolderRoot(string rootID)
{
/* Implementation notes:
*) Validate values. Throw ArgumnetExcetion if invalid values.
*) Ensure that root ID exists.
*) Delete root folder.
*/
//--- Validate values -------------------------------------//
if(rootID == null || rootID == ""){
throw new Exception("Invalid rootID value, rootID can't be '' or null !");
}
//---------------------------------------------------------//
/* We handle these is SQL, sql returns these errors in ErrorText
*) Ensure that root ID exists.
*) Delete root folder.
*/
// Delete group and it's emebres
using(WSqlCommand sqlCmd = new WSqlCommand(m_ConStr,"lspr_DeleteSharedFolderRoot")){
sqlCmd.AddParameter("@rootID" ,SqlDbType.NVarChar,rootID);
DataSet ds = sqlCmd.Execute();
ds.Tables[0].TableName = "Result";
// Proccess errors
if(ds.Tables["Result"].Rows.Count > 0 && ds.Tables["Result"].Rows[0]["ErrorText"].ToString().Length > 0){
throw new Exception(ds.Tables["Result"].Rows[0]["ErrorText"].ToString());
}
}
}
#endregion
#region method UpdateSharedFolderRoot
/// <summary>
/// Updates shared folder root.
/// </summary>
/// <param name="rootID">Root Folder IF which to update.</param>
/// <param name="enabled">Specifies if root folder is enabled.</param>
/// <param name="folder">Folder name which will be visible to public.</param>
/// <param name="description">Description text.</param>
/// <param name="rootType">Specifies what type root folder is.</param>
/// <param name="boundedUser">User which to bound root folder.</param>
/// <param name="boundedFolder">Folder which to bound to public folder.</param>
public void UpdateSharedFolderRoot(string rootID,bool enabled,string folder,string description,SharedFolderRootType_enum rootType,string boundedUser,string boundedFolder)
{
/* Implementation notes:
*) Validate values. Throw ArgumnetExcetion if invalid values.
*) Ensure that root ID exists.
*) If root folder name is changed, ensure that new root folder won't conflict
any other root folder name. Throw Exception if does.
*) Update root folder.
*/
if(rootID == null || rootID == ""){
throw new Exception("Invalid rootID value, rootID can't be '' or null !");
}
//--- Validate values -------------------------------------//
ArgsValidator.ValidateNotNull(rootID);
ArgsValidator.ValidateSharedFolderRoot(folder);
ArgsValidator.ValidateNotNull(description);
if(rootType == SharedFolderRootType_enum.BoundedRootFolder){
ArgsValidator.ValidateUserName(boundedUser);
ArgsValidator.ValidateFolder(boundedFolder);
}
//---------------------------------------------------------//
/* We handle these is SQL, sql returns these errors in ErrorText
*) Ensure that root ID exists.
*) If root folder name is changed, ensure that new root folder won't conflict
any other root folder name. Throw Exception if does.
*/
// Update root folder
using(WSqlCommand sqlCmd = new WSqlCommand(m_ConStr,"lspr_UpdateSharedFolderRoot")){
sqlCmd.AddParameter("@rootID" ,SqlDbType.NVarChar ,rootID);
sqlCmd.AddParameter("@enabled" ,SqlDbType.Bit ,enabled);
sqlCmd.AddParameter("@folder" ,SqlDbType.NVarChar ,folder);
sqlCmd.AddParameter("@description" ,SqlDbType.NVarChar ,description);
sqlCmd.AddParameter("@rootType" ,SqlDbType.Int ,rootType);
sqlCmd.AddParameter("@boundedUser" ,SqlDbType.NVarChar ,boundedUser);
sqlCmd.AddParameter("@boundedFolder" ,SqlDbType.NVarChar ,boundedFolder);
DataSet ds = sqlCmd.Execute();
ds.Tables[0].TableName = "Result";
// Proccess adding errors
if(ds.Tables["Result"].Rows.Count > 0 && ds.Tables["Result"].Rows[0]["ErrorText"].ToString().Length > 0){
throw new Exception(ds.Tables["Result"].Rows[0]["ErrorText"].ToString());
}
}
}
#endregion
#region method GetFolderACL
/// <summary>
/// Gets specified folder ACL.
/// </summary>
/// <param name="accessingUser">User who accesses this method.
/// User needs r permission to call this method or Exception is thrown.
/// There is special user 'system' for which permission check is skipped.</param>
/// <param name="folderOwnerUser">User who's folder it is.</param>
/// <param name="folder">Folder what ACL to get. For example: Inbox,Public Folders/Documnets .</param>
/// <returns></returns>
public DataView GetFolderACL(string accessingUser,string folderOwnerUser,string folder)
{
/* Implementation notes:
*) Validate values. Throw ArgumnetExcetion if invalid values.
*) Ensure that user exists.
*) Normalize folder. Remove '/' from folder start and end, ... .
*) Do Shared Folders mapping.
*) Ensure that folder exists. Throw Exception if don't.
*) See if user has sufficient permissions. User requires 'a' permission.
There is builtin user system, skip ACL for it.
*) Get folder ACL.
*/
//--- Validate values -------------------//
ArgsValidator.ValidateUserName(folderOwnerUser);
ArgsValidator.ValidateFolder(folder);
//---------------------------------------//
// Ensure that user exists.
if(!UserExists(folderOwnerUser)){
throw new Exception("User '" + folderOwnerUser + "' doesn't exist !");
}
// Normalize folder. Remove '/' from folder start and end.
folder = API_Utlis.NormalizeFolder(folder);
// Do Shared Folders mapping.
string originalFolder = folder;
SharedFolderMapInfo mappedFolder = MapSharedFolder(originalFolder);
if(mappedFolder.IsSharedFolder){
folderOwnerUser = mappedFolder.FolderOnwer;
folder = mappedFolder.Folder;
if(folderOwnerUser == "" || folder == ""){
throw new ArgumentException("Specified root folder '" + originalFolder + "' isn't accessible !");
}
}
// Ensure that folder doesn't exists. Throw Exception if don't.
if(!FolderExists(folderOwnerUser + "/" + folder)){
throw new Exception("Folder '" + folder + "' doesn't exist !");
}
// See if user has sufficient permissions. User requires 'a' permission.
// There is builtin user system, skip ACL for it.
if(accessingUser.ToLower() != "system"){
IMAP_ACL_Flags acl = GetUserACL(folderOwnerUser,folder,accessingUser);
if((acl & IMAP_ACL_Flags.a) == 0){
throw new InsufficientPermissionsException("Insufficient permissions for folder '" + accessingUser + "/" + folder + "' !");
}
}
using(WSqlCommand sqlCmd = new WSqlCommand(m_ConStr,"lspr_GetFolderACL")){
if(folder.Length > 0){
sqlCmd.AddParameter("@FolderName",SqlDbType.NVarChar,folderOwnerUser + "/" + folder);
}
DataSet ds = sqlCmd.Execute();
ds.Tables[0].TableName = "ACL";
return ds.Tables["ACL"].DefaultView;
}
}
#endregion
#region method DeleteFolderACL
/// <summary>
/// Deletes specified folder ACL for specified user.
/// </summary>
/// <param name="accessingUser">User who accesses this method.
/// User needs r permission to call this method or Exception is thrown.
/// There is special user 'system' for which permission check is skipped.</param>
/// <param name="folderOwnerUser">User who's folder it is.</param>
/// <param name="folder">Folder what ACL to delete. For example: Inbox,Public Folders/Documnets .</param>
/// <param name="userOrGroup">User or user group which ACL on specified folder to delete.</param>
public void DeleteFolderACL(string accessingUser,string folderOwnerUser,string folder,string userOrGroup)
{
/* Implementation notes:
*) Validate values. Throw ArgumnetExcetion if invalid values.
*) Ensure that folder owner user exists.
*) Ensure that user or user group exists.
*) Normalize folder. Remove '/' from folder start and end, ... .
*) Do Shared Folders mapping.
*) Ensure that folder exists. Throw Exception if don't.
*) See if user has sufficient permissions. User requires 'a' permission.
There is builtin user system, skip ACL for it.
*) Delete folder.
*/
//--- Validate values -------------------//
ArgsValidator.ValidateUserName(folderOwnerUser);
ArgsValidator.ValidateFolder(folder);
ArgsValidator.ValidateUserName(userOrGroup);
//---------------------------------------//
// Ensure that folder owner user exists.
if(!UserExists(folderOwnerUser)){
throw new Exception("User '" + folderOwnerUser + "' doesn't exist !");
}
// Ensure that user or user group exists. Skip check for anyone.
if(userOrGroup.ToLower() != "anyone" && !GroupExists(userOrGroup)){
if(!UserExists(userOrGroup)){
throw new Exception("Invalid userOrGroup value, there is no such user or group '" + userOrGroup + "' !");
}
}
// Normalize folder. Remove '/' from folder start and end.
folder = API_Utlis.NormalizeFolder(folder);
// Do Shared Folders mapping.
string originalFolder = folder;
SharedFolderMapInfo mappedFolder = MapSharedFolder(originalFolder);
if(mappedFolder.IsSharedFolder){
folderOwnerUser = mappedFolder.FolderOnwer;
folder = mappedFolder.Folder;
if(folderOwnerUser == "" || folder == ""){
throw new ArgumentException("Specified root folder '" + originalFolder + "' isn't accessible !");
}
}
// Ensure that folder doesn't exists. Throw Exception if don't.
if(!FolderExists(folderOwnerUser + "/" + folder)){
throw new Exception("Folder '" + folder + "' doesn't exist !");
}
// See if user has sufficient permissions. User requires 'a' permission.
// There is builtin user system, skip ACL for it.
if(accessingUser.ToLower() != "system"){
IMAP_ACL_Flags acl = GetUserACL(folderOwnerUser,folder,accessingUser);
if((acl & IMAP_ACL_Flags.a) == 0){
throw new InsufficientPermissionsException("Insufficient permissions for folder '" + accessingUser + "/" + folder + "' !");
}
}
//--- Delete folder ACL
using(WSqlCommand sqlCmd = new WSqlCommand(m_ConStr,"lspr_DeleteFolderACL")){
sqlCmd.AddParameter("@FolderName" ,SqlDbType.UniqueIdentifier,folderOwnerUser + "/" + folder);
sqlCmd.AddParameter("@UserName" ,SqlDbType.UniqueIdentifier,userOrGroup);
DataSet ds = sqlCmd.Execute();
}
}
#endregion
#region method SetFolderACL
/// <summary>
/// Sets specified folder ACL for specified user.
/// </summary>
/// <param name="accessingUser">User who accesses this method.
/// User needs r permission to call this method or Exception is thrown.
/// There is special user 'system' for which permission check is skipped.</param>
/// <param name="folderOwnerUser">User who's folder it is.</param>
/// <param name="folder">Folder what ACL to set. For example: Inbox,Public Folders/Documnets .</param>
/// <param name="userOrGroup">>User or user which group ACL set to specified folder.</param>
/// <param name="setType">Specifies how ACL flags must be stored (ADD,REMOVE,REPLACE).</param>
/// <param name="aclFlags">ACL flags.</param>
public void SetFolderACL(string accessingUser,string folderOwnerUser,string folder,string userOrGroup,IMAP_Flags_SetType setType,IMAP_ACL_Flags aclFlags)
{
/* Implementation notes:
*) Validate values. Throw ArgumnetExcetion if invalid values.
*) Ensure that folder owner user exists.
*) Ensure that user or user group exists.
*) Normalize folder. Remove '/' from folder start and end, ... .
*) Do Shared Folders mapping.
*) Ensure that folder exists. Throw Exception if don't.
*) See if user has sufficient permissions. User requires 'a' permission.
There is builtin user system, skip ACL for it.
*) Set folder ACL folder.
*/
//--- Validate values -------------------//
ArgsValidator.ValidateUserName(folderOwnerUser);
ArgsValidator.ValidateFolder(folder);
ArgsValidator.ValidateUserName(userOrGroup);
//---------------------------------------//
// Ensure that folder owner user exists.
if(!UserExists(folderOwnerUser)){
throw new Exception("User '" + folderOwnerUser + "' doesn't exist !");
}
// Ensure that user or user group exists. Skip check for anyone.
if(userOrGroup.ToLower() != "anyone" && !GroupExists(userOrGroup)){
if(!UserExists(userOrGroup)){
throw new Exception("Invalid userOrGroup value, there is no such user or group '" + userOrGroup + "' !");
}
}
// Normalize folder. Remove '/' from folder start and end.
folder = API_Utlis.NormalizeFolder(folder);
// Do Shared Folders mapping.
string originalFolder = folder;
SharedFolderMapInfo mappedFolder = MapSharedFolder(originalFolder);
if(mappedFolder.IsSharedFolder){
folderOwnerUser = mappedFolder.FolderOnwer;
folder = mappedFolder.Folder;
if(folderOwnerUser == "" || folder == ""){
throw new ArgumentException("Specified root folder '" + originalFolder + "' isn't accessible !");
}
}
// Ensure that folder doesn't exists. Throw Exception if don't.
if(!FolderExists(folderOwnerUser + "/" + folder)){
throw new Exception("Folder '" + folder + "' doesn't exist !");
}
// See if user has sufficient permissions. User requires 'a' permission.
// There is builtin user system, skip ACL for it.
if(accessingUser.ToLower() != "system"){
IMAP_ACL_Flags acl = GetUserACL(folderOwnerUser,folder,accessingUser);
if((acl & IMAP_ACL_Flags.a) == 0){
throw new InsufficientPermissionsException("Insufficient permissions for folder '" + accessingUser + "/" + folder + "' !");
}
}
//--- Set folder ACL
IMAP_ACL_Flags currentACL_Flags = GetUserACL(folderOwnerUser,folder,folderOwnerUser);
if(setType == IMAP_Flags_SetType.Replace){
currentACL_Flags = aclFlags;
}
else if(setType == IMAP_Flags_SetType.Add){
currentACL_Flags |= aclFlags;
}
else if(setType == IMAP_Flags_SetType.Remove){
currentACL_Flags &= ~aclFlags;
}
using(WSqlCommand sqlCmd = new WSqlCommand(m_ConStr,"lspr_SetFolderACL")){
sqlCmd.AddParameter("@FolderName" ,SqlDbType.UniqueIdentifier,folderOwnerUser + "/" + folder);
sqlCmd.AddParameter("@UserName" ,SqlDbType.UniqueIdentifier,userOrGroup);
sqlCmd.AddParameter("@Permissions" ,SqlDbType.UniqueIdentifier,IMAP_Utils.ACL_to_String(currentACL_Flags));
DataSet ds = sqlCmd.Execute();
}
}
#endregion
#region method GetUserACL
/// <summary>
/// Gets what permissions specified user has to specified folder.
/// </summary>
/// <param name="folderOwnerUser">User who's folder it is.</param>
/// <param name="folder">Folder which ACL to get. For example Inbox,Public Folders.</param>
/// <param name="user">User name which ACL to get.</param>
/// <returns></returns>
public IMAP_ACL_Flags GetUserACL(string folderOwnerUser,string folder,string user)
{
//--- Validate values -------------------//
ArgsValidator.ValidateUserName(folderOwnerUser);
ArgsValidator.ValidateFolder(folder);
ArgsValidator.ValidateUserName(user);
//---------------------------------------//
/*
*) Ensure that folder owner user exists.
*) Ensure that user exists.
*) Normalize folder. Remove '/' from folder start and end, ... .
*) Do Shared Folders mapping.
// ?? *) Ensure that folder exists. Throw Exception if don't.
If folder owner is user, and no permissions explicity set, then user have ALL permissions.
If user isn't folder owner:
*) Try to get User ACl. Also look user groups.
If doesn't exist, try to anyone ACL.
If anyone ACL doesn't exist, try to inherit ACL from parent folders.
NOTE: Get maximum ACL user has. For example if user has explicity ACL set and
and has Group ACL set, then ACL = max combination of ACL falgs.
*/
// Ensure that folder owner user exists.
if(!UserExists(folderOwnerUser)){
throw new Exception("User '" + folderOwnerUser + "' doesn't exist !");
}
// Ensure that folder user exists.
if(!UserExists(user)){
throw new Exception("User '" + user + "' doesn't exist !");
}
// Normalize folder. Remove '/' from folder start and end.
folder = API_Utlis.NormalizeFolder(folder);
// Do Shared Folders mapping.
string originalFolder = folder;
SharedFolderMapInfo mappedFolder = MapSharedFolder(originalFolder);
if(mappedFolder.IsSharedFolder){
folderOwnerUser = mappedFolder.FolderOnwer;
folder = mappedFolder.Folder;
if(folderOwnerUser == "" || folder == ""){
throw new ArgumentException("Specified root folder '" + originalFolder + "' isn't accessible !");
}
}
IMAP_ACL_Flags userACL = IMAP_ACL_Flags.None;
// See if ACL is set to this folder, if not show inhereted ACL
DataView dv = null;
try{
dv = GetFolderACL("system",folderOwnerUser,folder);
}
// Folder doesnt exist, just skip it
catch{
}
if(dv != null && dv.Count > 0){
bool aclSetToUser = false;
foreach(DataRowView drV in dv){
// This is group, user is member of that group
if(GroupExists(drV["User"].ToString()) && IsUserGroupMember(drV["User"].ToString(),user)){
userACL |= IMAP_Utils.ACL_From_String(drV["Permissions"].ToString());
}
// ACL is explicity set to user
else if(drV["User"].ToString().ToLower() == user.ToLower()){
userACL = IMAP_Utils.ACL_From_String(drV["Permissions"].ToString());
aclSetToUser = true;
}
// There is ANYONE access
else if(drV["User"].ToString().ToLower() == "anyone"){
userACL = IMAP_Utils.ACL_From_String(drV["Permissions"].ToString());
}
}
// ACL isn't explicity set to folder owner user,give all permissions to folder owner user.
if(!aclSetToUser && user.ToLower() == folderOwnerUser.ToLower()){
userACL = IMAP_ACL_Flags.All;
}
}
else{
// ACL isn't set and user owner, give full rights
if(user.ToLower() == folderOwnerUser.ToLower()){
userACL = IMAP_ACL_Flags.All;
}
else{
// Try to inherit ACL from parent folder(s)
// Move right to left in path.
while(folder.LastIndexOf('/') > -1){
// Move 1 level to right in path
folder = folder.Substring(0,folder.LastIndexOf('/'));
dv = GetFolderACL("system",folderOwnerUser,folder);
if(dv.Count > 0){
foreach(DataRowView drV in dv){
string userOrGroup = drV["User"].ToString();
// This is group, user is member of that group
if(GroupExists(userOrGroup) && IsUserGroupMember(drV["User"].ToString(),user)){
userACL |= IMAP_Utils.ACL_From_String(drV["Permissions"].ToString());
}
// ACL is explicity set to user
else if(drV["User"].ToString().ToLower() == user.ToLower()){
userACL |= IMAP_Utils.ACL_From_String(drV["Permissions"].ToString());
}
// There is ANYONE access
else if(drV["User"].ToString().ToLower() == "anyone"){
userACL |= IMAP_Utils.ACL_From_String(drV["Permissions"].ToString());
}
}
// We inhereted all permission, don't look other parent folders anymore
break;
}
}
}
}
return userACL;
}
#endregion
#region method CreateUserDefaultFolders
/// <summary>
/// Creates specified user default folders, if they don't exist already.
/// </summary>
/// <param name="userName">User name to who's default folders to create.</param>
public void CreateUserDefaultFolders(string userName)
{
foreach(DataRowView drV in GetUsersDefaultFolders()){
if(!FolderExists(userName + "/" + drV["FolderName"].ToString())){
CreateFolder("system",userName,drV["FolderName"].ToString());
SubscribeFolder(userName,drV["FolderName"].ToString());
}
}
}
#endregion
#region method GetUsersDefaultFolders
/// <summary>
/// Gets users default folders.
/// </summary>
/// <returns></returns>
public DataView GetUsersDefaultFolders()
{
using(WSqlCommand sqlCmd = new WSqlCommand(m_ConStr,"lspr_GetUsersDefaultFolders")){
DataSet ds = sqlCmd.Execute();
ds.Tables[0].TableName = "UsersDefaultFolders";
// Force Inbox to be created
if(ds.Tables["UsersDefaultFolders"].Rows.Count == 0){
DataRow dr = ds.Tables["UsersDefaultFolders"].NewRow();
dr["FolderName"] = "Inbox";
dr["Permanent"] = true;
ds.Tables["UsersDefaultFolders"].Rows.Add(dr);
}
return ds.Tables["UsersDefaultFolders"].DefaultView;
}
}
#endregion
#region method AddUsersDefaultFolder
/// <summary>
/// Adds users default folder.
/// </summary>
/// <param name="folderName">Folder name.</param>
/// <param name="permanent">Spcifies if folder is permanent, user can't delete it.</param>
public void AddUsersDefaultFolder(string folderName,bool permanent)
{
ArgsValidator.ValidateFolder(folderName);
using(WSqlCommand sqlCmd = new WSqlCommand(m_ConStr,"lspr_AddUsersDefaultFolder")){
sqlCmd.AddParameter("@folderName" ,SqlDbType.NVarChar,folderName);
sqlCmd.AddParameter("@permanent ",SqlDbType.Bit ,permanent);
DataSet ds = sqlCmd.Execute();
ds.Tables[0].TableName = "UsersDefaultFolders";
if(ds.Tables["UsersDefaultFolders"].Rows.Count > 0 && ds.Tables["UsersDefaultFolders"].Rows[0]["ErrorText"].ToString().Length > 0){
throw new Exception(ds.Tables["UsersDefaultFolders"].Rows[0]["ErrorText"].ToString());
}
}
}
#endregion
#region method DeleteUsersDefaultFolder
/// <summary>
/// Deletes specified users default folder.
/// </summary>
/// <param name="folderName">Folder name.</param>
public void DeleteUsersDefaultFolder(string folderName)
{
ArgsValidator.ValidateFolder(folderName);
using(WSqlCommand sqlCmd = new WSqlCommand(m_ConStr,"lspr_DeleteUsersDefaultFolder")){
sqlCmd.AddParameter("@folderName" ,SqlDbType.NVarChar,folderName);
DataSet ds = sqlCmd.Execute();
ds.Tables[0].TableName = "UsersDefaultFolders";
if(ds.Tables["UsersDefaultFolders"].Rows.Count > 0 && ds.Tables["UsersDefaultFolders"].Rows[0]["ErrorText"].ToString().Length > 0){
throw new Exception(ds.Tables["UsersDefaultFolders"].Rows[0]["ErrorText"].ToString());
}
}
}
#endregion
#region method GetMailboxSize
/// <summary>
/// Gets specified user mailbox size.
/// </summary>
/// <param name="userName">User name.</param>
/// <returns>Returns mailbox size.</returns>
public long GetMailboxSize(string userName)
{
using(WSqlCommand sqlCmd = new WSqlCommand(m_ConStr,"lspr_GetMailboxSize")){
sqlCmd.AddParameter("@UserName",SqlDbType.NVarChar,userName);
DataSet ds = sqlCmd.Execute();
ds.Tables[0].TableName = "Detail";
if(ds.Tables["Detail"].Rows.Count > 0){
return Convert.ToInt64(ds.Tables["Detail"].Rows[0]["MailboxSize"]);
}
else{
return 0;
}
}
}
#endregion
#region method GetRecycleBinSettings
/// <summary>
/// Gets recycle bin settings.
/// </summary>
/// <returns></returns>
public DataTable GetRecycleBinSettings()
{
using(WSqlCommand sqlCmd = new WSqlCommand(m_ConStr,"lspr_GetRecycleBinSettings")){
DataSet ds = sqlCmd.Execute();
ds.Tables[0].TableName = "RecycleBinSettings";
if(ds.Tables["RecycleBinSettings"].Rows.Count == 0){
DataRow dr = ds.Tables["RecycleBinSettings"].NewRow();
dr["DeleteToRecycleBin"] = false;
dr["DeleteMessagesAfter"] = 1;
ds.Tables["RecycleBinSettings"].Rows.Add(dr);
}
return ds.Tables["RecycleBinSettings"];
}
}
#endregion
#region method UpdateRecycleBinSettings
/// <summary>
/// Updates recycle bin settings.
/// </summary>
/// <param name="deleteToRecycleBin">Specifies if deleted messages are store to recycle bin.</param>
/// <param name="deleteMessagesAfter">Specifies how old messages will be deleted.</param>
public void UpdateRecycleBinSettings(bool deleteToRecycleBin,int deleteMessagesAfter)
{
using(WSqlCommand sqlCmd = new WSqlCommand(m_ConStr,"lspr_UpdateRecycleBinSettings")){
sqlCmd.AddParameter("@deleteToRecycleBin" ,SqlDbType.Bit,deleteToRecycleBin);
sqlCmd.AddParameter("@deleteMessagesAfter",SqlDbType.Int,deleteMessagesAfter);
DataSet ds = sqlCmd.Execute();
}
}
#endregion
#region method GetRecycleBinMessagesInfo
/// <summary>
/// Gets recycle bin messages info.
/// </summary>
/// <param name="user">User who's recyclebin messages to get or null if all users messages.</param>
/// <param name="startDate">Messages from specified date. Pass DateTime.MinValue if not used.</param>
/// <param name="endDate">Messages to specified date. Pass DateTime.MinValue if not used.</param>
/// <returns></returns>
public DataView GetRecycleBinMessagesInfo(string user,DateTime startDate,DateTime endDate)
{
using(WSqlCommand sqlCmd = new WSqlCommand(m_ConStr,"lspr_GetRecycleBinMessagesInfo")){
if(user != null && user != ""){
sqlCmd.AddParameter("@userName",SqlDbType.NVarChar,user);
}
else{
sqlCmd.AddParameter("@userName",SqlDbType.NVarChar,null);
}
if(startDate != DateTime.MinValue){
sqlCmd.AddParameter("@startDate",SqlDbType.DateTime,startDate);
}
else{
sqlCmd.AddParameter("@startDate",SqlDbType.DateTime,new DateTime(1900,1,1));
}
if(endDate != DateTime.MinValue){
sqlCmd.AddParameter("@endDate",SqlDbType.DateTime,endDate);
}
else{
sqlCmd.AddParameter("@endDate",SqlDbType.DateTime,DateTime.MaxValue);
}
DataSet ds = sqlCmd.Execute();
ds.Tables[0].TableName = "MessagesInfo";
return ds.Tables["MessagesInfo"].DefaultView;
}
}
#endregion
#region method GetRecycleBinMessages
/// <summary>
/// Gets recycle bin message stream. NOTE: This method caller must take care of closing stream.
/// </summary>
/// <param name="messageID">Message ID if of message what to get.</param>
/// <returns></returns>
public Stream GetRecycleBinMessage(string messageID)
{
// Get message and message info from recycle bin
using(WSqlCommand sqlCmd = new WSqlCommand(m_ConStr,"lspr_GetRecycleBinMessage")){
sqlCmd.AddParameter("@messageID" ,SqlDbType.VarChar,messageID);
DataSet ds = sqlCmd.Execute();
ds.Tables[0].TableName = "RecycleBin";
if(ds.Tables["RecycleBin"].Rows.Count > 0){
return new MemoryStream(((byte[])ds.Tables["RecycleBin"].Rows[0]["Data"]));
}
else{
throw new Exception("Specified message doesn't exist !");
}
}
}
#endregion
#region method DeleteRecycleBinMessage
/// <summary>
/// Deletes specified recycle bin message.
/// </summary>
/// <param name="messageID">Message ID.</param>
public void DeleteRecycleBinMessage(string messageID)
{
using(WSqlCommand sqlCmd = new WSqlCommand(m_ConStr,"lspr_DeleteRecycleBinMessage")){
sqlCmd.AddParameter("@messageID" ,SqlDbType.NVarChar,messageID);
DataSet ds = sqlCmd.Execute();
}
}
#endregion
#region method RestoreRecycleBinMessage
/// <summary>
/// Restores specified recycle bin message.
/// </summary>
/// <param name="messageID">Message ID.</param>
public void RestoreRecycleBinMessage(string messageID)
{
// Get message and message info from recycle bin
using(WSqlCommand sqlCmd = new WSqlCommand(m_ConStr,"lspr_GetRecycleBinMessage")){
sqlCmd.AddParameter("@messageID" ,SqlDbType.VarChar,messageID);
DataSet ds = sqlCmd.Execute();
ds.Tables[0].TableName = "RecycleBin";
if(ds.Tables["RecycleBin"].Rows.Count > 0){
string userName = ds.Tables["RecycleBin"].Rows[0]["User"].ToString();
string folder = ds.Tables["RecycleBin"].Rows[0]["Folder"].ToString();
// If folder doesn't exist, create it
if(!FolderExists(userName + "/" + folder)){
CreateFolder("system",userName,folder);
}
// Try to store message back
StoreMessage(
"system",
userName,
folder,
new MemoryStream(((byte[])ds.Tables["RecycleBin"].Rows[0]["Data"])),
DateTime.Now,
IMAP_MessageFlags.Recent
);
}
}
}
#endregion
#endregion
#region Security related
#region function GetSecurityList
/// <summary>
/// Gets security entries list.
/// </summary>
public DataView GetSecurityList()
{
using(WSqlCommand sqlCmd = new WSqlCommand(m_ConStr,"lspr_GetSecurityList")){
DataSet ds = sqlCmd.Execute();
ds.Tables[0].TableName = "IPSecurity";
return ds.Tables["IPSecurity"].DefaultView;
}
}
#endregion
#region method AddSecurityEntry
/// <summary>
/// Adds new IP security entry.
/// </summary>
/// <param name="id">IP security entry ID.</param>
/// <param name="enabled">Specifies if IP security entry is enabled.</param>
/// <param name="description">IP security entry description text.</param>
/// <param name="service">Specifies service for what security entry applies.</param>
/// <param name="action">Specifies what action done if IP matches to security entry range.</param>
/// <param name="startIP">Range start IP.</param>
/// <param name="endIP">Range end IP.</param>
public void AddSecurityEntry(string id,bool enabled,string description,Service_enum service,IPSecurityAction_enum action,IPAddress startIP,IPAddress endIP)
{
if(id.Length == 0){
throw new Exception("You must specify securityID");
}
using(WSqlCommand sqlCmd = new WSqlCommand(m_ConStr,"lspr_AddSecurityEntry")){
sqlCmd.AddParameter("@id" ,SqlDbType.NVarChar,id);
sqlCmd.AddParameter("@enabled" ,SqlDbType.BigInt,enabled);
sqlCmd.AddParameter("@description" ,SqlDbType.NVarChar,description);
sqlCmd.AddParameter("@service" ,SqlDbType.Int,(int)service);
sqlCmd.AddParameter("@Action" ,SqlDbType.Int,(int)action);
sqlCmd.AddParameter("@StartIP" ,SqlDbType.NVarChar,startIP.ToString());
sqlCmd.AddParameter("@EndIP" ,SqlDbType.NVarChar,endIP.ToString());
DataSet ds = sqlCmd.Execute();
ds.Tables[0].TableName = "IPSecurity";
if(ds.Tables["IPSecurity"].Rows.Count > 0 && ds.Tables["IPSecurity"].Rows[0]["ErrorText"].ToString().Length > 0){
throw new Exception(ds.Tables["IPSecurity"].Rows[0]["ErrorText"].ToString());
}
}
}
#endregion
#region function DeleteSecurityEntry
/// <summary>
/// Deletes security entry.
/// </summary>
/// <param name="id">IP security entry ID.</param>
public void DeleteSecurityEntry(string id)
{
using(WSqlCommand sqlCmd = new WSqlCommand(m_ConStr,"lspr_DeleteSecurityEntry")){
sqlCmd.AddParameter("@SecurityID" ,SqlDbType.NVarChar,id);
DataSet ds = sqlCmd.Execute();
}
}
#endregion
#region function UpdateSecurityEntry
/// <summary>
/// Updates IP security entry.
/// </summary>
/// <param name="id">IP security entry ID.</param>
/// <param name="enabled">Specifies if IP security entry is enabled.</param>
/// <param name="description">IP security entry description text.</param>
/// <param name="service">Specifies service for what security entry applies.</param>
/// <param name="action">Specifies what action done if IP matches to security entry range.</param>
/// <param name="startIP">Range start IP.</param>
/// <param name="endIP">Range end IP.</param>
public void UpdateSecurityEntry(string id,bool enabled,string description,Service_enum service,IPSecurityAction_enum action,IPAddress startIP,IPAddress endIP)
{
using(WSqlCommand sqlCmd = new WSqlCommand(m_ConStr,"lspr_UpdateSecurityEntry")){
sqlCmd.AddParameter("@id" ,SqlDbType.NVarChar,id);
sqlCmd.AddParameter("@enabled" ,SqlDbType.BigInt,enabled);
sqlCmd.AddParameter("@description" ,SqlDbType.NVarChar,description);
sqlCmd.AddParameter("@service" ,SqlDbType.Int,(int)service);
sqlCmd.AddParameter("@Action" ,SqlDbType.Int,(int)action);
sqlCmd.AddParameter("@StartIP" ,SqlDbType.NVarChar,startIP.ToString());
sqlCmd.AddParameter("@EndIP" ,SqlDbType.NVarChar,endIP.ToString());
DataSet ds = sqlCmd.Execute();
ds.Tables[0].TableName = "IPSecurity";
if(ds.Tables["IPSecurity"].Rows.Count > 0 && ds.Tables["IPSecurity"].Rows[0]["ErrorText"].ToString().Length > 0){
throw new Exception(ds.Tables["IPSecurity"].Rows[0]["ErrorText"].ToString());
}
}
}
#endregion
#endregion
#region Filters related
#region function GetFilters
/// <summary>
/// Gets filter list.
/// </summary>
/// <returns></returns>
public DataView GetFilters()
{
using(WSqlCommand sqlCmd = new WSqlCommand(m_ConStr,"lspr_GetFilters")){
DataSet ds = sqlCmd.Execute();
ds.Tables[0].TableName = "SmtpFilters";
return ds.Tables["SmtpFilters"].DefaultView;
}
}
#endregion
#region function AddFilter
/// <summary>
/// Adds new filter.
/// </summary>
/// <param name="filterID">Filter ID. Suggested value is Guid.NewGuid() .</param>
/// <param name="description">Filter description</param>
/// <param name="type">Filter type. Eg. ISmtpMessageFilter.</param>
/// <param name="assembly">Assembly with full location. Eg. C:\MailServer\Filters\filter.dll .</param>
/// <param name="className">Filter full class name, wih namespace. Eg. LumiSoft.MailServer.Fileters.Filter1 .</param>
/// <param name="cost">Filters are sorted by cost and proccessed with cost value. Smallest cost is proccessed first.</param>
/// <param name="enabled">Specifies if filter is enabled.</param>
/// <remarks>Throws exception if specified filter entry already exists.</remarks>
public void AddFilter(string filterID,string description,string type,string assembly,string className,long cost,bool enabled)
{
if(filterID.Length == 0){
throw new Exception("You must specify filterID");
}
using(WSqlCommand sqlCmd = new WSqlCommand(m_ConStr,"lspr_AddFilter")){
sqlCmd.AddParameter("@FilterID" ,SqlDbType.NVarChar,filterID);
sqlCmd.AddParameter("@Description" ,SqlDbType.NVarChar,description);
sqlCmd.AddParameter("@Type" ,SqlDbType.NVarChar,type);
sqlCmd.AddParameter("@Assembly" ,SqlDbType.NVarChar,assembly);
sqlCmd.AddParameter("@ClassName" ,SqlDbType.NVarChar,className);
sqlCmd.AddParameter("@Cost" ,SqlDbType.BigInt ,cost);
sqlCmd.AddParameter("@Enabled" ,SqlDbType.Bit ,enabled);
DataSet ds = sqlCmd.Execute();
ds.Tables[0].TableName = "Filters";
if(ds.Tables["Filters"].Rows.Count > 0 && ds.Tables["Filters"].Rows[0]["ErrorText"].ToString().Length > 0){
throw new Exception(ds.Tables["Filters"].Rows[0]["ErrorText"].ToString());
}
}
}
#endregion
#region function DeleteFilter
/// <summary>
/// Deletes specified filter.
/// </summary>
/// <param name="filterID">FilterID of the filter which to delete.</param>
public void DeleteFilter(string filterID)
{
using(WSqlCommand sqlCmd = new WSqlCommand(m_ConStr,"lspr_DeleteFilter")){
sqlCmd.AddParameter("@FilterID" ,SqlDbType.NVarChar,filterID);
DataSet ds = sqlCmd.Execute();
}
}
#endregion
#region function UpdateFilter
/// <summary>
/// Updates specified filter.
/// </summary>
/// <param name="filterID">FilterID which to update.</param>
/// <param name="description">Filter description</param>
/// <param name="type">Filter type. Eg. ISmtpMessageFilter.</param>
/// <param name="assembly">Assembly with full location. Eg. C:\MailServer\Filters\filter.dll .</param>
/// <param name="className">Filter full class name, wih namespace. Eg. LumiSoft.MailServer.Fileters.Filter1 .</param>
/// <param name="cost">Filters are sorted by cost and proccessed with cost value. Smallest cost is proccessed first.</param>
/// <param name="enabled">Specifies if filter is enabled.</param>
/// <returns></returns>
public void UpdateFilter(string filterID,string description,string type,string assembly,string className,long cost,bool enabled)
{
using(WSqlCommand sqlCmd = new WSqlCommand(m_ConStr,"lspr_UpdateFilter")){
sqlCmd.AddParameter("@FilterID" ,SqlDbType.NVarChar,filterID);
sqlCmd.AddParameter("@Description" ,SqlDbType.NVarChar,description);
sqlCmd.AddParameter("@Type" ,SqlDbType.NVarChar,type);
sqlCmd.AddParameter("@Assembly" ,SqlDbType.NVarChar,assembly);
sqlCmd.AddParameter("@ClassName" ,SqlDbType.NVarChar,className);
sqlCmd.AddParameter("@Cost" ,SqlDbType.BigInt ,cost);
sqlCmd.AddParameter("@Enabled" ,SqlDbType.Bit ,enabled);
DataSet ds = sqlCmd.Execute();
ds.Tables[0].TableName = "Filters";
if(ds.Tables["Filters"].Rows.Count > 0 && ds.Tables["Filters"].Rows[0]["ErrorText"].ToString().Length > 0){
throw new Exception(ds.Tables["Filters"].Rows[0]["ErrorText"].ToString());
}
}
}
#endregion
#endregion
#region Settings related
#region method GetSettings
/// <summary>
/// Gets server settings.
/// </summary>
/// <returns></returns>
public DataRow GetSettings()
{
DataSet ds = new DataSet();
API_Utlis.CreateSettingsSchema(ds);
using(WSqlCommand sqlCmd = new WSqlCommand(m_ConStr,"lspr_GetSettings")){
DataSet dsS = sqlCmd.Execute();
dsS.Tables[0].TableName = "Settings";
if(dsS.Tables["Settings"].Rows.Count > 0){
byte[] data = (byte[])dsS.Tables["Settings"].Rows[0]["Settings"];
ds.ReadXml(new MemoryStream(data));
}
}
if(ds.Tables["Settings"].Rows.Count == 0){
ds.Tables["Settings"].Rows.Add(ds.Tables["Settings"].NewRow());
}
foreach(DataRow dr in ds.Tables["Settings"].Rows){
foreach(DataColumn dc in ds.Tables["Settings"].Columns){
if(dr.IsNull(dc.ColumnName)){
dr[dc.ColumnName] = dc.DefaultValue;
}
}
}
if(ds.Tables["SMTP_Bindings"].Rows.Count == 0){
ds.Tables["SMTP_Bindings"].Rows.Add(ds.Tables["SMTP_Bindings"].NewRow());
}
foreach(DataRow dr in ds.Tables["SMTP_Bindings"].Rows){
foreach(DataColumn dc in ds.Tables["SMTP_Bindings"].Columns){
if(dr.IsNull(dc.ColumnName)){
dr[dc.ColumnName] = dc.DefaultValue;
}
}
}
if(ds.Tables["POP3_Bindings"].Rows.Count == 0){
ds.Tables["POP3_Bindings"].Rows.Add(ds.Tables["POP3_Bindings"].NewRow());
}
foreach(DataRow dr in ds.Tables["POP3_Bindings"].Rows){
foreach(DataColumn dc in ds.Tables["POP3_Bindings"].Columns){
if(dr.IsNull(dc.ColumnName)){
dr[dc.ColumnName] = dc.DefaultValue;
}
}
}
if(ds.Tables["IMAP_Bindings"].Rows.Count == 0){
ds.Tables["IMAP_Bindings"].Rows.Add(ds.Tables["IMAP_Bindings"].NewRow());
}
foreach(DataRow dr in ds.Tables["IMAP_Bindings"].Rows){
foreach(DataColumn dc in ds.Tables["IMAP_Bindings"].Columns){
if(dr.IsNull(dc.ColumnName)){
dr[dc.ColumnName] = dc.DefaultValue;
}
}
}
return ds.Tables["Settings"].Rows[0];
}
#endregion
#region method UpdateSettings
/// <summary>
/// Updates server settings.
/// </summary>
public void UpdateSettings(DataRow settings)
{/*
DataRow row = GetSettings();
foreach(DataColumn dc in row.Table.Columns){
row[dc.ColumnName] = settings[dc.ColumnName];
}*/
using(MemoryStream strm = new MemoryStream()){
settings.Table.DataSet.WriteXml(strm);
using(WSqlCommand sqlCmd = new WSqlCommand(m_ConStr,"lspr_UpdateSettings")){
sqlCmd.AddParameter("@Settings" ,SqlDbType.Image,strm.ToArray());
DataSet ds = sqlCmd.Execute();
}
}
}
#endregion
#endregion
#region method GetACL
/// <summary>
/// Gets all folders IMAP acl entries.
/// </summary>
/// <returns></returns>
private DataSet GetACL()
{
using(WSqlCommand sqlCmd = new WSqlCommand(m_ConStr,"select * from lsIMAP_ACL")){
DataSet ds = sqlCmd.Execute();
ds.Tables[0].TableName = "ACL";
return ds;
}
}
#endregion
#region method IsUserGroupMember
/// <summary>
/// Gets if specified user is specified user group member. Returns true if user is user group member.
/// </summary>
/// <param name="group">User group name.</param>
/// <param name="user">User name.</param>
/// <returns>Returns true if user is user group member.</returns>
private bool IsUserGroupMember(string group,string user)
{
List<string> proccessedGroups = new List<string>();
Queue<string> membersQueue = new Queue<string>();
string[] members = GetGroupMembers(group);
foreach(string member in members){
membersQueue.Enqueue(member);
}
while(membersQueue.Count > 0){
string member = membersQueue.Dequeue();
// Nested group
DataRow drGroup = GetGroup(member);
if(drGroup != null){
// Don't proccess poroccessed groups any more, causes infinite loop
if(!proccessedGroups.Contains(member.ToLower())){
// Skip disabled groups
if(Convert.ToBoolean(drGroup["Enabled"])){
members = GetGroupMembers(member);
foreach(string m in members){
membersQueue.Enqueue(m);
}
}
proccessedGroups.Add(member.ToLower());
}
}
// User
else{
if(member.ToLower() == user.ToLower()){
return true;
}
}
}
return false;
}
#endregion
#region method MapSharedFolder
/// <summary>
/// This call holds shaared folder mapping info.
/// </summary>
private class SharedFolderMapInfo
{
private string m_OriginalFolder = "";
private string m_FolderOwner = "";
private string m_Folder = "";
private string m_SharedRootName = "";
/// <summary>
/// Default constructor.
/// </summary>
/// <param name="originalFolder"></param>
/// <param name="folderOwner"></param>
/// <param name="folder"></param>
/// <param name="sharedRootName"></param>
public SharedFolderMapInfo(string originalFolder,string folderOwner,string folder,string sharedRootName)
{
m_OriginalFolder = originalFolder;
m_FolderOwner = folderOwner;
m_Folder = folder;
m_SharedRootName = sharedRootName;
}
#region Properties Implementation
/// <summary>
/// Gets original folder.
/// </summary>
public string OriginalFolder
{
get{ return m_OriginalFolder; }
}
/// <summary>
/// Shared folder owner. This is available only if OriginalFolder is shared folder.
/// </summary>
public string FolderOnwer
{
get{ return m_FolderOwner; }
}
/// <summary>
/// Gets shared folder owner folder. This is available only if OriginalFolder is shared folder.
/// </summary>
public string Folder
{
get{ return m_Folder; }
}
/// <summary>
/// Gets shared root folder name. This is available only if OriginalFolder is shared folder.
/// </summary>
public string SharedRootName
{
get{ return m_SharedRootName; }
}
/// <summary>
/// Gets if OriginalFolder is shared folder.
/// </summary>
public bool IsSharedFolder
{
get{ return m_SharedRootName != ""; }
}
#endregion
}
/// <summary>
/// If folder is Shared Folder, then maps folder to actual account.
/// </summary>
/// <param name="folder">Folder to map.</param>
/// <returns></returns>
private SharedFolderMapInfo MapSharedFolder(string folder)
{
string rootFolder = folder.Split(new char[]{'/'},2)[0];
SharedFolderRoot[] roots = GetSharedFolderRoots();
foreach(SharedFolderRoot root in roots){
if(root.RootType == SharedFolderRootType_enum.BoundedRootFolder){
if(rootFolder.ToLower() == root.FolderName.ToLower()){
// folder = root.BoundedUser + "/" + root.BoundedFolder + folder.Substring(root.FolderName.Length);
return new SharedFolderMapInfo(folder,root.BoundedUser,root.BoundedFolder,root.FolderName);
}
}
else if(root.RootType == SharedFolderRootType_enum.UsersSharedFolder){
if(rootFolder.ToLower() == root.FolderName.ToLower()){
// Cut off root folder name
string[] p = folder.Split(new char[]{'/'},3);
// root/user/folder
if(p.Length == 3){
return new SharedFolderMapInfo(folder,p[1],p[2],root.FolderName);
}
// root/user
else if(p.Length == 3){
return new SharedFolderMapInfo(folder,p[1],"",root.FolderName);
}
// root (User and folder missing)
else{
return new SharedFolderMapInfo(folder,"","",root.FolderName);
}
}
}
}
return new SharedFolderMapInfo(folder,"","","");
}
#endregion
#region method GetGroup
/// <summary>
/// Gets specified user group. If group doesn't exist, returns null;
/// </summary>
/// <param name="group">User group name.</param>
/// <returns></returns>
private DataRow GetGroup(string group)
{
foreach(DataRowView drV in GetGroups()){
if(group.ToLower() == drV["GroupName"].ToString().ToLower()){
return drV.Row;
}
}
return null;
}
#endregion
#region function GetTopLines
private byte[] GetTopLines(Stream strm,int nrLines)
{
TextReader reader = (TextReader)new StreamReader(strm);
strm.Position = 0;
int lCounter = 0;
int msgLine = -1;
bool msgLines = false;
StringBuilder strBuilder = new StringBuilder();
while(true){
string line = reader.ReadLine();
// Reached end of message
if(line == null){
break;
}
else{
// End of header reached
if(!msgLines && line.Length == 0){
// Set flag, that message lines reading start.
msgLines = true;
}
// Check that wanted message lines count isn't exceeded
if(msgLines){
if(msgLine > nrLines){
break;
}
msgLine++;
}
strBuilder.Append(line + "\r\n");
}
lCounter++;
}
return System.Text.Encoding.ASCII.GetBytes(strBuilder.ToString());
}
#endregion
}
}