// aplPacketMgr.cpp: implementation of the CaplPacketMgr class.
//
//////////////////////////////////////////////////////////////////////

#include "stdafx.h"
#include "aplPacketMgr.h"
#include "PacketDlg.h"
#include <aplPacket.h>

#ifdef _DEBUG
#undef THIS_FILE
static char THIS_FILE[]=__FILE__;
#define new DEBUG_NEW
#endif

//////////////////////////////////////////////////////////////////////
// Construction/Destruction
//////////////////////////////////////////////////////////////////////
#define apl_incorrect	APL_T("Некорректный")
#define apl_unpacked	APL_T("Распакован")
#define apl_correct		APL_T("Проверен")
#define apl_registred	APL_T("Зарегистрирован")
#define apl_sended		APL_T("Передан")
#define apl_confirmed	APL_T("Подтвержден")

CaplPacketMgr::CaplPacketMgr()
{
	Detach();

	m_OutPacketStates.RemoveAll();
	m_InPacketStates.RemoveAll();
	
	m_InPacketStates.Add(APL_T("Зарегистрирован"));
	m_InPacketStates.Add(APL_T("Проверен"));
	m_InPacketStates.Add(APL_T("Распакован"));
	m_InPacketStates.Add(APL_T("Некорректный"));
	
	m_OutPacketStates.Add(APL_T("Зарегистрирован"));
	m_OutPacketStates.Add(APL_T("Проверен"));
	m_OutPacketStates.Add(APL_T("Передан"));
	m_OutPacketStates.Add(APL_T("Подтвержден"));
	m_OutPacketStates.Add(APL_T("Некорректный"));
}

CaplPacketMgr::~CaplPacketMgr()
{
}

bool CaplPacketMgr::Attach(CaplAPI *api)
{
	if(api==0) {Detach();return false;}

	m_AllAttrDefined=true;
	CaplStepManager::Attach(api);
	
	CHECK_ZERO_ATTR(e_packet, api->m_data.GetEntityBN(_T("etd_packet")));
	CHECK_ZERO_ATTR(a_packet_id, api->m_data.GetAttrDefinition(e_packet,_T("id")));
	CHECK_ZERO_ATTR(a_packet_descr, api->m_data.GetAttrDefinition(e_packet,_T("description")));
	CHECK_ZERO_ATTR(a_packet_provider, api->m_data.GetAttrDefinition(e_packet,_T("provider")));
	CHECK_ZERO_ATTR(a_packet_date_send, api->m_data.GetAttrDefinition(e_packet,_T("date_send")));
	CHECK_ZERO_ATTR(a_packet_sender, api->m_data.GetAttrDefinition(e_packet,_T("sender")));
	CHECK_ZERO_ATTR(a_packet_date_receipt, api->m_data.GetAttrDefinition(e_packet,_T("date_receipt")));
	CHECK_ZERO_ATTR(a_packet_recipient, api->m_data.GetAttrDefinition(e_packet,_T("recipient")));
	CHECK_ZERO_ATTR(a_packet_date_registr, api->m_data.GetAttrDefinition(e_packet,_T("date_registr")));
	CHECK_ZERO_ATTR(a_packet_registrator, api->m_data.GetAttrDefinition(e_packet,_T("registrator")));
	CHECK_ZERO_ATTR(a_packet_date_load, api->m_data.GetAttrDefinition(e_packet,_T("date_load")));
	CHECK_ZERO_ATTR(a_packet_loader, api->m_data.GetAttrDefinition(e_packet,_T("loader")));
	CHECK_ZERO_ATTR(a_packet_date_confirmation_of_receipt, api->m_data.GetAttrDefinition(e_packet,_T("date_confirmation_of_receipt")));
	CHECK_ZERO_ATTR(a_packet_confirmatory_of_receipt, api->m_data.GetAttrDefinition(e_packet,_T("confirmatory_of_receipt")));
	CHECK_ZERO_ATTR(a_packet_state, api->m_data.GetAttrDefinition(e_packet,_T("state")));
	CHECK_ZERO_ATTR(a_packet_data, api->m_data.GetAttrDefinition(e_packet,_T("data")));
	CHECK_ZERO_ATTR(a_packet_type, api->m_data.GetAttrDefinition(e_packet,_T("type")));
	CHECK_ZERO_ATTR(a_packet_comment, api->m_data.GetAttrDefinition(e_packet,_T("comment")));
	
	CHECK_ZERO_ATTR(e_data_set, api->m_data.GetEntityBN(_T("etd_data_set")));
	CHECK_ZERO_ATTR(e_folder_data_set, api->m_data.GetEntityBN(_T("etd_folder_data_set")));
	CHECK_ZERO_ATTR(e_file_data_set, api->m_data.GetEntityBN(_T("etd_file_data_set")));
	CHECK_ZERO_ATTR(a_data_set_name, api->m_data.GetAttrDefinition(e_data_set,_T("name")));
	CHECK_ZERO_ATTR(a_data_set_of_packet, api->m_data.GetAttrDefinition(e_data_set,_T("of_packet")));
	CHECK_ZERO_ATTR(a_data_set_parametrs, api->m_data.GetAttrDefinition(e_data_set,_T("parametrs")));
	CHECK_ZERO_ATTR(a_data_set_signs, api->m_data.GetAttrDefinition(e_data_set,_T("signs")));
	CHECK_ZERO_ATTR(a_data_set_parent, api->m_data.GetAttrDefinition(e_data_set,_T("parent")));
	CHECK_ZERO_ATTR(a_folder_data_set_content, api->m_data.GetAttrDefinition(e_folder_data_set,_T("content")));
	CHECK_ZERO_ATTR(a_file_data_set_data, api->m_data.GetAttrDefinition(e_file_data_set,_T("data")));
	
	CHECK_ZERO_ATTR(e_data_set_parametr, api->m_data.GetEntityBN(_T("etd_data_set_parametr")));
	CHECK_ZERO_ATTR(a_data_set_parametr_name, api->m_data.GetAttrDefinition(e_data_set_parametr,_T("name")));
	CHECK_ZERO_ATTR(a_data_set_parametr_value, api->m_data.GetAttrDefinition(e_data_set_parametr,_T("value")));
	CHECK_ZERO_ATTR(a_data_set_parametr_of_data_set, api->m_data.GetAttrDefinition(e_data_set_parametr,_T("of_data_set")));

	CHECK_ZERO_ATTR(e_data_set_sign, api->m_data.GetEntityBN(_T("etd_data_set_sign")));
	CHECK_ZERO_ATTR(a_data_set_sign_date, api->m_data.GetAttrDefinition(e_data_set_sign,_T("date")));
	CHECK_ZERO_ATTR(a_data_set_sign_role, api->m_data.GetAttrDefinition(e_data_set_sign,_T("role")));
	CHECK_ZERO_ATTR(a_data_set_sign_of_data_set, api->m_data.GetAttrDefinition(e_data_set_sign,_T("of_data_set")));
	CHECK_ZERO_ATTR(a_data_set_sign_data, api->m_data.GetAttrDefinition(e_data_set_sign,_T("data")));
	CHECK_ZERO_ATTR(a_data_set_sign_sertificate, api->m_data.GetAttrDefinition(e_data_set_sign,_T("sertificate")));
	
	CHECK_ZERO_ATTR(e_sign_sertificate, api->m_data.GetEntityBN(_T("etd_sign_sertificate")));
	CHECK_ZERO_ATTR(a_sign_sertificate_name, api->m_data.GetAttrDefinition(e_sign_sertificate,_T("name")));
	CHECK_ZERO_ATTR(a_sign_sertificate_of_packet, api->m_data.GetAttrDefinition(e_sign_sertificate,_T("of_packet")));
	CHECK_ZERO_ATTR(a_sign_sertificate_data, api->m_data.GetAttrDefinition(e_sign_sertificate,_T("data")));
	return true;
}

