// FolderManager.cpp

#include "stdafx.h"
#include "resource.h"
#include "apl_api.h"
#include "dictionary.h"
#include "FolderDlg.h"
#include "DlgListInstances.h"
#include "SSCopyDocsDlg.h"
#include "CompareFoldersDlg.h"
#include "SSDiferencesDlg.h"
#include "SSWhatDlg.h"
#include "Cderr.h"

BOOL CaplFolderManager::m_create_assoc_folder_doc = FALSE;

//****************************************************************************
bool CaplFolderManager::Attach(CaplAPI *api)
{
	m_wait_dialog = 0;
	if(api==0) {Detach();return false;}
	CaplStepManager::Attach(api);

	e_folder=m_data->GetEntityBN(S::apl_folder);
	a_folder_name=m_data->GetAttrDefinition(e_folder,S::name);
	a_folder_descr=m_data->GetAttrDefinition(e_folder,S::description);
	a_folder_parent=m_data->GetAttrDefinition(e_folder,_T("parent"));
	a_folder_content=m_data->GetAttrDefinition(e_folder,S::content);
	CHECK_ZERO_ATTR(a_folder_contexts, m_data->GetAttrDefinition(e_folder,_T("contexts")));
	a_folder_guid=m_data->GetAttrDefinition(e_folder,_T("guid"));
	a_folder_packet_date=m_data->GetAttrDefinition(e_folder,_T("packet_date"));
	a_folder_packet_size=m_data->GetAttrDefinition(e_folder,_T("packet_size"));
	a_folder_packet_body=m_data->GetAttrDefinition(e_folder,_T("packet_body"));

	return true;
}
//****************************************************************************

void CaplFolderManager::Detach()
{
	m_data=0;
	e_folder=0;a_folder_name=0;a_folder_descr=0;a_folder_guid=0;
	a_folder_parent=0;a_folder_content=0; a_folder_contexts=0;
}

//****************************************************************************
bool CaplFolderManager::LoadFolderInfo(CaplInstance *folder, bool bLoadContent)
{
	if(m_data==0) return false;
	if(folder==0) return false;
	if(folder->GetType()==0) return false;
	if(folder->GetId()==0) return false;

	aplExtent ext; ext.Unique=false; ext.Add(folder);

	return LoadFolderInfo(ext, bLoadContent);
}
//****************************************************************************
bool CaplFolderManager::LoadFolderInfo(aplExtent &ext, bool bLoadContent)
{
	if(m_data==0) return false;
	if(e_folder==0) return false;
	if(!m_data->IsConnected()) return false;

	int i;
	int iLoad=0;
	CaplLoadData ld(m_data,DEF_SOURCE);

	for(i=0;i<ext.Size;i++) 
	{
		CaplInstance *folder=ext[i];
		if(folder==0) continue;
		if(folder->GetType()==0) continue;
		if(folder->GetId()==0) continue;
		if(!m_data->IsKindOf(folder,e_folder))continue;
		// ld.AddQuery(0,folder,true); так делать нельзя, так как автоматически грузится содержимое. Если содержимого много - виселица
		
		if(bLoadContent) ld.AddQuery(0,folder,true);
		else ld.AddQuery(0,folder,false);
		
		iLoad++;
		if(iLoad==m_MaxItemsLoad || (i==(ext.Size-1) && iLoad>0))
		{
			iLoad=0;
			if(!bLoadContent)
			{
				ld.AddQuery(_T('d'),0,0,a_folder_name,true);
				ld.AddQuery(_T('d'),0,0,a_folder_descr,true);
				ld.AddQuery(_T('d'),0,0,a_folder_parent,true);
				ld.AddQuery(_T('d'),0,0,a_folder_guid,true);
				//ld.AddQuery(_T('d'),0,0,a_folder_packet_size,true);
				//ld.AddQuery(_T('d'),0,0,a_folder_packet_date,true);
				//ld.AddQuery(_T('d'),0,0,a_folder_packet_body,true,true);
			}
			// ссылка
			if(!ld.LoadEx())
			{
				if(m_data->GetLastAplError()!=APL_SOCK_OPERATION_IN_PROGRESS){
					if(m_api->m_ModeInteractive)AfxMessageBox(S::ErrorLoadDataMgr(),MB_OK|MB_ICONSTOP);
				}
			}
		}
	}
	return true;
}
//****************************************************************************
	
bool CaplFolderManager::GetAllSubFolder(CaplInstance *folder, aplExtent &out_ext, bool recursive, bool bLoadContent)
{
	if(!recursive){out_ext.Clear();}
	if(folder!=0){if(folder->GetType()==0) return false;}
	if(e_folder==0) return false;
	if(m_data==0) return false;
	int size,i;
	bool is_new=false;
	aplExtent ext;
	CaplLoadData ld(m_data,DEF_SOURCE);
	
	CaplAttrValue tst_values[1];
	tst_values[0].value.Set(folder);
	tst_values[0].attr=a_folder_parent;
	
	size=m_data->NET_FindInstancesWithAttrValues(e_folder,1,&tst_values[0],ext,true);

	if(recursive){
		for(i=0;i<size;i++){
			if(out_ext.Find(ext[i])==-1){
				is_new=true;
				out_ext.Add(ext[i]);
				if(!GetAllSubFolder(ext[i],out_ext,recursive)){
					return false;
				}
			}
		}
	}else{
		is_new=true;
		out_ext.Append(ext);
	}
	

	if(m_data->IsConnected() && is_new)
	{
		if(size>0){
			// загружаем атрибуты
			LoadFolderInfo(out_ext, bLoadContent);
/*			
			DIV 22_01_2003
			for(i=0;i<size;i++){
				ld.AddQuery(0,out_ext.GetAt(i));
			}
			ld.AddQuery(_T('d'), 0, 0, a_folder_name, true);
			ld.AddQuery(_T('d'), 0, 0, a_folder_descr, true);
			ld.AddQuery(_T('d'), 0, 0, a_folder_content, true);
			ld.AddQuery(_T('d'), 0, 0, a_folder_parent, true);
			
			ld.LoadEx();
*/
		}
	}
/*	Старый вариант
	if(m_data->IsConnected())
	{
		if(folder==0)
		{

			i=	ld.AddQuery(_T('e'), 0, e_folder,0, true);
			ld.AddQuery(_T('d'), i, 0, a_folder_name, true);
			ld.AddQuery(_T('d'), i, 0, a_folder_descr, true);
			ld.AddQuery(_T('d'), i, 0, a_folder_content, true);
			ld.AddQuery(_T('d'), i, 0, a_folder_parent, true);
			
			ld.LoadEx();
		}
		else
		{
			if(folder->GetAccessmode()>aplRO) return false;
			if(folder->id!=0)
			{
				CaplLoadData ld(m_data,DEF_SOURCE);
				// документ
				i=	ld.AddQuery(_T('b'), folder->id, e_folder,a_folder_parent, true);
					ld.AddQuery(_T('d'), i, 0, a_folder_name, true);
					ld.AddQuery(_T('d'), i, 0, a_folder_descr, true);
					ld.AddQuery(_T('d'), i, 0, a_folder_content, true);
					ld.AddQuery(_T('d'), i, 0, a_folder_parent, true);
				
				if(!ld.LoadEx())
					if(m_api->m_ModeInteractive)AfxMessageBox(S::ErrorLoadDataMgr(),MB_OK|MB_ICONSTOP);
			}
		}
	}
	CaplInstance *inst;
	m_data->GetEntityExtent(e_folder,ext);
	for(i=0;i<ext.Size;i++)
	{
		if(ext[i]->GetType()==0) continue;
		if(ext[i]->GetAccessmode()>aplRO) continue;
		m_data->GetAttr(ext[i],a_folder_parent,inst);
		if(inst==folder) out_ext.Add(ext[i]);
	}
*/
	return true;
}
//****************************************************************************
bool CaplFolderManager::ShowFolderProperties(CaplInstance *folder)
{
	if(m_data==0) return 0;
	if(folder==0) return 0;
	if(folder->GetType()==0) return 0;
	if(e_folder==0) return false;

	m_data->ClearLastQuery();
	LoadFolderInfo(folder);

	CString sName,sDescr;
	CaplInstance *parent;
	m_data->GetAttr(folder,a_folder_name,sName);
	m_data->GetAttr(folder,a_folder_descr,sDescr);
	m_data->GetAttr(folder,a_folder_parent,parent);
	
	CaplSetResourceHandle setres(module_inst);

	CFolderDlg dlg;
	dlg.m_name=sName;
	dlg.m_descr=sDescr;
	dlg.m_folder=folder;
	dlg.m_parent=parent;
//	dlg.m_data=m_data;
	if(folder->GetAccessmode()>aplRW) dlg.bReadOnly=true;

	while(true)
	{
		if(dlg.DoModal()!=IDOK) 
		{
			return 0;
		}
		// Проверка уникальности имени
		CaplAttrValue tst_values[2];
		
		if(parent==0)tst_values[0].value.Clear();
		else tst_values[0].value.Set(parent);
		tst_values[0].attr=a_folder_parent;
		tst_values[1].value.Set((LPCTSTR)(dlg.m_name));
		tst_values[1].attr=a_folder_name;

		if(m_data->NET_TestUniqueAttrValues
			(e_folder,folder,2,&tst_values[0], false)) break;
			 
		AfxMessageBox( APL_T("Такая папка уже есть !"));
	}

	sName=dlg.m_name;
	sDescr=dlg.m_descr;
	m_data->PutAttr(folder,a_folder_name,sName);
	m_data->PutAttr(folder,a_folder_descr,sDescr);
	if(m_AutoSave) m_data->NET_SaveChanges();
	return true;
}
//****************************************************************************
CaplInstance *CaplFolderManager::CreateFolder(CaplInstance *parent, const TCHAR * name, const TCHAR *descr)
{
	if(m_data==0) return 0;
	if(e_folder==0) return 0;
	if(parent!=0){if(parent->GetType()==0) return 0;}
	CString sName=name,sDescr=descr;
	if(sName.IsEmpty())
	{
		if(0==parent)
		{
			if(!m_api->m_data.IsAdmin())
			{
				if(!m_api->m_appr_mgr.CheckPersonRoleByOption(0,APL_NO_T("Роли\\Роль для создания корневых папок"),false))
				{
					AfxMessageBox(APL_T("Вы не обладаете правами для  создания корневой папки!"),MB_ICONSTOP|MB_OK);
					return 0;
				}
			}
		}
		CaplSetResourceHandle setres(module_inst);

		CFolderDlg dlg;
		dlg.m_name=sName;
		dlg.m_descr=sDescr;
		while(true)
		{
			if(dlg.DoModal()!=IDOK) 
			{
				return 0;
			}
			// Проверка уникальности имени
			CaplAttrValue tst_values[2];
			tst_values[0].value.Set(parent);
			tst_values[0].attr=a_folder_parent;
			tst_values[1].value.Set((LPCTSTR)(dlg.m_name));
			tst_values[1].attr=a_folder_name;

			if(m_data->NET_TestUniqueAttrValues
				(e_folder,0,2,&tst_values[0], false)) break;
				 
			AfxMessageBox( APL_T("Такая папка уже есть !"));
		}
		sName=dlg.m_name;
		sDescr=dlg.m_descr;
	}
	else
	{
		aplExtent res;
		CaplAttrValue tst_values[2];
		tst_values[0].value.Set(parent);
		tst_values[0].attr=a_folder_parent;
		tst_values[1].value.Set((LPCTSTR)(name));
		tst_values[1].attr=a_folder_name;
		
		if(m_data->NET_FindInstancesWithAttrValues(e_folder, 2, &tst_values[0], res, false)>0)
			return res[0];

	}
	CaplInstance *folder=m_data->CreateInstance(e_folder);
	m_data->PutAttr(folder,a_folder_parent,parent);
	m_data->PutAttr(folder,a_folder_name,sName);
	m_data->PutAttr(folder,a_folder_descr,sDescr);
	CaplAggr aggr;
	m_data->PutAttr(folder,a_folder_content,aggr);
	if(m_AutoSave) 
		m_data->NET_SaveChanges();
	
	if(true==m_AutoUsurpire)
	{
		CaplEntity*	et	=NULL;
		aplExtent	aet;
		CString		csAccPat;

		et=e_folder;

		if(NULL!=folder)
			if(aplOWN==folder->GetAccessmode())
				aet.Add(folder);
		if(TRUE==m_api->m_options_mgr.GetDefPatern(et,csAccPat))
			apidata.NET_SetAccessFromPattern(&aet,csAccPat);
	}
	
	return folder;
}
//****************************************************************************
bool GetAllSubFolder(CaplFolderManager *fold_mgr, CaplInstance *inst, aplExtent &ext)
{
	if(ext.Find(inst)>=0) return true;
	if(inst->GetAccessmode()>aplOWN) return false;
	ext.Add(inst);

	aplExtent ext0;
	CaplAttrValue tst_values[1];
	tst_values[0].value.Set(inst);
	tst_values[0].attr=fold_mgr->a_folder_parent;
	fold_mgr->m_data->NET_FindInstancesWithAttrValues(fold_mgr->e_folder,1,&tst_values[0],ext0,true);
	for(int i=0;i<ext0.Size;i++)
	{
		if(!GetAllSubFolder(fold_mgr,ext0[i],ext)) return false;
	}
	return true;
}

