Index: src/ch/FileFilter.cpp
===================================================================
diff -u -r591f291e22d2ece89acb266c8aa0b05c257a407c -rc54aa186fda8c0af84325325276245e9d8fcfa26
--- src/ch/FileFilter.cpp	(.../FileFilter.cpp)	(revision 591f291e22d2ece89acb266c8aa0b05c257a407c)
+++ src/ch/FileFilter.cpp	(.../FileFilter.cpp)	(revision c54aa186fda8c0af84325325276245e9d8fcfa26)
@@ -19,6 +19,7 @@
 #include "stdafx.h"
 #include "FileInfo.h"
 #include "FileFilter.h"
+#include "TConfig.h"
 
 ////////////////////////////////////////////////////////////////////////////
 bool _tcicmp(TCHAR c1, TCHAR c2)
@@ -184,6 +185,124 @@
 	delete [] pszData;
 }
 
+void CFileFilter::StoreInConfig(TConfig& rConfig) const
+{
+   rConfig.SetValue(_T("IncludeMask.Use"), m_bUseMask);
+   rConfig.SetValue(_T("IncludeMask.MaskList.Mask"), m_astrMask);
+
+   rConfig.SetValue(_T("ExcludeMask.Use"), m_bUseExcludeMask);
+   rConfig.SetValue(_T("ExcludeMask.MaskList.Mask"), m_astrExcludeMask);
+
+   rConfig.SetValue(_T("SizeA.Use"), m_bUseSize);
+   rConfig.SetValue(_T("SizeA.FilteringType"), m_iSizeType1);
+   rConfig.SetValue(_T("SizeA.Value"), m_ullSize1);
+   rConfig.SetValue(_T("SizeB.Use"), m_bUseSize2);
+   rConfig.SetValue(_T("SizeB.FilteringType"), m_iSizeType2);
+   rConfig.SetValue(_T("SizeB.Value"), m_ullSize2);
+
+   rConfig.SetValue(_T("DateA.Use"), m_bUseDate);
+   rConfig.SetValue(_T("DateA.Type"), m_iDateType);	// created/last modified/last accessed
+   rConfig.SetValue(_T("DateA.FilteringType"), m_iDateType1);	// before/after
+   rConfig.SetValue(_T("DateA.EnableDatePart"), m_bDate1);
+   rConfig.SetValue(_T("DateA.DateValue"), m_tDate1.GetTime());
+   rConfig.SetValue(_T("DateA.EnableTimePart"), m_bTime1);
+   rConfig.SetValue(_T("DateA.TimeValue"), m_tTime1.GetTime());
+
+   rConfig.SetValue(_T("DateB.Type"), m_bUseDate2);
+   rConfig.SetValue(_T("DateB.FilteringType"), m_iDateType2);
+   rConfig.SetValue(_T("DateB.EnableDatePart"), m_bDate2);
+   rConfig.SetValue(_T("DateB.DateValue"), m_tDate2.GetTime());
+   rConfig.SetValue(_T("DateB.EnableTimePart"), m_bTime2);
+   rConfig.SetValue(_T("DateB.TimeValue"), m_tTime2.GetTime());
+
+   rConfig.SetValue(_T("Attributes.Use"), m_bUseAttributes);
+   rConfig.SetValue(_T("Attributes.Archive"), m_iArchive);
+   rConfig.SetValue(_T("Attributes.ReadOnly"), m_iReadOnly);
+   rConfig.SetValue(_T("Attributes.Hidden"), m_iHidden);
+   rConfig.SetValue(_T("Attributes.System"), m_iSystem);
+   rConfig.SetValue(_T("Attributes.Directory"), m_iDirectory);
+}
+
+void CFileFilter::ReadFromConfig(const TConfig& rConfig)
+{
+	__time64_t tTime = 0;
+
+	if(!rConfig.GetValue(_T("IncludeMask.Use"), m_bUseMask))
+		m_bUseMask = false;
+
+	m_astrMask.clear();
+	rConfig.GetValue(_T("IncludeMask.MaskList.Mask"), m_astrMask);
+
+	if(!rConfig.GetValue(_T("ExcludeMask.Use"), m_bUseExcludeMask))
+		m_bUseExcludeMask = false;
+
+	m_astrExcludeMask.clear();
+	rConfig.GetValue(_T("ExcludeMask.MaskList.Mask"), m_astrExcludeMask);
+
+	if(!rConfig.GetValue(_T("SizeA.Use"), m_bUseSize))
+		m_bUseSize = false;
+	if(!rConfig.GetValue(_T("SizeA.FilteringType"), m_iSizeType1))
+		m_iSizeType1 = EQ;
+	if(!rConfig.GetValue(_T("SizeA.Value"), m_ullSize1))
+		m_ullSize1 = 0;
+	if(!rConfig.GetValue(_T("SizeB.Use"), m_bUseSize2))
+		m_bUseSize2 = false;
+	if(!rConfig.GetValue(_T("SizeB.FilteringType"), m_iSizeType2))
+		m_iSizeType2 = EQ;
+	if(!rConfig.GetValue(_T("SizeB.Value"), m_ullSize2))
+		m_ullSize2 = 0;
+
+	if(!rConfig.GetValue(_T("DateA.Use"), m_bUseDate))
+		m_bUseDate = false;
+
+	if(!rConfig.GetValue(_T("DateA.Type"), m_iDateType))	// created/last modified/last accessed
+		m_iDateType = DATE_CREATED;
+	if(!rConfig.GetValue(_T("DateA.FilteringType"), m_iDateType1))	// before/after
+		m_iDateType1 = EQ;
+	if(!rConfig.GetValue(_T("DateA.EnableDatePart"), m_bDate1))
+		m_bDate1 = false;
+	
+	if(!rConfig.GetValue(_T("DateA.DateValue"), tTime))
+		tTime = 0;
+	m_tDate1 = tTime;
+
+	if(!rConfig.GetValue(_T("DateA.EnableTimePart"), m_bTime1))
+		m_bTime1 = false;
+
+	if(!rConfig.GetValue(_T("DateA.TimeValue"), tTime))
+		tTime = 0;
+	m_tTime1 = tTime;
+
+	if(!rConfig.GetValue(_T("DateB.Type"), m_bUseDate2))
+		m_bUseDate2 = false;
+	if(!rConfig.GetValue(_T("DateB.FilteringType"), m_iDateType2))
+		m_iDateType2 = EQ;
+	if(!rConfig.GetValue(_T("DateB.EnableDatePart"), m_bDate2))
+		m_bDate2 = false;
+
+	if(!rConfig.GetValue(_T("DateB.DateValue"), tTime))
+		tTime = 0;
+	m_tDate2 = tTime;
+	if(!rConfig.GetValue(_T("DateB.EnableTimePart"), m_bTime2))
+		m_bTime2 = false;
+	if(!rConfig.GetValue(_T("DateB.TimeValue"), tTime))
+		tTime = 0;
+	m_tTime2 = tTime;
+
+	if(!rConfig.GetValue(_T("Attributes.Use"), m_bUseAttributes))
+		m_bUseAttributes = false;
+	if(!rConfig.GetValue(_T("Attributes.Archive"), m_iArchive))
+		m_iArchive = 0;
+	if(!rConfig.GetValue(_T("Attributes.ReadOnly"), m_iReadOnly))
+		m_iReadOnly = false;
+	if(!rConfig.GetValue(_T("Attributes.Hidden"), m_iHidden))
+		m_iHidden = 0;
+	if(!rConfig.GetValue(_T("Attributes.System"), m_iSystem))
+		m_iSystem = 0;
+	if(!rConfig.GetValue(_T("Attributes.Directory"), m_iDirectory))
+		m_iDirectory = 0;
+}
+
 bool CFileFilter::Match(const CFileInfoPtr& spInfo) const
 {
 	// check by mask
@@ -467,6 +586,32 @@
 	return false;
 }
 