void CaplPacketMgr::Detach()
{
	e_packet = NULL;
	a_packet_id = NULL;
	a_packet_descr = NULL;
	a_packet_provider = NULL;
	a_packet_date_send = NULL;
	a_packet_sender = NULL;
	a_packet_date_receipt = NULL;
	a_packet_recipient = NULL;
	a_packet_date_registr = NULL;
	a_packet_registrator = NULL;
	a_packet_date_load = NULL;
	a_packet_loader = NULL;
	a_packet_date_confirmation_of_receipt = NULL;
	a_packet_confirmatory_of_receipt = NULL;
	a_packet_state = NULL;
	a_packet_data = NULL;
	a_packet_type = NULL;
	a_packet_comment = NULL;
	
	e_data_set = NULL;
	e_folder_data_set = NULL;
	e_file_data_set = NULL;
	a_data_set_name = NULL;
	a_data_set_of_packet = NULL;
	a_data_set_parametrs = NULL;
	a_data_set_parent = NULL;
	a_folder_data_set_content = NULL;
	a_file_data_set_data = NULL;
	
	e_data_set_parametr = NULL;
	a_data_set_parametr_name = NULL;
	a_data_set_parametr_value = NULL;
	a_data_set_parametr_of_data_set = NULL;

	e_data_set_sign = NULL;
	a_data_set_sign_date = NULL;
	a_data_set_sign_role = NULL;
	a_data_set_sign_of_data_set = NULL;
	a_data_set_sign_sertificate = NULL;
	a_data_set_sign_data = NULL;
	
	e_sign_sertificate = NULL;
	a_sign_sertificate_name = NULL;
	a_sign_sertificate_of_packet = NULL;
	a_sign_sertificate_data = NULL;
}

CaplInstance* CaplPacketMgr::CreateFromFile(LPCTSTR lpFileName, bool bOut,CString *err_mess,bool ignore_errors)
{
	CString buf;
	CaplInstance *nPacket = NULL;
	CaplInstance *root_data_set = NULL;
	CaplInstance *Provider = NULL;

	if(err_mess!=0){err_mess->Empty();}
	bool boldAS = m_AutoSave;
	m_AutoSave = false;

	CString sState = APL_T("Зарегистрирован");
	CString sDescr;
	try
	{
		sDescr.Empty();

		CaplPacket Packet;
		bool bRes = true;
		if(0!=Packet.Load(lpFileName)) bRes=false;

		sState = bRes?APL_T("Зарегистрирован"):APL_T("Некорректный");
		sDescr+=Packet.m_sLoadState+_T("\n");

		int code = Packet.CheckSigns(false);
		if(code!=APL_CRYPT_NO_ERROR)
		{
			sState = APL_T("Некорректный");
			buf.Empty();
			switch(code)
			{
			case APL_CRYPT_INVALID_HASH: buf = _T("INVALID_HASH");break;
			case APL_CRYPT_INVALID_SIGNATURE: buf = _T("INVALID_SIGNATURE");break;
			case APL_CRYPT_BAD_FILE: buf = _T("BAD_FILE");break;
			case APL_CRYPT_BAD_PASSWORD: buf = _T("BAD_PASSWORD");break;
			case APL_CRYPT_UNKNOWN_ERROR: buf = _T("UNKNOWN_ERROR");break;
			}
			sDescr+=buf+_T("\n");
			if(err_mess!=0){*err_mess+=sDescr;}
			if(ignore_errors){
				// такие ошибки игнорировать нельзя
				return 0;
			}
		}
		else
			sState = APL_T("Проверен");
			
		bool bShowDlg = false;
		
		if(Packet.m_sId.IsEmpty()) {
			if(ignore_errors){
				// пакет будет создан без диалога
				sState = APL_T("Некорректный");
			}else{
				bShowDlg = true;
			}
			if(err_mess!=0){*err_mess+=APL_T("Не задано обозначение пакета. ");}
		}
		else
		{
			// проверка задан ли поставщик
			if(Packet.m_sProviderCode.IsEmpty()) 
			{
				if(err_mess!=0){*err_mess+=APL_T("Не задан код поставщика. ");}
				if(ignore_errors){
					// пакет будет создан без диалога
					sState = APL_T("Некорректный");
				}else{
					bShowDlg = true;
				}
			}

			//пороверка на уникальность обозначения
			CaplAttrValue tst_value;
			aplExtent res;
			tst_value.attr = a_packet_id;
			tst_value.value.Set(Packet.m_sId);
			if(m_api->m_data.NET_FindInstancesWithAttrValues(e_packet, 1, &tst_value, res, false)>0)
			{
				LoadExtentInfo(res);
				//Пытаемся обновить состояние пакета
				if(sState.CompareNoCase(APL_T("Некорректный"))==0)
				{
					CString msg;
					msg.Format(APL_T("Загружаемый Вами пакет некорректен. Обновление пакета в БД невозможно!"));
					if(err_mess!=0){*err_mess=msg;}
					else AfxMessageBox(msg);
					return NULL;
				}
				Packet.m_pRootDataSet->GetParamValueBN(APL_T("Состояние"), buf);
				if(!buf.IsEmpty())
				{
					m_api->m_data.GetAttr(res[0], a_packet_state, sState);
					if(buf.CompareNoCase(APL_T("Некорректный"))==0 && sState.CompareNoCase(APL_T("Передан"))==0)
					{
						CString msg, descr;
						Packet.m_pRootDataSet->GetParamValueBN(APL_T("Описание"), descr);
						msg.Format(APL_T("Подтверждение о получении пакета потребителем содержит информацию о том, что пакет '%s' некорректный!\nПроверте корректность пакета, подписей и повторите отправку.\n%s"), Packet.m_sId, descr);
						if(err_mess!=0){*err_mess+=msg;}
						else AfxMessageBox(msg);
					}

					sState = buf;
					m_api->m_data.PutAttr(res[0], a_packet_state, sState);
					
					m_AutoSave = boldAS;
					if(m_AutoSave)
						m_api->SaveChanges();
					
					return res[0];
				}	
				else //Если наш пакет был некорректный, то удаляем все данные и создаем их заново
				{
					m_api->m_data.GetAttr(res[0], a_packet_state, buf);
					if(buf.CompareNoCase(APL_T("Некорректный"))==0)
					{
						//Делаем обновление данных
						nPacket = res[0];
						CaplInstance *pDS;
						m_api->m_data.GetAttr(nPacket, a_packet_data, pDS);
						if(Delete(pDS) || pDS==NULL)
						{
							pDS = LoadData(nPacket, Packet.m_pRootDataSet, &Packet, nPacket);
							m_api->m_data.PutAttr(nPacket, a_packet_data, pDS);
							m_api->m_data.PutAttr(nPacket, a_packet_state, sState);

							m_AutoSave = boldAS;
							if(m_AutoSave)
								m_api->SaveChanges();

							return res[0];
						}
						else
						{
							if(ignore_errors){
								// пакет будет создан без диалога
								sState = APL_T("Некорректный");
							}else{
								bShowDlg = true;
							}
							if(err_mess!=0){*err_mess+=APL_T("Некорректно задана дата. ");}
						}
					}
					else
					{
						if(ignore_errors){
							// пакет будет создан без диалога
							sState = APL_T("Некорректный");
						}else{
							bShowDlg = true;
						}
						if(err_mess!=0)
						{
							CString sMsg;
							sMsg.Format(APL_T("Состояние пакета \"%s\" - требуется ручная корректировка. "), buf);
							*err_mess+=sMsg;
						}
					}
				}
			}
		}
		aplDate2String(COleDateTime::GetCurrentTime(), buf);

		if(Packet.m_sProviderCode.IsEmpty()==FALSE){
			Provider = m_api->m_appr_mgr.FindOrganizationById(Packet.m_sProviderCode);
		}
		
		if(Provider==NULL)
		{
			if(m_api->m_options_mgr.GetIntOptionValueBN(APL_AUTOCREATE_PROVIDER, 0)>0)
			{
				Provider=m_api->m_appr_mgr.CreateOrganization(Packet.m_sProviderCode, _T(""));
				m_api->SaveChanges();
			}
		}

		if(!bShowDlg)
		{
			nPacket = m_api->m_data.CreateInstance(e_packet);
			m_api->m_data.PutAttr(nPacket, a_packet_id, Packet.m_sId);
			m_api->m_data.PutAttr(nPacket, a_packet_descr, Packet.m_sDescr);
			m_api->m_data.PutAttr(nPacket, a_packet_state, sState);
			m_api->m_data.PutAttr(nPacket, a_packet_provider, Provider);

			m_api->m_data.PutAttr(nPacket, a_packet_date_registr, buf);
			m_api->m_data.PutAttr(nPacket, a_packet_registrator, GetCurrentPerson());
		}
		else
		{
			if(m_api->m_ModeInteractive){
				if(sState.CompareNoCase(APL_T("Некорректный"))==0){
					if(err_mess!=0){*err_mess+=sDescr;}
					else AfxMessageBox(sDescr);
				}
				nPacket = ShowCreatePacketDlg(&Packet, sState, bOut);
			}else if(err_mess!=0){
				*err_mess+=APL_T("Во время регистрации потребовалась интерактивная корректрировка данных. Провести таковую в настоящее время не представляется возможным");
			}
			if(nPacket==NULL)
			{
				m_AutoSave = boldAS;
				return NULL;
			}
		}
		
		m_api->m_data.PutAttr(nPacket, a_packet_type, bOut?_T("out"):_T("in"));
		
		if(bRes)
			root_data_set = LoadData(nPacket, Packet.m_pRootDataSet, &Packet, nPacket);
		m_api->m_data.PutAttr(nPacket, a_packet_data, root_data_set);
	}
	catch(...)
	{
		if(m_api->m_ModeInteractive){
			AfxMessageBox(APL_T("Во время регистрации пакета в БД произошла неизвестная ошибка!"));
		}else if(err_mess!=0){*err_mess+=APL_T("Во время регистрации пакета в БД произошла неизвестная ошибка!");}

		sState = APL_T("Некорректный");
		if(nPacket)
			m_api->m_data.PutAttr(nPacket, a_packet_state, sState);
	}

	if(nPacket && bOut==false)
	{
		CaplPacket update;
		CString id, buf;
		CString path;
		path = path.Left(path.ReverseFind(_T('\\'))+1);
		m_api->m_data.GetAttr(nPacket, a_packet_id, id);
		update.m_pRootDataSet = new CFolderDataSet(&update);
		update.m_pRootDataSet->m_Parametrs.Add(new CDataSetParam(APL_T("Идентификатор"), id));
		if(sState.CompareNoCase(APL_T("Некорректный"))!=0)
			sState = APL_T("Подтвержден");
		update.m_pRootDataSet->m_Parametrs.Add(new CDataSetParam(APL_T("Состояние"), sState));
		update.m_pRootDataSet->m_Parametrs.Add(new CDataSetParam(APL_T("Описание"), sDescr));
		m_api->m_options_mgr.GetOptionValueBN(APL_PACKET_UPDATE_STATE_PATH, path);
		if(!path.IsEmpty())
		{
			if(path[path.GetLength()-1]!=_T('\\')) path+=_T("\\");
		}
		buf.Format(_T("%s%s-%s.etd"), path, APL_T("Обновление состояния"), id);
		update.Save(buf);
	}

	m_AutoSave = boldAS;
		
	if(m_AutoSave)
		m_api->SaveChanges();
	
	return nPacket;
}