bool CaplFolderManager::DeleteFolder(CaplInstance *folder)
{
	if(m_data==0) return false;
	if(folder==0) return false;
	if(folder->GetType()==0) return false;
	if(e_folder==0) return false;
	if(folder->GetAccessmode()>aplOWN) 
	{
		aplErrorMessage(S::NoAccessRight());
		return false;
	}
	// Поиск входящих
	int i;
	aplExtent ext;
	if(!::GetAllSubFolder(this,folder,ext))
	{
		AfxMessageBox( APL_T("Недостаточно прав для удаления одной из вложенных папок!"),MB_OK|MB_ICONSTOP);
		return false;
	}
	for(i=0;i<ext.Size;i++){
		//удалим ассоциации со справочником
		m_api->m_classifier_mgr.DeleteClassifierAssociation(ext[i],0);
		
		m_data->DeleteInstance(ext[i]);
	}

	if(m_AutoSave) m_data->NET_SaveChanges();
	return true;
}
//****************************************************************************

bool CaplFolderManager::GetFolderContents(CaplInstance *folder,aplExtent &out_ext, bool bWithAttrs/* = true*/)
{	
	out_ext.Clear();
	if(e_folder==0) return false;
	if(m_data==0) return false;
	if(folder==0) return false;
	if(folder->GetType()==0) return false;
	if(folder->GetId()==0) return false;
	if(folder->GetAccessmode()>aplRO) return false;

	if(m_api->m_data.IsKindOf(folder,e_folder))
	{
		CaplLoadData ld(m_data,DEF_SOURCE);
		ld.AddQuery(0,folder);
		ld.AddQuery(_T('d'),0,0,a_folder_content,true);
		if(!ld.LoadEx())
		{
			if(m_data->GetLastAplError()!=APL_SOCK_OPERATION_IN_PROGRESS){
				if(m_api->m_ModeInteractive)AfxMessageBox(S::ErrorLoadDataMgr(),MB_OK|MB_ICONSTOP);
			}
			return false;
		}
		m_data->GetAttr(folder,a_folder_content,out_ext);
	}
	else if(m_api->m_data.IsKindOf(folder,m_api->m_classifier_mgr.e_apl_classifier_level))
	{
		m_api->m_classifier_mgr.GetSubItems(folder,out_ext);
	}

	if (bWithAttrs)
	{
		LoadExtentInfo(out_ext);
	}

	if(m_data->IsConnected())
	{

		// Обновление содержимого папки после перечитвывния

		int i;
		CaplInstance *inst;

		for(i=0;i<out_ext.GetSize();i++)
		{
			inst=out_ext[i];
			if(inst!=0)	{if(inst->GetType()!=0) {if(inst->GetAccessmode()<=aplRO)continue;}}
			out_ext.Remove(i); i--;
		}
	}
	if(m_api->m_data.IsKindOf(folder,e_folder))
	{
		if(CaplFolderManager::m_create_assoc_folder_doc==TRUE)
		{
			aplExtent tmp, tmp_rel;
			m_api->m_doc_mgr.FindAssociatedDocuments(folder, tmp,tmp_rel);
			out_ext.Append(tmp);
		}
	}

	return true;
}
//****************************************************************************
bool CaplFolderManager::FindFolderContained(CaplInstance *item, aplExtent &folders)
{
	folders.Clear();
	if(m_data==0) return false;
	if(item==0) return false;
	if(item->GetType()==0) return false;
	if(e_folder==0) return false;
	if(item->GetAccessmode()>aplRO) 
	{
		aplErrorMessage(S::NoAccessRight());
		return false;
	}
	
	CaplAttrValue tst_val[1];
	tst_val[0].attr = a_folder_content;
	tst_val[0].value.Set(item);
	m_data->NET_FindInstancesWithAttrValues2(e_folder,1,tst_val,folders,false,false,0,aplSBMiddle,false,DEF_SOURCE);
	LoadExtentInfo(folders);
	return true;
}

//****************************************************************************
bool CaplFolderManager::FindInFolder(CaplInstance *folder, CaplInstance *item)
{
	if(m_data==0) return false;
	if(item==0) return false;
	if(item->GetType()==0) return false;
	if(folder==0) return false;
	if(e_folder==0) return false;
	if(folder->GetAccessmode()>aplRO) 
	{
		aplErrorMessage(S::NoAccessRight());
		return false;
	}
	int i;
	CaplInstance *inst;
	CaplAggr aggr;
	m_data->GetAttr(folder,a_folder_content,aggr);
	
	bool found=false;
	for(i=0;i<aggr.GetSize();i++)
	{
		aggr.GetByIndex(i,inst);
		if(inst==item) {found=true;break;}
	}
	return found;
}
bool CaplFolderManager::AddToFolder(CaplInstance *folder, aplExtent &items)
{
	if (folder==NULL)
		return false;
	if(m_data==0) return false;
	if(items.GetSize()==0) return true;
	if(e_folder==0) return false;
	if(folder->GetAccessmode()>aplRW) 
	{
		aplErrorMessage(S::NoAccessRight());
		return false;
	}
	int i,j;
	CaplInstance *inst,*item;
	CaplAggr aggr;
	m_data->GetAttr(folder,a_folder_content,aggr);
	
	bool found=false;
	// Чистка
	for(j=0;j<items.GetSize();j++){
		item=items[j];
		if(item==0) return false;
		if(item->GetType()==0) return false;
		
		found=false;
		for(i=0;i<aggr.GetSize();i++)
		{
			aggr.GetByIndex(i,inst);
			if(inst==item) found=true;
			else if(inst==0) {aggr.Remove(i);i--;}
		}
		if(!found) aggr.Add(item);
	}
	m_data->PutAttr(folder,a_folder_content,aggr);
	if(m_AutoSave) m_data->NET_SaveChanges();
	return true;
}

bool CaplFolderManager::AddToFolder(CaplInstance *folder,CaplInstance *item)
{
	if (folder==NULL)
		return false;
	if(m_data==0) return false;
	if(item==0) return false;
	if(item->GetType()==0) return false;
	if(e_folder==0) return false;
	if(folder->GetAccessmode()>aplRW) 
	{
		aplErrorMessage(S::NoAccessRight());
		return false;
	}

	if(0!=folder->GetId())
	{
		CaplLoadData ld(m_data,DEF_SOURCE);
		ld.AddQuery(0,folder);
		ld.LoadEx();
	}

	int i;
	CaplInstance *inst; 
	CaplAggr aggr;
	m_data->GetAttr(folder,a_folder_content,aggr);
	
	bool found=false;
	// Чистка и проверка
	for(i=0;i<aggr.GetSize();i++)
	{
		aggr.GetByIndex(i,inst);
		if(inst==item) found=true; 
		else if(0==inst) {aggr.Remove(i);i--;}
	}
	if(!found) aggr.Add(item);
	m_data->PutAttr(folder,a_folder_content,aggr);
	if(m_AutoSave) m_data->NET_SaveChanges();

	return true;
}
//****************************************************************************