+void CFiltersArray::StoreInConfig(TConfig& rConfig, PCTSTR pszNodeName) const
+{
+	rConfig.DeleteNode(pszNodeName);
+	BOOST_FOREACH(const CFileFilter& rFilter, m_vFilters)
+	{
+		TConfig cfgNode;
+		rFilter.StoreInConfig(cfgNode);
+		rConfig.AddSubConfig(CString(pszNodeName) + _T(".FilterDefinition"), cfgNode);
+	}
+}
+
+void CFiltersArray::ReadFromConfig(const TConfig& rConfig, PCTSTR pszNodeName)
+{
+	m_vFilters.clear();
+
+	std::vector<TConfig> vConfigs;
+	rConfig.ExtractMultiSubConfigs(pszNodeName, vConfigs);
+	BOOST_FOREACH(const TConfig& rCfg, vConfigs)
+	{
+		CFileFilter tFilter;
+		tFilter.ReadFromConfig(rCfg);
+
+		m_vFilters.push_back(tFilter);
+	}
+}
+
 bool CFiltersArray::IsEmpty() const
 {
 	return m_vFilters.empty();
Index: src/ch/FileFilter.h
===================================================================
diff -u -r22bbc4a87fa0b249e1e02ba385f28da9d77a4aa1 -rc54aa186fda8c0af84325325276245e9d8fcfa26
--- src/ch/FileFilter.h	(.../FileFilter.h)	(revision 22bbc4a87fa0b249e1e02ba385f28da9d77a4aa1)
+++ src/ch/FileFilter.h	(.../FileFilter.h)	(revision c54aa186fda8c0af84325325276245e9d8fcfa26)
@@ -31,6 +31,8 @@
 #define DATE_MODIFIED		1
 #define DATE_LASTACCESSED	2
 
+class TConfig;
+
 class CFileFilter
 {
 public:
@@ -46,6 +48,9 @@
 	CString& GetCombinedExcludeMask(CString& pMask) const;
 	void SetCombinedExcludeMask(const CString& pMask);
 
+    void StoreInConfig(TConfig& rConfig) const;
+    void ReadFromConfig(const TConfig& rConfig);
+
 	template<class Archive>
 	void serialize(Archive& ar, unsigned int /*uiVersion*/)
 	{
@@ -140,6 +145,9 @@
 	CFiltersArray& operator=(const CFiltersArray& rSrc);
 	bool Match(const CFileInfoPtr& spInfo) const;
 
+	void StoreInConfig(TConfig& rConfig, PCTSTR pszNodeName) const;
+	void ReadFromConfig(const TConfig& rConfig, PCTSTR pszNodeName);
+
 	template<class Archive>
 	void serialize(Archive& ar, unsigned int /*uiVersion*/)
 	{
Index: src/ch/MainWnd.cpp
===================================================================
diff -u -r69b48f0b4d7fad78f95854e95fca166014311474 -rc54aa186fda8c0af84325325276245e9d8fcfa26
--- src/ch/MainWnd.cpp	(.../MainWnd.cpp)	(revision 69b48f0b4d7fad78f95854e95fca166014311474)
+++ src/ch/MainWnd.cpp	(.../MainWnd.cpp)	(revision c54aa186fda8c0af84325325276245e9d8fcfa26)
@@ -530,14 +530,13 @@
 	SetTaskPropValue<eTO_AlternateFilenameFormatString_First>(tTaskDefinition.GetConfiguration(), GetResManager().LoadString(IDS_FIRSTCOPY_STRING));
 	SetTaskPropValue<eTO_AlternateFilenameFormatString_AfterFirst>(tTaskDefinition.GetConfiguration(), GetResManager().LoadString(IDS_NEXTCOPY_STRING));
 
+	ffFilters.StoreInConfig(tTaskDefinition.GetConfiguration(), TASK_PROP_NAME_FILTERING);
+
 	// create task with the above definition
 	CTaskPtr spTask = m_tasks.CreateTask();
 
 	spTask->SetTaskDefinition(tTaskDefinition);
 			
-	// set some stuff related with task
-	spTask->SetFilters(&ffFilters);
-
 	m_tasks.Add(spTask);
 
 	// save state of a task
@@ -620,12 +619,12 @@
 		SetTaskPropValue<eTO_AlternateFilenameFormatString_First>(tTaskDefinition.GetConfiguration(), GetResManager().LoadString(IDS_FIRSTCOPY_STRING));
 		SetTaskPropValue<eTO_AlternateFilenameFormatString_AfterFirst>(tTaskDefinition.GetConfiguration(), GetResManager().LoadString(IDS_NEXTCOPY_STRING));
 
+		dlg.m_ccData.m_afFilters.StoreInConfig(tTaskDefinition.GetConfiguration(), TASK_PROP_NAME_FILTERING);
+
 		// new task
 		CTaskPtr spTask = m_tasks.CreateTask();
 		spTask->SetTaskDefinition(tTaskDefinition);
 		
-		spTask->SetFilters(&dlg.m_ccData.m_afFilters);
-		
 		m_tasks.Add(spTask);
 
 		// save
Index: src/ch/TConfig.cpp
===================================================================
diff -u -r69b48f0b4d7fad78f95854e95fca166014311474 -rc54aa186fda8c0af84325325276245e9d8fcfa26
--- src/ch/TConfig.cpp	(.../TConfig.cpp)	(revision 69b48f0b4d7fad78f95854e95fca166014311474)
+++ src/ch/TConfig.cpp	(.../TConfig.cpp)	(revision c54aa186fda8c0af84325325276245e9d8fcfa26)
@@ -470,6 +470,23 @@
 		rSubConfig.m_propTree = optChildren.get();
 }
 
+void TConfig::ExtractMultiSubConfigs(PCTSTR pszSubTreeName, std::vector<TConfig>& rSubConfigs) const
+{
+   TConfig cfg;
+
+   boost::shared_lock<boost::shared_mutex> lock(m_lock);
+
+   boost::optional<const boost::property_tree::wiptree&> optChildren = m_propTree.get_child_optional(pszSubTreeName);
+   if(optChildren.is_initialized())
+   {
+      BOOST_FOREACH(const boost::property_tree::wiptree::value_type& rEntry, optChildren.get())
+      {
+         cfg.m_propTree = rEntry.second;
+         rSubConfigs.push_back(cfg);
+      }
+   }
+}
+
 void TConfig::PutSubConfig(PCTSTR pszSubTreeName, const TConfig& rSubConfig)
 {
 	boost::unique_lock<boost::shared_mutex> lock(m_lock);
@@ -480,6 +497,22 @@
 	m_bModified = true;
 }
 
+void TConfig::AddSubConfig(PCTSTR pszSubTreeName, const TConfig& rSubConfig)
+{
+   boost::unique_lock<boost::shared_mutex> lock(m_lock);
+   boost::shared_lock<boost::shared_mutex> src_lock(rSubConfig.m_lock);
+
+   m_propTree.add_child(pszSubTreeName, rSubConfig.m_propTree);
+
+   m_bModified = true;
+}
+
+void TConfig::DeleteNode(PCTSTR pszNodeName)
+{
+	boost::unique_lock<boost::shared_mutex> lock(m_lock);
+	m_propTree.erase(pszNodeName);
+}
+
 void TConfig::ConnectToNotifier(void (*pfnCallback)(const std::set<CString>&, void*), void* pParam)
 {
 	m_notifier.connect(TConfigNotifier(pfnCallback, pParam));
Index: src/ch/TConfig.h
===================================================================
diff -u -r69b48f0b4d7fad78f95854e95fca166014311474 -rc54aa186fda8c0af84325325276245e9d8fcfa26
--- src/ch/TConfig.h	(.../TConfig.h)	(revision 69b48f0b4d7fad78f95854e95fca166014311474)
+++ src/ch/TConfig.h	(.../TConfig.h)	(revision c54aa186fda8c0af84325325276245e9d8fcfa26)
@@ -111,9 +111,13 @@
 	bool GetValue(PCTSTR pszPropName, chcore::TPathContainer& rvValues) const;
 	void SetValue(PCTSTR pszPropName, const chcore::TPathContainer& rvValues);
 
+	void DeleteNode(PCTSTR pszNodeName);
+
 	// extraction of subtrees
 	void ExtractSubConfig(PCTSTR pszSubTreeName, TConfig& rSubConfig) const;
+    void ExtractMultiSubConfigs(PCTSTR pszSubTreeName, std::vector<TConfig>& rSubConfigs) const;
 	void PutSubConfig(PCTSTR pszSubTreeName, const TConfig& rSubConfig);
+    void AddSubConfig(PCTSTR pszSubTreeName, const TConfig& rSubConfig);
 
 	// property change notification
 	void ConnectToNotifier(void (*pfnCallback)(const std::set<CString>&, void*), void* pParam);
Index: src/ch/TTaskConfigTracker.cpp
===================================================================
diff -u -rb42450e5a25470c399e04cfbb7a368519aa455f2 -rc54aa186fda8c0af84325325276245e9d8fcfa26
--- src/ch/TTaskConfigTracker.cpp	(.../TTaskConfigTracker.cpp)	(revision b42450e5a25470c399e04cfbb7a368519aa455f2)
+++ src/ch/TTaskConfigTracker.cpp	(.../TTaskConfigTracker.cpp)	(revision c54aa186fda8c0af84325325276245e9d8fcfa26)
@@ -232,12 +232,14 @@
 		return eTO_AlternateFilenameFormatString_AfterFirst;
 	else if(strOption == TaskPropData<eTO_AlternateFilenameFormatString_AfterFirst>::GetPropertyName())
 		return eTO_AlternateFilenameFormatString_First;
+	else if(strOption == TASK_PROP_NAME_FILTERING)
+		return eTO_Filters;
 	else
 	{
 		BOOST_ASSERT(false);		// unhandled case
 		THROW(_T("Unhandled case"), 0, 0, 0);
 	}
 
 	// add new elements before this one
-	BOOST_STATIC_ASSERT(eTO_Last == eTO_AlternateFilenameFormatString_AfterFirst + 1);
+	BOOST_STATIC_ASSERT(eTO_Last == eTO_Filters + 1);
 }
Index: src/ch/TTaskConfiguration.h
===================================================================
diff -u -rb42450e5a25470c399e04cfbb7a368519aa455f2 -rc54aa186fda8c0af84325325276245e9d8fcfa26
--- src/ch/TTaskConfiguration.h	(.../TTaskConfiguration.h)	(revision b42450e5a25470c399e04cfbb7a368519aa455f2)
+++ src/ch/TTaskConfiguration.h	(.../TTaskConfiguration.h)	(revision c54aa186fda8c0af84325325276245e9d8fcfa26)
@@ -51,6 +51,8 @@
 	eTO_AlternateFilenameFormatString_First,
 	eTO_AlternateFilenameFormatString_AfterFirst,
 
+	eTO_Filters,
+
 	// add new elements before this one
 	eTO_Last
 };
@@ -109,6 +111,10 @@
 TASK_PROPERTY(eTO_AlternateFilenameFormatString_AfterFirst, CString, _T("Naming.AlternateFilenameFormatAfterFirst"), _T("Copy (%count) of %name"));
 
 /////////////////////////////////////////////////////////////////////////////////////////////
+// other properties names
+#define TASK_PROP_NAME_FILTERING		_T("Filtering")
+
+/////////////////////////////////////////////////////////////////////////////////////////////
 // Properties retrieval
 template<ETaskOptions PropID>
 typename TaskPropData<PropID>::value_type GetTaskPropValue(const TConfig& rConfig)
@@ -128,4 +134,5 @@
 	rConfig.SetPropValue<TaskPropData<PropID> >(rValue);
 }
 
+
 #endif
Index: src/ch/task.cpp
===================================================================
diff -u -r591f291e22d2ece89acb266c8aa0b05c257a407c -rc54aa186fda8c0af84325325276245e9d8fcfa26
--- src/ch/task.cpp	(.../task.cpp)	(revision 591f291e22d2ece89acb266c8aa0b05c257a407c)
+++ src/ch/task.cpp	(.../task.cpp)	(revision c54aa186fda8c0af84325325276245e9d8fcfa26)
@@ -590,8 +590,10 @@
 	m_tTaskDefinition.Load(strPath);
 	m_strFilePath = strPath;
 
+	// update members according to the task definition
 	// make sure to resize paths info array size to match source paths count
 	m_arrSourcePathsInfo.SetCount(m_tTaskDefinition.GetSourcePathCount());
+	m_afFilters.ReadFromConfig(m_tTaskDefinition.GetConfiguration(), TASK_PROP_NAME_FILTERING);
 
 	////////////////////////////////
 	// now rarely changing task progress data
@@ -604,8 +606,6 @@
 
 	CalculateTotalSizeNL();
 
-	ar >> m_afFilters;
-
 	///////////////////////////////////
 	// and often changing data
 	CString strOftenChangingPath = GetRelatedPathNL(ePathType_TaskOftenChangingState);
@@ -665,8 +665,6 @@
 
 		m_arrSourcePathsInfo.Store(ar, 0, true);
 		m_files.Store(ar, 0, false);
-
-		ar << m_afFilters;
 	}
 
 	if(m_bOftenStateModified)