CaplInstance* CaplPacketMgr::LoadData(CaplInstance *Item, CDataSet *pDataSet, CaplPacket *pPacket, CaplInstance *iPacket)
{
	int i;
	aplExtent param_ext;
	aplExtent content;
	aplExtent signs;
	aplExtent serts;
	CaplInstance *Sign;
	CaplInstance *Param;
	CaplInstance *Child;
	CaplInstance *data_set = m_api->m_data.CreateInstance(pDataSet->IsFolder()?e_folder_data_set:e_file_data_set);
	m_api->m_data.PutAttr(data_set, a_data_set_name, pDataSet->m_sName);
	m_api->m_data.PutAttr(data_set, a_data_set_of_packet, iPacket);
	if(m_api->m_data.IsKindOf(Item, e_data_set))
		m_api->m_data.PutAttr(data_set, a_data_set_parent, Item);
	
	for(i=0;i<pDataSet->m_Parametrs.GetSize();i++)
	{
		Param = m_api->m_data.CreateInstance(e_data_set_parametr);
		m_api->m_data.PutAttr(Param, a_data_set_parametr_name, pDataSet->m_Parametrs[i]->m_sName);
		m_api->m_data.PutAttr(Param, a_data_set_parametr_value, pDataSet->m_Parametrs[i]->m_sValue);
		m_api->m_data.PutAttr(Param, a_data_set_parametr_of_data_set, data_set);
		param_ext.Add(Param);
	}
	m_api->m_data.PutAttr(data_set, a_data_set_parametrs, param_ext);

	//подписи и сертификаты
	for(i=0; i<pPacket->m_DataSetSigns.GetSize(); i++)
	{
		if(pPacket->m_DataSetSigns[i]->m_pDataSet==pDataSet)
		{
			Sign = CreateDataSetSign(data_set, pPacket->m_DataSetSigns[i]);
			signs.Add(Sign);
		}
	}
	m_api->m_data.PutAttr(data_set, a_data_set_signs, signs);
	

	if(pDataSet->IsFolder())  // DataSet
	{
		// Чтение входящих DataSet
		content.Clear();
		for(i=0; i<((CFolderDataSet*)pDataSet)->m_Content.GetSize(); i++)
		{
			Child = LoadData(data_set, ((CFolderDataSet*)pDataSet)->m_Content[i], pPacket, iPacket);
			if(Child)
				content.Add(Child);
		}
		m_api->m_data.PutAttr(data_set, a_folder_data_set_content, content);
	}
	else		// File
	{
		if(!m_api->m_data.IsConnected()) throw(2);
		
		long code;
		CaplInstance *stored_document;
		stored_document = m_api->m_data.CreateInstance(m_api->m_doc_mgr.e_apl_stored_document);
		m_api->m_data.PutAttr(stored_document, m_api->m_doc_mgr.a_apl_stored_document_file_name, pDataSet->m_sName);
		if(((CFileDataSet*)pDataSet)->m_DataSize>0)
			m_api->m_data.NET_SaveFileFromMemory(stored_document, m_api->m_doc_mgr.a_apl_stored_document_source, (BYTE*)((CFileDataSet*)pDataSet)->m_pData, ((CFileDataSet*)pDataSet)->m_DataSize, code);
		m_api->m_data.PutAttr(data_set, a_file_data_set_data, stored_document);
	}

	return data_set;
}