bool CaplFolderManager::RemoveFromFolder(CaplInstance *folder, aplExtent &items)
{
	if(m_data==0) return false;
	if(items.GetSize()==0) return true;
	if(folder==0) return false;
	if(folder->GetType()==0) return false;
	if(e_folder==0) return false;
	LoadFolderInfo(folder);
	if(folder->GetAccessmode()>aplRW) 
	{
		aplErrorMessage(S::NoAccessRight());
		return false;
	}
	int i,j;
	CaplInstance *inst,*item;
	CaplAggr aggr;
	m_data->GetAttr(folder,a_folder_content,aggr);
	
	for(j=0;j<items.GetSize();j++){
		item=items[j];
		if(item==0) return false;
		if(item->GetType()==0) return false;
		for(i=0;i<aggr.GetSize();i++)
		{
			aggr.GetByIndex(i,inst);
			if((inst==item)||(inst==0)) {aggr.Remove(i);i--;}
		}
	}
	m_data->PutAttr(folder,a_folder_content,aggr);
	if(m_AutoSave) m_data->NET_SaveChanges();
	return true;
}
//****************************************************************************

bool CaplFolderManager::RemoveFromFolder(CaplInstance *folder,CaplInstance *item)
{
	if(m_data==0) return false;
	if(item==0) return false;
	if(item->GetType()==0) return false;
	if(folder==0) return false;
	if(folder->GetType()==0) return false;
	if(e_folder==0) return false;
	LoadFolderInfo(folder);
	if(folder->GetAccessmode()>aplRW) 
	{
		aplErrorMessage(S::NoAccessRight());
		return false;
	}
	int i;
	CaplInstance *inst; 
	CaplAggr aggr;
	m_data->GetAttr(folder,a_folder_content,aggr);
	
	for(i=0;i<aggr.GetSize();i++)
	{
		aggr.GetByIndex(i,inst);
		if((inst==item)||(inst==0)) {aggr.Remove(i);i--;}
	}
	m_data->PutAttr(folder,a_folder_content,aggr);
	if(m_AutoSave) m_data->NET_SaveChanges();
	return true;
}
//****************************************************************************
bool CaplFolderManager::MoveFolder(CaplInstance *folder, CaplInstance *parent, CString *message /*= NULL*/)
{
	if(m_data==0) return false;
	if(folder==0) return false;
	if(folder->GetType()==0) return false;
	if(parent!=0)
	{
		if(parent->GetType()==0) return false;
	}
	if(e_folder==0) return false;

	LoadFolderInfo(folder);
	LoadFolderInfo(parent);

	CaplInstance *old_parent;
	m_data->GetAttr(folder,a_folder_parent,old_parent);
	if(old_parent==parent) return false;

	if(0!=old_parent)
	{
		if(old_parent->GetAccessmode()>aplRW) // по просьбе ЦКБА
		{
			if(message)
				*message = _T("Нет прав доступа на изменение исходной родительской папки!");
			else
				aplErrorMessage(_T("Нет прав доступа на изменение\nисходной родительской папки!\n"),old_parent);
			return false;
		}
	}

	if(folder->GetAccessmode()>aplRW)
	{
		if(message)
			*message = S::NoAccessRight();
		else
			aplErrorMessage(S::NoAccessRight());
		return false;
	}
	if(parent!=0)
		if(parent->GetAccessmode()>aplRW)
		{
			if(message)
				*message = S::NoAccessRight();
			else
				aplErrorMessage(S::NoAccessRight());
			return false;
		}

	// Проверка уникальности имени
	CString name;
	m_data->GetAttr(folder,a_folder_name,name);
	CaplAttrValue tst_values[2];
	tst_values[0].value.Set(parent);
	tst_values[0].attr=a_folder_parent;
	tst_values[1].value.Set(name);
	tst_values[1].attr=a_folder_name;

	if(!m_data->NET_TestUniqueAttrValues
		(e_folder,0,2,&tst_values[0], false))
	{
		CString buf = APL_T("Папка с таким наименованием уже есть в данной папке!");
		if(message)
			*message = buf;
		else
			AfxMessageBox(buf);
		return false;
	}		 

	m_data->PutAttr(folder,a_folder_parent,parent);
	if(m_AutoSave) m_data->NET_SaveChanges();
	return true;
}

bool CaplFolderManager::MakeTable(CaplInstance *folder,bool is_hide_move_button,bool *redraw,bool show_assoc_doc,bool is_context_menu_categ)
{
	if(m_data==0)return false;
	if(folder==0)return false;
	if(redraw!=0){*redraw=false;}
	
	aplExtent ext,ext_fld;
	// получаем содержимое
	GetFolderContents(folder,ext);
	aplExtent tmp, tmp_rel;
	
	//сортировка, вернее отсортировка ненужных объектов
	tmp.Append(ext); ext.Clear();
	for(int i= 0; i<tmp.GetSize(); i++)
		if(!m_api->m_data.IsKindOf(tmp[i], m_api->m_message_mgr.e_message))
			ext.Add(tmp[i]); 
	
	// добавляем документы, которые были ассоциированы с папкой ассоциаторами
	m_api->m_doc_mgr.FindAssociatedDocuments(folder, tmp,tmp_rel);
	ext.Append(tmp);
	// А вот подпапки не отображаем
	//GetAllSubFolder(folder,ext_fld);
	//ext.Append(ext_fld);
	m_api->LoadExtentInfo(ext);
	
	int res=0;

	CaplSetResourceHandle setres(module_inst);
	CDlgListInstances dlg;
	dlg.m_base_inst=folder;
	dlg.m_content=&ext;
	dlg.m_api=m_api;
	dlg.m_is_context_menu_categ = is_context_menu_categ;
	dlg.m_is_hide_move_button=is_hide_move_button && !show_assoc_doc;
	dlg.m_delete_message= APL_T("Вы действительно хотите удалить выделенные объекты из папки?");
	dlg.m_ListObjects.m_create_assoc_doc=show_assoc_doc;
	if(folder->GetAccessmode()<=aplRW){
		dlg.m_can_delete=true;
	}
	res=dlg.DoModal();
	if(dlg.m_changed){
		m_data->PutAttr(folder,a_folder_content,ext);
		if(m_AutoSave) m_data->NET_SaveChanges();
		if(redraw!=0){*redraw=true;}
	}
	return true;
}
/*=======================Source Safe==============================================================*/