@@ -829,7 +827,7 @@
 
 	pData->m_nPriority = GetTaskPropValue<eTO_ThreadPriority>(m_tTaskDefinition.GetConfiguration());
 	pData->m_pathDstPath = m_tTaskDefinition.GetDestinationPath();
-	pData->m_pafFilters=&m_afFilters;
+	pData->m_pafFilters = &m_afFilters;
 	pData->m_eTaskState = m_eCurrentState;
 	pData->m_stIndex = stCurrentIndex;
 	pData->m_ullProcessedSize = m_localStats.GetProcessedSize();
@@ -897,16 +895,6 @@
 	}
 }
 
-void CTask::SetFilters(const CFiltersArray* pFilters)
-{
-	BOOST_ASSERT(pFilters);
-	if(!pFilters)
-		THROW(_T("Invalid argument"), 0, 0, 0);
-
-	boost::unique_lock<boost::shared_mutex> lock(m_lock);
-	m_afFilters = *pFilters;
-}
-
 bool CTask::CanBegin()
 {
 	bool bRet=true;
@@ -1045,6 +1033,9 @@
 	// delete the content of m_files
 	m_files.Clear();
 
+	// read filtering options
+	m_afFilters.ReadFromConfig(m_tTaskDefinition.GetConfiguration(), TASK_PROP_NAME_FILTERING);
+
 	// enter some data to m_files
 	int iDestDrvNumber = 0;
 	GetDriveData(m_tTaskDefinition.GetDestinationPath(), &iDestDrvNumber, NULL);
Index: src/ch/task.h
===================================================================
diff -u -r3fc1109991e7311d6b1e34ef0b730f9b4e1fd42a -rc54aa186fda8c0af84325325276245e9d8fcfa26
--- src/ch/task.h	(.../task.h)	(revision 3fc1109991e7311d6b1e34ef0b730f9b4e1fd42a)
+++ src/ch/task.h	(.../task.h)	(revision c54aa186fda8c0af84325325276245e9d8fcfa26)
@@ -278,8 +278,6 @@
 	void SetTaskDefinition(const TTaskDefinition& rTaskDefinition);
 	const TTaskDefinition& GetTaskDefinition() const { return m_tTaskDefinition; }
 
-	void SetFilters(const CFiltersArray* pFilters);
-
 	void SetTaskState(ETaskCurrentState eTaskState);
 	ETaskCurrentState GetTaskState() const;
 
@@ -412,9 +410,6 @@
 
 	TBasePathDataContainer m_arrSourcePathsInfo;
 
-	// task settings
-	CFiltersArray m_afFilters;          // filtering settings for files (will be filtered according to the rules inside when searching for files)
-
 	// current task state (derivatives of the task initial information)
 	// changing slowly or only partially
 	CFileInfoArray m_files;             // list of files/directories found during operating on the task input data (filled by search for files)
@@ -427,6 +422,9 @@
 	// task control variables (per-session state)
 	TTaskLocalStats m_localStats;       // local statistics
 
+	// task settings
+	CFiltersArray m_afFilters;          // filtering settings for files (will be filtered according to the rules inside when searching for files)
+
 	bool m_bForce;						// if the continuation of tasks should be independent of max concurrently running task limit
 	bool m_bContinue;					// allows task to continue