bool CaplPacketMgr::Delete(CaplInstance* inst)
{
	if(m_api==NULL) return false;
	if(!m_api->m_data.IsDictLoad()) return false;
	if(inst==NULL) return false;

	if(inst->GetAccessmode()>aplOWN) return false;

	bool bNeedAs = false;

	if(m_api->m_data.IsKindOf(inst, e_packet))
	{
		CaplInstance *data;
		m_api->m_data.GetAttr(inst, a_packet_data, data);
		Delete(data);

		bNeedAs = true;
	}
	else if(m_api->m_data.IsKindOf(inst, e_folder_data_set))
	{
		aplExtent ext;
		int i;
		m_api->m_data.GetAttr(inst, a_folder_data_set_content, ext);
		for(i=0; i<ext.GetSize(); i++)
			Delete(ext[i]);
		m_api->m_data.GetAttr(inst, a_data_set_parametrs, ext);
		for(i=0; i<ext.GetSize(); i++)
			Delete(ext[i]);
		m_api->m_data.GetAttr(inst, a_data_set_signs, ext);
		for(i=0; i<ext.GetSize(); i++)
			Delete(ext[i]);
	}
	else if(m_api->m_data.IsKindOf(inst, e_file_data_set))
	{
		aplExtent ext;
		int i;
		m_api->m_data.GetAttr(inst, a_data_set_parametrs, ext);
		for(i=0; i<ext.GetSize(); i++)
			Delete(ext[i]);
		m_api->m_data.GetAttr(inst, a_data_set_signs, ext);
		for(i=0; i<ext.GetSize(); i++)
			Delete(ext[i]);
	}
	else if(m_api->m_data.IsKindOf(inst, e_data_set_sign))
	{
		CaplInstance *sert;
		m_api->m_data.GetAttr(inst, a_data_set_sign_sertificate, sert);
		if(sert!=NULL)
			m_api->m_data.DeleteInstance(sert);
	}

	m_api->m_data.DeleteInstance(inst);
	if(bNeedAs && m_AutoSave)
		m_api->SaveChanges();

	return true;
}	

bool CaplPacketMgr::ShowPacketProperties(CaplInstance* packet)
{
	if(m_api==NULL) return false;
	if(!m_api->m_data.IsDictLoad()) return false;
	if(packet==NULL) return false;

	CaplSetResourceHandle setres(hDllInst);

	CPacketDlg dlg(m_api);
	dlg.m_inst = packet;
	bool bRes = (dlg.DoModal()==IDOK);
	return bRes;
}

CaplInstance* CaplPacketMgr::ShowCreatePacketDlg(CaplPacket *pPacket, LPCTSTR nState, bool bOut)
{
	if(m_api==NULL) return false;
	if(!m_api->m_data.IsDictLoad()) return false;
	
	CPacketDlg dlg(m_api);
	dlg.m_pPacket = pPacket;
	dlg.m_sState = nState;
	dlg.m_bOut = bOut;
	dlg.m_Provider = m_api->m_appr_mgr.FindOrganizationById(pPacket->m_sProviderCode);
	if(dlg.DoModal()==IDOK)
	{
		return dlg.m_inst;
	}
	else return NULL;
}
CaplInstance* CaplPacketMgr::CreateDataSetSign(CaplInstance* pDataSet, CDataSetSign* pDSSign)
{
	if(m_api==NULL) return NULL;
	if(!m_api->m_data.IsConnected()) return NULL;
	if(pDataSet==NULL) return NULL;

	long code = 0;

	CaplSignBuf signBuf;
	pDSSign->SaveToBuf(signBuf);

	int index = 0;
	CaplInstance* pPacket;

	m_api->m_data.GetAttr(pDataSet, a_data_set_of_packet, pPacket);
	CaplInstance* nSignSert = m_api->m_data.CreateInstance(e_sign_sertificate);
	CaplInstance* nDSSign = m_api->m_data.CreateInstance(e_data_set_sign);
	m_api->m_data.PutAttr(nSignSert, a_sign_sertificate_of_packet, pPacket);
	m_api->m_data.PutAttr(nSignSert, a_sign_sertificate_name, pDSSign->m_pSertificate->m_sPersonName);

	m_api->m_data.PutAttr(nDSSign, a_data_set_sign_of_data_set, pDataSet);
	m_api->m_data.PutAttr(nDSSign, a_data_set_sign_sertificate, nSignSert);
	m_api->m_data.PutAttr(nDSSign, a_data_set_sign_date, pDSSign->m_sDate);
	m_api->m_data.PutAttr(nDSSign, a_data_set_sign_role, pDSSign->m_sRole);
	m_api->m_data.NET_SaveFileFromMemory(nDSSign, a_data_set_sign_data, signBuf.GetData(), signBuf.GetDataSize(), code);

	signBuf.Clear();
	pDSSign->m_pSertificate->SaveToBuf(signBuf);
	m_api->m_data.NET_SaveFileFromMemory(nSignSert, a_sign_sertificate_data, signBuf.GetData(), signBuf.GetDataSize(), code);

	if(m_AutoSave)
		m_api->SaveChanges();

	return nDSSign;
}