bool CaplFolderManager::CopyDocOnDisk(CaplInstance *folder, CString &defpath, int mode)
{
	if(folder==0 || m_folders_map==0 || m_api==0 || m_data==0) return false;
	if(!m_data->IsConnected()) return false;
	if(folder->GetAccessmode()>aplRO)
	{
		AfxMessageBox(S::NoAccessRight());
		return false;
	}
	//++ Колесников 26.12.2011 по согласованию с Нахимовичем для КВЗ при выгрузке документоы прячем сообщения
	bool bOldErr = true;
	bool bOldHide = m_data->GetHideMode();

	m_data->SetErrorMessageMode(false);
	m_data->SetHideMode(true);

	CaplSetResourceHandle setres(module_inst);
	CSSCopyDocsDlg dlg;
	dlg.m_sFolder = defpath;
	if(mode==APL_CHECKOUT_DOCS) dlg.m_title= APL_T("Взять документы на редактирование");
	else if(mode==APL_PRINT_DOCS) dlg.m_title= APL_T("Настройка печати документов из папки");
	if(mode==APL_COPY_DOCS) dlg.m_show_check = true;
	if(dlg.DoModal()!=IDOK)
	{
		m_data->SetErrorMessageMode(bOldErr);
		m_data->SetHideMode(bOldHide);
		return false;
	}

	CreateFolderOndisk(dlg.m_sFolder);
	bool old = m_api->m_ModeInteractive;
	m_api->m_ModeInteractive = false;
	TCHAR dir[1024];
	GetCurrentDirectory(1024,dir);
	long wdlg = aplStartWaitDlg( APL_T("Идет обработка данных..."));
	defpath = dlg.m_sFolder;
	aplExtent docs;

	if(m_api->m_data.IsKindOf(folder,e_folder)) GetFolderContents(folder,docs);
	else if(m_api->m_data.IsKindOf(folder,m_api->m_classifier_mgr.e_apl_classifier_level)) // ЯАИ добавлено 18.06.2025
	{
		GetFolderContents(folder,docs); 
	}
	else if(0!=m_api->m_wf_mgr)
	{
		if(m_api->m_data.IsKindOfBN(folder,_T("apl_task")) || m_api->m_data.IsKindOfBN(folder,_T("apl_process")))
		{
			m_api->m_wf_mgr->GetWorkObjects(folder,docs);
		}
	}

	CString path,id;

	for(int i=0; i<docs.Size;i++)
	{
		CaplInstance *doc_i= docs[i];
		if(0==doc_i) continue;
		if(doc_i->GetAccessmode()>aplRO)
		if(! ( m_data->IsKindOf(doc_i,m_api->m_doc_mgr.e_doc) 
			|| m_data->IsKindOf(doc_i,m_api->m_doc_mgr.e_apl_doc_rev)
			|| m_data->IsKindOf(doc_i,m_api->m_doc_mgr.e_apl_stored_document)
			)) continue;
		
		CaplInstance *doc_rev=0;
		
		if(m_data->IsKindOf(doc_i,m_api->m_doc_mgr.e_doc))
		{
			if(mode==APL_CHECKOUT_DOCS)
			{
				CaplInstance *lock=0;
				m_data->GetAttr(doc_i,m_api->m_doc_mgr.a_apl_doc_lock,lock);
				if(lock!=0) continue;
			}
			m_data->GetAttr(doc_i,m_api->m_doc_mgr.a_apl_doc_active,doc_rev);
		}
		else if(m_data->IsKindOf(doc_i,m_api->m_doc_mgr.e_apl_doc_rev)) 
			doc_rev=doc_i;
		else if(m_data->IsKindOf(doc_i,m_api->m_doc_mgr.e_apl_stored_document)) 
			doc_rev=doc_i;
		else continue;

		if(doc_rev==0)continue;

		if(m_data->IsKindOf(doc_i,m_api->m_doc_mgr.e_apl_stored_document)) 
		{
			path = dlg.m_sFolder;
			m_data->GetAttr(doc_i,m_api->m_doc_mgr.a_apl_stored_document_file_name,id);
			int k=id.ReverseFind(_T('\\'));
			if(k>0) {CString buf=id.Right(id.GetLength()-k-1); id=buf;}
			path+=id;
			m_api->m_doc_mgr.LogDocAccess(doc_i,_T("CopyDocOnDisk"),path);
			m_data->NET_LoadBlob(doc_i,m_api->m_doc_mgr.a_apl_stored_document_source,path);
			continue;
		}

		path = dlg.m_sFolder; id=_T("");
		path += CCompareFoldersDlg::GetDocFileName(doc_i,m_api);

		CaplInstance *doc;
		m_api->m_doc_mgr.LogDocAccess(doc_rev,_T("CopyDocOnDisk"),path);
		m_data->GetAttr(doc_rev,m_api->m_doc_mgr.a_apl_doc_rev_access_form,doc);
		if(!doc)
		{
			if(dlg.m_rec_docs) RecursiveCopyDocs(doc_i,dlg.m_sFolder, mode, (dlg.m_bcheck==TRUE));
			continue;
		}
		if(mode!=APL_CHECKOUT_DOCS)
		{
			CFileStatus fs;
			int crc_1=0, crc_2 = 0;
			if(CFile::GetStatus(path,fs))
			{
				if(fs.m_attribute&CFile::readOnly) fs.m_attribute&=~CFile::readOnly;
				CFile::SetStatus(path,fs);
				crc_2 = GetFileCRC32(path);
			}
			m_data->GetAttrBN(doc_rev,_T("crc"),crc_1);
			if(crc_2!=crc_1 || crc_2==0)
			{
				CString source = _T("");
				if(m_data->IsKindOf(doc,m_api->m_doc_mgr.e_apl_stored_document)) source = _T("source");
				else if(m_data->IsKindOf(doc,m_api->m_doc_mgr.e_apl_assigned_document)) source = _T("location_path");
				BOOL rs=0;
				if(mode!=APL_CHECKOUT_DOCS)
					while(!m_data->NET_LoadBlobBN(doc,source,path))
					{
						//if (!sDistrCode.CompareNoCase(_T("KVZ")))
						if(m_api->m_options_mgr.CheckInstallCode(_T("KVZ")))
						{
							rs=IDIGNORE;
							break;
						}
						TRACE( APL_T("Не могу создать файл: ")+path);
						rs = MessageBox(NULL, APL_T("Не могу создать файл ")+path, APL_T("Ошибка."),MB_ABORTRETRYIGNORE|MB_ICONERROR);
						if(rs==IDIGNORE) break;
						if(rs==IDABORT)
						{
							m_api->m_ModeInteractive = old;
							SetCurrentDirectory(dir);
							m_data->SetErrorMessageMode(bOldErr);
							m_data->SetHideMode(bOldHide);
							return true;
						}
					}
				if(rs==IDIGNORE) continue;
				else
				{
					if(dlg.m_bcheck)
					{
						CFile::GetStatus(path,fs);
						fs.m_attribute |=CFile::readOnly;
						CFile::SetStatus(path,fs);
					}
					TRACE( APL_T("Сохранен документ ")+id+_T("\n"));
					if(mode==APL_PRINT_DOCS)
					{
						CString tmp_dir; tmp_dir.GetEnvironmentVariable(_T("temp"));
						ShellExecute(NULL,_T("print"),path,NULL,tmp_dir,SW_HIDE);
					}
					if(dlg.m_rec_docs) RecursiveCopyDocs(doc_i,dlg.m_sFolder, mode, (dlg.m_bcheck==TRUE));
				}
			}
			else
			{
				CFileStatus fs;
				if(CFile::GetStatus(path, fs))
				{
					if((dlg.m_bcheck==TRUE) && (!(fs.m_attribute&CFile::readOnly))) fs.m_attribute|=CFile::readOnly;
					else if((dlg.m_bcheck==FALSE) && fs.m_attribute&CFile::readOnly) fs.m_attribute&=~CFile::readOnly;
					CFile::SetStatus(path,fs);
				}
				if(mode==APL_PRINT_DOCS)
				{
					CString tmp_dir; tmp_dir.GetEnvironmentVariable(_T("temp"));
					ShellExecute(NULL,_T("print"),path,NULL,tmp_dir,SW_HIDE);
				}
				if(dlg.m_rec_docs) RecursiveCopyDocs(doc_i,dlg.m_sFolder, mode, (dlg.m_bcheck==TRUE));
			}
		}
		else 
		{
			m_api->m_doc_mgr.CheckOutEx(doc_rev,path,false,false);
			if(dlg.m_rec_docs) RecursiveCopyDocs(doc_i,dlg.m_sFolder, mode, (dlg.m_bcheck==TRUE));
		}
	}

	if(dlg.m_recursive)
	{
		aplExtent subfolders;
		if(m_api->m_data.IsKindOf(folder,e_folder))  GetAllSubFolder(folder,subfolders);
		else if(m_api->m_data.IsKindOf(folder,m_api->m_classifier_mgr.e_apl_classifier_level))
		{
			aplExtent ext0;
			m_api->m_classifier_mgr.GetSubItems(folder,ext0);
			for(int i=0; i<ext0.GetSize(); i++) 
			{
				CaplInstance *inst0=ext0[i];
				if(m_api->m_data.IsKindOf(inst0, e_folder)) subfolders.Add(inst0);
			}

			m_api->m_classifier_mgr.LoadSubClassifierLevels(folder,ext0);
			for(int i=0; i<ext0.GetSize(); i++) 
			{
				subfolders.Add(ext0[i]);
			}
		}
		else if(m_api->m_data.IsKindOf(folder,m_api->m_classifier_mgr.e_apl_classifier_system))
		{
			aplExtent ext0;
			m_api->m_classifier_mgr.LoadSubClassifierLevels(folder,ext0);
			for(int i=0; i<ext0.GetSize(); i++) 
			{
				subfolders.Add(ext0[i]);
			}
		}

		if(subfolders.GetSize()>0)	CopyDocOnDisk(subfolders, dlg.m_sFolder, dlg.m_recursive==TRUE, mode, dlg.m_rec_docs==TRUE, (dlg.m_bcheck==TRUE));
	}


	SetCurrentDirectory(dir);
	aplEndWaitDlg(wdlg);
	if(mode==APL_COPY_DOCS) AfxMessageBox( APL_T("Сохранение документов завершено."));
	else AfxMessageBox( APL_T("Операция завершена."));
	m_api->m_ModeInteractive = old;
	m_data->SetErrorMessageMode(bOldErr);
	m_data->SetHideMode(bOldHide);
	return true;
}
//****************************************************************************
bool CaplFolderManager::CopyDocOnDisk(aplExtent &folder, CString path, bool recursive, int mode, bool rec_doc, bool set_RO)
{
	if(folder.Size<=0) return false;
	if(m_folders_map==0 || m_api==0 || m_data==0) return false;
	if(!m_data->IsConnected()) return false;

	//++ Колесников 26.12.2011 по согласованию с Нахимовичем для КВЗ при выгрузке документоы прячем сообщения
	CString sDistrCode;
	m_api->m_options_mgr.GetOptionValueBN( APL_NO_T("Код установки"), sDistrCode, _T(""));

	bool bOldErr = true;
	bool bOldHide = m_data->GetHideMode();

	m_data->SetErrorMessageMode(false);
	m_data->SetHideMode(true);


	for(int f=0; f<folder.Size;f++)
	{
		CaplInstance *folder_f=folder[f];
		if(folder_f==0) continue;
		if(folder_f->GetAccessmode()>aplRO) continue;
		CString tpath = path;
		CString name;

		if(m_api->m_data.IsKindOf(folder_f,e_folder)) m_data->GetAttr(folder_f,a_folder_name,name);
		else if(m_api->m_data.IsKindOf(folder_f,m_api->m_classifier_mgr.e_apl_classifier_level))
		{
			/*m_data->GetAttr(folder_f,m_api->m_classifier_mgr.a_apl_classifier_level_id,name);
			CString sTmp;
			 m_data->GetAttr(folder_f,m_api->m_classifier_mgr.a_apl_classifier_level_name,sTmp);
			 if(sTmp!=_T("")) { name+=_T(" - "); name+=sTmp;}*/
			m_api->m_classifier_mgr.GetItemName(folder_f,name);
		}
		else continue;

		CaplFile::NormalizeFileName(name);

		aplExtent docs;
		GetFolderContents(folder_f,docs);

		tpath+=name;
		if((tpath.GetLength() + 4) > MAX_PATH)
		{
			if(tpath.Left(4)!=_T("\\\\?\\"))	tpath.Insert(0,_T("\\\\?\\"));  // Обработка очень длинных путей
		}
		if(!CaplFile::CreateFolder(tpath))
		{
			CString sBuf=_T("Ошибка создания папки:");
			sBuf+=_T("\n\n'");
			sBuf+=tpath;
			sBuf+=_T("'\n\n");
			sBuf+=_T("Содержимое игнорируется!");

			AfxMessageBox(sBuf,MB_OK|MB_ICONSTOP);
			continue;
		}
		tpath+=_T("\\");
		m_folders_map->SetAt(folder_f->GetId(),tpath);
		for(int i=0; i<docs.Size;i++)
		{
			if(m_data->IsKindOf(docs[i],m_api->m_doc_mgr.e_doc))
			if(docs[i]!=0)
			{
				if(docs[i]->GetAccessmode()>aplRO) continue;
				if(mode==APL_CHECKOUT_DOCS)
				{
					CaplInstance *lock=0;
					m_data->GetAttr(docs[i],m_api->m_doc_mgr.a_apl_doc_lock,lock);
					if(lock!=0) continue;
				}
				CString id=_T(""), tmp = tpath;
				CaplInstance *active;
				m_data->GetAttrBN(docs[i],_T("active"),active);
				m_api->m_doc_mgr.LogDocAccess(active,_T("CopyDocOnDisk"),tpath);
				CaplInstance *doc;
				m_data->GetAttr(active,m_api->m_doc_mgr.a_apl_doc_rev_access_form,doc);
				tmp+=CCompareFoldersDlg::GetDocFileName(docs[i],m_api);

				if((tmp.GetLength() + 4) > MAX_PATH)
				{
					if(tmp.Left(4)!=_T("\\\\?\\"))	tmp.Insert(0,_T("\\\\?\\"));  // Обработка очень длинных путей
				}

				if(mode!=APL_CHECKOUT_DOCS)
				{
					int crc_1=0, crc_2 = 0;
					m_data->GetAttrBN(active,_T("crc"),crc_1);

					
					/* ЯАИ не работает с путями > MAX_PATH
					CFileStatus fs;
					if(CFile::GetStatus(tmp,fs))
					{
						if(fs.m_attribute&CFile::readOnly) fs.m_attribute&=~CFile::readOnly;
						CFile::SetStatus(tmp,fs);
						crc_2 = GetFileCRC32(tmp);
					}*/

					bool bFileExist=false;
					DWORD dwFileAttributes=GetFileAttributes(tmp);
					if (INVALID_FILE_ATTRIBUTES!=dwFileAttributes)
					{
						bFileExist=true;
						crc_2 = GetFileCRC32(tmp);
					}

					CString source = _T("");
					if(m_data->IsKindOf(doc,m_api->m_doc_mgr.e_apl_stored_document)) source = _T("source");
					else if(m_data->IsKindOf(doc,m_api->m_doc_mgr.e_apl_assigned_document)) source = _T("location_path");
					if(crc_2!=crc_1 || crc_2==0)
					{
						if(bFileExist)
						{
							::SetFileAttributes(tmp, FILE_ATTRIBUTE_NORMAL);
							::DeleteFile(tmp);
						}
						BOOL rs=0;
						while(!m_data->NET_LoadBlobBN(doc,source,tmp))
						{
							//if (!sDistrCode.CompareNoCase(_T("KVZ")))
							if(m_api->m_options_mgr.CheckInstallCode(_T("KVZ")))
							{
								rs=IDIGNORE;
								break;
							}

							rs = MessageBox(NULL, APL_T("Не могу создать файл ")+tmp, APL_T("Ошибка."),MB_ABORTRETRYIGNORE|MB_ICONERROR);
							if(rs==IDIGNORE) break;
							if(rs==IDABORT) 
							{
								m_data->SetErrorMessageMode(bOldErr);
								m_data->SetHideMode(bOldHide);
								return true;
							}
						}
						if(rs==IDIGNORE) continue;
						else
						{
							//CFile::GetStatus(tmp,fs);
							//if(set_RO && (!(fs.m_attribute&CFile::readOnly))) fs.m_attribute|=CFile::readOnly;
							//CFile::SetStatus(tmp,fs);
							DWORD dwFileAttributes=GetFileAttributes(tmp);
							if (INVALID_FILE_ATTRIBUTES!=dwFileAttributes) ::SetFileAttributes(tmp, FILE_ATTRIBUTE_NORMAL);

							TRACE( APL_T("Сохранен документ ")+id+_T("\n"));
							if(mode==APL_PRINT_DOCS)
							{
								CString tmp_dir; tmp_dir.GetEnvironmentVariable(_T("temp"));
								ShellExecute(NULL,_T("print"),tmp,NULL,tmp_dir,SW_HIDE);
							}
							if(rec_doc) RecursiveCopyDocs(docs[i],tpath, mode, set_RO);
						}
					}
					else
					{
						CFileStatus fs;
						if(CFile::GetStatus(tmp, fs))
						{
							if(set_RO && (!(fs.m_attribute&CFile::readOnly))) fs.m_attribute|=CFile::readOnly;
							else if(!set_RO && (fs.m_attribute&CFile::readOnly)) fs.m_attribute&=~CFile::readOnly;
							CFile::SetStatus(tmp,fs);
						}
						if(mode==APL_PRINT_DOCS)
						{
							CString tmp_dir; tmp_dir.GetEnvironmentVariable(_T("temp"));
							ShellExecute(NULL,_T("print"),tmp,NULL,tmp_dir,SW_HIDE);
						}
						if(rec_doc) RecursiveCopyDocs(docs[i],tpath, mode, set_RO);
					}
				}
				else
				{
					m_api->m_doc_mgr.CheckOutEx(active,path,false,false);
					if(rec_doc) RecursiveCopyDocs(docs[i],path, mode, set_RO);
					TRACE( APL_T("Документ ")+id+ APL_T(" взят на редактирование\n"));
				}
			}
			else { docs.Remove(i);i--;}
		}
		if(recursive)
		{
			// ЯАИ добавил обработку для справочников
			//aplExtent fol;
			//GetAllSubFolder(folder[f],fol);
			//CopyDocOnDisk(fol,tpath,true,mode, rec_doc, set_RO);

			aplExtent subfolders;
			if(m_api->m_data.IsKindOf(folder_f,e_folder))  GetAllSubFolder(folder_f,subfolders);
			else if(m_api->m_data.IsKindOf(folder_f,m_api->m_classifier_mgr.e_apl_classifier_level))
			{
				aplExtent ext0;
				m_api->m_classifier_mgr.GetSubItems(folder_f,ext0);
				for(int i=0; i<ext0.GetSize(); i++) 
				{
					CaplInstance *inst0=ext0[i];
					if(m_api->m_data.IsKindOf(inst0, e_folder)) subfolders.Add(inst0);
				}

				m_api->m_classifier_mgr.LoadSubClassifierLevels(folder_f,ext0);
				for(int i=0; i<ext0.GetSize(); i++)  subfolders.Add(ext0[i]);
			}
			if(subfolders.GetSize()>0)	CopyDocOnDisk(subfolders,tpath,true,mode, rec_doc, set_RO);

		}
	}
	m_data->SetErrorMessageMode(bOldErr);
	m_data->SetHideMode(bOldHide);
	return true;
}
//****************************************************************************
bool CaplFolderManager::AddDocFromDisk(CaplInstance *folder, CString &defpath)
{
	if(folder==0 || m_folders_map==0 || m_api==0 || m_data==0) return false;
	if(!m_data->IsConnected()) return false;
	if(folder->GetAccessmode()>aplRW)
	{
		AfxMessageBox(S::NoAccessRight());
		return false;
	}
	TCHAR dir[1024];
	long filelist_size=1024*1024;
	TCHAR *filelist=new TCHAR[filelist_size];
	memset(filelist,0,filelist_size);
	GetCurrentDirectory(1024,dir);
//	CFileDialog dlg(true,_T(""),defpath+_T("*.*"),OFN_HIDEREADONLY|OFN_ALLOWMULTISELECT,APL_T("Все файлы|*.*|"));
	CFileDialog dlg(true,_T(""),_T(""),OFN_HIDEREADONLY|OFN_ALLOWMULTISELECT, APL_T("Все файлы|*.*|"));
//	delete dlg.m_ofn.lpstrFile;
	dlg.m_ofn.lpstrFile=filelist;
	dlg.m_ofn.nMaxFile=filelist_size;
	if(dlg.DoModal()==IDOK)
	{
		POSITION pos = dlg.GetStartPosition();
		while(pos)
		{
			CString path = dlg.GetNextPathName(pos);
			CString id, name;
			int p = path.ReverseFind(_T('.'));
			if(p<0) p=path.GetLength()-path.ReverseFind(_T('\\'))-1;
			else p = path.ReverseFind(_T('.')) - path.ReverseFind(_T('\\'))-1;
			id = path.Mid(path.ReverseFind(_T('\\'))+1,p);
			name = path.Mid(path.ReverseFind(_T('\\'))+1,path.GetLength()-path.ReverseFind(_T('\\'))-1);
			CaplInstance *rel=0;
			CaplInstance *inst = m_api->m_doc_mgr.FindDocById(id);
			if(inst!=NULL)
			{
				if(inst->GetAccessmode()>=aplRO) continue;
				bool lock = true;
				CaplInstance *locker=0;
				m_data->GetAttr(inst,m_api->m_doc_mgr.a_apl_doc_lock,locker);
				if(locker!=0)
				{
					CaplInstance *pers=m_api->m_appr_mgr.GetCurrentPerson();
					aplExtent ext;
					CString name=_T("");
					if(pers!=0) m_api->m_appr_mgr.GetPersonName(pers,name);
					if(pers) name+=_T(" (");
					name+= m_api->m_data.GetNameCurrUser();
					if(pers) name+=_T(")");
					
					CString username;
					m_data->GetAttr(locker,m_api->m_doc_mgr.a_apl_doc_rev_user,username);
					if(username!=name) lock = false;
				}
				else lock = false;
				CSSWhatDlg wdlg;
				wdlg.m_api = m_api;
				wdlg.m_doc_db = inst;
				wdlg.m_lock = !lock;
				wdlg.m_disc_doc = path;
				BOOL res = 0;
				res = wdlg.DoModal();
				if(res==IDCANCEL){
					if(filelist!=0)delete[] filelist;
					return true;
				}
				if(wdlg.m_what==1)
				{
					m_api->m_doc_mgr.CheckInEx(inst,path,(wdlg.m_acver==TRUE),false, true);
						TRACE( APL_T("Создана новая версия документа\n"));
				}
				else if(wdlg.m_what==2)
				{
					CaplInstance *doc = m_api->m_doc_mgr.CreateDocument(id,path,_T(""),0,name,true);
					if(doc!=0) 
					{
						AddToFolder(folder,doc);
						TRACE( APL_T("Создан новый документ\n"));
					}
					else
						TRACE( APL_T("Ошибка создания нового документа или отмена создания нового документа\n"));
				}
				else 
					TRACE( APL_T("Документ ")+path+ APL_T(" пропущен\n"));
			}
			else
				rel = m_api->m_doc_mgr.CreateDocument(id,name,_T(""),0,path,true);
			if(rel!=0) AddToFolder(folder,rel);
			TRACE( APL_T("Документ ")+path+ APL_T(" был добавлен в БД\n"));
		}
		AfxMessageBox( APL_T("Операция завершена."));
		SetCurrentDirectory(dir);
		if(filelist!=0)delete[] filelist;
		return true;
	}else{
		DWORD err=CommDlgExtendedError();
		if(err==FNERR_BUFFERTOOSMALL){
			AfxMessageBox( APL_T("Буфер не может вместить все имена выделенных файлов!"));
		}
	}
	if(filelist!=0)delete[] filelist;
	SetCurrentDirectory(dir);
	return false;
}
//****************************************************************************
bool CaplFolderManager::AddDocFromPath(CaplInstance *folder, CString &defpath)
{
	if(folder==0 || m_folders_map==0 || m_api==0 || m_data==0) return false;
	if(!m_data->IsConnected()) return false;
	if(folder->GetAccessmode()>aplRW)
	{
		AfxMessageBox(S::NoAccessRight());
		return false;
	}
	CaplSetResourceHandle setres(module_inst);
	TCHAR dir[1024]=_T("");
	GetCurrentDirectory(1024,dir);
	CSSCopyDocsDlg dlg;
	dlg.m_title =  APL_T("Добавить документы из папки");
	dlg.m_sFolder = defpath;
	dlg.m_add_or_copy = false;
	dlg.m_show_check = true;
	dlg.m_check_title =  APL_T("Снимать атрибут \"Только для чтения\"");
	if(dlg.DoModal()==IDOK)
	{
		m_wait_dialog = aplStartWaitDlg( APL_T("Идет обработка данных..."));

		defpath = dlg.m_sFolder;

		CFileFind ff;
		BOOL bFind = ff.FindFile(dlg.m_sFolder+_T("*.*"));
		CString t = _T("");
		t+=dir;
		while(bFind)
		{
			bFind = ff.FindNextFile();
			CString str = ff.GetFileName();
			if(ff.IsDirectory() || ff.IsHidden() || ff.IsSystem()) continue;
			CString name = ff.GetFilePath();
			CString id;
			int p = str.ReverseFind(_T('.'));
			if(p<0) p=str.GetLength();
			id = str.Left(p);
			CaplInstance *inst = m_api->m_doc_mgr.FindDocById(id);
			if(inst==0)
			{
				CaplInstance *doc = m_api->m_doc_mgr.CreateDocument(id,str,_T(""),0,name,true);
				if(doc) AddToFolder(folder,doc);
				TRACE( APL_T("Документ ")+name+ APL_T(" был добавлен в БД\n"));
			}
			else
			{
				bool locker = true;
				if(inst->GetAccessmode()<aplRO)
				{
					CaplInstance *lock;
					m_data->GetAttr(inst,m_api->m_doc_mgr.a_apl_doc_lock, lock);
					if(lock==0) locker=false;
					else
					{
						CaplInstance *pers=m_api->m_appr_mgr.GetCurrentPerson();
						aplExtent ext;
						CString name=_T("");
						if(pers!=0) m_api->m_appr_mgr.GetPersonName(pers,name);
						if(pers) name+=_T(" (");
						name+= m_api->m_data.GetNameCurrUser();
						if(pers) name+=_T(")");

						CString username;
						m_data->GetAttr(lock,m_api->m_doc_mgr.a_apl_doc_rev_user,username);
						if(username!=name) locker = false;
					}
				}
				if(inst->GetAccessmode()<aplRO)
				{
					TRACE( APL_T("Документ с таким обозначением (")+id+ APL_T(") уже существует в БД\n"));
					int crc_doc=0, crc_file=0;
					CaplInstance *active;
					m_data->GetAttr(inst,m_api->m_doc_mgr.a_apl_doc_active,active);
					ASSERT(active);
					m_data->GetAttr(active,m_api->m_doc_mgr.a_apl_doc_rev_crc, crc_doc);
					crc_file = ::GetFileCRC32(name);
					if(crc_file!=crc_doc)
					{
						//Показать диалог
						if(m_wait_dialog!=0) aplEndWaitDlg(m_wait_dialog);
						CSSWhatDlg wdlg;
						wdlg.m_api = m_api;
						wdlg.m_doc_db = inst;
						wdlg.m_lock = false;
						wdlg.m_disc_doc = name;
						wdlg.m_what = 1;
						CSSWhatDlg::s_acver = TRUE;
						CSSWhatDlg::s_what = 1;
						if(wdlg.DoModal()==IDCANCEL) 
						{
							SetCurrentDirectory(dir);
							return true;
						}
						if(wdlg.m_what==1)
						{
							if(locker)
							{
								m_api->m_doc_mgr.CheckInEx(inst,str,(wdlg.m_acver==TRUE),false, true);
							}
							else
							{
								CaplInstance *ver = m_api->m_doc_mgr.CreateDocumentRevision(inst, name, true, (wdlg.m_acver==TRUE));
							}
							TRACE( APL_T("Создана новая версия документа\n"));
						}
						else if(wdlg.m_what==2)
						{
							CaplInstance *doc = m_api->m_doc_mgr.CreateDocument(id,str,_T(""),0,name,true);
							if(doc!=0) 
							{
								AddToFolder(folder,doc);
								TRACE( APL_T("Создан новый документ\n"));
							}
							else
								TRACE( APL_T("Ошибка создания нового документа или отмена создания нового документа\n"));
							CFileStatus fs;
							CFile::GetStatus(name,fs);
							if(fs.m_attribute&CFile::readOnly && dlg.m_bcheck)
							{
								fs.m_attribute&=~CFile::readOnly;
								CFile::SetStatus(name,fs);
							}
						}
						else 
							TRACE( APL_T("Документ ")+name+ APL_T(" пропущен\n"));
						if(m_wait_dialog!=0) m_wait_dialog = aplStartWaitDlg( APL_T("Идет обработка данных..."));
					}
					else 
					{
						TRACE( APL_T("Документ ")+name+ APL_T(" пропущен из-за совпадения файлов\n"));
						AddToFolder(folder,inst);
					}
				}
				else
					TRACE( APL_T("Документ ")+id+ APL_T(" пропущен. Нет доступа\n"));
			}
			CFileStatus fs;
			CFile::GetStatus(name,fs);
			if(fs.m_attribute&CFile::readOnly && dlg.m_bcheck)
			{
				fs.m_attribute&=~CFile::readOnly;
				CFile::SetStatus(name, fs);
			}
		}
		if(dlg.m_recursive)
		{
			bFind = ff.FindFile(dlg.m_sFolder+_T("\\*"));
			while(bFind)
			{
				bFind = ff.FindNextFile();
				if(ff.IsDots()) continue;
				if(!ff.IsDirectory()) continue;
				CString str = ff.GetFileName();
				if(str.IsEmpty()) continue;
				CaplInstance *inst = FindFolderByName(str.GetBuffer(0), folder);
				if(inst==0)
				{
					inst = CreateFolder(folder,str,_T(""));
					m_folders_map->SetAt(inst->GetId(),dlg.m_sFolder+str+_T("\\"));
					TRACE( APL_T("Папка ")+defpath+str+ APL_T(" была добавлена в БД\n"));
				}
				else
					TRACE( APL_T("Папка с таким именем уже существует в данной директории\n"));
				if(AddDocPath(inst,dlg.m_sFolder+str+_T("\\"),true,dlg.m_bcheck)==false)
				{
					if(m_wait_dialog!=0) aplEndWaitDlg(m_wait_dialog);
					m_wait_dialog = 0;
					return true;
				}
			}
		}
		if(m_wait_dialog!=0) aplEndWaitDlg(m_wait_dialog);
		m_wait_dialog = 0;
		AfxMessageBox( APL_T("Операция завершена."));
		SetCurrentDirectory(dir);
		return true;
	}
	SetCurrentDirectory(dir);
	return false;
}
//****************************************************************************
bool CaplFolderManager::AddDocPath(CaplInstance *folder, CString path, bool recursive, BOOL UnSetRO)
{
	if(folder==0 || m_folders_map==0 || m_api==0 || m_data==0) return false;
	if(!m_data->IsConnected()) return false;
	CFileFind ff;
	char dir[1024];
	BOOL bFind = ff.FindFile(path+_T("*.*"));
	CString t = _T("");
	t+=dir;
	while(bFind)
	{
		bFind = ff.FindNextFile();
		if(ff.IsDirectory() || ff.IsHidden() || ff.IsSystem()) continue;
		CString str = ff.GetFileName();
		CString name = ff.GetFilePath();
		CString id;
		int p = str.ReverseFind(_T('.'));
		if(p<0) p=str.GetLength();
		id = str.Left(p);
		CaplInstance *inst = m_api->m_doc_mgr.FindDocById(id);
		if(inst==0)
		{
			CaplInstance *doc = m_api->m_doc_mgr.CreateDocument(id,str,_T(""),0,name,true);
			AddToFolder(folder,doc);
			TRACE( APL_T("Документ ")+name+ APL_T(" был добавлен в БД\n"));
		}
		else
		{
			bool locker = true;
			if(inst->GetAccessmode()<aplRO)
			{
				CaplInstance *lock;
				m_data->GetAttr(inst,m_api->m_doc_mgr.a_apl_doc_lock, lock);
				if(lock==0) locker=false;
				else
				{
					CaplInstance *pers=m_api->m_appr_mgr.GetCurrentPerson();
					aplExtent ext;
					CString name=_T("");
					if(pers!=0) m_api->m_appr_mgr.GetPersonName(pers,name);
					if(pers) name+=_T(" (");
					name+= m_api->m_data.GetNameCurrUser();
					if(pers) name+=_T(")");

					CString username;
					m_data->GetAttr(lock,m_api->m_doc_mgr.a_apl_doc_rev_user,username);
					if(username!=name) locker = false;
				}
			}
			if(inst->GetAccessmode()<aplRO)
			{
				TRACE( APL_T("Документ с таким обозначением (")+id+ APL_T(") уже существует в БД\n"));
				int crc_doc=0, crc_file=0;
				CaplInstance *active;
				m_data->GetAttr(inst,m_api->m_doc_mgr.a_apl_doc_active,active);
				ASSERT(active);
				m_data->GetAttr(active,m_api->m_doc_mgr.a_apl_doc_rev_crc, crc_doc);
				crc_file = ::GetFileCRC32(name);
				if(crc_file!=crc_doc)
				{
					//Показать диалог
					if(m_wait_dialog!=0) aplEndWaitDlg(m_wait_dialog);
					CSSWhatDlg wdlg;
					wdlg.m_api = m_api;
					wdlg.m_doc_db = inst;
					wdlg.m_lock = false;
					wdlg.m_what = 1;
					CSSWhatDlg::s_acver = TRUE;
					wdlg.m_disc_doc = name;
					if(wdlg.DoModal()==IDCANCEL) return false;
					if(wdlg.m_what==1)
					{
						CaplInstance *ver = m_api->m_doc_mgr.CreateDocumentRevision(inst, str, true, (wdlg.m_acver==TRUE));
						if(ver)
							TRACE( APL_T("Создана новая версия документа\n"));
						else
							TRACE( APL_T("Ошибка создания новой версии документа\n"));
					}
					else if(wdlg.m_what==2)
					{
						CaplInstance *doc = m_api->m_doc_mgr.CreateDocument(id,str,_T(""),0,name,true);
						if(doc!=0) 
						{
							AddToFolder(folder,doc);
							TRACE( APL_T("Создан новый документ\n"));
						}
						else
							TRACE( APL_T("Ошибка создания нового документа или отмена создания нового документа\n"));
					}
					else 
						TRACE( APL_T("Документ ")+id+ APL_T(" пропущен\n"));
					if(m_wait_dialog!=0) m_wait_dialog = aplStartWaitDlg( APL_T("Идет обработка данных..."));
				}
				else 
				{
					TRACE( APL_T("Документ ")+id+ APL_T(" пропущен из-за совпадения файлов\n"));
					AddToFolder(folder,inst);
				}
				CFileStatus fs;
				CFile::GetStatus(name,fs);
				if(fs.m_attribute&CFile::readOnly && UnSetRO)
				{
					fs.m_attribute&=~CFile::readOnly;
					CFile::SetStatus(name, fs);
				}
			}
			else 
				TRACE( APL_T("Документ ")+id+ APL_T(" пропущен из-за совпадения файлов"));
		}
		CFileStatus fs;
		CFile::GetStatus(name,fs);
		if(fs.m_attribute&CFile::readOnly && UnSetRO)
		{
			fs.m_attribute&=~CFile::readOnly;
			CFile::SetStatus(name, fs);
		}
	}
	if(recursive)
	{
		bFind = ff.FindFile(path+_T("\\*"));
		while(bFind)
		{
			bFind = ff.FindNextFile();
			if(ff.IsDots()) continue;
			if(!ff.IsDirectory()) continue;
			CString str = ff.GetFileName();
			if(str.IsEmpty()) continue;
			CaplInstance *inst = FindFolderByName(str.GetBuffer(0), folder);
			if(inst==0)
			{
				inst = CreateFolder(folder,str,_T(""));
				m_folders_map->SetAt(inst->GetId(),path+str+_T("\\"));
				TRACE( APL_T("Папка ")+path+str+ APL_T(" была добавлена в БД\n"));
			}
			else
				TRACE( APL_T("Папка с таким именем уже существует в данной директории\n"));
			AddDocPath(inst,path+str+_T("\\"),true);
		}
	}
	return true;
}
//****************************************************************************
bool CaplFolderManager::CheckInAllDocs(CaplInstance *folder, CString &defpath)
{
	if(folder==0 || m_folders_map==0 || m_api==0 || m_data==0) return false;
	if(!m_data->IsConnected()) return false;
	CaplSetResourceHandle setres(module_inst);;
	TCHAR dir[1024]=_T("");
	GetCurrentDirectory(1024,dir);
	CSSCopyDocsDlg dlg;
	dlg.m_add_or_copy = true;
	dlg.m_title =  APL_T("Завершить редактирование");
	dlg.m_sFolder = defpath;
	dlg.m_show_check = true;
	dlg.m_check_title =  APL_T("Делать версии документов активными");
	int res = dlg.DoModal();

	if(res!=IDOK) 
	{
		SetCurrentDirectory(dir);
		return false;
	}

		m_wait_dialog = aplStartWaitDlg( APL_T("Идет обработка данных..."));

		bool oldmode = m_api->m_ModeInteractive;
		m_api->m_ModeInteractive = false;
		aplExtent ext;
		CString name=_T(""), error=_T("");

		CaplInstance *pers=m_api->m_appr_mgr.GetCurrentPerson();
		if(pers!=0) m_api->m_appr_mgr.GetPersonName(pers,name);
		if(pers) name+=_T(" (");
		name+= m_api->m_data.GetNameCurrUser();
		if(pers) name+=_T(")");

		CString query;
		query = _T("SELECT\nExt_doc\nFROM\nExt_doc{apl_document(.locker->apl_document_revision(.user = \"")
			+name+_T("\"))}END_SELECT");
		m_api->m_data.NET_QueryEditParse(query, false, &error);
		m_api->m_data.NET_QueryExecute(ext, APL_T("Пожалуйста, подождите..."));
		m_api->m_doc_mgr.LoadExtentInfo(ext);
		aplExtent cont;
		GetFolderContents(folder,cont);
		while(cont.Size>0 && ext.Size>0)
		{
			int ind = ext.Find(cont[0]);
			if(ind>=0) 
			{
				CString path;
				CaplInstance *active;
				m_data->GetAttrBN(ext[ind],_T("locker"),active);
				if(active) m_data->GetAttrBN(active,_T("edit_path"),path);
				if(m_wait_dialog!=0) aplEndWaitDlg(m_wait_dialog);
				if(m_api->m_doc_mgr.CheckInEx(ext[ind],path,dlg.m_bcheck==TRUE,false,dlg.m_rec_docs==TRUE))
				{
					CFileStatus fs;
					if(CFile::GetStatus(path, fs))
					{
						if(!(fs.m_attribute&CFile::readOnly))
						{
							fs.m_attribute |=CFile::readOnly;
							CFile::SetStatus(path,fs);
						}
					}
					TRACE( APL_T("Завершено редактирование документа ")+path+_T("\n"));
				}
				if(m_wait_dialog!=0) m_wait_dialog = aplStartWaitDlg( APL_T("Идет обработка данных..."));
				ext.Remove(ind);
			}
			cont.Remove(0);
		}
		if(dlg.m_recursive)
		{
			aplExtent fol;
			GetAllSubFolder(folder, fol);
			CheckInAllDocs(fol,ext,dlg.m_recursive==TRUE, dlg.m_rec_docs==TRUE, dlg.m_bcheck==TRUE);
		}
	m_api->m_ModeInteractive = oldmode;
// 				m_api->m_ModeInteractive = TRUE;
	if(m_wait_dialog!=0) aplEndWaitDlg(m_wait_dialog);
	m_wait_dialog = 0;
	AfxMessageBox( APL_T("Операция завершена."));
	SetCurrentDirectory(dir);
	return true;
}
//****************************************************************************
bool CaplFolderManager::CheckInAllDocs(aplExtent &folder, aplExtent &checkoutdocs, bool recursive /* = true */, bool rec_doc, bool activate)
{
	if(m_folders_map==0 || m_api==0 || m_data==0) return false;
	if(!m_data->IsConnected()) return false;
	if(folder.Size==0) return false;
	for(int i=0; i<folder.Size; i++)
	{
		if(folder[i]->GetAccessmode()>aplRO) continue;
		CString name=_T(""), error=_T("");
		aplExtent cont;
		GetFolderContents(folder[i],cont);
		while(cont.Size>0 && checkoutdocs.Size>0)
		{
			int ind = checkoutdocs.Find(cont[0]);
			if(ind>=0) 
			{
				CString path;
				CaplInstance *active;
				m_data->GetAttrBN(checkoutdocs[ind],_T("locker"),active);
				if(active) m_data->GetAttrBN(active,_T("edit_path"),path);
				if(m_wait_dialog!=0) aplEndWaitDlg(m_wait_dialog);
				if(m_api->m_doc_mgr.CheckInEx(checkoutdocs.GetAt(ind),path, activate, false, rec_doc))
				{
					CFileStatus fs;
					if(CFile::GetStatus(path, fs))
					{
						if(!(fs.m_attribute&CFile::readOnly)) 
						{
							fs.m_attribute |=CFile::readOnly;
							CFile::SetStatus(path,fs);
						}
					}
					TRACE( APL_T("Завершено редактирование документа ")+path+"\n");
				}
				if(m_wait_dialog!=0) m_wait_dialog = aplStartWaitDlg( APL_T("Идет обработка данных..."));
				checkoutdocs.Remove(ind);
			}
			cont.Remove(0);
		}
		if(recursive)
		{
			aplExtent fol;
			GetAllSubFolder(folder[i], fol);
			CheckInAllDocs(fol,checkoutdocs,recursive, rec_doc, activate);
		}
	}
	return true;
}
//****************************************************************************
bool CaplFolderManager::UndoCheckOut(CaplInstance *folder)
{ 
	if(folder==0 || m_folders_map==0 || m_api==0 || m_data==0) return false;
	if(!m_data->IsConnected()) return false;
	if(folder->GetAccessmode()>aplRO)
	{
		AfxMessageBox(S::NoAccessRight());
		return false;
	}
	bool rec = MessageBox(NULL, APL_T("Обрабатывать вложенные папки"),_T(""),MB_YESNO|MB_ICONQUESTION)==IDYES;

	long wdlg = aplStartWaitDlg( APL_T("Идет обработка данных..."));

	aplExtent ext;
	CString name=_T(""), error=_T("");

	CaplInstance *pers=m_api->m_appr_mgr.GetCurrentPerson();
	if(pers!=0) m_api->m_appr_mgr.GetPersonName(pers,name);
	if(pers) name+=_T(" (");
	name+= m_api->m_data.GetNameCurrUser();
	if(pers) name+=_T(")");
	
	CString query;
	query = _T("SELECT\nExt_doc\nFROM\nExt_doc{apl_document(.locker->apl_document_revision(.user = \"")
		+name+_T("\"))}END_SELECT");
	m_api->m_data.NET_QueryEditParse(query, false, &error);
	m_api->m_data.NET_QueryExecute(ext, APL_T("Пожалуйста, подождите..."));
	m_api->m_doc_mgr.LoadExtentInfo(ext);

	aplExtent cont;
	GetFolderContents(folder,cont);
	while(cont.Size>0 && ext.Size>0)
	{
		int ind = ext.Find(cont[0]);
		if(ind>=0) 
		{
			CString path;
			m_api->m_doc_mgr.GetFullFileName(ext[ind],path);
			CaplInstance *active;
			m_data->GetAttrBN(ext[ind],_T("locker"),active);
			if(active==0)
			{
				ext.Remove(ind);
				continue;
			}
			m_data->GetAttrBN(active,_T("edit_path"),path);
			if(m_api->m_doc_mgr.UndoCheckOutEx(ext[ind],true))
				TRACE( APL_T("Отменено редактирование документа ")+path+_T("\n"));
			ext.Remove(ind);
		}
		cont.Remove(0);
	}
	if(rec)
	{
		aplExtent fol;
		GetAllSubFolder(folder, fol);
		UndoCheckOut(fol,ext);
	}
	aplEndWaitDlg(wdlg);
	AfxMessageBox( APL_T("Операция завершена."));

	return true;
}
//****************************************************************************
bool CaplFolderManager::UndoCheckOut(aplExtent &folder, aplExtent &cdocs)
{
	for(int i=0; i<folder.Size; i++)
	{
		CString name=_T(""), error=_T("");
		aplExtent cont;
		GetFolderContents(folder[i],cont);
		while(cont.Size>0 && cdocs.Size>0)
		{
			int ind = cdocs.Find(cont[0]);
			if(ind>=0) 
			{
				CString path;
				CaplInstance *active;
				m_data->GetAttrBN(cdocs[ind],_T("locker"),active);
				if(active==0) 
				{
					cdocs.Remove(ind);
					continue;
				}
				m_data->GetAttrBN(active,_T("edit_path"),path);
				if(m_api->m_doc_mgr.UndoCheckOutEx(cdocs[ind],true))
					TRACE( APL_T("Отменено редактирование документа ")+path+_T("\n"));
				cdocs.Remove(ind);
			}
			cont.Remove(0);
		}
		aplExtent fol;
		GetAllSubFolder(folder[i], fol);
		UndoCheckOut(fol,cdocs);
	}
	return true;
}
//****************************************************************************
bool CaplFolderManager::GetAllSubDocuments(CaplInstance *folder, aplExtent &docs, bool recursive)
{
	if(folder==0 || m_folders_map==0 || m_api==0 || m_data==0) return false;
	if(!m_data->IsConnected()) return false;
	if(folder->GetAccessmode()>=aplRW) return false;
	docs.Add(folder);
	aplExtent ext;
	GetFolderContents(folder, ext);
	for(int i=0; i<ext.Size;i++)
		if(m_data->IsKindOf(ext[i],m_api->m_doc_mgr.e_doc))
		{
			if(ext[i]->GetAccessmode()>=aplRW) continue;
			docs.Add(ext[i]);
		}
	ext.Clear();
	GetAllSubFolder(folder,ext);
	for(int f=0;f<ext.Size;f++)
		GetAllSubDocuments(ext[f],docs);
	return true;
}
//****************************************************************************
bool CaplFolderManager::CompareFolders(CaplInstance *folder, CString &defpath)
{
	if(folder==0 || m_folders_map==0 || m_api==0 || m_data==0) return false;
	if(!m_data->IsConnected()) return false;
	if(folder->GetAccessmode()>aplRW)
	{
		AfxMessageBox(S::NoAccessRight());
		return false;
	}
	CaplSetResourceHandle setres(module_inst);
	TCHAR dir[1024]=_T("");
	GetCurrentDirectory(1024,dir);
	CSSDiferencesDlg dlg;
	dlg.m_disk_path = defpath;
	dlg.m_folder = folder;
	dlg.m_api = m_api;
	m_data->GetAttr(folder,a_folder_name,dlg.m_psm_name);
	if(dlg.DoModal()==IDOK)
	{
		CCompareFoldersDlg cdlg;
		cdlg.m_folder_map = m_folders_map;
		cdlg.m_psm_show = dlg.m_psm_show;
		cdlg.m_dif_show = dlg.m_dif_show;
		cdlg.m_disk_show = dlg.m_diskc_show;
		cdlg.m_folder_rec = (dlg.m_folder_recursive==TRUE);
		cdlg.m_compare_show = dlg.m_compare_only;
		cdlg.m_doc_rec = (dlg.m_doc_recursive==TRUE);
		cdlg.m_api = m_api;
		cdlg.m_path = dlg.m_disk_path;
		cdlg.m_folder = dlg.m_folder;
		cdlg.DoModal();
	}
	SetCurrentDirectory(dir);
	return true;
}
//****************************************************************************
bool CaplFolderManager::RecursiveCopyDocs(CaplInstance *doc, CString path, int mode /* = false */, bool set_RO)
{
	if(doc==0) return false;
	if(m_folders_map==0 || m_api==0 || m_data==0) return false;
	if(!m_data->IsConnected()) return false;
	if(!m_data->IsKindOf(doc,m_api->m_doc_mgr.e_doc)) return false;
	if(doc->GetAccessmode()>aplRO) return false;
	aplExtent ext, rel;
	m_api->m_doc_mgr.FindAssociatedDocuments(doc,ext,rel);
	for(int i=0; i<ext.Size;i++)
	{
		CString id, name;
		m_data->GetAttr(ext[i],m_api->m_doc_mgr.a_doc_id,id);
		m_data->GetAttr(ext[i],m_api->m_doc_mgr.a_doc_name,name);
		
		CaplInstance *active;
		m_data->GetAttr(ext[i],m_api->m_doc_mgr.a_apl_doc_active,active);
		m_data->GetAttr(active,m_api->m_doc_mgr.a_apl_doc_rev_access_form,active);
		CString fname;
		m_data->GetAttrBN(active,S::file_name,fname);
		int pos = fname.ReverseFind(_T('.'));
		if(pos>-1) fname = fname.Right(fname.GetLength()-pos);
		else fname = _T("");

		if(mode == APL_CHECKOUT_DOCS)
		{
			m_api->m_doc_mgr.CheckOutEx(ext[i],path+id+fname);
			RecursiveCopyDocs(ext[i], path, mode, set_RO);
			continue;
		}
		CaplAttr *source = 0;
		m_api->m_doc_mgr.LogDocAccess(active,_T("RecursiveCopyDocs"),path);
		if(m_data->IsKindOf(active,m_api->m_doc_mgr.e_apl_stored_document)) source = m_api->m_doc_mgr.a_apl_stored_document_source;
		else if(m_data->IsKindOf(active,m_api->m_doc_mgr.e_apl_assigned_document)) source = m_api->m_doc_mgr.a_apl_assigned_document_location_path;
		if(!m_data->NET_LoadBlob(active,source,path+id+fname))
		{
			MessageBox(NULL, APL_T("Не могу создать файл!"), APL_T("Ошибка"),MB_OK|MB_ICONERROR);
			return false;
		}
		else
		{
			TRACE( APL_T("Сохранен документ ")+path+id+fname+_T("\n"));
			if(set_RO)
			{
				CFileStatus fs;
				CFile::GetStatus(path+id+fname, fs);
				if(!(fs.m_attribute&CFile::readOnly))
				{
					fs.m_attribute|=CFile::readOnly;
					CFile::SetStatus(path+id+fname,fs);
				}
			}
			else
			{
				CFileStatus fs;
				CFile::GetStatus(path+id+fname, fs);
				if(fs.m_attribute&CFile::readOnly)
				{
					fs.m_attribute&=~CFile::readOnly;
					CFile::SetStatus(path+id+fname,fs);
				}
			}
			if(mode==APL_PRINT_DOCS)
			{
				CString tmp_dir; tmp_dir.GetEnvironmentVariable(_T("temp"));
				ShellExecute(NULL,_T("print"),path+id+fname,NULL,tmp_dir,SW_HIDE);
			}
		}
		RecursiveCopyDocs(ext[i], path, mode, set_RO);
	}
	return true;
}
//****************************************************************************
CaplInstance *CaplFolderManager::FindFolderByName(const TCHAR *name, CaplInstance *parent)
{
	if(m_api==0) return NULL;
	if(m_data==0) return NULL;
	if(!m_data->IsConnected()) return NULL;

	CaplAttrValue tst_value;
	aplExtent ext;
	tst_value.value.Set(name);
	tst_value.attr=a_folder_name;
	m_data->NET_FindInstancesWithAttrValues(e_folder,1,&tst_value,ext,false);
	LoadFolderInfo(ext);
	for(int i=0; i<ext.Size;i++)
	{
		CaplInstance *p;
		m_data->GetAttr(ext[i],a_folder_parent,p);
		if(p==parent) return ext[i];
	}
	return NULL;
}
//****************************************************************************
CaplInstance *CaplFolderManager::FindFolderByGUID(const TCHAR *s_guid)
{
	if(m_api==0) return NULL;
	if(m_data==0) return NULL;
	if(!m_data->IsConnected()) return NULL;

	CaplAttrValue tst_value;
	aplExtent ext;
	tst_value.value.Set(s_guid);
	tst_value.attr=a_folder_guid;
	m_data->NET_FindInstancesWithAttrValues(e_folder,1,&tst_value,ext,false);

	if(0==ext.GetSize()) return 0;
	LoadFolderInfo(ext);
	return ext[0];
}

//****************************************************************************
bool CaplFolderManager::CreateFolderOndisk(CString folder)
{
	TCHAR cdir[1024]=_T("");
	GetCurrentDirectory(1024,cdir);
	CString path = folder, crpath = _T("");
	if(path.Right(1)==_T("\\")) path = path.Left(path.GetLength()-1);
	else
		path = path.Left(path.ReverseFind(_T('\\')));
	while(!SetCurrentDirectory(path))
	{
		crpath += path.Right(path.GetLength()-path.ReverseFind(_T('\\')));
		int ind = path.ReverseFind(_T('\\'));
		if(ind>0) path=path.Left(ind);
		else return false;
	}
	CString tmp=_T("");
	while(crpath>_T(""))
	{
		tmp = path+crpath.Right(crpath.GetLength()- crpath.ReverseFind(_T('\\')));
		crpath = crpath.Left(crpath.ReverseFind(_T('\\')));
		if(!CreateDirectory(tmp, NULL)) return false;
		path = tmp;
	}
	SetCurrentDirectory(cdir);
	return true;
}
