using System;
using System.Collections;
using LumiSoft.Net;
namespace LumiSoft.Net.IMAP.Server
{
/// <summary>
/// IMAP search command grouped(parenthesized) search-key collection.
/// </summary>
internal class SearchGroup
{
private ArrayList m_pSearchKeys = null;
/// <summary>
/// Default constructor.
/// </summary>
public SearchGroup()
{
m_pSearchKeys = new ArrayList();
}
#region method Parse
/// <summary>
/// Parses search key from current position.
/// </summary>
/// <param name="reader"></param>
public void Parse(StringReader reader)
{
//Remove spaces from string start
reader.ReadToFirstChar();
if(reader.StartsWith("(")){
reader = new StringReader(reader.ReadParenthesized().Trim());
}
//--- Start parsing search keys --------------//
while(reader.Available > 0){
object searchKey = ParseSearchKey(reader);
if(searchKey != null){
m_pSearchKeys.Add(searchKey);
}
}
//--------------------------------------------//
}
#endregion
#region method IsHeaderNeeded
/// <summary>
/// Gets if message Header is needed for matching.
/// </summary>
/// <returns></returns>
public bool IsHeaderNeeded()
{
foreach(object searchKey in m_pSearchKeys){
if(SearchGroup.IsHeaderNeededForKey(searchKey)){
return true;
}
}
return false;
}
#endregion
#region method IsBodyTextNeeded
/// <summary>
/// Gets if message body text is needed for matching.
/// </summary>
/// <returns></returns>
public bool IsBodyTextNeeded()
{
foreach(object searchKey in m_pSearchKeys){
if(SearchGroup.IsBodyTextNeededForKey(searchKey)){
return true;
}
}
return false;
}
#endregion
#region static method ParseSearchKey
/// <summary>
/// Parses SearchGroup or SearchItem from reader. If reader starts with (, then parses searchGroup, otherwise SearchItem.
/// </summary>
/// <param name="reader"></param>
/// <returns></returns>
internal static object ParseSearchKey(StringReader reader)
{
//Remove spaces from string start
reader.ReadToFirstChar();
// SearchGroup
if(reader.StartsWith("(")){
SearchGroup searchGroup = new SearchGroup();
searchGroup.Parse(reader);
return searchGroup;
}
// SearchItem
else{
return SearchKey.Parse(reader);
}
}
#endregion
#region static method Match_Key_Value
/// <summary>
/// Gets if specified message matches to specified search key.
/// </summary>
/// <param name="searchKey">SearchKey or SearchGroup.</param>
/// <param name="no">IMAP message sequence number.</param>
/// <param name="uid">IMAP message UID.</param>
/// <param name="size">IMAP message size in bytes.</param>
/// <param name="internalDate">IMAP message INTERNALDATE (dateTime when server stored message).</param>
/// <param name="flags">IMAP message flags.</param>
/// <param name="mime">Mime message main header only.</param>
/// <param name="bodyText">Message body text.</param>
/// <returns></returns>
internal static bool Match_Key_Value(object searchKey,long no,long uid,long size,DateTime internalDate,IMAP_MessageFlags flags,LumiSoft.Net.Mime.Mime mime,string bodyText)
{
if(searchKey.GetType() == typeof(SearchKey)){
if(!((SearchKey)searchKey).Match(no,uid,size,internalDate,flags,mime,bodyText)){
return false;
}
}
else if(searchKey.GetType() == typeof(SearchGroup)){
if(!((SearchGroup)searchKey).Match(no,uid,size,internalDate,flags,mime,bodyText)){
return false;
}
}
return true;
}
#endregion
#region static method IsHeaderNeededForKey
/// <summary>
/// Gets if message header is needed for matching.
/// </summary>
/// <param name="searchKey"></param>
/// <returns></returns>
internal static bool IsHeaderNeededForKey(object searchKey)
{
if(searchKey.GetType() == typeof(SearchKey)){
if(((SearchKey)searchKey).IsHeaderNeeded()){
return true;
}
}
else if(searchKey.GetType() == typeof(SearchGroup)){
if(((SearchGroup)searchKey).IsHeaderNeeded()){
return true;
}
}
return false;
}
#endregion
#region static method IsBodyTextNeededForKey
/// <summary>
/// Gets if message body text is needed for matching.
/// </summary>
/// <param name="searchKey"></param>
/// <returns></returns>
internal static bool IsBodyTextNeededForKey(object searchKey)
{
if(searchKey.GetType() == typeof(SearchKey)){
if(((SearchKey)searchKey).IsBodyTextNeeded()){
return true;
}
}
else if(searchKey.GetType() == typeof(SearchGroup)){
if(((SearchGroup)searchKey).IsBodyTextNeeded()){
return true;
}
}
return false;
}
#endregion
#region method Match
/// <summary>
/// Gets if specified message matches with this class search-key.
/// </summary>
/// <param name="no">IMAP message sequence number.</param>
/// <param name="uid">IMAP message UID.</param>
/// <param name="size">IMAP message size in bytes.</param>
/// <param name="internalDate">IMAP message INTERNALDATE (dateTime when server stored message).</param>
/// <param name="flags">IMAP message flags.</param>
/// <param name="mime">Mime message main header only.</param>
/// <param name="bodyText">Message body text.</param>
/// <returns></returns>
public bool Match(long no,long uid,long size,DateTime internalDate,IMAP_MessageFlags flags,LumiSoft.Net.Mime.Mime mime,string bodyText)
{
// We must match all keys, if one fails, no need to check others
foreach(object searckKey in m_pSearchKeys){
if(!Match_Key_Value(searckKey,no,uid,size,internalDate,flags,mime,bodyText)){
return false;
}
}
return true;
}
#endregion
}
}