bool CaplPacketMgr::SaveData(CaplInstance *Item, CDataSet *pDataSet, CaplPacket *pPacket)
{
	if(m_api==NULL) return false;
	if(!m_api->m_data.IsDictLoad()) return false;
	if(Item==NULL) return false;

	int i;
	aplExtent params;
	aplExtent signs;
	CString name, val;

	try
	{
		m_api->m_data.GetAttr(Item, a_data_set_name, pDataSet->m_sName);
		m_api->m_data.GetAttr(Item, a_data_set_parametrs, params);
		
		m_api->LoadExtentInfo(params);
		for(i=0; i<params.GetSize(); i++)
		{
			m_api->m_data.GetAttr(params[i], a_data_set_parametr_name, name);
			m_api->m_data.GetAttr(params[i], a_data_set_parametr_value, val);
			pDataSet->m_Parametrs.Add(new CDataSetParam(name, val));
		}
		
		//подписи и сертификаты
		long size_sert, size_sign;
		int index;
		BYTE *pBufSert, *pBufSign;
		CaplInstance *sert;
		m_api->m_data.GetAttr(Item, a_data_set_signs, signs);
		for(i=0; i<signs.GetSize(); i++)
		{
			m_api->m_data.GetAttr(signs[i], a_data_set_sign_sertificate, sert);
			if(sert==NULL) continue;
			if(!m_api->m_data.NET_GetBlobSize(sert, a_sign_sertificate_data, size_sert)) continue;
			if(!m_api->m_data.NET_GetBlobSize(signs[i], a_data_set_sign_data, size_sign)) continue;
			pBufSign = new BYTE[size_sign];
			if(!m_api->m_data.NET_LoadBlob2Memory(signs[i], a_data_set_sign_data, (BYTE*)pBufSign, size_sign))
			{
				delete pBufSign;
				continue;
			}
			pBufSert = new BYTE[size_sert];
			if(!m_api->m_data.NET_LoadBlob2Memory(sert, a_sign_sertificate_data, (BYTE*)pBufSert, size_sert))
			{
				delete pBufSert;
				delete pBufSign;
				continue;
			}
			CSignSert *pSign = new CSignSert(pPacket);
			index = 0;
			pSign->LoadFromBuf(pBufSert, index);
			CDataSetSign *pDSSign = new CDataSetSign(pPacket);
			index = 0;
			pDSSign->LoadFromBuf(pBufSign, index);
			delete pBufSert;
			delete pBufSign;
		}
		
		if(m_api->m_data.IsKindOf(Item, e_folder_data_set))
		{
			if(!pDataSet->IsFolder()) return false;
			CFolderDataSet *pFolderDS = (CFolderDataSet*)pDataSet;
			
			int i;
			aplExtent ext;
			CDataSet *pChildDS;
			m_api->m_data.GetAttr(Item, a_folder_data_set_content, ext);
			for(i=0; i<ext.GetSize(); i++)
			{
				if(m_api->m_data.IsKindOf(ext[i], e_folder_data_set))
					pChildDS = new CFolderDataSet(pPacket, pDataSet);
				else
					pChildDS = new CFileDataSet(pPacket, pDataSet);
				if(!SaveData(ext[i], pChildDS, pPacket)) return false;
			}
		}
		else
		{
			if(pDataSet->IsFolder()) return false;
			
			CaplInstance *st_doc;
			CFileDataSet *pFileDS = (CFileDataSet*)pDataSet;
			m_api->m_data.GetAttr(Item, a_file_data_set_data, st_doc);
			if(st_doc)
			{
				long lBlobSize;
				if(m_api->m_data.NET_GetBlobSize(st_doc, m_api->m_doc_mgr.a_apl_stored_document_source, lBlobSize))
				{
					pFileDS->m_DataSize=lBlobSize;
					pFileDS->m_pData = new char[pFileDS->m_DataSize];
					if(!m_api->m_data.NET_LoadBlob2Memory(st_doc, m_api->m_doc_mgr.a_apl_stored_document_source, (BYTE*)pFileDS->m_pData, lBlobSize))
					{
						delete pFileDS->m_pData;
						pFileDS->m_DataSize = 0;
						return false;
					}
				}
				else return false;
			}
		}
	}
	catch(int code)
	{
		CString msg;
		switch(code)
		{
		case APL_LOAD_DATASETSIGN_FROM_BUF_ERROR:
		case APL_LOAD_DATASETSIGN_FROM_FILE_ERROR:
			msg = APL_T("Ошибка чтения информации о цифровой подписи");
			break;
		case APL_SAVE_DATASETSIGN_TO_FILE_ERROR:
		case APL_SAVE_DATASETSIGN_TO_BUF_ERROR:
			msg = APL_T("Ошибка записи цифровой подписи");
			break;
		case APL_LOAD_DATASETPARAM_FROM_BUF_ERROR:
		case APL_LOAD_DATASETPARAM_FROM_FILE_ERROR:
			msg = APL_T("Ошибка чтения параметра");
			break;
		case APL_SAVE_DATASETPARAM_TO_FILE_ERROR:
		case APL_SAVE_DATASETPARAM_TO_BUF_ERROR:
			msg = APL_T("Ошибка записи параметра");
			break;
		case APL_LOAD_FOLDERDATASET_FROM_FILE_ERROR:
		case APL_LOAD_FILERDATASET_FROM_FILE_ERROR:
			msg = APL_T("Ошибка чтения блока данных");
			break;
		case APL_SAVE_FOLDERDATASET_TO_FILE_ERROR:
		case APL_SAVE_FILERDATASET_TO_FILE_ERROR:
			msg = APL_T("Ошибка записи блока данных");
			break;
		case APL_LOAD_PACKET_FROM_FILE_ERROR:
			msg = APL_T("Ошибка чтения пакета");
			break;
		case APL_SAVE_PACKET_TO_FILE_ERROR:
			msg = APL_T("Ошибка записи пакета");
			break;
		case APL_UNKNOWN_FILE_FORMAT:
			msg = APL_T("Неизвестный формат файла");
			break;
		case APL_CRC32_ERROR:
			msg = APL_T("Некорректный файл (не совпадают контрольные суммы)");
			break;
		case APL_INCORRECT_FILE_VERSION:
			msg = APL_T("Неподдерживаемая версия файла");
			break;
		default:
			msg = APL_T("Во время выполнения операции произошла неизвестная ошибка!");
			break;
		}
		AfxMessageBox(msg);
		return false;
	}

	return true;
}

bool CaplPacketMgr::SaveToFile(CaplInstance *iPacket, LPCTSTR lpFileName)
{
	if(m_api==NULL) return false;
	if(!m_api->m_data.IsDictLoad()) return false;
	if(iPacket==NULL) return false;

	CaplPacket	aplPacket;

	LoadItemInfo(iPacket);
	
	CaplInstance *DataSet;
	CString type;
	m_api->m_data.GetAttr(iPacket, a_packet_type, type);
	if(type!=_T("out"))
	{
		if(m_api->m_ModeInteractive)
			AfxMessageBox(APL_T("Передавать можно только исходящие пакеты!"));
		return false;
	}
	m_api->m_data.GetAttr(iPacket, a_packet_data, DataSet);
	if(DataSet==NULL) return false;
	if(m_api->m_data.IsKindOf(DataSet, e_folder_data_set))
	{
		aplPacket.m_pRootDataSet = new CFolderDataSet(&aplPacket);
	}
	else
	{
		aplPacket.m_pRootDataSet = new CFileDataSet(&aplPacket);
	}

	if(!SaveData(DataSet, aplPacket.m_pRootDataSet, &aplPacket)) return false;

	if(m_api->m_ModeInteractive && aplPacket.m_DataSetSigns.GetSize()==0)
	{
		if(AfxMessageBox(APL_T("Пакет не имеет ни одной цифровой подписи. Продолжить сохранение пакета для его последующей отправки?"), MB_YESNO|MB_ICONQUESTION)!=IDYES)
			return false;
	}

	bool bRes = aplPacket.Save(lpFileName);
	if(bRes)
	{
		CString buf;
		aplDate2String(COleDateTime::GetCurrentTime(), buf);
		m_api->m_data.PutAttr(iPacket, a_packet_state, APL_T("Передан"));
		m_api->m_data.PutAttr(iPacket, a_packet_date_send, buf);
		m_api->m_data.PutAttr(iPacket, a_packet_sender, GetCurrentPerson());
	}

	if(m_AutoSave)
		m_api->SaveChanges();

	return bRes;
}

bool CaplPacketMgr::LoadItemInfo(CaplInstance *Inst)
{
	aplExtent ext;
	ext.Add(Inst);
	return LoadExtentInfo(ext);
}

bool CaplPacketMgr::LoadExtentInfo(aplExtent &ext)
{
	if(m_api==NULL) return false;
	if(!m_api->m_data.IsDictLoad()) return false;
	if(!m_api->m_data.IsConnected()) return true;//Если соединение не установлено, а словарь зачитан. значит работаем с файлом
	if(ext.GetSize()==0) return true;

	bool bRes = true;
	aplExtent packets;
	aplExtent data_sets;
	aplExtent params;
	aplExtent sertificates;
	aplExtent signs;
	int i;
	for(i=0; i<ext.GetSize(); i++)
	{
		if(ext[i]==NULL) continue;
		if(ext[i]->GetId()==0) continue;

		if(m_api->m_data.IsKindOf(ext[i], e_packet))
			packets.Add(ext[i]);
		else if(m_api->m_data.IsKindOf(ext[i], e_data_set))
			data_sets.Add(ext[i]);
		else if(m_api->m_data.IsKindOf(ext[i], e_data_set_parametr))
			params.Add(ext[i]);
		else if(m_api->m_data.IsKindOf(ext[i], e_data_set_sign))
			signs.Add(ext[i]);
		else if(m_api->m_data.IsKindOf(ext[i], e_sign_sertificate))
			sertificates.Add(ext[i]);
		else
			continue;
	}

	if(packets.GetSize()>0)
	{
		CaplLoadData ld(&m_api->m_data, DEF_SOURCE);
		for(i=0; i<packets.GetSize(); i++)
			ld.AddQuery(0, packets[i], true);
		int ind1 = ld.AddQuery(_T('r'), 0, e_data_set, a_data_set_of_packet, true, true);
		int ind2 = ld.AddQuery(_T('r'), 0, e_sign_sertificate, a_sign_sertificate_of_packet, true, true);
		int ind3 = ld.AddQuery(_T('r'), ind1, e_data_set_parametr, a_data_set_parametr_of_data_set, true, true);
		int ind4 = ld.AddQuery(_T('r'), ind1, e_data_set_sign, a_data_set_sign_of_data_set, true, true);
		int ind5 = ld.AddQuery(_T('d'), ind1, e_file_data_set, a_file_data_set_data, true, true);

		bRes &= ld.LoadEx();
	}
	if(data_sets.GetSize()>0)
	{
		CaplLoadData ld(&m_api->m_data, DEF_SOURCE);
		for(i=0; i<data_sets.GetSize(); i++)
			ld.AddQuery(0, data_sets[i], true);
		
		bRes &= ld.LoadEx();
	}
	if(params.GetSize()>0)
	{
		CaplLoadData ld(&m_api->m_data, DEF_SOURCE);
		for(i=0; i<params.GetSize(); i++)
			ld.AddQuery(0, params[i], true);
		
		bRes &= ld.LoadEx();
	}
	if(signs.GetSize()>0)
	{
		CaplLoadData ld(&m_api->m_data, DEF_SOURCE);
		for(i=0; i<signs.GetSize(); i++)
			ld.AddQuery(0, signs[i], true);
		int ind1 = ld.AddQuery(_T('d'), 0, 0, a_data_set_sign_sertificate, true, true);
		
		bRes &= ld.LoadEx();
	}
	if(sertificates.GetSize()>0)
	{
		CaplLoadData ld(&m_api->m_data, DEF_SOURCE);
		for(i=0; i<sertificates.GetSize(); i++)
			ld.AddQuery(0, sertificates[i], true);
		
		bRes &= ld.LoadEx();
	}

	return bRes;
}

bool CaplPacketMgr::ExportData(CaplInstance *iPacket, LPCTSTR lpPathName)
{
	if(m_api==NULL) return false;
	if(!m_api->m_data.IsDictLoad()) return false;
	if(iPacket==NULL) return false;
	
	LoadItemInfo(iPacket);
	
	CaplInstance *DataSet;
	m_api->m_data.GetAttr(iPacket, a_packet_data, DataSet);
	if(DataSet==NULL) return false;
	CaplPacket	aplPacket;
	if(m_api->m_data.IsKindOf(DataSet, e_folder_data_set))
		aplPacket.m_pRootDataSet = new CFolderDataSet(&aplPacket);
	else
		aplPacket.m_pRootDataSet = new CFileDataSet(&aplPacket);
	
	if(!SaveData(DataSet, aplPacket.m_pRootDataSet, &aplPacket)) return false;
	
	bool bRes = aplPacket.m_pRootDataSet->SaveFiles(lpPathName);
	if(bRes)
	{
		CString buf;
		CString id;
		aplDate2String(COleDateTime::GetCurrentTime(), buf);
		m_api->m_data.PutAttr(iPacket, a_packet_state, APL_T("Распакован"));
		m_api->m_data.PutAttr(iPacket, a_packet_date_load, buf);
		m_api->m_data.PutAttr(iPacket, a_packet_loader, GetCurrentPerson());

		//создаем пакет, подтверждающий распаковку
		CString path;
		CaplPacket update;
		m_api->m_data.GetAttr(iPacket, a_packet_id, id);
		update.m_pRootDataSet = new CFolderDataSet(&update);
		update.m_pRootDataSet->m_Parametrs.Add(new CDataSetParam(APL_T("Идентификатор"), id));
		update.m_pRootDataSet->m_Parametrs.Add(new CDataSetParam(APL_T("Состояние"), APL_T("Распакован")));
		m_api->m_options_mgr.GetOptionValueBN(APL_PACKET_UPDATE_STATE_PATH, path);
		if(!path.IsEmpty())
		{
			if(path[path.GetLength()-1]!=_T('\\')) path+=_T("\\");
		}
		buf.Format(_T("%s%s-%s.etd"), path, APL_T("Обновление состояния"), id);
		update.Save(buf);
	}
	
	if(m_AutoSave)
		m_api->SaveChanges();

	return bRes;
}

bool CaplPacketMgr::Check(CaplInstance *iPacket)
{
	if(m_api==NULL) return false;
	if(!m_api->m_data.IsDictLoad()) return false;
	if(iPacket==NULL) return false;

	CaplInstance *DataSet;
	m_api->m_data.GetAttr(iPacket, a_packet_data, DataSet);
	if(DataSet==NULL) return false;

	CaplPacket	aplPacket;
	
	if(m_api->m_data.IsKindOf(DataSet, e_folder_data_set))
		aplPacket.m_pRootDataSet = new CFolderDataSet(&aplPacket);
	else
		aplPacket.m_pRootDataSet = new CFileDataSet(&aplPacket);
	
	if(!SaveData(DataSet, aplPacket.m_pRootDataSet, &aplPacket))
	{
		m_api->m_data.PutAttr(iPacket, a_packet_state, apl_incorrect);
		if(m_api->m_AutoSave) m_api->SaveChanges();
		AfxMessageBox(APL_T("Пакет поврежден!"));
		return false;
	}

	int res = aplPacket.m_pRootDataSet->CheckSigns(m_api->m_ModeInteractive);

	if(res!=APL_CRYPT_NO_ERROR)
		m_api->m_data.PutAttr(iPacket, a_packet_state, APL_T("Некорректный"));
	else
		m_api->m_data.PutAttr(iPacket, a_packet_state, APL_T("Проверен"));
	
	if(m_AutoSave)
		m_api->SaveChanges();

	return res==APL_CRYPT_NO_ERROR;
}

bool CaplPacketMgr::ExtractStpFile(CaplInstance *pDataSet)
{
	if(m_api==NULL) return false;
	if(!m_api->m_data.IsDictLoad()) return false;
	if(pDataSet==NULL) return false;
	if(!m_api->m_data.IsKindOf(pDataSet, e_file_data_set)) return false;

	CaplInstance *inst_sd;
	CaplInstance *packet;
	CString name;
	CString sPath;
	CString sTemp; sTemp.GetEnvironmentVariable(_T("TEMP"));
	GetTempFileName(sTemp, NULL, 0, sPath.GetBuffer(MAX_PATH));
	sPath.ReleaseBuffer();
	::DeleteFile(sPath);
	m_api->m_data.GetAttr(pDataSet, a_data_set_name, name);
	m_api->m_data.GetAttr(pDataSet, a_data_set_of_packet, packet);
	sPath+=name;
	m_api->m_data.GetAttr(pDataSet, a_file_data_set_data, inst_sd);
	if(inst_sd)
	{
		if(m_api->m_data.NET_LoadBlob(inst_sd, m_api->m_doc_mgr.a_apl_stored_document_source, sPath))
		{
			CaplExchangeManager ExchangeMgr;
			ExchangeMgr.Attach(m_api);
			bool bOldMI = m_api->m_ModeInteractive;
			m_api->m_ModeInteractive = false;
			bool bRes = ExchangeMgr.ImportDataFromFile(sPath, packet);
			m_api->m_ModeInteractive = bOldMI;
			ExchangeMgr.Detach();
			::DeleteFile(sPath);
			
			return bRes;
		}
	}

	return false;
}

bool CaplPacketMgr::Extract(CaplInstance *Packet)
{
	if(m_api==NULL) return false;
	if(!m_api->m_data.IsDictLoad()) return false;
	if(Packet==NULL) return false;

	//Распаковываем все документы кроме тех, у которых есть расширение stp.
	//Если документ не имеет параметра с наименованием "Обозначение" записываем в лог
	LoadItemInfo(Packet);

	//Берем все DataSet
	int i;
	int j;
	long	tmpLong;
	CString buf, name, sPath;
	CString packet_id, packet_descr;
	CString doc_id, doc_type;
	CString sLog, msg;
	bool		bCorrect = true;
	aplExtent	ext;
	aplExtent	params;
	aplExtent	folder_content;
	aplExtent	res;
	aplExtent	stp_files;
	CaplInstance *inst;
	CaplInstance *access_form;
	CaplInstance *folder;
	CaplInstance *RootDS;
	CaplInstance *ParentDoc;
	CaplInstance *document;
	CaplMap DataSet2Doc;
	CaplAttrValue tst_val[2];

	m_api->m_data.GetAttr(Packet, a_packet_state, buf);
	m_api->m_data.GetAttr(Packet, a_packet_data, RootDS);
	
	if(buf.CompareNoCase(apl_correct)!=0)
	{
		if(m_api->m_ModeInteractive)
			AfxMessageBox(APL_T("Можно распаковывать только пакеты, имеющие состояние 'Проверен'!"), MB_ICONINFORMATION);
		return false;
	}

	m_api->m_data.GetAttr(Packet, a_packet_id, packet_id);
	m_api->m_data.GetAttr(Packet, a_packet_descr, packet_descr);
	
	m_api->m_data.GetEntityExtent(e_data_set, ext);
	for(i=0; i<ext.GetSize(); i++)
	{
		if(ext[i]==NULL) {ext.Remove(i--);continue;}
		if(ext[i]->GetAccessmode()>aplRO) {ext.Remove(i--);continue;}

		m_api->m_data.GetAttr(ext[i], a_data_set_of_packet, inst);
		if(inst!=Packet) 
			ext.Remove(i--);
	}

	//Распаковываем в БД
	for(i=0; i<ext.GetSize(); i++)
	{
		m_api->m_data.GetAttr(ext[i], a_data_set_name, name);
		if(name.Right(4).CompareNoCase(_T(".stp"))==0)
		{
			stp_files.Add(ext[i]);
			continue; //файлы stp пропускаем
		}
		if(name.Right(4).CompareNoCase(_T(".std"))==0) 
		{
			stp_files.Add(ext[i]);
			continue; //файлы std пропускаем
		}
	}

	if(stp_files.GetSize()==0)
	{
		long DlgId = aplStartWaitDlg(APL_T("Распаковка документов..."), APL_T("Распаковка"));

		folder = m_api->m_folder_mgr.FindFolderByName(packet_id);
		if(folder==NULL)
			folder = m_api->m_folder_mgr.CreateFolder(NULL, packet_id, packet_descr);
		for(i=0; i<ext.GetSize(); i++)
		{
			m_api->m_data.GetAttr(ext[i], a_data_set_name, name);
			if(name.Right(4).CompareNoCase(_T(".stp"))==0)
			{
				stp_files.Add(ext[i]);
				continue; //файлы stp пропускаем
			}
			if(name.Right(4).CompareNoCase(_T(".std"))==0) 
			{
				stp_files.Add(ext[i]);
				continue; //файлы std пропускаем
			}
			
			if(ext[i]==RootDS) continue;
			
			doc_id.Empty();
			doc_type.Empty();
			m_api->m_data.GetAttr(ext[i], a_data_set_parametrs, params);
			//Ищем среди них параметр с наименование обозначение
			for(j=0; j<params.GetSize(); j++)
			{
				if(params[j]==NULL) continue;
				if(params[j]->GetAccessmode()>aplRO) continue;
				
				m_api->m_data.GetAttr(params[j], a_data_set_parametr_name, buf);
				if(buf.CompareNoCase(APL_T("Обозначение"))==0)
					m_api->m_data.GetAttr(params[j], a_data_set_parametr_value, doc_id);
				else if(buf.CompareNoCase(APL_T("Тип"))==0)
					m_api->m_data.GetAttr(params[j], a_data_set_parametr_value, doc_type);
			}
			if(doc_id.IsEmpty())
			{
				msg.Format(APL_T("Для файла '%s' не указано обозначение. Импорт такого файла в БД невозможен!\r\n"), name);
				sLog+=msg;
				bCorrect = false;
			}
			else
			{
				//Ищем документ в БД. если такого нет, то создаем.
				CaplInstance *document_type;
				CaplInstance *document_old_aver = NULL;
				CString doc_rev_id = _T("1");
				document = m_api->m_doc_mgr.FindDocById(doc_id);
				if(document==NULL)
				{
					document = m_api->m_data.CreateInstance(m_api->m_doc_mgr.e_apl_doc);
					m_api->m_data.PutAttr(document, m_api->m_doc_mgr.a_doc_id, doc_id);
					m_api->m_data.PutAttr(document, m_api->m_doc_mgr.a_doc_name, name);
					m_api->m_data.PutAttr(document, m_api->m_doc_mgr.a_apl_doc_wf_state, _T("approved"));
					if(!doc_type.IsEmpty())
					{
						document_type = m_api->m_doc_mgr.GetDocumentTypeBN(doc_type);
						m_api->m_data.PutAttr(document, m_api->m_doc_mgr.a_doc_kind, document_type);
					}
					m_api->SaveChanges();
				}
				else
				{
					m_api->m_data.GetAttr(document, m_api->m_doc_mgr.a_apl_doc_active, document_old_aver);
					
					CaplLoadData ld(m_data,DEF_SOURCE);
					j=ld.AddQuery(_T('b'), document->GetId(), m_api->m_doc_mgr.e_apl_doc_rev, m_api->m_doc_mgr.a_apl_doc_rev_doc, true);
					ld.AddQuery(_T('d'), j, 0, m_api->m_doc_mgr.a_apl_doc_rev_doc, true);
					ld.AddQuery(_T('d'), j, 0, m_api->m_doc_mgr.a_apl_doc_rev_id, true);
					ld.LoadEx();
					
					aplExtent ext_rev;
					int max_id=-1;
					int tmp;
					m_data->GetEntityExtent(m_api->m_doc_mgr.e_apl_doc_rev, ext_rev);
					for(j=0; j<ext_rev.Size; j++)
					{
						m_data->GetAttr(ext_rev[j], m_api->m_doc_mgr.a_apl_doc_rev_doc, inst);
						if(inst==document)
						{
							m_data->GetAttr(ext_rev[j], m_api->m_doc_mgr.a_apl_doc_rev_id, buf);
							tmp=_atoi(buf);
							if(tmp>max_id) max_id=tmp;
						}
					}
					max_id++;
					doc_rev_id.Format(_T("%d"),max_id);
				}
				DataSet2Doc.Add((long)ext[i], (long)document);
				//Создаем для документа активную версию и связываем её с сторед документ в БД.
				CaplInstance *doc_ver;
				m_api->GetItemName(m_api->m_data.GetCurrUser(), buf);
				doc_ver = m_api->m_data.CreateInstance(m_api->m_doc_mgr.e_apl_digital_document);
				m_api->m_data.PutAttr(document, m_api->m_doc_mgr.a_apl_doc_active, doc_ver);
				m_api->m_data.PutAttr(doc_ver, m_api->m_doc_mgr.a_apl_doc_rev_id, doc_rev_id);
				m_api->m_data.PutAttr(doc_ver, m_api->m_doc_mgr.a_apl_doc_rev_doc, document);
				m_api->m_data.PutAttr(doc_ver, m_api->m_doc_mgr.a_apl_doc_rev_base, document_old_aver);
				m_api->m_data.PutAttr(doc_ver, m_api->m_doc_mgr.a_apl_doc_rev_user,  m_api->m_appr_mgr.GetOperatorName()); // Установка автора
				
				if(m_api->m_data.IsKindOf(ext[i], e_file_data_set))
				{
					m_api->m_data.GetAttr(ext[i], a_file_data_set_data, access_form);
					int crc32 = -1;
					long size;
					BYTE* pBlobBuf = NULL;
					//Вычисляем CRC32 для блоба в БД
					m_api->m_data.NET_GetBlobSize(access_form, m_api->m_doc_mgr.a_apl_stored_document_source, size);
					if(size>0)
					{
						pBlobBuf = new BYTE[size];
						m_api->m_data.NET_LoadBlob2Memory(access_form, m_api->m_doc_mgr.a_apl_stored_document_source, pBlobBuf,size);
						crc32 = GetCRC32((char*)pBlobBuf, size);
						delete pBlobBuf;
					}
					m_api->m_data.PutAttr(doc_ver, m_api->m_doc_mgr.a_apl_doc_rev_access_form, access_form);
					m_api->m_data.PutAttr(doc_ver, m_api->m_doc_mgr.a_apl_doc_rev_crc, crc32);
				}
			}
		}
		//Воссоздаем структуру документов
		DataSet2Doc.SortIn();
		tst_val[0].attr = m_api->m_doc_mgr.a_apl_doc_ref_doc;//ed
		tst_val[1].attr = m_api->m_doc_mgr.a_apl_doc_ref_item;//ing
		for(i=0; i<ext.Size; i++)
		{
			tmpLong = DataSet2Doc.QGetByIn((long)ext[i]);
			if(tmpLong!=-1)
				document = (CaplInstance*)tmpLong;
			else
				continue;
			m_api->m_data.GetAttr(ext[i], a_data_set_parent, inst);
			if(inst==NULL)
			{
				folder_content.Add(document);
				continue;
			}
			tmpLong = DataSet2Doc.QGetByIn((long)inst);
			if(tmpLong!=-1)
				ParentDoc = (CaplInstance*)tmpLong;
			else
			{
				folder_content.Add(document);
				continue;
			}
			
			//проверяем есть ли такая связь, и если её нет, то создаем её
			tst_val[0].value.Set(document);
			tst_val[1].value.Set(ParentDoc);
			if(m_api->m_data.NET_FindInstancesWithAttrValues(m_api->m_doc_mgr.e_apl_doc_ref, 2, &tst_val[0], res, false)>0) continue;
			//Создаем связь
			m_api->m_doc_mgr.CreateAssociation(ParentDoc, document);
		}
		aplEndWaitDlg(DlgId);

		m_api->m_data.PutAttr(folder, m_api->m_folder_mgr.a_folder_content, folder_content);
	}
	else
	{
		for(i=0; i<stp_files.GetSize(); i++)
		{
			bCorrect&=ExtractStpFile(stp_files[i]);
			if(!bCorrect)
			{
				msg.Format(APL_T("Не удалось импортировать обменный файл \"%s\"\r\n"), stp_files[i]);
				sLog+=msg;
			}
		}
	}

	//обновление состояния распаковки
	CString path;
	CaplPacket update;
	m_api->m_data.GetAttr(Packet, a_packet_id, buf);
	update.m_pRootDataSet = new CFolderDataSet(&update);
	update.m_pRootDataSet->m_Parametrs.Add(new CDataSetParam(APL_T("Идентификатор"), buf));
	update.m_pRootDataSet->m_Parametrs.Add(new CDataSetParam(APL_T("Состояние"), bCorrect?apl_unpacked:apl_incorrect));
	update.m_pRootDataSet->m_Parametrs.Add(new CDataSetParam(APL_T("Комментарий"), sLog));

	m_api->m_options_mgr.GetOptionValueBN(APL_PACKET_UPDATE_STATE_PATH, path);
	if(!path.IsEmpty())
	{
		if(path[path.GetLength()-1]!=_T('\\')) path+=_T("\\");
	}
	buf.Format(_T("%s%s-%s.etd"), path, APL_T("Обновление состояния"), packet_id);
	if(!update.Save(buf))
	{
		if(m_api->m_ModeInteractive)
			AfxMessageBox(APL_T("Не удалось сохранить файл обновления состояния пакета!"));
	}

	m_api->m_data.PutAttr(Packet, a_packet_state, bCorrect?apl_unpacked:apl_incorrect);
	m_api->m_data.PutAttr(Packet, a_packet_comment, bCorrect ? _T(""):sLog);
	aplDate2String(COleDateTime::GetCurrentTime(), buf);
	m_api->m_data.PutAttr(Packet, a_packet_date_load, buf);
	m_api->m_data.PutAttr(Packet, a_packet_loader, GetCurrentPerson());

	if(m_AutoSave)
		m_api->SaveChanges();

	return bCorrect;
}