// ApprovalManager.cpp

#include "stdafx.h"
#include <aplNetStepData.h>
#include "apl_api.h"
#include <apl_gui.h>
#include "dictionary.h"
#include "resource.h"
#include "SelectPecipientsDlg.h"
#include "ApprovalDlg.h"
#include "OfficialHistDlg.h"
#include "PersOfficialDlg.h"
#include "PersonPropDlg.h"
#include "OfficialPropDlg.h"
#include "OrganizationPropDlg.h"
//#include "QueryUserSignParamDlg.h"
#include "OrgStrDlg.h"
#include "SelectUsersDlg.h"
#include "aplCertificateDlg.h"
#include "ShowItemApprovals.h"
#include "GetPasswordDialog.h"


// Обработки ГРПЗ при присвоении статуса

bool CreateApprovalGrpzPreProcessing(CaplAPI *m_api, CaplInstance *item , CaplInstance **pitem2)  
{
	*pitem2=0;
	bool bSzv=m_api->m_options_mgr.CheckInstallCode(APL_NO_T("Созвездие"));
	bool bGrpz=m_api->m_options_mgr.CheckInstallCode(_T("grpz"));
	if((!bSzv)&&(!bGrpz)) return true;

	if(m_api->m_data.IsKindOf(item, m_api->m_doc_mgr.e_apl_doc_rev))
	{
		CaplInstance *doc;
		CString buf;
		apidata.GetAttr(item,m_api->m_doc_mgr.a_apl_doc_rev_doc,doc);
		apidata.GetAttr(doc,m_api->m_doc_mgr.a_apl_doc_system,buf);
		if(buf==_T("GenerateIe"))
		{
			AfxMessageBox(APL_T("Данный документ создан как отчет для пакета изменений!\nЕго нельзя подписывать напрямую.\n\nПодписывать необходимо пакет изменений!"), MB_OK|MB_ICONEXCLAMATION);
			return false;
		}

		apidata.GetAttr(doc,m_api->m_doc_mgr.a_doc_add_dt_code,buf);
		if(buf!=_T("2D")) return true;

		int iVal;
		m_api->m_options_mgr.GetOptionValueBN( APL_NO_T("Настройка документов\\При подписи 2D подписывать 3D"), iVal, 0);
		if(0==iVal) return true;

		// Это 2D модель - ищем 3D
		apidata.GetAttr(doc,m_api->m_doc_mgr.a_doc_id,buf);

		aplExtent ext;
		CaplAttrValue tst_value[4];
		tst_value[0].value.Set(buf);
		tst_value[0].attr=m_api->m_doc_mgr.a_doc_id;
		tst_value[1].value.Set(APL_T("МД"));
		tst_value[1].attr=m_api->m_doc_mgr.a_doc_add_dt_code;

		apidata.NET_FindInstancesWithAttrValues(m_api->m_doc_mgr.e_doc,2,&tst_value[0],ext,false);
		if(ext.Size==0)
		{
			tst_value[1].value.Set(APL_T("МС"));
			apidata.NET_FindInstancesWithAttrValues(m_api->m_doc_mgr.e_doc,2,&tst_value[0],ext,false);
			if(ext.Size==0) 
			{

				CString id2=buf+APL_T("МС");
				tst_value[0].value.Set(id2);
				tst_value[1].value.Set(APL_T("МС"));
				apidata.NET_FindInstancesWithAttrValues(m_api->m_doc_mgr.e_doc,2,&tst_value[0],ext,false);
				if(ext.Size==0) 
				{
					id2=buf+APL_T("МД");
					tst_value[0].value.Set(id2);
					tst_value[1].value.Set(APL_T("МД"));
					apidata.NET_FindInstancesWithAttrValues(m_api->m_doc_mgr.e_doc,2,&tst_value[0],ext,false);
					if(ext.Size==0) return true;
				}
			}
		}

		CaplInstance *doc2=ext[0];
		m_api->m_doc_mgr.LoadDocInfo(doc2);

		// Определяем версию
		CaplInstance *rev2=0;
		
		//apidata.GetAttr(doc,m_api->m_doc_mgr.a_apl_doc_wf_state,buf);
		//if(buf!=_T("approved")) apidata.GetAttr(doc2,m_api->m_doc_mgr.a_apl_doc_active,rev2);
		//else
		
		tst_value[0].value.Set(item);
		tst_value[0].attr=m_api->m_change_mgr.a_avc_new_rev;
		apidata.NET_FindInstancesWithAttrValues(m_api->m_change_mgr.e_avc,1,&tst_value[0],ext,false);

		if(ext.GetSize()==0)
		{
			apidata.GetAttr(doc2,m_api->m_doc_mgr.a_apl_doc_active,rev2);
			*pitem2=rev2;
			return true;
		}
		if(ext.GetSize()>1)
		{
			AfxMessageBox(APL_T("Существует несколько изменений устанавливающих данную версию 2D документа активной!\n\n3D Модель не будет подписана автоматически!"), MB_ICONSTOP|MB_OK);
			return true;
		}
		if(ext.GetSize()==1) // Нашли пакет - ищем связанную версию
		{
			CaplLoadData ld(&(m_api->m_data));
			int k=ld.AddQuery(_T('i'),ext[0]->GetId(),0,m_api->m_change_mgr.a_chng_item_of_chng,true,true);
			ld.AddQuery(_T('d'),k,0,m_api->m_change_mgr.a_chng_items,true,true);
			ld.LoadEx();
			CaplInstance *chng,*rev3,*doc3;
			aplExtent ext_chng_items;
			apidata.GetAttr(ext[0],m_api->m_change_mgr.a_chng_item_of_chng,chng);
			apidata.GetAttr(chng,m_api->m_change_mgr.a_chng_items,ext_chng_items);
			int i;

			for(i=0;i<ext_chng_items.GetSize();i++)
			{
				CaplInstance *chng_item=ext_chng_items[i];
				if(!apidata.IsKindOf(chng_item,m_api->m_change_mgr.e_avc)) continue;
				doc3=0;
				apidata.GetAttr(chng_item,m_api->m_change_mgr.a_avc_new_rev,rev3);
				if(0!=rev3)	apidata.GetAttr(rev3,m_api->m_doc_mgr.a_apl_doc_rev_doc,doc3);
				if(doc3==doc2)
				{
					*pitem2=rev3;
					break;
				}
			}
			if(0==*pitem2)
			{
				
				int rez=AfxMessageBox(APL_T("Для подписываемого 2D документа наден 3D документ и правила изменения!\n\nНо в найденном изменении отсутствует правило для назначения активной версии 3D документа.\n\nПодписать автоматически активную версию 3D документа?")
					, MB_YESNOCANCEL|MB_ICONWARNING);
				
				if(rez==IDNO)return true;
				if(rez==IDCANCEL)return false;
			}
		}
		apidata.GetAttr(doc2,m_api->m_doc_mgr.a_apl_doc_active,rev2);
		*pitem2=rev2;
		return true;
	}
	else if(m_api->m_data.IsKindOf(item, m_api->m_change_mgr.e_chng))
	{
		// Ищем документ связанный с изменением
		CString cng_id;
		CaplInstance *item2=0;
		m_api->m_data.GetAttr(item,m_api->m_change_mgr.a_chng_id,cng_id);
		if(cng_id!=_T("")) 
		{
			CaplInstance *doc=m_api->m_doc_mgr.FindDocById(cng_id);
			if(0!=doc)
			{	
				m_api->m_doc_mgr.LoadDocInfo(doc);
				m_api->m_data.GetAttr(doc,m_api->m_doc_mgr.a_apl_doc_active, item2);
			}
		}
		if(0==item2)
		{
			if(bSzv)
			{
				if(IDYES==AfxMessageBox(APL_T("Для пакета изменений не сгенерировано извещение!\n\nВы всё равно хотите подписать пакет изменений?"), MB_YESNO|MB_ICONEXCLAMATION))
					return true;
				return false;
			}
			else
			{
				AfxMessageBox(APL_T("Для пакета изменений не сгенерировано извещение!"), MB_OK|MB_ICONEXCLAMATION);
				return false;
			}
		}
		*pitem2=item2;
	}
	return true;
}



void CreateApprovalGrpzPostProcessing(CaplAPI *m_api, CaplInstance *inst, CaplInstance *status, CString sRole, CString sDscr)  
{
	if(!m_api->m_options_mgr.CheckInstallCode(_T("grpz"))) return;

	// Простановка срочности для ПИ
	if(m_api->m_data.IsKindOf(inst, m_api->m_change_mgr.e_chng))
	{
		CString sStatus;
		m_api->m_data.GetAttr(status, m_api->m_appr_mgr.a_appr_status_name, sStatus);
		sStatus.MakeLower();
		if(sStatus.Find(APL_T("срочно"))>=0)
		{
			m_api->m_data.PutAttr(inst, m_api->m_change_mgr.a_chng_urgency, APL_T("Срочно"));
		}
		else if(sStatus.Find(APL_T("согласовано"))>=0)
		{
			CString buf=sRole; buf.MakeLower();
			CaplAttr *attr=0;
			if(buf.Find(_T("180"))>=0) attr=m_api->m_change_mgr.a_chng_to_date;
			else if(buf.Find(_T("103"))>=0) attr=m_api->m_change_mgr.a_chng_complect_num;

			if(0!=attr)
			{
				CaplAdminModeProvider adminmode(&(m_api->m_data),-1, -1,DEF_SOURCE);
				m_api->m_data.PutAttr(inst, attr, sDscr);
				m_api->SaveChanges();
			}
		}
	}
};

// фиксируем примечания службы автоматизированного кодирования
void CreateApprovalGrpzFixAK_Note(CaplAPI *m_api, CaplInstance *item, CaplInstance *status, CString sRole, CaplInstance *po, CaplInstance *approval)  
{
	if(0==m_api || 0==item || 0==approval) return;
	if(!m_api->m_options_mgr.CheckInstallCode(_T("grpz"))) return;
	if(!m_api->m_data.IsKindOf(item, m_api->m_doc_mgr.e_apl_doc_rev)) return;
	if(sRole!=APL_T("АК 159")) return;

	CaplInstance *doc;
	m_api->m_data.GetAttr(item, m_api->m_doc_mgr.a_apl_doc_rev_doc, doc);
	CString sSytem;
	m_api->m_data.GetAttr(doc, m_api->m_doc_mgr.a_apl_doc_system, sSytem);
	if(sSytem!=_T("GenerateIe"))  return;

	aplExtent ext_notes;
	m_api->m_appr_mgr.FindAssociatedNotes(item,ext_notes);
	int i;
	bool bNeedSave=false;
	for(i=0;i<ext_notes.GetSize();i++)
	{
		CaplInstance *inst7,*note=ext_notes[i];
		m_api->m_data.GetAttr(note,m_api->m_appr_mgr.a_note_author,inst7);
		if(inst7!=po) continue;
		m_api->m_data.GetAttr(note,m_api->m_appr_mgr.a_note_approval,inst7);
		if(0!=inst7) continue;

		bNeedSave=true;

		m_api->m_data.PutAttr(note,m_api->m_appr_mgr.a_note_approval,approval);
		m_api->m_data.PutAttr(note,m_api->m_appr_mgr.a_note_nohide, true);
	}
	if(bNeedSave)m_api->SaveChanges();

};

CaplAutorizationManager::CaplAutorizationManager()
{
	m_bHolydeysLoaded=false;
	m_holydays_map.Clear();

	m_bAllowCreateOrgInSelect=false;
	m_bAllowCreatePersonInSelect=false;
}

CaplAutorizationManager::~CaplAutorizationManager()
{	

}

/*CCryptographicProvider *CaplAutorizationManager::GetCryptProv()
{
	if(m_crypt_prov==0) m_crypt_prov=new CCryptographicProvider;
	return m_crypt_prov;
}*/


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

	e_apl_appr=m_data->GetEntityBN(_T("approval"));
	e_apl_appr_pers_org=m_data->GetEntityBN(_T("apl_approval_person_organization"));

	a_appr_status=m_data->GetAttrDefinition(e_apl_appr,_T("status"));
	a_appr_level=m_data->GetAttrDefinition(e_apl_appr,_T("level"));
	a_appr_item=m_data->GetAttrDefinition(e_apl_appr_pers_org,_T("item"));
	a_appr_role=m_data->GetAttrDefinition(e_apl_appr_pers_org,_T("role"));
	a_appr_active=m_data->GetAttrDefinition(e_apl_appr_pers_org,_T("active"));
	a_appr_appr_date_time_s=m_data->GetAttrDefinition(e_apl_appr_pers_org,_T("approval_date_time_s"));
	a_appr_state=m_data->GetAttrDefinition(e_apl_appr_pers_org,_T("state"));
	a_appr_pers_org=m_data->GetAttrDefinition(e_apl_appr_pers_org,_T("person_organization"));
	a_appr_dg_sign_hash=m_data->GetAttrDefinition(e_apl_appr_pers_org,_T("digital_sign_hash"));
	a_appr_dg_sign_met=m_data->GetAttrDefinition(e_apl_appr_pers_org,_T("digital_sign_metdod"));
	a_appr_dg_sign_inventory=m_data->GetAttrDefinition(e_apl_appr_pers_org,_T("digital_sign_inventory"));
	a_appr_dg_sign_snapshot=m_data->GetAttrDefinition(e_apl_appr_pers_org,_T("digital_sign_snapshot"));
	a_appr_dg_sign=m_data->GetAttrDefinition(e_apl_appr_pers_org,_T("digital_sign"));
	a_appr_dg_sign_open_key=m_data->GetAttrDefinition(e_apl_appr_pers_org,_T("digital_sign_open_key"));
	a_appr_dg_sign_author=m_data->GetAttrDefinition(e_apl_appr_pers_org,_T("digital_sign_author"));
	a_appr_dg_sign_cert=m_data->GetAttrDefinition(e_apl_appr_pers_org,_T("digital_sign_cert"));

	a_appr_appr_owner=m_data->GetAttrDefinition(e_apl_appr_pers_org,_T("approval_owner"));
	a_appr_po_entries=m_data->GetAttrDefinition(e_apl_appr_pers_org,_T("entries"));
	a_appr_po_item_note= m_data->GetAttrDefinition(e_apl_appr_pers_org,_T("item_note"));
	a_appr_entries_used= m_data->GetAttrDefinition(e_apl_appr_pers_org,_T("entries_used"));

	a_appr_format= m_data->GetAttrDefinition(e_apl_appr_pers_org,_T("format"));
	a_appr_total_sheets_count= m_data->GetAttrDefinition(e_apl_appr_pers_org,_T("total_sheets_count"));
	a_appr_total_sheets_count_a4= m_data->GetAttrDefinition(e_apl_appr_pers_org,_T("total_sheets_count_a4"));

	e_appr_rel=m_data->GetEntityBN(_T("approval_relationship"));
	
	a_appr_rel_name=m_data->GetAttrDefinition(e_appr_rel,_T("name"));
	a_appr_rel_descr=m_data->GetAttrDefinition(e_appr_rel,_T("description"));
	a_appr_rel_relating=m_data->GetAttrDefinition(e_appr_rel,_T("relating_approval"));
	a_appr_rel_related=m_data->GetAttrDefinition(e_appr_rel,_T("related_approval"));
	
	e_appr_status=m_data->GetEntityBN(_T("approval_status"));
	a_appr_status_name=m_data->GetAttrDefinition(e_appr_status,_T("name"));
	a_appr_status_icon=m_data->GetAttrDefinition(e_appr_status,_T("icon_index"));
	a_appr_status_set_state=m_data->GetAttrDefinition(e_appr_status,_T("set_state"));
	a_appr_status_str4label=m_data->GetAttrDefinition(e_appr_status,_T("str4label"));

	CHECK_ZERO_ATTR(a_appr_status_set_needs_work, m_data->GetAttrDefinition(e_appr_status,_T("set_needs_work")));
	CHECK_ZERO_ATTR(a_appr_status_unset_needs_work, m_data->GetAttrDefinition(e_appr_status,_T("unset_needs_work")));
	CHECK_ZERO_ATTR(a_appr_status_need_description, m_data->GetAttrDefinition(e_appr_status,_T("need_description")));

	CHECK_ZERO_ATTR(e_appr_cont,                               m_data->GetEntityBN(_T("apl_approval_container")));
	CHECK_ZERO_ATTR(a_appr_cont_abbreviation,                  m_data->GetAttrDefinition(e_appr_cont, _T("abbreviation")));
	CHECK_ZERO_ATTR(a_appr_cont_description,                   m_data->GetAttrDefinition(e_appr_cont, _T("description")));
	CHECK_ZERO_ATTR(a_appr_cont_approval,                      m_data->GetAttrDefinition(e_appr_cont, _T("approval")));
	CHECK_ZERO_ATTR(a_appr_cont_item,						   m_data->GetAttrDefinition(e_appr_cont, _T("item")));
	CHECK_ZERO_ATTR(a_appr_cont_status_code,                   m_data->GetAttrDefinition(e_appr_cont, _T("status_code")));
	CHECK_ZERO_ATTR(a_appr_cont_date,						   m_data->GetAttrDefinition(e_appr_cont, _T("date")));	
	CHECK_ZERO_ATTR(a_appr_cont_person,						   m_data->GetAttrDefinition(e_appr_cont, _T("person")));	
	
	e_po_role=m_data->GetEntityBN(_T("person_and_organization_role"));
	a_po_role_name=m_data->GetAttrDefinition(e_po_role,_T("name"));
	a_po_role_system=m_data->GetAttrDefinition(e_po_role,_T("system"));

	a_po_role_contexts = m_data->GetAttrDefinition(e_po_role,_T("contexts"));
	a_po_role_document_types = m_data->GetAttrDefinition(e_po_role,_T("document_types"));
	a_po_role_status = m_data->GetAttrDefinition(e_po_role,_T("approval_status"));
	a_po_role_specified_contexts_set = m_data->GetAttrDefinition(e_po_role,_T("specified_contexts_set"));
	a_po_role_specified_document_types_set = m_data->GetAttrDefinition(e_po_role,_T("specified_document_types_set"));
	a_po_role_specified_status_set = m_data->GetAttrDefinition(e_po_role,_T("specified_approval_status_set"));
	a_po_role_system_buf = m_data->GetAttrDefinition(e_po_role,_T("system_buf"));
	a_po_role_ro_buf = m_data->GetAttrDefinition(e_po_role,_T("ro_buf"));
	a_po_role_interface_elements = m_data->GetAttrDefinition(e_po_role,_T("interface_elements"));
	a_po_role_data_class = m_data->GetAttrDefinition(e_po_role,_T("data_class"));	
	a_po_role_auto_save_user_column_settings = m_data->GetAttrDefinition(e_po_role,_T("auto_save_user_column_settings"));	
	
	e_pers_org	= m_data->GetEntityBN(_T("person_and_organization"));
	e_person	= m_data->GetEntityBN(_T("person"));
	e_org		= m_data->GetEntityBN(_T("organization"));
	e_org_rel	= m_data->GetEntityBN(_T("organization_relationship"));

	a_po_the_pers	= m_data->GetAttrDefinition(e_pers_org, _T("the_person"));
	a_po_the_org	= m_data->GetAttrDefinition(e_pers_org, _T("the_organization"));
	a_po_start_date = m_data->GetAttrDefinition(e_pers_org, _T("start_date"));
	a_po_end_date	= m_data->GetAttrDefinition(e_pers_org, _T("end_date"));
	a_po_person_pos	= m_data->GetAttrDefinition(e_pers_org, _T("person_position"));
	a_po_code		= m_data->GetAttrDefinition(e_pers_org, _T("code"));

	a_pers_id			= m_data->GetAttrDefinition(e_person, _T("id"));
	a_pers_last_name	= m_data->GetAttrDefinition(e_person, _T("last_name"));
	a_pers_first_name	= m_data->GetAttrDefinition(e_person, _T("first_name"));
	a_pers_code			= m_data->GetAttrDefinition(e_person, _T("code"));
	a_pers_middle_names	= m_data->GetAttrDefinition(e_person, _T("middle_names"));
	a_pers_prefix_titles= m_data->GetAttrDefinition(e_person, _T("prefix_titles"));
	a_pers_suffix_titles= m_data->GetAttrDefinition(e_person, _T("suffix_titles"));
	a_pers_roles		= m_data->GetAttrDefinition(e_person, _T("apl_person_roles"));
	a_pers_descr		= m_data->GetAttrDefinition(e_person, _T("description"));
	a_pers_forum_last_visit_date = m_data->GetAttrDefinition(e_person,_T("forum_last_visit_date"));
	a_pers_phone =		  m_data->GetAttrDefinition(e_person, _T("phone"));
	a_pers_actual_address =		  m_data->GetAttrDefinition(e_person, _T("actual_address"));
	a_pers_e_mail =		  m_data->GetAttrDefinition(e_person, _T("e_mail"));
	a_pers_send_copy_message_to_email =		  m_data->GetAttrDefinition(e_person, _T("send_copy_message_to_email"));
	a_pers_mail_template =		  m_data->GetAttrDefinition(e_person, _T("mail_template"));
	a_pers_options =		  m_data->GetAttrDefinition(e_person, _T("options"));
	
	a_org_id=m_data->GetAttrDefinition(e_org,_T("id"));
	a_org_name=m_data->GetAttrDefinition(e_org,_T("name"));
	a_org_name_eng = m_data->GetAttrDefinition(e_org, _T("name_eng"));
	a_org_descr=m_data->GetAttrDefinition(e_org,_T("description"));
	a_org_type = m_data->GetAttrDefinition(e_org, _T("type"));
	a_org_warehouse = m_data->GetAttrDefinition(e_org, _T("recalc_goods_count"));
	a_org_tranz_counter = m_data->GetAttrDefinition(e_org, _T("tranzaction_counter"));
	a_org_successor = m_data->GetAttrDefinition(e_org, _T("successor"));
	a_org_guid = m_data->GetAttrDefinition(e_org, _T("guid"));

	a_org_inn = m_data->GetAttrDefinition(e_org, _T("inn"));
	a_org_kpp = m_data->GetAttrDefinition(e_org, _T("kpp"));
	a_org_ogrn = m_data->GetAttrDefinition(e_org, _T("ogrn"));
	a_org_okpo = m_data->GetAttrDefinition(e_org, _T("okpo"));
	a_org_cage_code = m_data->GetAttrDefinition(e_org, _T("cage_code"));
	a_org_legal_address = m_data->GetAttrDefinition(e_org, _T("legal_address"));
	a_org_actual_address = m_data->GetAttrDefinition(e_org, _T("actual_address"));
	a_org_postal_address = m_data->GetAttrDefinition(e_org, _T("postal_address"));
	a_org_start_date = m_data->GetAttrDefinition(e_org, _T("start_date"));
	a_org_end_date = m_data->GetAttrDefinition(e_org, _T("end_date"));
	a_org_phone = m_data->GetAttrDefinition(e_org, _T("phone"));
	a_org_fax = m_data->GetAttrDefinition(e_org, _T("fax"));
	a_org_e_mail = m_data->GetAttrDefinition(e_org, _T("e_mail"));
	a_org_web = m_data->GetAttrDefinition(e_org, _T("web"));
	a_org_bik = m_data->GetAttrDefinition(e_org, _T("bik"));
	a_org_default_account = m_data->GetAttrDefinition(e_org, _T("default_account"));
	a_org_chief = m_data->GetAttrDefinition(e_org, _T("chief"));
	a_org_country = m_data->GetAttrDefinition(e_org, _T("country"));
	a_org_federal_subject =  m_data->GetAttrDefinition(e_org, _T("federal_subject"));
	a_org_classes = m_data->GetAttrDefinition(e_org, _T("classes"));
	a_org_date_actual = m_data->GetAttrDefinition(e_org, _T("date_actual"));
	a_org_city = m_data->GetAttrDefinition(e_org, _T("city"));
	a_org_coordinates = m_data->GetAttrDefinition(e_org, _T("coordinates"));
	

	e_org_account	= m_data->GetEntityBN(_T("organization_account"));
	a_org_account_org = m_data->GetAttrDefinition(e_org_account, _T("organization"));
	a_org_account_bank = m_data->GetAttrDefinition(e_org_account, _T("bank"));
	a_org_account_type = m_data->GetAttrDefinition(e_org_account, _T("type"));
	a_org_account_number = m_data->GetAttrDefinition(e_org_account, _T("number"));
	a_org_account_description = m_data->GetAttrDefinition(e_org_account, _T("description"));
	a_org_account_cor_account = m_data->GetAttrDefinition(e_org_account, _T("correspondent_account"));

	a_org_rel_name=m_data->GetAttrDefinition(e_org_rel,_T("name"));
	a_org_rel_descr=m_data->GetAttrDefinition(e_org_rel,_T("description"));
	a_org_rel_relating=m_data->GetAttrDefinition(e_org_rel,_T("relating_organization"));
	a_org_rel_related=m_data->GetAttrDefinition(e_org_rel,_T("related_organization"));

	e_apl_org_type = m_data->GetEntityBN(_T("apl_organization_type"));
	a_apl_org_type_name = m_data->GetAttrDefinition(e_apl_org_type, _T("name"));


	e_apl_user=m_data->GetEntityBN(_T("apl_user"));
	e_apl_access_agent=m_data->GetEntityBN(_T("apl_access_agent"));
	e_apl_workgroup=m_data->GetEntityBN(_T("apl_workgroup"));
	a_apl_user_name=m_data->GetAttrDefinition(e_apl_user,_T("name"));
	a_apl_user_descript=m_data->GetAttrDefinition(e_apl_user,_T("description"));
	a_apl_user_po=m_data->GetAttrDefinition(e_apl_user,_T("personality"));
	a_apl_user_groups=m_data->GetAttrDefinition(e_apl_user,_T("groups"));
	a_apl_user_is_ro=m_data->GetAttrDefinition(e_apl_user,_T("read_only"));
	a_apl_user_is_ar=m_data->GetAttrDefinition(e_apl_user,_T("all_read"));
	a_apl_user_is_disabled=m_data->GetAttrDefinition(e_apl_user,_T("disabled"));
	a_apl_user_for_web_server=m_data->GetAttrDefinition(e_apl_user,_T("for_web_server"));	
	a_apl_user_access_pattern=m_data->GetAttrDefinition(e_apl_user,_T("access_pattern"));	


	e_apl_acc_pat=m_data->GetEntityBN(_T("apl_access_pattern"));
	a_apl_acc_pat_name=m_data->GetAttrDefinition(e_apl_acc_pat,_T("name"));
	a_apl_acc_pat_pattern=m_data->GetAttrDefinition(e_apl_acc_pat,_T("pattern"));

	e_official = m_data->GetEntityBN(_T("apl_official"));
	a_official_id = m_data->GetAttrDefinition(e_official,_T("id"));
	a_official_descr = m_data->GetAttrDefinition(e_official,_T("description"));
	a_official_roles = m_data->GetAttrDefinition(e_official,_T("roles"));
	a_official_owner = m_data->GetAttrDefinition(e_official,_T("owner"));
	a_official_owner_hist = m_data->GetAttrDefinition(e_official,_T("owner_history"));
	a_official_act_person = m_data->GetAttrDefinition(e_official,_T("actual_person"));
	a_official_act_person_hist = m_data->GetAttrDefinition(e_official,_T("actual_person_history"));
	a_official_possible_persons = m_data->GetAttrDefinition(e_official,_T("possible_persons"));

	e_official_hist = m_data->GetEntityBN(_T("apl_official_history"));
	a_off_hist_person = m_data->GetAttrDefinition(e_official_hist,_T("person"));
	a_off_hist_date = m_data->GetAttrDefinition(e_official_hist,_T("date"));
	a_off_hist_descr = m_data->GetAttrDefinition(e_official_hist,_T("description"));
	a_off_hist_user = m_data->GetAttrDefinition(e_official_hist,_T("user"));

	a_appr_notes = m_data->GetAttrDefinition(e_apl_appr_pers_org,_T("notes"));
	a_appr_attachment = m_data->GetAttrDefinition(e_apl_appr_pers_org,_T("attachment"));
	a_appr_revocation_date_time = m_data->GetAttrDefinition(e_apl_appr_pers_org,_T("revocation_date_time"));
	
	// настройка армов
	e_arm = m_data->GetEntityBN(_T("apl_arm"));
	a_arm_name = m_data->GetAttrDefinition(e_arm, _T("name"));
	a_arm_roles = m_data->GetAttrDefinition(e_arm, _T("roles"));

	e_arm_role = m_data->GetEntityBN(_T("apl_arm_role"));
	a_arm_role_name = m_data->GetAttrDefinition(e_arm_role, _T("name"));
	a_arm_unwork_role = m_data->GetAttrDefinition(e_arm_role, _T("unwork_role"));
	a_arm_unwork_status = m_data->GetAttrDefinition(e_arm_role, _T("unwork_status"));
	a_arm_role_rules = m_data->GetAttrDefinition(e_arm_role, _T("role_rules"));

	e_role_rule = m_data->GetEntityBN(_T("apl_status_rule"));
	a_role_rule_set = m_data->GetAttrDefinition(e_role_rule, _T("set"));
	a_role_rule_name = m_data->GetAttrDefinition(e_role_rule, _T("name"));


	// сертификат ЭЦП
	e_apl_digital_sign_open_key = m_data->GetEntityBN(_T("apl_digital_sign_open_key"));
	a_apl_digital_sign_open_key_person = m_data->GetAttrDefinition(e_apl_digital_sign_open_key, _T("the_person"));
	a_apl_digital_sign_open_key_open_key_metod = m_data->GetAttrDefinition(e_apl_digital_sign_open_key, _T("digital_sign_metdod"));
	a_apl_digital_sign_open_key_open_key_cert_serial_num = m_data->GetAttrDefinition(e_apl_digital_sign_open_key, _T("cert_serial_number"));
	a_apl_digital_sign_open_key_open_key_cert_issuer = m_data->GetAttrDefinition(e_apl_digital_sign_open_key, _T("cert_issuer"));
	a_apl_digital_sign_open_key_open_key_cert_subject = m_data->GetAttrDefinition(e_apl_digital_sign_open_key, _T("cert_subject"));
	a_apl_digital_sign_open_key_open_key_cert_blob = m_data->GetAttrDefinition(e_apl_digital_sign_open_key, _T("cert_blob"));
	a_apl_digital_sign_open_key_open_key = m_data->GetAttrDefinition(e_apl_digital_sign_open_key, _T("digital_sign_open_key"));
	a_apl_digital_sign_open_not_before = m_data->GetAttrDefinition(e_apl_digital_sign_open_key, _T("not_before"));
	a_apl_digital_sign_open_not_after = m_data->GetAttrDefinition(e_apl_digital_sign_open_key, _T("not_after"));
	a_apl_digital_sign_open_revocation_date = m_data->GetAttrDefinition(e_apl_digital_sign_open_key, _T("revocation_date"));
	a_apl_digital_sign_open_key_container = m_data->GetAttrDefinition(e_apl_digital_sign_open_key, _T("digital_sign_container"));
	a_apl_digital_sign_open_key_author = m_data->GetAttrDefinition(e_apl_digital_sign_open_key, _T("author"));
	a_apl_digital_sign_cert_type = m_data->GetAttrDefinition(e_apl_digital_sign_open_key, _T("cert_type"));
	a_apl_digital_sign_open_key_confidential = m_data->GetAttrDefinition(e_apl_digital_sign_open_key, _T("confidential"));
	
	e_calendar_holyday = m_data->GetEntityBN(_T("apl_calendar_holiday"));
	a_calendar_holyday_day = m_data->GetAttrDefinition(e_calendar_holyday, _T("apl_calendar_holiday_date"));

	e_role_colset = m_data->GetEntityBN(_T("apl_role_saved_column_set"));
	a_role_colset_role = m_data->GetAttrDefinition(e_role_colset, _T("role"));
	a_role_colset_view_name = m_data->GetAttrDefinition(e_role_colset, _T("view_name"));
	a_role_colset_column_set = m_data->GetAttrDefinition(e_role_colset, _T("column_set"));

	m_bHolydeysLoaded=false;
	m_holydays_map.Clear();

	return true;
}

//*************************************************************
void CaplAutorizationManager::Detach()
{
	m_data=0;

	m_bHolydeysLoaded=false;
	m_holydays_map.Clear();


	e_apl_appr=0;
	e_apl_appr_pers_org=0;

	a_appr_status=0;
	a_appr_level=0;
	a_appr_item=0;
	a_appr_role=0;
	a_appr_active=0;
	a_appr_appr_date_time_s=0;
	a_appr_state=0;
	a_appr_pers_org=0;
	a_appr_dg_sign_hash=0;
	a_appr_dg_sign_met=0;
	a_appr_dg_sign=0;
	a_appr_dg_sign_open_key=0;
	a_appr_appr_owner=0;
	a_appr_dg_sign_inventory=0;
	a_appr_dg_sign_snapshot=0;

	
	a_appr_dg_sign_author=0;
	a_appr_dg_sign_cert=0;

	e_appr_rel=0;
	
	a_appr_rel_name=0;
	a_appr_rel_descr=0;
	a_appr_rel_relating=0;
	a_appr_rel_related=0;

	e_appr_cont = 0;
	a_appr_cont_abbreviation = 0;
	a_appr_cont_description = 0;
	a_appr_cont_approval = 0;  
	a_appr_cont_person = 0;
	a_appr_cont_item = 0;
	a_appr_cont_status_code = 0;
	a_appr_cont_date = 0;
	
	e_appr_status = NULL; a_appr_status_name = NULL;
	a_appr_status_icon = NULL;
	a_appr_status_set_state=0; a_appr_status_str4label=0; a_appr_status_set_needs_work=0; a_appr_status_unset_needs_work=0;
	a_appr_status_need_description=0;
	a_appr_po_item_note= NULL;
	a_appr_entries_used = NULL;
	a_appr_format= 0;
	a_appr_total_sheets_count= 0;
	a_appr_total_sheets_count_a4= 0;
	
	e_po_role = NULL; a_po_role_name = NULL; a_po_role_system=0;
	a_po_role_contexts = NULL;
	a_po_role_document_types = NULL;
	a_po_role_status = NULL;
	a_po_role_specified_contexts_set = NULL;
	a_po_role_specified_document_types_set = NULL;
	a_po_role_specified_status_set = NULL;
	a_po_role_system_buf = NULL;
	a_po_role_ro_buf = NULL;
	a_po_role_interface_elements = NULL;
	a_po_role_data_class = NULL;
	a_po_role_auto_save_user_column_settings = NULL;
	a_po_code = NULL;
	a_pers_forum_last_visit_date = NULL;

	e_pers_org=0;
	e_person=0;
	e_org=0;
	e_org_rel=0;

	a_po_the_pers = 0;
	a_po_the_org = 0;
	a_po_person_pos = 0;

	a_pers_id=0;
	a_pers_last_name=0;
	a_pers_first_name=0;
	a_pers_middle_names=0;
	a_pers_prefix_titles=0;
	a_pers_suffix_titles=0;
	a_pers_descr=0;
	a_pers_phone=0;
	a_pers_actual_address=0;
	a_pers_e_mail=0;
	a_pers_send_copy_message_to_email=0;
	a_pers_mail_template=0;
	a_pers_options=0;

	a_org_id=0;
	a_org_name=0;
	a_org_name_eng = 0;
	a_org_descr=0;
	a_org_type = NULL;
	a_org_successor=0;
	a_org_guid = 0;
	a_org_cage_code=0;
	a_org_successor=0;
	a_org_inn=0;
	a_org_kpp=0;
	a_org_ogrn=0;
	a_org_okpo=0;
	a_org_legal_address=0;
	a_org_actual_address=0;
	a_org_postal_address=0;
	a_org_start_date=0;
	a_org_end_date=0;
	a_org_phone=0;
	a_org_fax=0;
	a_org_e_mail=0;
	a_org_web=0;

	a_org_bik=0;
	a_org_default_account=0;
	a_org_chief=0;
	a_org_country=0;
	a_org_classes=0;
	a_org_date_actual=0;
	a_org_city = 0;
	a_org_coordinates = 0;


	e_org_account	=0;
	a_org_account_org =0;
	a_org_account_bank = 0;
	a_org_account_type = 0;
	a_org_account_number = 0;
	a_org_account_description = 0;
	a_org_account_cor_account = 0;

	a_org_rel_name=0;
	a_org_rel_descr=0;
	a_org_rel_relating=0;
	a_org_rel_related=0;
	a_org_warehouse=0;
	a_org_tranz_counter=0;

	e_apl_user=0; e_apl_access_agent=0;e_apl_workgroup=0; a_apl_user_name=0; a_apl_user_descript=0; a_apl_user_po=0;a_apl_user_groups=0;
	a_apl_user_is_ro=0;a_apl_user_is_ar=0;a_apl_user_is_disabled=0;
	a_apl_user_for_web_server = 0; a_apl_user_access_pattern = 0;

	e_apl_acc_pat=0;a_apl_acc_pat_name=0;a_apl_acc_pat_pattern=0;

	e_calendar_holyday=0;
	a_calendar_holyday_day=0;

	e_official = 0;
	a_official_id = 0;
	a_official_descr = 0;
	a_official_roles = 0;
	a_official_owner = 0;
	a_official_owner_hist = 0;
	a_official_act_person = 0;
	a_official_act_person_hist = 0;
	a_official_possible_persons = 0;

	e_official_hist = 0;
	a_off_hist_person = 0;
	a_off_hist_date = 0;
	a_off_hist_descr = 0;
	a_off_hist_user = 0;

	e_apl_digital_sign_open_key=0;
	a_apl_digital_sign_open_key_open_key_metod=0;
	a_apl_digital_sign_open_key_open_key_cert_serial_num=0;
	a_apl_digital_sign_open_key_open_key_cert_issuer=0;
	a_apl_digital_sign_open_key_open_key_cert_subject=0;
	a_apl_digital_sign_open_key_open_key_cert_blob=0;
	a_apl_digital_sign_open_key_open_key=0;
	a_apl_digital_sign_open_not_before=0;
	a_apl_digital_sign_open_not_after=0;
	a_apl_digital_sign_open_revocation_date=0;

	e_role_colset = 0;
	a_role_colset_role = 0;
	a_role_colset_view_name = 0;
	a_role_colset_column_set = 0;
}


bool CaplAutorizationManager::LoadDictionary()
{
	if(m_data==0) return false;
	if(e_apl_appr_pers_org==0) return false;
	if(!m_data->IsConnected())  return false;

	CaplLoadData ld(m_data,DEF_SOURCE);
	ld.AddQuery(_T('e'), 0, e_appr_status,0, true, true);
	ld.AddQuery(_T('e'), 0, e_po_role,0, true,true);

	if (!ld.LoadEx(true,0, APL_T("Чтение ролей и статусов"))) 
	{
		if(m_api->m_ModeInteractive)AfxMessageBox(S::ErrorLoadDataMgr(),MB_OK|MB_ICONSTOP);
		return false;
	}
	return true;
}

bool CaplAutorizationManager::LoadOrgStruct(aplExtent *ext)
{
	if(m_data==0) return false;
	if(e_apl_appr_pers_org==0) return false;
	if(ext!=0) ext->Clear();

	// Чтение только актуальных person_and_organization.  Но он получается заметно меделеннее
	bool bNotLoadOrgStructHistory=false;

	//DWORD t0=GetTickCount();
	//DWORD t00=0,tz0=0;

	if(!LoadDictionary()) return false;

	if(m_data->IsConnected())
	{
		aplExtent tmp_ext, full_ext;
		tmp_ext.Unique = false;
		CaplLoadData ld(m_data,DEF_SOURCE);
		//ld.AddQuery(_T('e'), 0, e_appr_status,0, true, true);
		//ld.AddQuery(_T('e'), 0, e_po_role,0, true,true);
		ld.AddQuery(_T('e'),  0, e_person,0, true,true);
		ld.AddQuery(_T('e'),  0, e_official,0, true,true);
		ld.AddQuery(_T('e'),  0, e_official_hist,0, true,true);
		ld.AddQuery(_T('e'),  0, e_org,0, true,true);
		ld.AddQuery(_T('e'),  0, e_org_rel,0, true,true);

		if(!bNotLoadOrgStructHistory)
		{
			ld.AddQuery(_T('e'),  0, e_pers_org,0, true,true);
		}
		ld.AddQuery(_T('e'),  0, e_apl_access_agent,0, true,true);
		//ld.AddQuery(_T('e'),  0, e_apl_user,0, true,true); - предыдущий запрос вернет и юзеров, и их группы
		ld.AddQuery(_T('e'),  0, e_apl_acc_pat,0, true,true);
		
		if (!ld.LoadEx(true,0, APL_T("Чтение оргструктуры"))){
			if(m_data->GetLastAplError()!=APL_SOCK_OPERATION_IN_PROGRESS){
				if(m_api->m_ModeInteractive)AfxMessageBox(S::ErrorLoadDataMgr(),MB_OK|MB_ICONSTOP);
			}
		}else{
			// чтобы при каждом show_in_list_ctrl и т.п. не загружались пользователи
			m_data->m_load_access_agent_from_serv=false;
		}

		if(bNotLoadOrgStructHistory)
		{
			// Читаем только актуальные связи оргсруктуры
			// Но так получается очень меделенно (в 2 раза дольше, чем чтоение всех связей)

			//t00=GetTickCount();

			// Вариант 1. 1.2 сек  ( 5 сек. на всё)
			aplExtent ext_actual_po;
			CaplAttrValue tst_value[1];
			tst_value[0].value.Set(_T(""));
			tst_value[0].attr=a_po_end_date;
			apidata.NET_FindInstancesWithAttrValues(e_pers_org,1,&tst_value[0],ext_actual_po,false);
			if(ext_actual_po.GetSize()>0)
			{
				CaplLoadData ld(&(m_api->m_data));
				for(int i=0;i<ext_actual_po.GetSize();i++)
				{
					ld.AddQuery(0,ext_actual_po[i],true); 
					if(ld.m_queries.GetSize()>=4000)
					{
						ld.LoadEx();
						ld.ClearQuery();
					}
				}
				if(ld.m_queries.GetSize()>0) ld.LoadEx();
			}

			// Вариант 2. 2.9 сек. (7 сек. на всё)
			/*aplExtent ext_out;
			CString sQuery=_T("SELECT_LOAD_ALL Ext_ FROM Ext_{person_and_organization.end_date=''} END_SELECT");
			if(m_data->NET_QueryEditParse(sQuery))	m_data->NET_QueryExecute(ext_out,APL_T("Чтение оргструктуры (2)"));
			ext_out.Clear();*/

			//tz0=GetTickCount()-t00;
		}
		
		if(ext!=0)
		{
			m_data->GetEntityExtent(e_appr_status,*ext);
			bool b_old_ext_unique=ext->Unique;
			ext->Unique=false;
			m_data->GetEntityExtent(e_po_role,tmp_ext);
			ext->Append(tmp_ext);
			m_data->GetEntityExtent(e_person,tmp_ext);
			ext->Append(tmp_ext);
			m_data->GetEntityExtent(e_official,tmp_ext);
			ext->Append(tmp_ext);
			m_data->GetEntityExtent(e_org,tmp_ext);
			ext->Append(tmp_ext);
			m_data->GetEntityExtent(e_org_rel,tmp_ext);
			ext->Append(tmp_ext);
			m_data->GetEntityExtent(e_apl_user,tmp_ext);
			ext->Append(tmp_ext);
			m_data->GetEntityExtent(e_apl_acc_pat,tmp_ext);
			ext->Append(tmp_ext);
			m_data->GetEntityExtent(e_official_hist,tmp_ext);
			ext->Append(tmp_ext);
			ext->Unique=b_old_ext_unique;
		}

		ld.ClearQuery();
		ld.AddQuery(_T('e'), 0, e_apl_digital_sign_open_key->id, 0, true,true);
		if (!ld.LoadEx(true,0, APL_T("Чтение сертификатов ЭП"))){
			if(m_data->GetLastAplError()!=APL_SOCK_OPERATION_IN_PROGRESS){
				if(m_api->m_ModeInteractive)AfxMessageBox(S::ErrorLoadDataMgr(),MB_OK|MB_ICONSTOP);
			}
		}

		if(ext!=0)
		{
			m_data->GetEntityExtent(e_apl_digital_sign_open_key,tmp_ext);
			ext->Append(tmp_ext);
		}

	}
	if(0!=m_api) m_api->m_bLoadedOrgstruct=true;

	//DWORD tz=GetTickCount()-t0;
	//CString buf;
	//buf.Format("Чтение оргструктуры  %i (%i)",tz0, tz);
	//AfxMessageBox(buf);

	return true;
}


//*************************************************************
bool CaplAutorizationManager::LoadItemApproval(CaplInstance* item, aplExtent &ext_approval,bool from_base, bool bReturnRevocated)
{
	aplExtent ext;
	ext.Add(item);
	return LoadItemApproval(ext, ext_approval, from_base, bReturnRevocated);
}
//****************************************************************
bool CaplAutorizationManager::LoadItemApproval(aplExtent &ext, aplExtent &ext_approval,bool from_base, bool bReturnRevocated)
{
	ext_approval.Clear();

	if(!m_api->m_data.IsDictLoad()) return false;
	
	aplExtent ext_items, ext_load;
	
	if(m_data->IsConnected() && from_base)
	{
		int i, r1;
		CaplLoadData ld(m_data,DEF_SOURCE);
		for(i=0; i<ext.GetSize(); i++)
		{
			CaplInstance *inst=ext[i];
			if(inst==NULL) continue;
			if(inst->IsDeleted()) continue;
			if(inst->GetAccessmode()>aplRO) continue;

			if(m_data->IsKindOf(inst,m_api->m_doc_mgr.e_doc))
			{
				m_data->GetAttr(inst,m_api->m_doc_mgr.a_apl_doc_active,inst);
				if(inst==NULL) continue;
				if(inst->IsDeleted()) continue;
				if(inst->GetAccessmode()>aplRO) continue;
			}

			ld.AddQuery(0, inst, true);
			ext_items.Add(inst);
		}
		if(ld.m_queries.GetSize()>0){
			r1 =	ld.AddQuery(_T('r'), 0, e_apl_appr_pers_org, a_appr_item, true,true);
			ld.AddQuery(_T('d'), r1, 0, a_appr_attachment,true,true);
			if(!m_api->m_bLoadedOrgstruct)
			{
				ld.AddQuery(_T('d'), r1, 0, a_appr_pers_org,true,true);
				ld.AddQuery(_T('d'), r1, 0, a_appr_appr_owner,true,true);
			}
			if(!ld.LoadEx(true,&ext_load))
			{
				if(m_data->GetLastAplError()!=APL_SOCK_OPERATION_IN_PROGRESS){
					if(m_api->m_ModeInteractive)AfxMessageBox(S::ErrorLoadDataMgr(),MB_OK|MB_ICONSTOP);
				}
			}
		}
	}
	
	int i;
	CString sRevDate;
	for(i=0;i<ext_load.Size;i++)
	{
		CaplInstance *appr=ext_load[i];
		if(appr==NULL) continue;
		if(appr->IsDeleted()) continue;
		if(appr->GetAccessmode()>aplRO) continue;
		if(!m_data->IsKindOf(appr,e_apl_appr)) continue;

		if(false==bReturnRevocated)
		{
			m_data->GetAttr(appr,a_appr_revocation_date_time,sRevDate);
			if(sRevDate!=_T(""))continue; // Подпись отменена.
		}

		CaplInstance *inst0;
		m_data->GetAttr(appr,a_appr_item,inst0);
		if(ext_items.Find(inst0)<0) continue;
		if(inst0!=0) ext_approval.Add(appr);
	}
	return true;
}
//****************************************************************

bool CaplAutorizationManager::LoadApprovalInfo(aplExtent &ext_approval)
{
	if(!m_api->m_data.IsDictLoad()) return false;

	int i;
	CaplLoadData ld(m_data,DEF_SOURCE);
	for(i=0; i<ext_approval.GetSize(); i++)
	{
		CaplInstance *appr=ext_approval[i];
		if(appr==NULL) continue;
		if(appr->GetId()==0) continue;
		if(appr->GetAccessmode()>aplRO) continue;
		ld.AddQuery(0, appr, true);
	}
	if(ld.m_queries.GetSize()>0)
	{
		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 CaplAutorizationManager::SelectPersonsOrganizations(long lMode, aplExtent &ext, bool bShowUserWG, bool Traverse,
													CString sTitle, CString sTreeTitle, aplExtent* rootExt, bool bExpand)
{
	if((lMode&APL_MODE_SELECT_PERSON)>0 && (lMode&APL_MODE_SELECT_PERSORG)>0) return false;

	if(!m_api->m_bLoadedOrgstruct)m_api->m_appr_mgr.LoadOrgStruct();
	
	CaplSetResourceHandle setres(module_inst);

	CSelectRecipientsDlg dlg;
	dlg.m_mode= lMode;
	dlg.m_api= m_api;
	dlg.m_bExpand= bExpand;
//	dlg.m_curPerson= m_sender;
	dlg.m_sTitle= sTitle;
	dlg.m_sTreeTitle= sTreeTitle;
	dlg.m_bTraverseTree= Traverse;
	dlg.m_bShowPerWG= bShowUserWG;
	if(rootExt!=0)
		for(int i= 0; i<rootExt->GetSize(); i++)
			dlg.m_poExt.Add(rootExt->GetAt(i));
	
	if(bShowUserWG)
	{
		dlg.m_curPerson=GetCurrentPerson();
		if(!dlg.m_curPerson) dlg.m_bShowPerWG= false;
	}


	for(int i= 0; i<ext.GetSize(); i++)
		dlg.m_resExt.Add(ext[i]);
	
	if(IDOK==dlg.DoModal())
	{
		ext.Clear();
		for(int i= 0; i<dlg.m_resExt.GetSize(); i++)
			ext.Add(dlg.m_resExt[i]);
		return true;
	}

	return false;
}
//****************************************************************
CaplInstance* CaplAutorizationManager::SelectPersonOrOrganization
		(long lMode, aplExtent &rootPO, CString sTitle, CString sTreeTitle, 
		 bool bExpand)
{
	CaplInstance* po= NULL;
	if((lMode&APL_MODE_SELECT_PERSON)>0 && (lMode&APL_MODE_SELECT_PERSORG)>0) return po;

	if(!m_api->m_bLoadedOrgstruct)m_api->m_appr_mgr.LoadOrgStruct();

	CaplSetResourceHandle setres(module_inst);

	CSelectRecipientsDlg dlg;
	dlg.m_mode= lMode;
	dlg.m_bExpand= bExpand;
	dlg.m_api= m_api;
	dlg.m_sTitle= sTitle;
	dlg.m_sTreeTitle= sTreeTitle;
	dlg.m_bShowPerWG= false;
	dlg.m_bSingleSelect= true;
	dlg.m_bTraverseTree= false;
	for(int i= 0; i<rootPO.GetSize(); i++)
		dlg.m_poExt.Add(rootPO[i]);

	if(IDOK==dlg.DoModal())
	{
		po= dlg.m_inst;
	}
	return po;
}

//****************************************************************
// Позволяет выбирать пользователя или группу пользователей
CaplInstance* CaplAutorizationManager::SelectAplUserOrGroup
		(long lMode, CString sTitle, CString sTreeTitle, bool bExpand)
{
	CaplInstance* apl_aa= NULL;
	if((lMode&APL_MODE_SELECT_USER)>0 && (lMode&APL_MODE_SELECT_USER_GROUP)>0) return apl_aa;
	
	CaplSetResourceHandle setres(module_inst);
	
	CSelectUsersDlg dlg;
	dlg.m_mode= lMode;
	dlg.m_api= m_api;
	dlg.m_sTitle= sTitle;
	dlg.m_sTreeTitle= sTreeTitle;
	
	if(IDOK==dlg.DoModal())
	{
		apl_aa= dlg.m_inst;
	}
	
	return apl_aa;
}

CaplInstance* CaplAutorizationManager::CreateWfApproval(CaplInstance* task, CaplInstance* item, CaplInstance *defStatus)
{
	if(m_data==0) return 0;
	if(e_apl_appr_pers_org==0) return 0;
	if(item==0) return 0;
	if(item->GetType()==0) return 0;
	if(!task) return NULL;

	if(item->GetAccessmode()>aplRO)
	{
		aplErrorMessage(S::NoAccessRight(),item);
		return 0;
	}

	if(0==GetCurrentPerson())
	{
		AfxMessageBox( APL_T("Анонимный пользователь не может создавать электронные подписи !!!"));
		return 0;
	}

	CString sLevel, sRole, sDt, sDscr, sMethod, sSign, sHash, sOpenKey, sSignOwner, sInventory, sSnapshot, sSignCert ;
	
	CaplInstance* DefRole;
	CString sDefStatus;

	CString date_time_s;
	CStringArray newFiles;
	aplExtent fileExt;
	CaplInstance* store_file;
	int i;

	CaplInstance* inst= NULL;
	CaplInstance* appr_inst= NULL;
	CaplInstance* Note=NULL;
	CaplInstance* activity= NULL;
	CaplInstance* status;
	aplExtent status_ext;
	aplExtent ext;

	if(m_api->m_data.IsKindOf(item, m_api->m_doc_mgr.e_apl_doc))
		m_api->m_data.GetAttr(item, m_api->m_doc_mgr.a_apl_doc_active, appr_inst);
	else
		appr_inst= item;


	/*Проверка наличия всех обязательных реквизитов и атрибутов*/
	// (копия куска из CreateApproval)
	if(m_data->IsKindOf(appr_inst, m_api->m_doc_mgr.e_apl_doc_rev))
	{
		//Проверяем реквизиты
		CString sMissingEntry;
		if(!m_api->m_doc_mgr.HasAllNecessaryEntries(appr_inst,true,&sMissingEntry))
		{
			if(m_api->m_ModeInteractive)
			{
				CString msg;
				msg.Format(APL_T("Заданы не все постоянные реквизиты.\n\n(Отсутствует реквизит '%s')\n\n Подписание невозможно."),LPCTSTR(sMissingEntry));
				AfxMessageBox( msg, MB_OK|MB_ICONSTOP);
			}
			return 0;
		}

		// проверяем атрибуты
		if(!m_api->m_doc_mgr.HasAllNecessaryDocRevAttr(appr_inst))
		{
			if(m_api->m_ModeInteractive) AfxMessageBox( APL_T("Не задан формат или количество листов.\n\nПодпись запрещена настройками"), MB_OK|MB_ICONSTOP);
			return 0;
		}

		//apidata.GetAttr(item,m_api->m_doc_mgr.a_apl_doc_rev_format,dlg.m_sFormat);
		//if(dlg.m_sFormat==_T("")) apidata.GetAttr(ciDoc,m_api->m_doc_mgr.a_doc_format,dlg.m_sFormat);

	}


	CaplEntity*	e_task= m_data->GetEntityBN(_T("apl_task"));
	CaplAttr*a_task_activity= m_data->GetAttrDefinition(e_task, _T("of_activity"));
	CaplEntity*	e_activity= m_data->GetEntityBN(_T("apl_activity"));
	CaplAttr*a_activity_role= m_data->GetAttrDefinition(e_activity, _T("role"));
	
	CaplEntity* e_act_rel= m_data->GetEntityBN(_T("apl_action_relationship"));
	CaplAttr*a_act_rel_from= m_data->GetAttrDefinition(e_act_rel, _T("from"));

	CaplEntity* e_act_secuence= m_data->GetEntityBN(_T("apl_action_secuence"));
	CaplAttr*a_act_secuence_status= m_data->GetAttrDefinition(e_act_secuence, _T("status"));
	CaplAttr*a_act_secuence_tmpl= m_data->GetAttrDefinition(e_act_secuence, _T("of_process_template"));
	CaplAttr*a_act_secuence_not_sign= m_data->GetAttrDefinition(e_act_secuence, _T("not_sign"));

	if(m_api->m_data.IsKindOf(task, e_task))
		m_api->m_data.GetAttr(task, a_task_activity, activity);
	else if(m_api->m_data.IsKindOf(task, e_activity))
		activity= task;
	
	if(!activity)
		return NULL;

	/*Зачитка статусов*/
	CaplLoadData ld(m_data,DEF_SOURCE);
	ld.AddQuery(_T('b'), activity->GetId(), e_act_secuence, a_act_rel_from, true,true);
	if (!ld.LoadEx())
	{
		if(apidata.GetLastAplError()!=APL_SOCK_OPERATION_IN_PROGRESS)
			AfxMessageBox( APL_T("Ошибка чтения данных (MGR)"), MB_OK|MB_ICONSTOP);
	}

	m_api->m_data.GetEntityExtent(e_act_rel, ext);
	for(i= 0; i<ext.GetSize(); ++i)
	{
		m_data->GetAttr(ext[i], a_act_rel_from, inst);
		if(activity==inst) 
		{
			m_api->m_data.GetAttr(ext[i], a_act_secuence_status, inst);
			if(inst)
				status_ext.Add(inst);
		}
	}	

	ld.LoadEx();
	ld.ClearQuery();
	ld.AddQuery(0, activity, true);
	ld.LoadEx();

	/*Получение роли*/
	m_api->m_data.GetAttr(activity, a_activity_role, DefRole);
	if(defStatus)
		m_api->m_data.GetAttr(defStatus, a_appr_status_name, sDefStatus);

	CaplInstance *item2=0; //документ связанный с изменением
	// Теперь проверка внутри
	// Обработки ГРПЗ
	//if(m_api->m_options_mgr.CheckInstallCode(_T("grpz")))
	{
		if(!CreateApprovalGrpzPreProcessing(m_api,item,&item2)) return 0;
	}

	CaplSetResourceHandle setres(module_inst);	

	CApprovalDlg dlg;

	dlg.m_api= m_api;
	dlg.m_mode= _T("Create");
	dlg.m_item= appr_inst;
	dlg.m_person_inst= GetCurrentPerson();
	dlg.m_pNote = &Note;
	dlg.m_sDefStatus= sDefStatus;
	dlg.m_DefRole= DefRole;
	dlg.m_status_ext.Append(status_ext);


	if(dlg.DoModal()!=IDOK) 
	{
		return NULL;
	}
	
	sRole= dlg.m_sRole;
	sLevel= dlg.m_sLevel;
	sDscr= dlg.m_sNotes;
	
	status= dlg.m_status_inst;
	date_time_s= dlg.m_dt;

	sMethod= dlg.m_sMethid;
	sSign= dlg.m_sSign;
	sHash= dlg.m_sHash;
	sOpenKey= dlg.m_sOpenKey;

	sSignOwner= dlg.m_sSignOwner;
	sInventory =dlg.m_sInventory;
	sSnapshot = dlg.m_sSnapShot;
	sSignCert  =dlg.m_sSignCert;

	newFiles.Append(dlg.m_newFiles);


	CString sStatusState,str4label;
	CaplInstance* doc_inst= NULL;
	m_data->GetAttr(status, a_appr_status_set_state, sStatusState);	
	m_data->GetAttr(status, a_appr_status_str4label, str4label);	
	
	bool bSetNeedWork, bUnSetNeedWork;
	m_data->GetAttr(status, a_appr_status_set_needs_work, bSetNeedWork);
	m_data->GetAttr(status, a_appr_status_unset_needs_work, bUnSetNeedWork);
	if(bSetNeedWork && bUnSetNeedWork) {bSetNeedWork=false; bUnSetNeedWork=false;}

	CaplInstance *created_approval= m_data->CreateInstance(e_apl_appr_pers_org);
	if(created_approval)
	{
		m_data->PutAttr(created_approval, a_appr_item, appr_inst);
		m_data->PutAttr(created_approval, a_appr_status, status);
		m_data->PutAttr(created_approval,a_appr_role, sRole);
		m_data->PutAttr(created_approval, a_appr_level, sLevel);
		m_data->PutAttr(created_approval, a_appr_notes, sDscr);
		
		m_data->PutAttr(created_approval,a_appr_pers_org, GetCurrentPerson());		
		m_data->PutAttr(created_approval,a_appr_appr_owner,(CaplInstance*)NULL);
		
		m_data->PutAttr(created_approval, a_appr_dg_sign_met, sMethod);
		m_data->PutAttr(created_approval, a_appr_dg_sign, sSign);
		m_data->PutAttr(created_approval, a_appr_dg_sign_open_key, sOpenKey);
		m_data->PutAttr(created_approval, a_appr_dg_sign_hash, sHash);
		m_data->PutAttr(created_approval, a_appr_dg_sign_author, sSignOwner);
		m_data->PutAttr(created_approval, a_appr_dg_sign_inventory, sInventory);
		m_data->PutAttr(created_approval, a_appr_dg_sign_snapshot, sSnapshot);	

		if(!sSign.IsEmpty()) m_data->PutAttr(created_approval, a_appr_entries_used, true);

		if(sSignCert!=_T(""))
		{
			long blob;
			if(!m_data->NET_SaveBlob(created_approval,a_appr_dg_sign_cert,sSignCert,blob))
			{
				AfxMessageBox( APL_T("Сертификат не найден!"),MB_OK|MB_ICONSTOP);
			}
			else
			{
				// удаляем сертификат, если он был
				if(!sSignCert.IsEmpty())
				{
					::SetFileAttributes(sSignCert, FILE_ATTRIBUTE_NORMAL);
					::DeleteFile(sSignCert);
				}
			}
		}

		// записываем значения реквизитов , участвующих в подписи
		CreateEntryApproval(appr_inst, created_approval);

		if(!sStatusState.IsEmpty())
		{
			CaplInstance *doc_act_rev=0;
			if(m_api->m_data.IsKindOf(inst, m_api->m_doc_mgr.e_apl_doc_rev))
			{
				m_api->m_data.GetAttr(inst, m_api->m_doc_mgr.a_apl_doc_rev_doc, doc_inst);
				m_api->m_data.GetAttr(doc_inst, m_api->m_doc_mgr.a_apl_doc_active, doc_act_rev);
			}

			if(inst==doc_act_rev)
			{
				CaplAdminModeProvider adminmode(&(m_api->m_data),-1, -1,DEF_SOURCE);
				
				if(m_api->m_data.IsKindOf(appr_inst, m_api->m_doc_mgr.e_apl_doc_rev))
					m_api->m_data.GetAttr(appr_inst, m_api->m_doc_mgr.a_apl_doc_rev_doc, doc_inst);
				
				ChangeWFState(doc_inst, sStatusState, APL_NOT_TEST_POSSIBLE_STATES);
			}
		}
		
		if(date_time_s.IsEmpty()) 
		{
			COleDateTime dt;
			m_data->NET_GetServerDateTime(dt);
			aplDate2String(dt,date_time_s);
		}
		
		m_data->PutAttr(created_approval,a_appr_appr_date_time_s,date_time_s);

		if(Note!=NULL)
			m_data->PutAttr(created_approval, a_appr_po_item_note, Note);

		for(i= 0; i<newFiles.GetSize(); i++)
		{
			store_file= m_api->m_doc_mgr.CreateFile(newFiles[i]);
			if(store_file)fileExt.Add(store_file);
		}

		m_api->m_data.PutAttr(created_approval, a_appr_attachment, fileExt);	

		if(str4label!=_T("")) AddLabel4DocRevision(inst,str4label);
		if(bSetNeedWork) SetNeedWork4DocRevision(inst, true, true);
		else if(bUnSetNeedWork) SetNeedWork4DocRevision(inst, false, true);


		if(0!=item2 && !CheckItemStatus(item2,status,sRole))
		{
			CaplInstance *created_approval= m_data->CreateInstance(e_apl_appr_pers_org);
			if(created_approval)
			{
				m_data->PutAttr(created_approval, a_appr_item, item2);
				m_data->PutAttr(created_approval, a_appr_status, status);
				m_data->PutAttr(created_approval,a_appr_role, sRole);
				m_data->PutAttr(created_approval, a_appr_level, sLevel);
				m_data->PutAttr(created_approval, a_appr_notes, sDscr);

				apidata.PutAttr(created_approval,m_api->m_appr_mgr.a_appr_format,dlg.m_sFormat);
				apidata.PutAttr(created_approval,m_api->m_appr_mgr.a_appr_total_sheets_count,dlg.m_sNumList);
				apidata.PutAttr(created_approval,m_api->m_appr_mgr.a_appr_total_sheets_count_a4,dlg.m_sNumListA4);

				m_data->PutAttr(created_approval,a_appr_pers_org, GetCurrentPerson());		
				m_data->PutAttr(created_approval,a_appr_appr_owner,(CaplInstance*)NULL);

				if(sSign!=_T(""))
				{
					ESignMode mode=m_api->m_appr_mgr.SeSignModeForCryptMgr(APL_QUICK_MODE_WITHOUT_DLG);
					CString sOpenKey2, sSign2,  sHash2, sSignOwner2,sSignCert2,sInventory2,sSnapShot2;
					CaplInstance *sign_pers=GetCurrentPerson();
					m_api->m_appr_mgr.SignObject(item2, sMethod, sSign2, sHash2, sOpenKey2,sSignOwner2,sSignCert2,sInventory2,sSnapShot2,&sign_pers);
					m_api->m_appr_mgr.SeSignModeForCryptMgr(mode);

					m_data->PutAttr(created_approval, a_appr_dg_sign_met, sMethod);
					m_data->PutAttr(created_approval, a_appr_dg_sign, sSign2);
					m_data->PutAttr(created_approval, a_appr_dg_sign_open_key, sOpenKey);
					m_data->PutAttr(created_approval, a_appr_dg_sign_hash, sHash2);
					m_data->PutAttr(created_approval, a_appr_dg_sign_author, sSignOwner);
					m_data->PutAttr(created_approval, a_appr_dg_sign_inventory, sInventory2);
					m_data->PutAttr(created_approval, a_appr_dg_sign_snapshot, sSnapShot2);

					if(!sSign.IsEmpty()) m_data->PutAttr(created_approval, a_appr_entries_used, true);

					if(sSignCert2!=_T(""))
					{
						long blob;
						if(!m_data->NET_SaveBlob(created_approval,a_appr_dg_sign_cert,sSignCert2,blob))
						{
							AfxMessageBox( APL_T("Сертификат не найден!"),MB_OK|MB_ICONSTOP);
						}
						else
						{
							// удаляем сертификат, если он был
							if(!sSignCert.IsEmpty())
							{
								::SetFileAttributes(sSignCert2, FILE_ATTRIBUTE_NORMAL);
								::DeleteFile(sSignCert2);
							}
						}
					}
				}

				m_data->PutAttr(created_approval,a_appr_appr_date_time_s,date_time_s);

				if(str4label!=_T("")) AddLabel4DocRevision(item2,str4label);
				if(bSetNeedWork) SetNeedWork4DocRevision(item2, true, true);
				else if(bUnSetNeedWork) SetNeedWork4DocRevision(item2, false, true);
			}
		}
	}
	
	if(m_AutoSave) 
		m_api->SaveChanges();

	if(m_api->m_options_mgr.CheckInstallCode(_T("grpz")))
	{
		CreateApprovalGrpzPostProcessing(m_api,appr_inst,status, sRole, sDscr);
		CreateApprovalGrpzFixAK_Note(m_api,appr_inst,status, sRole, GetCurrentPerson(), created_approval);
	}
	

	if(NULL!=created_approval && true==m_AutoSave && true==m_AutoUsurpire)
	{
		aplExtent aet;
		aet.Add(created_approval);
		//if(_T("")!=dlg.m_csAccessString)
		//	apidata.NET_SetAccessFromPattern(&aet,dlg.m_csAccessString);
		//else
		{
			CString csAccPat;

			if(TRUE==m_api->m_options_mgr.GetDefPatern(e_apl_appr_pers_org,csAccPat))
				apidata.NET_SetAccessFromPattern(&aet,csAccPat);
		}
	}
	
	aplExtent items;
	items.Add(item);
	PostUpdateApprovalItems(items);

	return created_approval;
}

bool CaplAutorizationManager::PostUpdateApprovalItems(aplExtent& items)
{
	CaplInstance* inst1= NULL;
	aplExtent accessItems;
	int i;

	for(i= 0; i<items.GetSize(); i++)
	{
		if(m_api->m_data.IsKindOf(items[i], m_api->m_doc_mgr.e_doc))
			m_api->m_data.GetAttr(items[i], m_api->m_doc_mgr.a_apl_doc_active, inst1);
		else
			inst1= items[i];

		if(inst1->GetAccessmode()>aplRW)
			continue;

		if(m_api->m_data.IsKindOf(inst1, m_api->m_change_mgr.e_chng))
		{
			CString buf;
			m_api->m_data.GetAttr(inst1, m_api->m_change_mgr.a_chng_state, buf);
			if(buf!=_T("applied") && buf!=_T("canceled"))
				m_api->m_data.PutAttr(inst1, m_api->m_change_mgr.a_chng_state, _T("approving"));
		}
		else if(m_api->m_data.IsKindOf(inst1, m_api->m_doc_mgr.e_apl_doc_rev))
		{
			if(m_api->m_show.m_auto_wfstate)
			{
				CString old=_T("");
				CaplInstance *doc=0;
				m_api->m_data.GetAttr(inst1, m_api->m_doc_mgr.a_apl_doc_rev_doc, doc);
				if(doc)
				{
					m_api->m_data.GetAttr(doc,m_api->m_doc_mgr.a_apl_doc_wf_state, old);
					if(old==_T("working") || old==_T("")) old = _T("approving");
					else if(old==_T("changing")) old = _T("approving_change");

					m_api->m_doc_mgr.ChangeWFState(doc,old.GetBuffer(0));
				}
			}
		}
		else if(m_api->m_data.IsKindOf(inst1, m_api->m_prd_mgr.e_pdf))
		{
			if(m_api->m_show.m_auto_wfstate)
			{
				CString old=_T("");
				m_api->m_data.GetAttr(inst1,m_api->m_prd_mgr.a_apl_pdf_state, old);
				if(old==_T("working") || old==_T("")) old = _T("approving");
				else if(old==_T("changing")) old = _T("approving_change");

				m_api->m_doc_mgr.ChangeWFState(inst1,old.GetBuffer(0));
			}
		}
		else if(m_api->m_data.IsKindOf(inst1, m_api->m_bp_mgr.e_apl_bp_ver))
		{
			if(m_api->m_show.m_auto_wfstate)
			{
				CString old=_T("");
				CaplInstance *bp=0;
				m_api->m_data.GetAttr(inst1, m_api->m_bp_mgr.a_bp_ver_bp, bp);
				if(bp)
				{
					m_api->m_data.GetAttr(bp,m_api->m_bp_mgr.a_bp_state, old);
					if(old==_T("working") || old==_T("")) old = _T("approving");
					else if(old==_T("changing")) old = _T("approving_change");

					m_api->m_doc_mgr.ChangeWFState(bp,old.GetBuffer(0));
				}
			}
		}
		else accessItems.Add(inst1);
	}

	if(m_AutoSave)
		m_api->m_data.NET_SaveChanges();

	// Назначение доступа
	if(0!=m_api->m_options_mgr.GetIntOptionValueBN(APL_NO_T("Политики доступа\\Не запрещать доступ при присвоении статуса"),0))
	{
		aplUsers usersList;
		aplAccessList *accessList = NULL;
		aplAccessEl *accessEL= NULL;
		
		if(accessItems.GetSize())
		{
			accessList = new aplAccessList;
			accessList->user= NULL;
			usersList.Add(accessList);
		}

		for(i= 0; i<accessItems.GetSize(); i++)
		{
			accessEL = new aplAccessEl;
			accessEL->access = aplRO;// 2
			accessEL->inst= accessItems[i];
			accessList->Add(accessEL);
		}

		if(accessItems.GetSize())
		{
			m_api->m_data.NET_SetGroupeAccess(usersList,  APL_T("Установка доступа"), -1, -1);
		}
	}
	return true;
}

//****************************************************************
CaplInstance *CaplAutorizationManager::CreateApproval(CaplInstance *item, CaplInstance *status,
	const TCHAR *level, CaplInstance *person_org, CaplInstance *app_owner,
	const TCHAR *role, const TCHAR *date_time,
	const TCHAR* sign_method, const TCHAR* key_path, const TCHAR* password,
	LPCTSTR sign_owner, LPCTSTR cert_file, aplExtent *statusesToHide,bool bNoCheckRepeatStatus,bool CheckStatusForRole/*=true*/)
{
	if(m_data==0) return 0;
	if(e_apl_appr_pers_org==0) return 0;
	if(item==0) return 0;
	if(item->GetType()==0) return 0;
	if(item->GetAccessmode()>aplRO)
	{
		aplErrorMessage(S::NoAccessRight(),item);
		return 0;
	}

	//person_org=(CaplInstance*)-2; //для отладки автовыбора сотрудника

	if(0==person_org)
	{
		CaplInstance *person=m_api->m_appr_mgr.GetCurrentPerson();
		if(!person)
		{
			if(m_api->m_ModeInteractive) AfxMessageBox( APL_T("Анонимный пользователь не может создавать электронные подписи !!!"));
			return 0;
		}
		person_org=person;
	}

	/* Проверка наличия вида документа */
	CaplInstance *ciDoc = NULL, *ciDT = NULL;

	if(m_data->IsKindOf(item, m_api->m_doc_mgr.e_apl_doc_rev)) m_api->m_data.GetAttr(item, m_api->m_doc_mgr.a_apl_doc_rev_doc, ciDoc);
	else if(m_data->IsKindOf(item, m_api->m_doc_mgr.e_doc)) ciDoc = item;

	if(ciDoc)
	{
		m_api->m_data.GetAttr(ciDoc, m_api->m_doc_mgr.a_doc_kind, ciDT);
		if(ciDT == NULL)
		{
			if(m_api->m_ModeInteractive) AfxMessageBox( APL_T("Не задан вид документа. Подпись невозможна!"), MB_ICONSTOP);
			return 0;
		}

		m_api->m_doc_mgr.AttachDocToPrd(ciDoc);
	}

	//Проверка заполненности атрибутов


	CApprovalDlg dlg;
	CaplInstance *Note=NULL;


	/*Проверка наличия всех обязательных реквизитов и атрибутов*/
	if(m_data->IsKindOf(item, m_api->m_doc_mgr.e_apl_doc_rev))
	{
		//Проверяем реквизиты
		CString sMissingEntry;
		if(!m_api->m_doc_mgr.HasAllNecessaryEntries(item,true,&sMissingEntry))
		{
			if(m_api->m_ModeInteractive)
			{
				CString msg;
				msg.Format(APL_T("Заданы не все постоянные реквизиты.\n\n(Отсутствует реквизит '%s')\n\n Подписание невозможно."),LPCTSTR(sMissingEntry));
				AfxMessageBox( msg, MB_OK|MB_ICONSTOP);
			}
			return 0;
		}

		// проверяем атрибуты
		if(!m_api->m_doc_mgr.HasAllNecessaryDocRevAttr(item))
		{
			if(m_api->m_ModeInteractive) AfxMessageBox( APL_T("Не задан формат или количество листов.\n\nПодпись запрещена настройками"), MB_OK|MB_ICONSTOP);
			return 0;
		}

		apidata.GetAttr(item,m_api->m_doc_mgr.a_apl_doc_rev_format,dlg.m_sFormat);
		if(dlg.m_sFormat==_T("")) apidata.GetAttr(ciDoc,m_api->m_doc_mgr.a_doc_format,dlg.m_sFormat);

	}

	/*Проверка на нахождение объекта в незавершенном процессе*/
	if(m_api->m_data.IsConnected())
	{
		int iVal;

		m_api->m_options_mgr.GetOptionValueBN( APL_NO_T("Настройка Workflow\\Не давать присваивать статусы рабочим объектам процесса"), iVal, 0);
		if(0!=iVal)
		{
			CString buf= _T("SELECT Ext FROM ")
//						_T("Ext {apl_process(.state!='terminated' AND .state!='completed' AND .work_objects->apl_work_object.object= #%i)} ")
						_T("Ext{apl_work_object(.object= #%i AND .for_note_only= false AND .action->apl_process(.state!='terminated' AND .state!='completed'))}.action->apl_process ")
						_T("END_SELECT");
			CString sQuery;
			CaplInstance* testInst= item, *testInst2=0;
			
			if(m_api->m_data.IsKindOf(item, m_api->m_doc_mgr.e_apl_doc_rev))
			{
				testInst2=item;
				m_api->m_data.GetAttr(item, m_api->m_doc_mgr.a_apl_doc_rev_doc, testInst);
			}

			bool bBloked=false;

			sQuery.Format(buf, testInst->GetId());
			if(m_api->m_data.NET_QueryEditParse(sQuery))
			{
				aplExtent objs;
				m_api->m_data.NET_QueryExecute(objs);

				if(objs.GetSize())bBloked=true;
			}

			if(bBloked==false && testInst2!=0)
			{
				sQuery.Format(buf, testInst2->GetId());
				if(m_api->m_data.NET_QueryEditParse(sQuery))
				{
					aplExtent objs;
					m_api->m_data.NET_QueryExecute(objs);
					if(objs.GetSize())bBloked=true;
				}
			}
			if(bBloked)
			{

				m_api->m_options_mgr.GetOptionValueBN( APL_NO_T("Настройка Workflow\\Список ролей, которым можно присваивать статусы рабочим объектам процесса"),buf,0);
				if(buf!=_T(""))
				{
					if(m_api->m_appr_mgr.CheckPersonRole(0,buf)) bBloked=false;
				}
				if(bBloked)
				{
					AfxMessageBox( APL_T("Объект заблокирован системой управления потоками работ.\nВ данный момент невозможно поставить электронную подпись!!!"), 
						MB_OK|MB_ICONERROR);
					return NULL;
				}
			}
		}
	}
	
	CString sLevel, sRole, sDt, sDscr, sMethod, sSign, sHash, sOpenKey,sInventory,sSnapshot; 
		
	CString	sSignOwner=sign_owner;
	CString sSignCert=cert_file;

	CString date_time_s;
	CStringArray newFiles;
	aplExtent fileExt;
	CaplInstance* store_file;
	int i;

	CaplInstance *inst= NULL;
	if(m_api->m_data.IsKindOf(item, m_api->m_doc_mgr.e_apl_doc))
		m_api->m_data.GetAttr(item, m_api->m_doc_mgr.a_apl_doc_active, inst);
	else
		inst= item;


	CaplInstance *item2=0; //документ связанный с изменением
	// Обработки ГРПЗ
	// Теперь проверка внутри
	//if(m_api->m_options_mgr.CheckInstallCode(_T("grpz")))
	{
		if(!CreateApprovalGrpzPreProcessing(m_api,item,&item2)) return 0;
	}

	if(!status)
	{
		CaplSetResourceHandle setres(module_inst);	

		dlg.m_api= m_api;
		dlg.m_mode= _T("Create");
		dlg.m_item= inst;
		dlg.m_person_inst= person_org;
		dlg.m_dt= date_time;
		dlg.m_pNote = &Note;
		dlg.m_sRole = role;
		dlg.m_bNoCheckRepeatStatus =bNoCheckRepeatStatus;
		dlg.m_bCheckStatusForRole=CheckStatusForRole;

		if(statusesToHide)
			dlg.m_statusesToHide.Append(*statusesToHide);

		if(dlg.DoModal()!=IDOK) return NULL;
		
		sRole= dlg.m_sRole;
		sLevel= dlg.m_sLevel;
		sDscr= dlg.m_sNotes;
		
		status= dlg.m_status_inst;
		date_time_s= dlg.m_dt;

		sMethod= dlg.m_sMethid;
		sSign= dlg.m_sSign;
		sHash= dlg.m_sHash;
		sOpenKey= dlg.m_sOpenKey;
		sSignOwner= dlg.m_sSignOwner;
		sSignCert= dlg.m_sSignCert;
		sInventory= dlg.m_sInventory;
		sSnapshot= dlg.m_sSnapShot;

		newFiles.Append(dlg.m_newFiles);

	}
	else
	{
		/*если вывели диалог, то подпись там можно было присвоить
		  если не присвоили, значит не захотели :))*/
		sRole= role;
		sLevel= level;
		date_time_s=date_time;
		sMethod=sign_method;

		//const char* key_path;
		//const char* password,

		if(sMethod!=_T(""))
		{
			if(!SignObject(inst, sMethod, sSign, sHash, sOpenKey,sSignOwner,sSignCert,sInventory,sSnapshot,&person_org))
				return NULL;
		}
	}

	CString sStatusState,str4label;
	CaplInstance* doc_inst= NULL;
	bool bModeInteractive;
	m_data->GetAttr(status, a_appr_status_set_state, sStatusState);	
	m_data->GetAttr(status, a_appr_status_str4label, str4label);	

	bool bSetNeedWork,bUnSetNeedWork;
	m_data->GetAttr(status, a_appr_status_set_needs_work, bSetNeedWork);
	m_data->GetAttr(status, a_appr_status_unset_needs_work, bUnSetNeedWork);
	if(bSetNeedWork && bUnSetNeedWork) {bSetNeedWork=false; bUnSetNeedWork=false;}

	CaplInstance *created_approval= m_data->CreateInstance(e_apl_appr_pers_org);
	if(created_approval)
	{
		m_data->PutAttr(created_approval, a_appr_item, inst);
		m_data->PutAttr(created_approval, a_appr_status, status);
		m_data->PutAttr(created_approval,a_appr_role, sRole);
		m_data->PutAttr(created_approval, a_appr_level, sLevel);
		m_data->PutAttr(created_approval, a_appr_notes, sDscr);

		apidata.PutAttr(created_approval,m_api->m_appr_mgr.a_appr_format,dlg.m_sFormat);
		apidata.PutAttr(created_approval,m_api->m_appr_mgr.a_appr_total_sheets_count,dlg.m_sNumList);
		apidata.PutAttr(created_approval,m_api->m_appr_mgr.a_appr_total_sheets_count_a4,dlg.m_sNumListA4);
		
		m_data->PutAttr(created_approval,a_appr_pers_org, person_org);		
		m_data->PutAttr(created_approval,a_appr_appr_owner,app_owner);
		
		m_data->PutAttr(created_approval, a_appr_dg_sign_met, sMethod);
		m_data->PutAttr(created_approval, a_appr_dg_sign, sSign);
		m_data->PutAttr(created_approval, a_appr_dg_sign_open_key, sOpenKey);
		m_data->PutAttr(created_approval, a_appr_dg_sign_hash, sHash);
		m_data->PutAttr(created_approval, a_appr_dg_sign_author, sSignOwner);
		m_data->PutAttr(created_approval, a_appr_dg_sign_inventory, sInventory);
		m_data->PutAttr(created_approval, a_appr_dg_sign_snapshot, sSnapshot);

		if(!sSign.IsEmpty()) m_data->PutAttr(created_approval, a_appr_entries_used, true);
		
		if(sSignCert!=_T(""))
		{
			long blob;
			if(!m_data->NET_SaveBlob(created_approval,a_appr_dg_sign_cert,sSignCert,blob))
			{
				AfxMessageBox( APL_T("Сертификат не найден!"),MB_OK|MB_ICONSTOP);
			}
			else
			{
				// удаляем сертификат, если он был
				if(!sSignCert.IsEmpty())
				{
					::SetFileAttributes(sSignCert, FILE_ATTRIBUTE_NORMAL);
					::DeleteFile(sSignCert);
				}
			}
		}

		
		// записываем значения реквизитов , участвующих в подписи
		CreateEntryApproval(inst, created_approval);

		if(!sStatusState.IsEmpty())
		{
			CaplInstance *doc_act_rev=0;
			CaplInstance* ciInst(NULL);
			if(m_api->m_data.IsKindOf(inst, m_api->m_doc_mgr.e_apl_doc_rev))
			{
				m_api->m_data.GetAttr(inst, m_api->m_doc_mgr.a_apl_doc_rev_doc, doc_inst);
				m_api->m_data.GetAttr(doc_inst, m_api->m_doc_mgr.a_apl_doc_active, doc_act_rev);
				if(inst==doc_act_rev)
				{
					ciInst= doc_inst;
				}
			}
			else if(m_api->m_data.IsKindOf(inst, m_api->m_bp_mgr.e_apl_bp_ver))
			{
				m_api->m_data.GetAttr(inst, m_api->m_bp_mgr.a_bp_ver_bp, ciInst);
			}
			else
			{
				ciInst= inst;
			}
			
			if(ciInst)
			{
				CaplAdminModeProvider adminmode(&(m_api->m_data),-1, -1,DEF_SOURCE);

				bModeInteractive= m_api->m_ModeInteractive;
				m_api->m_ModeInteractive= false;
				ChangeWFState(ciInst, sStatusState,APL_NOT_TEST_POSSIBLE_STATES);
				m_api->m_ModeInteractive= bModeInteractive;
			}
		}
		
		if(date_time_s.IsEmpty()) 
		{
			COleDateTime dt;
			m_data->NET_GetServerDateTime(dt);
			aplDate2String(dt,date_time_s);
		}
		
		m_data->PutAttr(created_approval,a_appr_appr_date_time_s,date_time_s);

		if(Note!=NULL)
			m_data->PutAttr(created_approval, a_appr_po_item_note, Note);

		for(i= 0; i<newFiles.GetSize(); i++)
		{
			store_file= m_api->m_doc_mgr.CreateFile(newFiles[i]);
			if(store_file)fileExt.Add(store_file);
		}

		m_api->m_data.PutAttr(created_approval, a_appr_attachment, fileExt);	

		if(str4label!=_T("")) AddLabel4DocRevision(inst,str4label);
		if(bSetNeedWork) SetNeedWork4DocRevision(inst, true, true);
		else if(bUnSetNeedWork) SetNeedWork4DocRevision(inst, false, true);

		if(0!=item2)
		{
			CaplInstance *created_approval= m_data->CreateInstance(e_apl_appr_pers_org);
			if(created_approval)
			{
				m_data->PutAttr(created_approval, a_appr_item, item2);
				m_data->PutAttr(created_approval, a_appr_status, status);
				m_data->PutAttr(created_approval,a_appr_role, sRole);
				m_data->PutAttr(created_approval, a_appr_level, sLevel);
				m_data->PutAttr(created_approval, a_appr_notes, sDscr);

				apidata.PutAttr(created_approval,m_api->m_appr_mgr.a_appr_format,dlg.m_sFormat);
				apidata.PutAttr(created_approval,m_api->m_appr_mgr.a_appr_total_sheets_count,dlg.m_sNumList);
				apidata.PutAttr(created_approval,m_api->m_appr_mgr.a_appr_total_sheets_count_a4,dlg.m_sNumListA4);

				m_data->PutAttr(created_approval,a_appr_pers_org, person_org);		
				m_data->PutAttr(created_approval,a_appr_appr_owner,app_owner);

				if(sSign!=_T(""))
				{
					ESignMode mode=m_api->m_appr_mgr.SeSignModeForCryptMgr(APL_QUICK_MODE_WITHOUT_DLG);
					CString sOpenKey2, sSign2,  sHash2, sSignOwner2,sSignCert2,sInventory2,sSnapShot2;
					CaplInstance *sign_pers=person_org;
					m_api->m_appr_mgr.SignObject(item2, sMethod, sSign2, sHash2, sOpenKey2,sSignOwner2,sSignCert2,sInventory2,sSnapShot2,&sign_pers);
					m_api->m_appr_mgr.SeSignModeForCryptMgr(mode);

					m_data->PutAttr(created_approval, a_appr_dg_sign_met, sMethod);
					m_data->PutAttr(created_approval, a_appr_dg_sign, sSign2);
					m_data->PutAttr(created_approval, a_appr_dg_sign_open_key, sOpenKey);
					m_data->PutAttr(created_approval, a_appr_dg_sign_hash, sHash2);
					m_data->PutAttr(created_approval, a_appr_dg_sign_author, sSignOwner);
					m_data->PutAttr(created_approval, a_appr_dg_sign_inventory, sInventory2);
					m_data->PutAttr(created_approval, a_appr_dg_sign_snapshot, sSnapShot2);

					if(!sSign.IsEmpty()) m_data->PutAttr(created_approval, a_appr_entries_used, true);

					if(sSignCert2!=_T(""))
					{
						long blob;
						if(!m_data->NET_SaveBlob(created_approval,a_appr_dg_sign_cert,sSignCert2,blob))
						{
							AfxMessageBox( APL_T("Сертификат не найден!"),MB_OK|MB_ICONSTOP);
						}
						else
						{
							// удаляем сертификат, если он был
							if(!sSignCert.IsEmpty())
							{
								::SetFileAttributes(sSignCert2, FILE_ATTRIBUTE_NORMAL);
								::DeleteFile(sSignCert2);
							}
						}
					}
				}

				m_data->PutAttr(created_approval,a_appr_appr_date_time_s,date_time_s);

				if(str4label!=_T("")) AddLabel4DocRevision(item2,str4label);
				if(bSetNeedWork) SetNeedWork4DocRevision(item2, true, true);
				else if(bUnSetNeedWork) SetNeedWork4DocRevision(item2, false, true);
			}
		}
	}
	if(m_AutoSave) 
		m_api->SaveChanges();

	// Обработки ГРПЗ
	if(m_api->m_options_mgr.CheckInstallCode(_T("grpz")))
	{
		CreateApprovalGrpzPostProcessing(m_api,inst,status, sRole, sDscr);
		CreateApprovalGrpzFixAK_Note(m_api,inst,status, sRole, person_org, created_approval);
		CreateApprovalGrpzFixAK_Note(m_api,item2,status, sRole, person_org, created_approval);
	}
	

	if(NULL!=created_approval && true==m_AutoSave && true==m_AutoUsurpire)
	{
		aplExtent aet;
		aet.Add(created_approval);
		//if(_T("")!=dlg.m_csAccessString)
		//	apidata.NET_SetAccessFromPattern(&aet,dlg.m_csAccessString);
		//else
		{
			CString csAccPat;

			if(TRUE==m_api->m_options_mgr.GetDefPatern(e_apl_appr_pers_org,csAccPat))
				apidata.NET_SetAccessFromPattern(&aet,csAccPat);
		}
	}

	//запрещаем изменение подписанной версии документа
	if(m_api->m_data.IsKindOf(inst, m_api->m_doc_mgr.e_apl_doc_rev))
	{
		aplExtent ext;
		ext.Add(inst);
		apidata.NET_SetInstancesAccess(&ext,(CaplInstance *)-1,aplRO);
	}

	aplExtent items;
	items.Add(item);
	PostUpdateApprovalItems(items);
	return created_approval;
}

bool CaplAutorizationManager::SetNeedWork4DocRevision(CaplInstance *doc_rev, bool bSetNeedWork, bool bFromCreateApproval)
{
	if(0==doc_rev) return false;
	if(doc_rev->IsDeleted()) return false;
	if(!m_api->m_data.IsKindOf(doc_rev,m_api->m_doc_mgr.e_apl_doc_rev)) return false;

	bool b;
	m_api->m_data.GetAttr(doc_rev,m_api->m_doc_mgr.a_apl_doc_rev_it_needs_work, b);
	if(b==bSetNeedWork) return true;

	if(doc_rev->GetAccessmode()<=aplRW)
	{
		m_api->m_data.PutAttr(doc_rev,m_api->m_doc_mgr.a_apl_doc_rev_it_needs_work, bSetNeedWork);
		return true;
	}
	
	if(!bFromCreateApproval)
	{
		CString sRoleName;
		m_api->m_options_mgr.GetOptionValueBN( APL_NO_T("Роли\\Роль для изменения флага 'Требует доработки'"), sRoleName, _T(""));
		
		bool bHasRole=false;
		if(sRoleName!=_T("")) bHasRole=CheckPersonRole(0,LPCTSTR(sRoleName));

		if(!bHasRole)
		{
			if(m_api->m_ModeInteractive) AfxMessageBox(APL_T("Вы не обладаете ролью для выполнения операции!"),MB_ICONSTOP|MB_OK);
			return false;

		}
	}

	CaplAdminModeProvider adminmode(&(m_api->m_data),-1, -1,DEF_SOURCE);
	m_api->m_data.PutAttr(doc_rev,m_api->m_doc_mgr.a_apl_doc_rev_it_needs_work, bSetNeedWork);

	return true;
}

bool CaplAutorizationManager::AddLabel4DocRevision(CaplInstance *doc_rev, LPCTSTR sLabel)
{
	if(0==doc_rev) return false;
	if(0==sLabel) return false;
	if(_T('\0')==sLabel[0]) return false;
	if(!m_api->m_data.IsKindOf(doc_rev,m_api->m_doc_mgr.e_apl_doc_rev)) return false;

	CString curLabel;
	m_api->m_data.GetAttr(doc_rev,m_api->m_doc_mgr.a_apl_doc_rev_label,curLabel);
	if(curLabel!=_T(""))
	{
		if(curLabel.Find(sLabel)>=0) return true;
		if(curLabel[curLabel.GetLength()-1]!=_T(' ')) curLabel+=_T(' ');
	}
	curLabel+=sLabel;

	CaplAdminModeProvider adminmode;
	if(doc_rev->GetAccessmode()>aplRW)
	{
		adminmode.SetData(&(m_api->m_data));
		adminmode.StartAdminMode(-1, -1,DEF_SOURCE);
	}
	m_api->m_data.PutAttr(doc_rev,m_api->m_doc_mgr.a_apl_doc_rev_label,curLabel);
	
	return true;
}

int CaplAutorizationManager::CreateApprovalMulti(	aplExtent *items, 
															CaplInstance *status,
															const TCHAR *level, 
															CaplInstance *person_org, 
															CaplInstance *app_owner,
															const TCHAR *role, 
															const TCHAR *date_time,
															const TCHAR* sign_method, 
															const TCHAR* key_path, 
															const TCHAR* password,
															LPCTSTR sign_owner, 
															LPCTSTR cert_file, 
															aplExtent *statusesToHide )
{
	CApprovalDlg dlg;
	CaplInstance *Note=NULL;

	if(m_data==0) return 0;
	if(e_apl_appr_pers_org==0) return 0;
	
	if(items->Size == 0) return 0;
	
	for (int i = 0 ; i < items->Size  ; i++)
	{
		CaplInstance* pInst = (CaplInstance*)items->GetAt(i) ;
		if(pInst->GetType()==0) return 0;
	}

	for (int i = 0 ; i < items->Size  ; i++)
	{
		CaplInstance* pInst = (CaplInstance*)items->GetAt(i);
		if(pInst->GetAccessmode()>aplRO)
		{
			aplErrorMessage(S::NoAccessRight(),pInst);
			return 0;
		}
	}
	
	if(!person_org)
	{
		CaplInstance *person=m_api->m_appr_mgr.GetCurrentPerson();
		if(!person)
		{
			if(m_api->m_ModeInteractive) AfxMessageBox( APL_T("Анонимный пользователь не может создавать электронные подписи !!!"));
			return 0;
		}
		person_org=person;
	}

	/* Проверка наличия вида документа */
	CaplInstance *ciDoc = NULL, *ciDT = NULL;

	for (int i = 0 ; i < items->Size  ; i++)
	{
		CaplInstance* pInst = (CaplInstance*)items->GetAt(i) ;

		if(m_data->IsKindOf(pInst, m_api->m_doc_mgr.e_apl_doc_rev))
		{
			m_api->m_data.GetAttr(pInst, m_api->m_doc_mgr.a_apl_doc_rev_doc, ciDoc);
		}
		else if(m_data->IsKindOf(pInst, m_api->m_doc_mgr.e_doc))
		{
			ciDoc = pInst;
		}

		if(ciDoc)
		{
			m_api->m_data.GetAttr(ciDoc, m_api->m_doc_mgr.a_doc_kind, ciDT);
			if(ciDT == NULL)
			{
				if(m_api->m_ModeInteractive) AfxMessageBox( APL_T("Не задан вид документа. Подпись невозможна!"), MB_ICONSTOP);
				return 0;
			}
		}

		/*Проверка наличия всех обязательных реквизитов*/
		if(m_data->IsKindOf(pInst, m_api->m_doc_mgr.e_apl_doc_rev))
		{
			if(!m_api->m_doc_mgr.HasAllNecessaryEntries(pInst))
			{
				if(m_api->m_ModeInteractive) AfxMessageBox( APL_T("Заданы не все постоянные реквизиты. Подписание невозможно."), MB_OK|MB_ICONSTOP);
				return 0;
			}
		}

		/*Проверка на нахождение объекта в незавершенном процессе*/
		if(m_api->m_data.IsConnected())
		{
			int iVal;

			m_api->m_options_mgr.GetOptionValueBN( APL_NO_T("Настройка Workflow\\Не давать присваивать статусы рабочим объектам процесса"), iVal, 0);
			if(0!=iVal)
			{
				CString buf= _T("SELECT Ext FROM ")
//					_T("Ext {apl_process(.state!='terminated' AND .state!='completed' AND .work_objects->apl_work_object.object= #%i)} ")
					_T("Ext{apl_work_object(.object= #%i AND .for_note_only= false AND .action->apl_process(.state!='terminated' AND .state!='completed'))}.action->apl_process ")
					_T("END_SELECT");
				CString sQuery;
				CaplInstance* testInst= pInst, *testInst2=0;

				if(m_api->m_data.IsKindOf(pInst, m_api->m_doc_mgr.e_apl_doc_rev))
				{
					testInst2=pInst;
					m_api->m_data.GetAttr(pInst, m_api->m_doc_mgr.a_apl_doc_rev_doc, testInst);
				}

				bool bBloked=false;

				sQuery.Format(buf, testInst->GetId());
				if(m_api->m_data.NET_QueryEditParse(sQuery))
				{
					aplExtent objs;
					m_api->m_data.NET_QueryExecute(objs);

					if(objs.GetSize())bBloked=true;
				}

				if(bBloked==false && testInst2!=0)
				{
					sQuery.Format(buf, testInst2->GetId());
					if(m_api->m_data.NET_QueryEditParse(sQuery))
					{
						aplExtent objs;
						m_api->m_data.NET_QueryExecute(objs);
						if(objs.GetSize())bBloked=true;
					}
				}
				if(bBloked)
				{
					m_api->m_options_mgr.GetOptionValueBN( APL_NO_T("Настройка Workflow\\Список ролей, которым можно присваивать статусы рабочим объектам процесса"),buf,0);
					if(buf!=_T(""))
					{
						if(m_api->m_appr_mgr.CheckPersonRole(0,buf)) bBloked=false;
					}
					if(bBloked)
					{
						AfxMessageBox( APL_T("Объект заблокирован системой управления потоками работ.\nВ данный момент невозможно поставить электронную подпись!!!"), 
							MB_OK|MB_ICONERROR);
						return NULL;
					}
				}
			}
		}
		/**/
	}
	
	CString sLevel, sRole, sDt, sDscr, sMethod, sSign, sHash, sOpenKey,sInventory,sSnapshot; 
		
	CString	sSignOwner=sign_owner;
	CString sSignCert=cert_file;

	CString date_time_s;
	CStringArray newFiles;
	aplExtent fileExt;
	CaplInstance* store_file;

	aplExtent insts ;

	for (int i = 0 ; i < items->Size  ; i++)
	{
		CaplInstance* pInst = (CaplInstance*)items->GetAt(i) ;
		CaplInstance* inst = NULL ;
		if(m_api->m_data.IsKindOf(pInst, m_api->m_doc_mgr.e_apl_doc))
		{
			m_api->m_data.GetAttr(pInst, m_api->m_doc_mgr.a_apl_doc_active, inst);
		}
		else
		{
			inst= pInst;
		}

		insts.Add (inst) ;
	}



	if(!status)
	{
		CaplSetResourceHandle setres(module_inst);	

		dlg.m_api= m_api;
		dlg.m_mode= _T("Create");
		dlg.m_bMultiItemsMode = true ;
		dlg.m_MultiItemsExtent= &insts;
		dlg.m_person_inst= person_org;
		dlg.m_dt= date_time;
		dlg.m_pNote = &Note;

		if(statusesToHide)
		{
			dlg.m_statusesToHide.Append(*statusesToHide);
		}

		if(dlg.DoModal()!=IDOK) return NULL;
		
		sRole= dlg.m_sRole;
		sLevel= dlg.m_sLevel;
		sDscr= dlg.m_sNotes;
		
		status= dlg.m_status_inst;
		date_time_s= dlg.m_dt;

		sMethod= dlg.m_sMethid;
		sSign= dlg.m_sSign;
		sHash= dlg.m_sHash;
		sOpenKey= dlg.m_sOpenKey;
		sSignOwner= dlg.m_sSignOwner;
		sSignCert= dlg.m_sSignCert;
		sInventory= dlg.m_sInventory;
		sSnapshot= dlg.m_sSnapShot;

		newFiles.Append(dlg.m_newFiles);
	}
	else
	{
		/*если вывели диалог, то подпись там можно было присвоить
		  если не присвоили, значит не захотели :))*/
		sRole= role;
		sLevel= level;
		date_time_s=date_time;
		
		for (int i = 0 ; i < insts.Size  ; i++)
		{
			CaplInstance* inst = (CaplInstance*)insts.GetAt(i) ;

			if(m_api->m_data.IsKindOf(inst, m_api->m_doc_mgr.e_apl_doc_rev))
			{
				if(!sMethod.IsEmpty())
				{

					if(!SignObject(inst, sMethod, sSign, sHash, sOpenKey,sSignOwner,sSignCert,sInventory,sSnapshot))
						return NULL;
				}
			}
		}
		
	}

	CString sStatusState,str4label;
	CaplInstance* doc_inst= NULL;
	bool bModeInteractive;
	m_data->GetAttr(status, a_appr_status_set_state, sStatusState);	
	m_data->GetAttr(status, a_appr_status_str4label, str4label);	

	bool bSetNeedWork,bUnSetNeedWork;
	m_data->GetAttr(status, a_appr_status_set_needs_work, bSetNeedWork);
	m_data->GetAttr(status, a_appr_status_unset_needs_work, bUnSetNeedWork);
	if(bSetNeedWork && bUnSetNeedWork) {bSetNeedWork=false; bUnSetNeedWork=false;}

	for (int i = 0 ; i < insts.Size  ; i++)
	{
		CaplInstance* inst = (CaplInstance*)insts.GetAt(i) ;

		CaplInstance *created_approval= m_data->CreateInstance(e_apl_appr_pers_org);
		if(created_approval)
		{
			m_data->PutAttr(created_approval, a_appr_item, inst);
			m_data->PutAttr(created_approval, a_appr_status, status);
			m_data->PutAttr(created_approval,a_appr_role, sRole);
			m_data->PutAttr(created_approval, a_appr_level, sLevel);
			m_data->PutAttr(created_approval, a_appr_notes, sDscr);

			m_data->PutAttr(created_approval,a_appr_pers_org, person_org);		
			m_data->PutAttr(created_approval,a_appr_appr_owner,app_owner);

			m_data->PutAttr(created_approval, a_appr_dg_sign_met, sMethod);
			m_data->PutAttr(created_approval, a_appr_dg_sign, sSign);
			m_data->PutAttr(created_approval, a_appr_dg_sign_open_key, sOpenKey);
			m_data->PutAttr(created_approval, a_appr_dg_sign_hash, sHash);
			m_data->PutAttr(created_approval, a_appr_dg_sign_author, sSignOwner);
			m_data->PutAttr(created_approval, a_appr_dg_sign_inventory, sInventory);
			m_data->PutAttr(created_approval, a_appr_dg_sign_snapshot, sSnapshot);

			if(!sSign.IsEmpty()) m_data->PutAttr(created_approval, a_appr_entries_used, true);

			if(sSignCert!=_T(""))
			{
				long blob;
				if(!m_data->NET_SaveBlob(created_approval,a_appr_dg_sign_cert,sSignCert,blob))
				{
					AfxMessageBox( APL_T("Сертификат не найден!"),MB_OK|MB_ICONSTOP);
				}
				else
				{
					// удаляем сертификат, если он был
					if(!sSignCert.IsEmpty())
					{
						::SetFileAttributes(sSignCert, FILE_ATTRIBUTE_NORMAL);
						::DeleteFile(sSignCert);
					}
				}
			}


			// записываем значения реквизитов , участвующих в подписи
			CreateEntryApproval(inst, created_approval);

			if(!sStatusState.IsEmpty())
			{
				CaplInstance *doc_act_rev=0;
				if(m_api->m_data.IsKindOf(inst, m_api->m_doc_mgr.e_apl_doc_rev))
				{
					m_api->m_data.GetAttr(inst, m_api->m_doc_mgr.a_apl_doc_rev_doc, doc_inst);
					m_api->m_data.GetAttr(doc_inst, m_api->m_doc_mgr.a_apl_doc_active, doc_act_rev);
				}

				if(inst==doc_act_rev)
				{
					CaplAdminModeProvider adminmode(&(m_api->m_data),-1, -1,DEF_SOURCE);

					if(m_api->m_data.IsKindOf(inst, m_api->m_doc_mgr.e_apl_doc_rev))
						m_api->m_data.GetAttr(inst, m_api->m_doc_mgr.a_apl_doc_rev_doc, doc_inst);
					bModeInteractive= m_api->m_ModeInteractive;
					m_api->m_ModeInteractive= false;
					ChangeWFState(doc_inst, sStatusState);
					m_api->m_ModeInteractive= bModeInteractive;
				}
			}

			if(date_time_s.IsEmpty()) 
			{
				COleDateTime dt;
				m_data->NET_GetServerDateTime(dt);
				aplDate2String(dt,date_time_s);
			}

			m_data->PutAttr(created_approval,a_appr_appr_date_time_s,date_time_s);

			if(Note!=NULL)
				m_data->PutAttr(created_approval, a_appr_po_item_note, Note);

			for(int j= 0; j<newFiles.GetSize(); j++)
			{
				store_file= m_api->m_doc_mgr.CreateFile(newFiles[j]);
				if(store_file)fileExt.Add(store_file);
			}

			m_api->m_data.PutAttr(created_approval, a_appr_attachment, fileExt);	

			if(str4label!=_T("")) AddLabel4DocRevision(inst,str4label);
			if(bSetNeedWork) SetNeedWork4DocRevision(inst, true, true);
			else if(bUnSetNeedWork) SetNeedWork4DocRevision(inst, false, true);

			if(NULL!=created_approval && true==m_AutoSave && true==m_AutoUsurpire)
			{
				aplExtent aet;
				aet.Add(created_approval);
				//if(_T("")!=dlg.m_csAccessString)
				//	apidata.NET_SetAccessFromPattern(&aet,dlg.m_csAccessString);
				//else
				{
					CString csAccPat;

					if(TRUE==m_api->m_options_mgr.GetDefPatern(e_apl_appr_pers_org,csAccPat))
						apidata.NET_SetAccessFromPattern(&aet,csAccPat);
				}
			}
		}
	}
	
	if(m_AutoSave)
	{
		m_api->SaveChanges();
	}

	for (int i = 0 ; i < insts.Size  ; i++)
	{
		CaplInstance* inst = (CaplInstance*)insts.GetAt(i) ;

		//запрещаем изменение подписанной версии документа
		if(m_api->m_data.IsKindOf(inst, m_api->m_doc_mgr.e_apl_doc_rev))
		{
			aplExtent ext;
			ext.Add(inst);
			apidata.NET_SetInstancesAccess(&ext,(CaplInstance *)-1,aplRO);
		}
	}
	

	for (int i = 0 ; i < items->Size  ; i++)
	{
		CaplInstance* item = (CaplInstance*)items->GetAt(i) ;

		aplExtent specitems;
		specitems.Add(item);
		PostUpdateApprovalItems(specitems);
	}

	return 1;
}

void CaplAutorizationManager::CreateEntryApproval(CaplInstance *ciItem, CaplInstance *ciAppr)
{
	if(!ciItem) return;
	if(apidata.IsKindOf(ciItem, m_api->m_doc_mgr.e_doc))
		apidata.GetAttr(ciItem, m_api->m_doc_mgr.a_apl_doc_active, ciItem);

	if(!ciItem) return; //-V649
	if(!apidata.IsKindOf(ciItem, m_api->m_doc_mgr.e_apl_doc_rev)) return;

	CString t_str;
	aplExtent aeEntryVal, aeResult;
	COleDateTime time(COleDateTime::GetCurrentTime());

	aplDate2String(time, t_str);

	apidata.GetAttr(ciItem, m_api->m_doc_mgr.a_apl_doc_rev_entries, aeEntryVal);
	m_api->LoadExtentInfo(aeEntryVal);

	// всем значениям реквизитов устанавливаем stored в true и пишем дату
	for(int i=0; i<aeEntryVal.GetSize(); i++)
	{
		apidata.PutAttr(aeEntryVal[i], m_api->m_doc_mgr.a_doc_entry_val_stored, true);		
		apidata.PutAttr(aeEntryVal[i], m_api->m_doc_mgr.a_doc_entry_val_descr, t_str);

		//aeResult.Add(aeEntryVal[i]);
	}
	
	// массив значений реквизитов , участвующих в подписи
	m_api->m_doc_mgr.GetActualEntriesVal(ciItem, aeResult);
	apidata.PutAttr(ciAppr,a_appr_po_entries, aeResult);
}

bool CaplAutorizationManager::ConfidentialCertExistInBase(CString sIssure)
{
	bool bConfidential;
	CString sSql, sSubject;
	aplExtent aeTrustfulCert;

	sSql.Format(_T("SELECT Ext_1 FROM Ext_1 { apl_digital_sign_open_key(.cert_subject = '%s' AND .revocation_date ='' AND .confidential = true) } END_SELECT"), sIssure);
	if(m_api->m_data.NET_QueryEditParse(sSql, false))
	{
		m_api->m_data.NET_QueryExecute(aeTrustfulCert);

		if(aeTrustfulCert.Size == 0)
		{				
			return false;
		}
		else if(aeTrustfulCert.Size >= 1)
		{
			CaplLoadData ld(&m_api->m_data,DEF_SOURCE);
			for(int i=0; i<aeTrustfulCert.Size; ++i)ld.AddQuery(i,aeTrustfulCert[i],true);
			ld.LoadEx();


			for(int i=0; i<aeTrustfulCert.Size; ++i)
			{
				m_api->m_data.GetAttr(aeTrustfulCert[i], a_apl_digital_sign_open_key_confidential, bConfidential);
				if(bConfidential) return true;

				m_api->m_data.GetAttr(aeTrustfulCert[i], a_apl_digital_sign_open_key_open_key_cert_issuer, sIssure);
				m_api->m_data.GetAttr(aeTrustfulCert[i], a_apl_digital_sign_open_key_open_key_cert_subject, sSubject);

				if(sIssure == sSubject) return false;
				if(ConfidentialCertExistInBase(sIssure)) return true;
			}
		}
	}
	else
	{
		AfxMessageBox( APL_T("Ошибка выполнения запроса"), MB_ICONSTOP);
		return false;
	}


	return true;
}

bool CaplAutorizationManager::LoadDTinfoOfApprovalItem(aplExtent &aeApproval)
{
	int nCount = 0;
	aplExtent aeTmp;
	CaplLoadData ld(&m_api->m_data, DEF_SOURCE);

	// загружаем только нужное
	for(int i=0; i<aeApproval.Size; i++) 
	{
		if(!aeApproval[i]->GetType()) continue;

		nCount++;
		ld.AddQuery(0, aeApproval[i], true);

		if(nCount==1500 || i==(aeApproval.Size-1))
		{	
			int m1 =	ld.AddQuery(_T('d'), 0, e_apl_appr_pers_org, a_appr_item, true);
			int m2 =	ld.AddQuery(_T('d'), m1, m_api->m_doc_mgr.e_apl_doc_rev, m_api->m_doc_mgr.a_apl_doc_rev_doc, true);
						ld.AddQuery(_T('d'), m2, m_api->m_doc_mgr.e_doc, m_api->m_doc_mgr.a_doc_kind, true, true);

			ld.LoadEx(true, NULL);
			nCount = 0;	
		}
	}

	return true;
}

bool CaplAutorizationManager::IsEntryUsedInEDS(CaplInstance *ciEntry, CaplInstance *ciDocType)
{
	if(!ciEntry) return false;

	if(0==ciDocType)
	{
		CaplAttrValue tst_val[2];
		tst_val[0].attr = m_api->m_doc_mgr.a_doc_entry_val_entry;
		tst_val[0].value.Set(ciEntry);
		tst_val[1].attr = m_api->m_doc_mgr.a_doc_entry_val_stored;
		tst_val[1].value.Set(true);

		if(false==m_api->m_data.NET_TestUniqueAttrValues(m_api->m_doc_mgr.e_doc_entry_val, 0, 2, &tst_val[0], false,  APL_T("Поиск подписей с ЭЦП...")))
			return true;
		return false;
	}

	aplExtent aeApproval;
	CString sSql, sAdditionalRequest;
	CaplInstance *ciItem, *ciDoc, *ciDT;

	// ЯАИ этот запрос дико тормозит, но т.к. с такими параметрами функция нишде не вызывается,
	// то пока менять не буду

	// ищем все версии документов, у которых встречается реквизит
	long dID = aplStartWaitDlg( APL_T("Поиск подписей с ЭЦП..."));

	sSql.Format(_T("SELECT Ext FROM Ext {apl_approval_person_organization(.digital_sign!='' AND .entries->apl_document_entry_value.entry = #%i)} END_SELECT"), ciEntry->GetId());
	m_api->m_data.NET_QueryEditParse(sSql);
	bool b=m_api->m_data.NET_QueryExecute(aeApproval);
	aplEndWaitDlg(dID);
	if(b==false) return true; // если запрос прервали - считаем что используется

	LoadDTinfoOfApprovalItem(aeApproval);
	for(int i=0; i<aeApproval.Size; i++)
	{
		m_api->m_data.GetAttr(aeApproval[i], a_appr_item, ciItem);
		if(!m_api->m_data.IsKindOf(ciItem, m_api->m_doc_mgr.e_apl_doc_rev)) continue;
			
		m_api->m_data.GetAttr(ciItem, m_api->m_doc_mgr.a_apl_doc_rev_doc, ciDoc);
		if(!ciDoc) continue;

		m_api->m_data.GetAttr(ciDoc, m_api->m_doc_mgr.a_doc_kind, ciDT);
		if(ciDT == ciDocType) return true;
	}

	return false;

}

bool CaplAutorizationManager::IsEntryUsedInEDS(CString sEntryName, CaplInstance *ciDocType)
{
	if(sEntryName.IsEmpty()) return false;

	CaplInstance *ciEntry = m_api->m_doc_mgr.GetEntryBN(sEntryName);
	return 	IsEntryUsedInEDS(ciEntry, ciDocType);
}

int CaplAutorizationManager::GetDSInfo(CaplInstance *ciItem, char *&addInfo)
{
	if(!ciItem) return 0;
	if(!m_api) return 0;
	if(!m_api->m_data.IsConnected()) return 0;

	int nIndex = 0;
	int count = 0, i;
	__int64 blobSize = 0;

	CString sFileName;
	CString sEntriesBuf;
	CString sEntryName;
	CString sEntryValue;

	CStringArray saEntriesValue;

	CaplInstance *ciSource;
	CaplInstance *ciActiveVer;
	CaplInstance *ciEntry;

	aplExtent aeEntries;
	aplExtent aeEntriesValue;


	CaplInstance *appr=0;

	if(m_api->m_data.IsKindOf(ciItem, e_apl_appr_pers_org))
	{
		appr=ciItem;
		m_api->m_data.GetAttr(ciItem, a_appr_item, ciItem);
	}

	// получаем значения реквизиттов
	if(!ciItem) return 0; //-V649
	if(m_api->m_data.IsKindOf(ciItem, m_api->m_doc_mgr.e_doc))
	{
		m_api->m_data.GetAttr(ciItem, m_api->m_doc_mgr.a_apl_doc_active, ciActiveVer);
		if(!ciActiveVer) return 0;

		m_api->LoadItemInfo(ciActiveVer);
		m_api->m_data.GetAttr(ciActiveVer, m_api->m_doc_mgr.a_apl_doc_rev_entries, aeEntriesValue);

		// имя документа
		m_api->m_doc_mgr.GetFullFileName(ciItem, sFileName); 

		// размер документа
		m_api->m_data.GetAttr(ciActiveVer, m_api->m_doc_mgr.a_apl_doc_rev_access_form, ciSource);
		m_api->m_data.NET_GetBlobSize(ciSource, m_api->m_doc_mgr.a_apl_stored_document_source, blobSize);
	}
	else if(m_api->m_data.IsKindOf(ciItem, m_api->m_doc_mgr.e_apl_doc_rev))
	{		
		m_api->LoadItemInfo(ciItem);
		m_api->m_data.GetAttr(ciItem, m_api->m_doc_mgr.a_apl_doc_rev_entries, aeEntriesValue);

		// имя документа
		m_api->m_doc_mgr.GetFullFileName(ciItem, sFileName); 

		// размер документа
		m_api->m_data.GetAttr(ciItem, m_api->m_doc_mgr.a_apl_doc_rev_access_form, ciSource);
		m_api->m_data.NET_GetBlobSize(ciSource, m_api->m_doc_mgr.a_apl_stored_document_source, blobSize);
	}	
	else return 0;		

	// загружаем инфо о реквизитах
	m_api->LoadExtentInfo(aeEntriesValue);
	for(int i=0; i<aeEntriesValue.Size; i++)
	{
		m_api->m_data.GetAttr(aeEntriesValue[i], m_api->m_doc_mgr.a_doc_entry_val_entry, ciEntry);
		if(ciEntry) aeEntries.Add(ciEntry);
	}

	m_api->LoadExtentInfo(aeEntries);	
	aeEntries.Clear();

	// пишем значения реквизитов в строку	
	if(appr) m_api->m_doc_mgr.GetActualEntriesVal(appr, aeEntriesValue);
	else m_api->m_doc_mgr.GetActualEntriesVal(ciItem, aeEntriesValue);
	
	for(i=0; i<aeEntriesValue.Size; ++i)
	{
		m_api->m_data.GetAttr(aeEntriesValue[i], m_api->m_doc_mgr.a_doc_entry_val_entry, ciEntry);
		if(ciEntry == 0) continue;

		// добавляем информацию о реквизите
		m_api->m_data.GetAttr(ciEntry, m_api->m_doc_mgr.a_entry_name, sEntryName);
		m_api->m_data.GetAttr(aeEntriesValue[i], m_api->m_doc_mgr.a_doc_entry_val_val, sEntryValue);

		count++;
		saEntriesValue.Add(sEntryName);
		saEntriesValue.Add(sEntryValue);

		sEntriesBuf += sEntryName;
		sEntriesBuf += sEntryValue;
	}

	/*for(i=aeEntriesValue.Size-1; i>=0; i--)
	{
		m_api->m_data.GetAttr(aeEntriesValue[i], m_api->m_doc_mgr.a_doc_entry_val_entry, ciEntry);
		if(ciEntry == 0) continue;

		// каждый реквизит только один раз
		int size = aeEntries.Size;
		aeEntries.Add(ciEntry);
		if(size == aeEntries.Size) continue;				

		// добавляем информацию о реквизите
		m_api->m_data.GetAttr(ciEntry, m_api->m_doc_mgr.a_entry_name, sEntryName);
		m_api->m_data.GetAttr(aeEntriesValue[i], m_api->m_doc_mgr.a_doc_entry_val_val, sEntryValue);

		count++;
		saEntriesValue.Add(sEntryName);
		saEntriesValue.Add(sEntryValue);

		sEntriesBuf += sEntryName;
		sEntriesBuf += sEntryValue;
	}*/
		
	// теперь заполянем данными	
	int size = 1 + sFileName.GetLength()+1 + count + sizeof(int)*2*count+sEntriesBuf.GetLength()+count*2 + sizeof(int)*8;
	addInfo = new char[size];	

	addInfo[nIndex++] = _T('F');
	m_Crypto.SaveStr2Buf(sFileName, addInfo, nIndex);
	m_Crypto.SaveStr2Buf(_T(""), addInfo, nIndex);
	m_Crypto.SaveStr2Buf(_T(""), addInfo, nIndex);
	m_Crypto.SaveInt2Buf(count, addInfo, nIndex);

	for(i=0; i<saEntriesValue.GetSize(); i+=2)
	{
		m_Crypto.SaveStr2Buf(saEntriesValue[i], addInfo, nIndex);
		m_Crypto.SaveStr2Buf(saEntriesValue[i+1], addInfo, nIndex);
	}

	//!!! Внимание! Здесь ошибка - это не будет корректно работать при размере файла >4Гб.
	// Но формат пока менять не можем, поэтому пока так.
	
	m_Crypto.SaveInt2Buf((int)blobSize, addInfo, nIndex);
	//delete addInfo;  Удаляться должна снаружи
	return nIndex;
}


//onpp<--
bool GetAllAttributes(CaplInstance *inst, CString& sInventoy, CString& sData)
{
	CString buf; //Объявление буфера
	int j;
	CaplInstance *cur_inst=inst; //Объявление указателя на элемент массива
	buf.Format(_T("#%i{"),cur_inst->GetId()); //Запись в буфер идентификатора инстанса

	sInventoy+=buf;
	sData+=buf;
	CaplEntity *ent=cur_inst->GetType(); //Объявление указателя на элемент словаря для данного инстанса
	for(j=0;j<ent->all_attrs.GetSize();j++) //Цикл по массиву атрибутов  элемента словаря для данного инстанса
	{
		if(j>0){sInventoy+=_T(","); sData+=_T(",");}
		buf.Format(_T("%i"),ent->all_attrs[j]->id); //Запись в буфер идентификатора атрибута как элемента словаря
		sInventoy+=buf;
		sData+=buf;
		sData+=_T("=");
		//Запись в буфер значения атрибута
		CaplValue *val=&(cur_inst->attrs[j].value);
		buf=_T("");
		if(val!=0)
		{
			val->Print(buf,0,0,aplWIN,0,true);
		}
		if(buf==_T("")) buf=_T("$");
		sData+=buf;
	}
	sInventoy+=_T("}");
	sData+=_T("}");
	return true;
}
//onpp-->
bool CaplAutorizationManager::CreateSnapShot4DigSign(CaplInstance *inst, CString & sData, CString& sInventoy)
{
	sData=_T("");
	sInventoy=_T("");
	if(!inst) return false;
	
	CString buf; //Объявление буфера

	if(m_api->m_data.IsKindOf(inst, m_api->m_prd_mgr.e_pdf)) 
	{
		//Формируем подписываемые данные
		aplExtent ext_rel,ext_pdf; //Объявление массивов инстансов
		m_api->m_prd_mgr.LoadAllSubProduct(0,0,inst,ext_rel,ext_pdf,true); //Считывает состав изделия
		CSortClass::SortExtentById(ext_rel); //Сортировка связей


		int i,j;
		for(i=0;i<ext_rel.GetSize();i++) //Цикл по массиву связей
		{
			CaplInstance *cur_inst=ext_rel[i]; //Объявление указателя на элемент массива
			buf.Format(_T("#%i{"),cur_inst->GetId()); //Запись в буфер идентификатора инстанса

			sInventoy+=buf;
			sData+=buf;
			CaplEntity *ent=cur_inst->GetType(); //Объявление указателя на элемент словаря для данного инстанса
			for(j=0;j<ent->all_attrs.GetSize();j++) //Цикл по массиву атрибутов  элемента словаря для данного инстанса
			{
				if(j>0){sInventoy+=_T(","); sData+=_T(",");}
				buf.Format(_T("%i"),ent->all_attrs[j]->id); //Запись в буфер идентификатора атрибута как элемента словаря
				sInventoy+=buf;
				sData+=buf; 
				//sData+=ent->all_attrs[j]->name; 
				sData+=_T("=");
				//Запись в буфер значения атрибута
				CaplValue *val=&(cur_inst->attrs[j].value);
				buf=_T("");
				if(val!=0)
				{
					val->Print(buf,0,0,aplWIN,0,true);
				}
				if(buf==_T("")) buf=_T("$");
				sData+=buf;
			}
			sInventoy+=_T("}");
			sData+=_T("}");
		}
		return true;
	}
	else if(m_api->m_data.IsKindOf(inst, m_api->m_bp_mgr.e_apl_bp_inst)			|| //Если ЭБП
			m_api->m_data.IsKindOf(inst, m_api->m_bp_mgr.e_bp_res)				|| //Если ресурс бизнес-процесса
			m_api->m_data.IsKindOf(inst, m_api->m_charact_mgr.e_table_row)		|| //Если строка табличной характеристики
			m_api->m_data.IsKindOf(inst, m_api->m_charact_mgr.e_meas_value_ver)	|| //Если версия измеряемой характеристики
			m_api->m_data.IsKindOf(inst, m_api->m_charact_mgr.e_descr_value_ver)|| //Если версия строковой характеристики
			m_api->m_data.IsKindOf(inst, m_api->m_charact_mgr.e_enum_value_ver)	|| //Если версия списочной характеристики
			m_api->m_data.IsKindOf(inst, m_api->m_charact_mgr.e_aggr_val_ver)   || //Если версия составной характеристики
			m_api->m_data.IsKindOf(inst, m_api->m_charact_mgr.e_apl_reference_value_ver)|| //Если версия ссылочной характеристики
			m_api->m_data.IsKindOf(inst, m_api->m_charact_mgr.e_time_val_ver)   || //Если версия временнОй характеристики
			m_api->m_data.IsKindOf(inst, m_api->m_charact_mgr.e_monet_value_ver)|| //Если версия денежной характеристики
			m_api->m_data.IsKindOf(inst, m_api->m_charact_mgr.e_table_val_ver))	   //Если версия табличной характеристики
	{
		CString buf; //Объявление буфера
		GetAllAttributes(inst, sInventoy, sData);//вызов функции для подписываемого объекта

		if (m_api->m_data.IsKindOf(inst, m_api->m_charact_mgr.e_table_val_ver)) //Доп. обработка для версии табличной характеристики
		{
			aplExtent extRows;
			m_api->m_data.GetAttrBN(inst, _T("values"), extRows);
			m_api->LoadExtentInfo(extRows);
			for (int iRow = 0; iRow < extRows.GetSize(); iRow++)
			{
				CaplInstance *pRow = extRows[iRow];
				GetAllAttributes(pRow, sInventoy, sData);//вызов функции для row
				aplExtent extItems;
				aplExtent extTmp;
				m_api->m_data.GetAttrBN(pRow, _T("items"), extItems);
				m_api->LoadExtentInfo(extItems);
				for (int iItem = 0; iItem < extItems.GetSize(); iItem++)
				{
					CaplInstance *pItem = extItems[iItem];
					GetAllAttributes(pItem, sInventoy, sData);//вызов функции для pItem
					CaplInstance *pValue = NULL;
					m_api->m_data.GetAttrBN(pItem, _T("val"), pValue);
					extTmp.Clear();
					extTmp.Add(pValue);
					m_api->LoadExtentInfo(extTmp);
					GetAllAttributes(pValue, sInventoy, sData);//вызов функции для pValue
				}
			}
		}
		if (m_api->m_data.IsKindOf(inst, m_api->m_charact_mgr.e_table_row)) //Доп. обработка для строки табличной характеристики
		{
			aplExtent extItems;
			aplExtent extTmp;
			m_api->m_data.GetAttrBN(inst, _T("items"), extItems);
			m_api->LoadExtentInfo(extItems);
			for (int iItem = 0; iItem < extItems.GetSize(); iItem++)
			{
				CaplInstance *pItem = extItems[iItem];
				GetAllAttributes(pItem, sInventoy, sData);//вызов функции для pItem
				CaplInstance *pValue = NULL;
				m_api->m_data.GetAttrBN(pItem, _T("val"), pValue);
				extTmp.Clear();
				extTmp.Add(pValue);
				m_api->LoadExtentInfo(extTmp);
				GetAllAttributes(pValue, sInventoy, sData);//вызов функции для pValue
			}
		}
		return true;
	}
	else if(m_api->m_data.IsKindOf(inst, m_api->m_change_mgr.e_chng))
	{
		aplExtent ext4sign;
		ext4sign.Add(inst);

		int i,j;
		aplExtent ChangeItems, ext_psc, ext_avc, ext_attacment;

		m_api->m_data.GetAttr(inst, m_api->m_change_mgr.a_chng_items, ChangeItems);
		m_api->m_change_mgr.LoadItemInfo(ChangeItems);

		for(i=0; i<ChangeItems.GetSize(); i++)
		{
			CaplInstance* item = ChangeItems.GetAt(i);
			ext4sign.Add(item);
			//if(api->m_data.IsKindOf(item, api->m_change_mgr.e_avc)) ext_avc.Add(item);
			//else  if(api->m_data.IsKindOf(item,api->m_change_mgr.e_psc))ext_psc.Add(item);
		}

		CSortClass::SortExtentById(ext4sign);

		for(i=0; i<ext4sign.GetSize(); i++)
		{
			CaplInstance *cur_inst=ext4sign[i];
			buf.Format(_T("#%i{"),cur_inst->GetId()); //Запись в буфер идентификатора инстанса
			sInventoy+=buf;
			sData+=buf;

			CaplEntity *ent=cur_inst->GetType(); //Объявление указателя на элемент словаря для данного инстанса
			for(j=0;j<ent->all_attrs.GetSize();j++) //Цикл по массиву атрибутов  элемента словаря для данного инстанса
			{
				CaplAttr *attr=ent->all_attrs[j];

				// Не все атрибуты используем
				if(ent== m_api->m_change_mgr.e_chng)
				{
					continue; // по факту получились, что все атрибуты могут меняться
					/*if(attr==m_api->m_change_mgr.a_chng_state || attr==m_api->m_change_mgr.a_chng_user 
						|| attr==m_api->m_change_mgr.a_chng_autor || attr==m_api->m_change_mgr.a_chng_is_modify
						|| attr==m_api->m_change_mgr.a_chng_create_date ||  attr==m_api->m_change_mgr.a_chng_apply_date
						|| attr==m_api->m_change_mgr.a_chng_create_user || attr==m_api->m_change_mgr.a_chng_create_autor  
						|| attr==m_api->m_change_mgr.a_chng_start_date || attr==m_api->m_change_mgr.a_chng_end_date  
						|| attr==m_api->m_change_mgr.a_chng_stock || attr==m_api->m_change_mgr.a_chng_stock_introd
						|| attr==m_api->m_change_mgr.a_chng_usage || attr==m_api->m_change_mgr.a_chng_list
						|| attr==m_api->m_change_mgr.a_chng_otd_date || attr==m_api->m_change_mgr.a_chng_critical_date
						|| attr==m_api->m_change_mgr.a_chng_stock_ceh ||attr==m_api->m_change_mgr.a_chng_name
						) continue;
						*/
				}
				if(ent== m_api->m_change_mgr.e_chng_item)
				{
					if(attr==m_api->m_change_mgr.a_chng_item_autor || attr==m_api->m_change_mgr.a_chng_item_user 
						|| attr==m_api->m_change_mgr.a_chng_item_accept_date || attr==m_api->m_change_mgr.a_chng_item_replace_state )
						continue;
				}
				CaplValue *val=&(cur_inst->attrs[j].value);

				if(attr->type==aplSTRING)  // Не учитываем пустые строки
				{
					if(val->sval==0 ) continue;
					if(val->sval[0]==_T('\0') ) continue;
				}

				if(j>0){sInventoy+=_T(","); sData+=_T(",");}
				buf.Format(_T("%i"),ent->all_attrs[j]->id); //Запись в буфер идентификатора атрибута как элемента словаря
				sInventoy+=buf;
				sData+=buf; 
				//sData+=ent->all_attrs[j]->name; 
				sData+=_T("=");
				//Запись в буфер значения атрибута
				
				buf=_T("");
				if(val!=0)
				{
					val->Print(buf,0,0,aplWIN,0,true);
				}
				if(buf==_T("")) buf=_T("$");
				sData+=buf;
			}
			sInventoy+=_T("}");
			sData+=_T("}");

		}
		return true;
	}


	AfxMessageBox(APL_T("Пока не реализовано!"));
	return false;
}

bool GetAttrInSnapShot(CString &snapshot, int &startpos, int attr, CString &val)
{
	val=_T("");
	if (startpos<=0 || attr<=0) return false;
	CString buf;
	buf.Format(_T("%i="),attr);
	int j,i=snapshot.Find(buf,startpos);
	if(i<0) return false;

	i+=buf.GetLength();
	j=i;

	bool bQute=false;
	int iBrackets=0;
	while(true)
	{
		TCHAR c=snapshot[j];
		if(c==_T('\0')) break;
		
		if(c==_T('\'')) bQute=!bQute;
		else if(c==_T('(')) {if(!bQute) iBrackets++;}
		else if(c==_T(')')) {if(!bQute) iBrackets--;}
		else if(c==_T(',') || c==_T('}') )
		{
			if(!bQute && 0==iBrackets)
			{
				val=snapshot.Mid(i,j-i);
				startpos=j;
				return true;
			}
		}
		j++;
	}
	return false;
}

bool CaplAutorizationManager::CreateSnapShotByInventory(CString& sInventoy, CString & sData, CString *psOldData, CString *psDiff)
{
	sData=_T("");
	if(sInventoy==_T("")) return false;
	CString buf;
	int pos=0;

	// Чтение атрибутов из БД
		
	//Опеделяем объекты для чтения

	int inst_count_1=0, inst_count_2=0; //для проверки

	CaplLoadData ld(&(m_api->m_data),DEF_SOURCE);

	int len=sInventoy.GetLength();

	while(pos<len)
	{
		TCHAR c=sInventoy[pos];
		if(c!=_T('#')) break;
		pos++;
		int start=pos;
		while(sInventoy[pos]!=_T('{')) pos++;
		buf=sInventoy.Mid(start,pos-start);
		long inst_id = _atoi(buf);

		ld.AddQuery(_T('a'),inst_id,(CaplEntity*)0,0,true,true);
		inst_count_1++;

		pos++;
		while(sInventoy[pos]!=_T('}') && pos<len) pos++;
		pos++;
	}

	if(inst_count_1>0) ld.LoadEx();


	// Восстанавливаем Data по inventory
	pos=0;
	int posInstInOldDataPrev=0;

	while(pos<sInventoy.GetLength())
	{
		TCHAR c=sInventoy[pos];
		if(c!=_T('#')) break;
		pos++;
		int start=pos;
		while(sInventoy[pos]!=_T('{')) pos++;
		buf=sInventoy.Mid(start,pos-start);
		int inst_id = _atoi(buf);

		inst_count_2++;

		CaplInstance *inst=m_api->m_data.GetInstById(inst_id);
		if(inst==0)
		{
			buf.Format( APL_T("В снимке неизвестный объект (%i)!"),inst_id);
			AfxMessageBox(buf,MB_ICONSTOP|MB_OK);
			return false;
		}
		buf.Format(_T("#%i{"),inst_id);
		sData+=buf;

			int posInstInOldData=0;
			if(0!=psOldData && 0!=psDiff) // Дописываем протокол различий
			{
				posInstInOldData=psOldData->Find(buf,posInstInOldDataPrev);
				if(posInstInOldData<0)
				{
					buf.Format( APL_T("В снимке не найден объект #%i\n"),inst_id);
					(*psDiff)+=buf;
				}
				else posInstInOldDataPrev=posInstInOldData+buf.GetLength();
			}

		bool bFirstAttr=true;

		while(true)
		{
			pos++;
			start=pos;
			while(sInventoy[pos]!=_T(',') && sInventoy[pos]!=_T('}') && sInventoy[pos]!=_T('\0')) pos++;
			buf=sInventoy.Mid(start,pos-start);
			if(pos==start)
			{
				// такое возникает, если нет атрибутов
				if( sInventoy[pos]==_T('}') ||  sInventoy[pos]==_T('\0')) break;
			}
			int attr_id=_atoi(buf);

			if(bFirstAttr) bFirstAttr=false;
			else sData+=_T(",");
			buf.Format(_T("%i="),attr_id);
			sData+=buf;
			
			CaplAttr *attr=m_api->m_data.GetAttrDefinitionById(attr_id);
			if(attr==0)
			{
				buf.Format( APL_T("В снимке неизвестный атрибут (%i) объекта (%i)!"),attr_id,inst_id);
				AfxMessageBox(buf,MB_ICONSTOP|MB_OK);
				return false;
			}
			bool bInstShowedInDiff=false;

			CaplValue *val=0;
			m_api->m_data.GetAttr(inst,attr,&val);
			if(val) val->Print(buf,0,0,aplWIN,0,true);
			if(buf==_T("")) buf=_T("$");
			
			sData+=buf;

				if(0!=psOldData && 0!=psDiff) // Дописываем протокол различий
				{
					CString val; 
					GetAttrInSnapShot(*psOldData,posInstInOldDataPrev,attr_id,val);

					if(buf!=val)
					{
						CString buf1;

						if(!bInstShowedInDiff)
						{
							bInstShowedInDiff=true;
							buf1.Format(_T("\nInstance %i - %s\n"),inst_id,LPCTSTR(inst->GetType()->name));
							(*psDiff)+=buf1;
						}
						buf1.Format(_T("   attr %i - %s\n"),attr_id,LPCTSTR(attr->name));
						(*psDiff)+=buf1;
						(*psDiff)+=_T("      old="); (*psDiff)+=val;  (*psDiff)+=_T("\n");
						(*psDiff)+=_T("      new="); (*psDiff)+=buf;  (*psDiff)+=_T("\n");
					}
				}
			

			if( sInventoy[pos]==_T('}') ||  sInventoy[pos]==_T('\0')) break;
		}
		sData+=_T("}");
		pos++;
	}

	if(inst_count_1!=inst_count_2)
	{
		AfxMessageBox( APL_T("Ошибка разбора описи снимка!"),MB_OK|MB_ICONSTOP);
		return false;
	}

	return true;
}
//**********************************************************************************************
//**********************************************************************************************
//**********************************************************************************************
bool CaplAutorizationManager::SignObject(CaplInstance* doc, const TCHAR* system,
	CString &sSign, CString &sHash, CString &sOpenKey, 	CString &UserName, CString &CertFileName,
	CString &sInventory, CString &sShapShot, CaplInstance **pPerson)
{
	if(!doc) return false;
	if(!m_api->m_data.IsKindOf(doc, m_api->m_doc_mgr.e_apl_doc_rev) &&
		!m_api->m_data.IsKindOf(doc, m_api->m_doc_mgr.e_apl_doc)&&
		!m_api->m_data.IsKindOf(doc, m_api->m_prd_mgr.e_pdf) &&		
		!m_api->m_data.IsKindOf(doc, m_api->m_bp_mgr.e_bp)&&	
		!m_api->m_data.IsKindOf(doc, m_api->m_bp_mgr.e_apl_bp_inst)&&	
		!m_api->m_data.IsKindOf(doc, m_api->m_charact_mgr.e_apl_charact_value)&&	
		!m_api->m_data.IsKindOf(doc, m_api->m_charact_mgr.e_apl_charact_value_ver)&&	
		!m_api->m_data.IsKindOf(doc, m_api->m_bp_mgr.e_apl_bp_ver)&&
		!m_api->m_data.IsKindOf(doc, m_api->m_bp_mgr.e_bp_res)&&	
		!m_api->m_data.IsKindOf(doc, m_api->m_change_mgr.e_chng)	
		) return false;

	if((m_api->m_data.IsKindOf(doc, m_api->m_charact_mgr.e_apl_charact_value))&&(!m_api->m_data.IsKindOf(doc, m_api->m_charact_mgr.e_table_row))) //onpp
	{
		m_api->m_data.GetAttr(doc,m_api->m_charact_mgr.a_apl_charact_val_act_ver,doc);
		if(0==doc) return false;
		if(doc->GetAccessmode()>aplRO)return false;
	}

	CString strSystem=system;


	sShapShot=_T("");
	sInventory=_T("");
	sSign=_T("");
	sHash=_T("");
	sOpenKey=_T("");
	CertFileName=_T("");

	CaplInstance *person=0; // если останется 0 - берем из ключа
	if(0==pPerson) person=  GetCurrentPerson();
	else
	{
		if(*pPerson!=0 && ((long)(*pPerson))!=-2) person=*pPerson;
		else if(0==(*pPerson)) 	person= GetCurrentPerson();
	}
	if(0!=person)GetPersonName(person,UserName,false);


	//Готовим подписываемые данные
	BYTE* SignedBuffer=0;
	long  SignedBufferLen=0;

	//CString sData;		//снимок подписываемых данных (для PDF)
	//CString sInventoy;	//опись подписываемых данных  (для PDF)
	CString sSignedFile;//имя подписывемого документа (для doc)
	CaplInstance* rev= NULL;

	if(m_api->m_data.IsKindOf(doc, m_api->m_prd_mgr.e_pdf)||
		m_api->m_data.IsKindOf(doc, m_api->m_bp_mgr.e_bp) ||		
		m_api->m_data.IsKindOf(doc, m_api->m_change_mgr.e_chng) ||	
		m_api->m_data.IsKindOf(doc, m_api->m_bp_mgr.e_apl_bp_ver) ||	
		m_api->m_data.IsKindOf(doc, m_api->m_bp_mgr.e_apl_bp_inst) ||	
		m_api->m_data.IsKindOf(doc, m_api->m_bp_mgr.e_bp_res) ||	
		m_api->m_data.IsKindOf(doc, m_api->m_charact_mgr.e_apl_charact_value_ver) ||	
		m_api->m_data.IsKindOf(doc, m_api->m_charact_mgr.e_table_row) //onpp 	
		)
	{

		if(!CreateSnapShot4DigSign(doc,sShapShot,sInventory)) return false;
		SignedBuffer=(BYTE*)LPCTSTR(sShapShot);
		SignedBufferLen=sShapShot.GetLength(); // Под Юникодом будет не так

		if(0==SignedBufferLen)
		{
			AfxMessageBox(APL_T("Нет данных для вычисления ЭП!"),MB_ICONWARNING|MB_OK);
			return false;
		}

#ifdef UNICODE
		AfxMessageBox(_T("Вариант под Юникодом будет несовместим с вариантом ANSI!"),MB_ICONSTOP);
#endif
	}
	else
	{
		if(m_api->m_data.IsKindOf(doc, m_api->m_doc_mgr.e_apl_doc))
			m_api->m_data.GetAttr(doc, m_api->m_doc_mgr.a_apl_doc_active, rev);
		else 
			rev= doc;

		// получаем файл
		CString sPath, sFileName; 
		aplGetTempPath(sPath);

		TCHAR *tempfname=new TCHAR[MAX_PATH];
		GetTempFileName(sPath,_T("aplsign"),0,tempfname);
		sSignedFile=tempfname;
		delete [] tempfname;

		long dID = aplStartWaitDlg(APL_T("Чтение данных из БД..."));
		bool b=m_api->m_doc_mgr.LoadRevision(rev, sSignedFile,-1,false);
		aplEndWaitDlg(dID);
		if(!b) return false;
		SignedBuffer = (BYTE*)(LPCTSTR(sSignedFile));  // Имя файла
	}


	
	char *bBuf=0;
	DWORD lLen=0;

	// получаем полные данные, от которых будем брать вычислять хеш
	char *addInfo = 0;	
	int infoSize = 0;
	infoSize = GetDSInfo(doc, addInfo);	
	
	int res = APL_CRYPT_NO_ERROR;
	bool bOldKeyFormat = false;
	CStringArray saKeysFromBase;
	
	if(strSystem == APL_CRYPTO_PRO_34_10_2001 || strSystem == APL_CRYPTO_PRO_34_10_2012 )
	{
		// подпись КриптоПрошным ключом
		res = m_Crypto.Sign(LPCTSTR(UserName), 0, SignedBuffer, SignedBufferLen, sHash, sOpenKey, sSign, CertFileName, system, bOldKeyFormat, saKeysFromBase, addInfo, infoSize);		
	}
	else if(strSystem == APL_CRYPT_MGR)
	{
		// получим список ключей пользователя, которые были сохранены в базе данных
		aplExtent aeCerts;
		CaplAttrValue val[2];		
		CString sDate, buf, key, t_str;

		while(true) // Для возможности создания сертификата
		{
			 m_Crypto.m_bEnableBtnCreareCert4Me=false;

			if(0!=person)
			{
				// ищем ключ , сохраненный в базе данных
				val[0].attr = a_apl_digital_sign_open_key_person;
				val[0].value.Set(GetCurrentPerson());

				val[1].attr = a_apl_digital_sign_open_revocation_date;
				val[1].value.Set(_T(""));

				long dID = aplStartWaitDlg( APL_T("Поиск ключей, сохраненных в базе данных..."));
				m_api->m_data.NET_FindInstancesWithAttrValues(e_apl_digital_sign_open_key, 2, &val[0], aeCerts, false);
				aplEndWaitDlg(dID);

				COleDateTime cur_odt=COleDateTime::GetCurrentTime();
				CString sCurDate;
				aplDate2String(cur_odt,sCurDate);

				int iNumOldKeys=0;


				if(aeCerts.Size) m_api->LoadExtentInfo(aeCerts);
				for(int i=0; i<aeCerts.Size; ++i)
				{
					m_api->m_data.GetAttr(aeCerts[i], a_apl_digital_sign_open_key_container, key);
					if(key.IsEmpty()) continue;
					if(key.Left(6) == _T("[file]")) continue;

					m_api->m_data.GetAttr(aeCerts[i], a_apl_digital_sign_open_revocation_date, buf);
					if(!buf.IsEmpty()) {iNumOldKeys++; continue;}

					m_api->m_data.GetAttr(aeCerts[i], a_apl_digital_sign_open_not_after, buf);
					if(buf.IsEmpty() || buf<sCurDate) {iNumOldKeys++; continue;}

					m_api->m_data.GetAttr(aeCerts[i], a_apl_digital_sign_open_key_open_key_cert_subject, buf);

					saKeysFromBase.Add(buf);
					saKeysFromBase.Add(key);
				}

				if(0==saKeysFromBase.GetSize() && (iNumOldKeys>0))
				{
					AfxMessageBox( APL_T("Все Ваши сертификаты ЭП просрочены или отозваны!\n\nПолучите новый сертификат!"), MB_ICONWARNING);
				}

				if(0==saKeysFromBase.GetCount())
				{
					CString sCACertSN;
					m_api->m_options_mgr.GetOptionValueBN(APL_NO_T("ЭЦП\\Генерация сертификата пользователем\\Серийный номер сертификата УЦ"),sCACertSN,_T(""));
					if(sCACertSN!=_T(""))  m_Crypto.m_bEnableBtnCreareCert4Me=true;
				}
			}

			// подпись ключом от AplCryptMgr
			res = m_Crypto.Sign(LPCTSTR(UserName), 0, SignedBuffer, SignedBufferLen, sHash, sOpenKey, sSign, CertFileName, system, bOldKeyFormat, saKeysFromBase, addInfo, infoSize);

			if(APL_CRYPT_ERROR_RET_CREATE_KEY==res) {CreateDigSignCert4CurrentPerson(); continue;}
				
			break;
		}
	}
	else if(strSystem == APL_OPENSSL_34_10_2001)
	{	
		AfxMessageBox( APL_T("В разработке!"), MB_ICONSTOP);
		res=APL_CRYPT_UNKNOWN_ERROR;
	}
	else
	{	
		// система не выбрана
		AfxMessageBox( APL_T("Не выбрана система ЭЦП!"), MB_ICONSTOP);
		res=APL_CRYPT_UNKNOWN_ERROR;
	}
	
	if(sSignedFile!=_T(""))
	{
		::SetFileAttributes(sSignedFile, FILE_ATTRIBUTE_NORMAL);
		DeleteFile(sSignedFile);
	}

	if(addInfo) delete addInfo;
	if(bBuf) delete [] bBuf;	

	if(res!=APL_CRYPT_NO_ERROR) return false;

	// смотрим, если старый формат ключа, то нужно проверить: "А можно ли подписывать старыми ключами?"
	if(bOldKeyFormat)
	{
		int nValue = -1;
		CaplInstance *ciOption = m_api->m_options_mgr.FindOptionBN( APL_NO_T("Запретить использование контейнеров AplCryptManager версии 0"));
		if(!ciOption)
		{
			m_api->m_options_mgr.CreateOption( APL_NO_T("Запретить использование контейнеров AplCryptManager версии 0"), 0);
		}
		else
		{
			m_api->m_options_mgr.GetOptionValueBN( APL_NO_T("Запретить использование контейнеров AplCryptManager версии 0"), nValue, 0);
			if(nValue == 1)
			{
				AfxMessageBox( APL_NO_T("Выбранный ключ является устаревшим. Для работы с ЭЦП необходимо использовать ключ новой версии."), MB_ICONSTOP);
				return false;
			}		
		}
	}

	// проверяем доверительный сертификат для ключа
	COleDateTime t1, t2;
	CString sSql, sMethod;
	aplExtent aeTrustfulCert, aeTmp;

	CString sSubject, sCertOpenKey, sIssure, sCertNum, sAlg;
	m_Crypto.GetDataFromCertFile(CertFileName, sSubject, sCertOpenKey, t1, t2, sIssure, sCertNum, sAlg);	

	if(!bOldKeyFormat && !ConfidentialCertExistInBase(sIssure)) 
	{
		AfxMessageBox( APL_T("Для ключа не найден доверительный сертификат (сертификат УЦ)! Подпись невозможна!"), MB_ICONSTOP);
		return false;		
	}		

	// Проверка нахождения открытого ключа в отозванных + проверка, что это действительно открытый ключ текущего пользователя +
	// проверка того, что ключ и сертификат были выданы центром, которому можно доверять

	aplExtent ext;
	CaplAttrValue val;
	CaplInstance *ciOpenKeyPerson;

	sSql.Format(_T("SELECT Ext_1 FROM Ext_1 { apl_digital_sign_open_key.digital_sign_open_key = '%s' } END_SELECT"), sOpenKey);
	if(m_api->m_data.NET_QueryEditParse(sSql, false) == false) return false;
	m_api->m_data.NET_QueryExecute(ext);

	if(ext.Size == 1)
	{		
		CaplInstance *key=ext[0];
		m_api->LoadItemInfo(key);		

		// проверяем на метод шифрования
		m_api->m_data.GetAttr(key, a_apl_digital_sign_open_key_open_key_metod, sMethod);
		if(sMethod.IsEmpty()) sMethod = APL_CRYPT_MGR;
		
		if(sMethod.CompareNoCase(system))
		{
			AfxMessageBox( APL_T("Данный ключ предназначен для системы шифрования: \"") + sMethod +  _T("\""), MB_ICONSTOP);
			m_Crypto.ResetSignTime();
			return false;
		}

		// проверяем пользователя
		m_api->m_data.GetAttr(key, a_apl_digital_sign_open_key_person, ciOpenKeyPerson);
		if(0!=person) 
		{
			if(ciOpenKeyPerson !=  person)
			{
				AfxMessageBox( APL_T("Данный ключ не является открытым криптографическим\nключом пользователя."),MB_OK|MB_ICONERROR);
				m_Crypto.ResetSignTime();
				return false;
			}
		}

		COleDateTime timeBefore, timeAfter, timeNow;
		CString sRevocationDate, sDateBefore, sDateAfter, sDateNow;

		m_api->m_data.GetAttr(key, a_apl_digital_sign_open_revocation_date, sRevocationDate);
		m_api->m_data.GetAttr(key, a_apl_digital_sign_open_not_before, sDateBefore);
		m_api->m_data.GetAttr(key, a_apl_digital_sign_open_not_after, sDateAfter);
		
		// проверяем на отзыв
		if(!sRevocationDate.IsEmpty())
		{
			AfxMessageBox( APL_T("Сертификат открытого ключа отозван. Закрытым ключём подписывать нельзя!"),MB_OK|MB_ICONSTOP);
			m_Crypto.ResetSignTime();
			return false;
		}

		if(!sDateBefore.IsEmpty() && !sDateAfter.IsEmpty())
		{
			// проверяем на временные ограничения сертификата
			m_api->m_data.NET_GetServerDateTime(timeNow);
			aplDate2String(timeNow, sDateNow);

			if(sDateNow < sDateBefore)
			{
				AfxMessageBox( APL_T("Сертификат еще не действителен!"), MB_ICONINFORMATION);
				m_Crypto.ResetSignTime();
				return false;
			}

			if(sDateNow > sDateAfter)
			{
				AfxMessageBox( APL_T("Срок действия сертификата истек!"), MB_ICONINFORMATION);
				m_Crypto.ResetSignTime();
				return false;
			}	
		}

		// Записываем сотрудника
		if(ciOpenKeyPerson==0 && person!=0) m_api->m_data.PutAttr(key, a_apl_digital_sign_open_key_person, person);

		if(pPerson!=0) *pPerson=ciOpenKeyPerson;
		
	}
	else if(ext.Size > 1)
	{
		// открытый ключ - штука уникальная
		AfxMessageBox( APL_T("Подпись невозможна, так как в базе данных имеется несколько записей с подобным открытым ключом. Обратитесь к администратору удостоверяющего центра."), MB_ICONSTOP);
		return false;
	}
	else if(ext.Size == 0 && person!=0)
	{
		// Создаем запись о ключе

		//19.06.2019 НАМ
		//Но проверяем совпадение фамилии текущего пользователя и сведений, указанных в сертификате (в CN и в SN)

		if(CertFileName!=_T(""))
		{
			// Читаем данные из сертификата
			COleDateTime dNotBefore, dNotAfter;
			CString sCertOpenKey, sSerialNum, sSubject, sIssuer,sNotBefore, sNotAfter, sAlg, sError;

			if(m_Crypto.GetDataFromCertFile(CertFileName, sSubject, sCertOpenKey, dNotBefore, dNotAfter, sIssuer,sSerialNum, sAlg))
			{
				if(false==CaplCryptographicManager::IsCertUser(UserName, sSubject))
				{
					sError.Format(APL_T("Сертификат не принадлежит сотруднику! \n\nСотрудник: %s\n\nВладелец ключа: %s\n"),LPCTSTR(UserName),LPCTSTR(sSubject));
					AfxMessageBox(sError,MB_OK|MB_ICONERROR);
					m_Crypto.ResetSignTime();
					return false;
				}

				aplDate2String(dNotBefore,sNotBefore);
				aplDate2String(dNotAfter,sNotAfter);

				CaplInstance *inst=m_api->m_data.CreateInstance(e_apl_digital_sign_open_key);

				m_api->m_data.PutAttr(inst,a_apl_digital_sign_open_key_open_key_metod, sAlg);
				m_api->m_data.PutAttr(inst,a_apl_digital_sign_open_key_person,GetCurrentPerson());
				m_api->m_data.PutAttr(inst,a_apl_digital_sign_open_key_open_key,sCertOpenKey);
				m_api->m_data.PutAttr(inst,a_apl_digital_sign_open_key_open_key_cert_subject,sSubject);
				m_api->m_data.PutAttr(inst,a_apl_digital_sign_open_key_open_key_cert_issuer,sIssuer);
				m_api->m_data.PutAttr(inst,a_apl_digital_sign_open_key_open_key_cert_serial_num,sSerialNum);
				m_api->m_data.PutAttr(inst,a_apl_digital_sign_open_not_before,sNotBefore);
				m_api->m_data.PutAttr(inst,a_apl_digital_sign_open_not_after,sNotAfter);
				m_api->SaveChanges();
				long code;
				m_api->m_data.NET_SaveBlob(inst,a_apl_digital_sign_open_key_open_key_cert_blob,CertFileName,code);
				m_api->SaveChanges();
			}
		}
		else 
		{
			//20.06.2019
			//То подписал текущий пользователь каким-то ключем без сертификата???
		}
	}

	if(sHash==_T("") || sOpenKey==_T("") || sSign==_T(""))return false;

	return true;	
}

bool CaplAutorizationManager::IsApprovalActual(CaplInstance *ciApproval)
{
	if(!ciApproval) return false;
	if(!m_api->m_data.IsKindOf(ciApproval, e_apl_appr_pers_org)) return false;

	CaplInstance *ciItem;
	CString sApprEntryVal, sDocEntryVal;
	aplExtent aeApprEntries, aeDocEntries;

	// берем актуальные реквизиты дял подписи и версии документа
	m_api->m_data.GetAttr(ciApproval, a_appr_item, ciItem);
	m_api->m_doc_mgr.GetActualEntriesVal(ciApproval, aeApprEntries);
	m_api->m_doc_mgr.GetActualEntriesVal(ciItem, aeDocEntries);

	// сравниваем реквизиты
	if(aeApprEntries.Size != aeDocEntries.Size) return false;
	for(int i=0; i<aeDocEntries.Size; i++)
	{
		m_api->m_data.GetAttr(aeDocEntries[i], m_api->m_doc_mgr.a_doc_entry_val_val, sDocEntryVal);
		m_api->m_data.GetAttr(aeApprEntries[i], m_api->m_doc_mgr.a_doc_entry_val_val, sApprEntryVal);

		if(sDocEntryVal != sApprEntryVal) 
			return false;
	}

	return true;
}

int CaplAutorizationManager::CheckApproval(CaplInstance* approval, bool bShowResult)
{
	int iRes= 0;
	char *bBuf=0;
	DWORD lLen=0;
		
	if(!approval)
	{
		if(bShowResult)MessageBox(NULL,  APL_T("Ошибка во время выполнения программы!"),  APL_T("Проверка подписи"), MB_OK|MB_ICONERROR);
		return 1;
	}
	
	CaplInstance* inst0= NULL, *inst1= NULL, *inst2= NULL;
	
	CaplInstance* item= NULL;
	m_api->m_data.GetAttr(approval, a_appr_item, item);
	if(0==item) return 0;

	CaplInstance* person= NULL;
	m_api->m_data.GetAttr(approval, a_appr_pers_org, inst0);
	if(inst0)
	{
		if(m_api->m_data.IsKindOf(inst0, e_pers_org))
			apidata.GetAttr(inst0, a_po_the_pers, person);
		else if(m_api->m_data.IsKindOf(inst0, e_person))
			person= inst0;
	}
	if(!person)
	{
		if(bShowResult)MessageBox(NULL,  APL_T("Ошибка: нет информации о сотруднике!"),  APL_T("Проверка подписи"), MB_OK|MB_ICONERROR);
		return 1;
	}

	long lCertSize=0;
	COleDateTime appr_odt;
	CString buf,sSignDate, sCertBlob;
	CString sHash, sOpenKey, sSignature, sMethod,sInventory,sSnapShot;

	BYTE *cert_buf=0;
	bool bUseCertificateToCheckApproval = false;

	m_api->m_data.GetAttr(approval, a_appr_dg_sign_met, sMethod);
	m_api->m_data.GetAttr(approval, a_appr_dg_sign, sSignature);
	m_api->m_data.GetAttr(approval, a_appr_dg_sign_hash, sHash);
	m_api->m_data.GetAttr(approval, a_appr_dg_sign_inventory, sInventory);
	m_api->m_data.GetAttr(approval, a_appr_dg_sign_snapshot, sSnapShot);
	m_api->m_data.GetAttr(approval, a_appr_dg_sign_open_key, sOpenKey);
	m_api->m_data.GetAttr(approval, a_appr_appr_date_time_s, sSignDate);

	aplString2Date(sSignDate,appr_odt);
	if(sMethod.IsEmpty() || sHash.IsEmpty() || sSignature.IsEmpty()) 
	{
		if(bShowResult)MessageBox(NULL,  APL_T("Ошибка: ЭЦП не полная или отсутствует!"),  APL_T("Проверка подписи"), MB_OK|MB_ICONERROR);
		return 5;
	}

	// Ищем открытый ключ для сотрудника
	CaplInstance *pers_key=0;
	aplExtent ext;
	CaplAttrValue tst_value;
	tst_value.value.Set(sOpenKey);
	tst_value.attr=a_apl_digital_sign_open_key_open_key;
	m_data->NET_FindInstancesWithAttrValues(e_apl_digital_sign_open_key,1,&tst_value,ext,false);
	if(ext.Size>0)
	{
		pers_key=ext[0];
		CaplLoadData ld(&(m_api->m_data),DEF_SOURCE);
		ld.AddQuery(-1,pers_key,true);
		ld.LoadEx();

		// принадлежит ли сертификат  пользователю, который проставил статус ?
		CaplInstance *key_person;
		m_api->m_data.GetAttr(pers_key, a_apl_digital_sign_open_key_person, key_person);
		if(key_person != person)
		{
			if(IDNO==AfxMessageBox( APL_T("Данный ключ проверки электронной подписи не принадлежит подписавшему пользователю.\n\nПродолжить проверку подписи?"), 
				MB_YESNO|MB_ICONERROR))	
				return 4;
		}

		//Проверка нахождения открытого ключа в отозванных
		CString sRevocationDate;
		m_api->m_data.GetAttr(pers_key, a_apl_digital_sign_open_revocation_date, sRevocationDate);
		if(!sRevocationDate.IsEmpty())
		{
			if(sRevocationDate <= sSignDate)
			{
				AfxMessageBox( APL_T("Данный сертификат на момент подписи был отозван!\n\nПодпись не действительна."),MB_ICONERROR);
				return 4;
			}
		}
	}
	
	// получаем сертификат, чтобы потом загрузиь его в провайдер и проверить подпись
	// если его нет, то берем просто открытый ключ из approval и запихиваем его в провайдер

	m_api->m_data.GetAttr(approval,a_appr_dg_sign_cert, sCertBlob);
	if(sCertBlob!=_T(""))
	{
		m_api->m_data.NET_GetBlobSize(approval,a_appr_dg_sign_cert, lCertSize);
		if(lCertSize > 10)
		{
			cert_buf=new unsigned char[lCertSize];
			m_api->m_data.NET_LoadBlob2Memory(approval,a_appr_dg_sign_cert, cert_buf, lCertSize);
			bUseCertificateToCheckApproval = true;
		}
		else
		{
			// удаляем кривой сертификат (испр. бага)
			if(approval->GetAccessmode()<aplRO)
			{
				m_api->m_data.NET_DeleteBlob(approval,a_appr_dg_sign_cert);
				m_api->SaveChanges();
			}
		}
	}

	if((bUseCertificateToCheckApproval == false)	&& (pers_key!=0)) // сертификат в статусе отсутствует или кривой - берем сертификат из сотрудника
	{
		m_api->m_data.NET_GetBlobSize(pers_key,a_apl_digital_sign_open_key_open_key_cert_blob, lCertSize);
		if(lCertSize > 10)
		{
			cert_buf=new unsigned char[lCertSize];
			m_api->m_data.NET_LoadBlob2Memory(pers_key,a_apl_digital_sign_open_key_open_key_cert_blob, cert_buf, lCertSize);
			// заодно копируем в статус
			if((bUseCertificateToCheckApproval == false) && (approval->GetAccessmode()<aplRO))
			{
				long code;
				m_api->m_data.NET_SaveFileFromMemory(approval,a_appr_dg_sign_cert, cert_buf, lCertSize,code);
			}
			bUseCertificateToCheckApproval = true;
		}
	}

	// проверяем данные в сертификате
	if(bUseCertificateToCheckApproval)
	{
		// не истек ли срок действия ключа
		COleDateTime timeBefore, timeAfter;
		CString sSubj, sIssure, sSN, sTimeBefore, sTimeAfter, sAlg, sOpenKey_cert;
		if(	m_Crypto.GetDataFromCert(cert_buf, lCertSize, sSubj, sOpenKey_cert, timeBefore, timeAfter, sIssure, sSN, sAlg))
		{
			aplDate2String(timeBefore, sTimeBefore);
			aplDate2String(timeAfter, sTimeAfter);			

			if(sTimeAfter.IsEmpty() || sTimeBefore.IsEmpty())
			{
				AfxMessageBox( APL_T("Для сертификата не задан период действия! Подлинность подписи не может быть установлена."), MB_ICONINFORMATION);
				return APL_CRYPT_UNKNOWN_ERROR;
			}

			if( !(sSignDate>=sTimeBefore && sSignDate<=sTimeAfter) )
			{
				AfxMessageBox( APL_T("Электронная подпись не действительна, так как на момент подписи\n истек срок действия квалификационного сертификата."), MB_ICONINFORMATION);
				return APL_CRYPT_UNKNOWN_ERROR;
			}	
		}
		else
		{
			if(sOpenKey_cert==_T(""))
			{
				if(IDYES!=AfxMessageBox(APL_T("Некорректный сертификат! \n\nПроверить по указанному в подписи ключу проверки ?"), MB_ICONSTOP|MB_YESNO))
				return APL_CRYPT_INVALID_CERT;

				bUseCertificateToCheckApproval=false;
			}
			else
			{
				if(IDYES!=AfxMessageBox(APL_T("В сертификате некоректные данные.\n Период действия сертификата определить не удалось.\n\nПродолжить проверку ?"),MB_ICONSTOP|MB_YESNO)) 
					return APL_CRYPT_INVALID_CERT;
			}
		}

		if((sOpenKey_cert!=sOpenKey) && bUseCertificateToCheckApproval)
		{
			if(IDYES!=AfxMessageBox(APL_T("Ключи проверки ЭЦП в подписи и сертификате не совпадают!\nДанные в БД изменены!\n\nПродолжить проверку ?"),MB_ICONSTOP|MB_YESNO)) 
				return APL_CRYPT_INVALID_SIGNATURE;

			AfxMessageBox( APL_T("Используем ключ проверки подписи из сертификата."), MB_ICONINFORMATION|MB_OK);
		}
		
		// есть ли у этого сертификата доверительный
		if(0!=pers_key)
		{
			CString sIssureTmp;
			m_api->m_data.GetAttr(pers_key, a_apl_digital_sign_open_key_open_key_cert_issuer, sIssureTmp);
			ConfidentialCertExistInBase(sIssureTmp);
		}
	}

	void *signedBuffer=0;
	DWORD signedBufferLen=0;
	CString sNewSnapShot;
	CString sPath;
	char *addInfo = 0;
	bool bUseEntry = true;
	int infoSize = 0;


	if(m_api->m_data.IsKindOf(item, m_api->m_doc_mgr.e_apl_doc) || m_api->m_data.IsKindOf(item, m_api->m_doc_mgr.e_apl_doc_rev))
	{
		aplGetTempPath(sPath);
		TCHAR *tempfname=new TCHAR[MAX_PATH];
		GetTempFileName(sPath,_T("aplsign"),0,tempfname);
		sPath=tempfname;
		delete [] tempfname;

		long dID = aplStartWaitDlg( APL_T("Загрузка документа..."));
		if(!m_api->m_doc_mgr.LoadRevision(item, sPath)) { aplEndWaitDlg(dID); return 1; }
		aplEndWaitDlg(dID);

		// добавляем реквизиты подписи (если нужно)
		m_api->m_data.GetAttr(approval, a_appr_entries_used, bUseEntry);

		// ЯАИ:  27/09/2001  обнаружен баг, из - за которого в АРМ подписывалось с реквизитами, но без сертификата
		// т.к. базу исправить нельзя, считсае что все аодписи после 2010 были с реквизитами
		if(sSignDate>_T("2010000000000"))bUseEntry=true;

		if(bUseEntry) infoSize = GetDSInfo(approval, addInfo);

		signedBuffer=(void*)LPCTSTR(sPath);	
	}
	else
	{
		if(!CreateSnapShotByInventory(sInventory,sNewSnapShot)) return false;
		signedBuffer=(char*)LPCTSTR(sNewSnapShot);
		signedBufferLen=sNewSnapShot.GetLength();

		//if(sNewSnapShot!=sSnapShot) AfxMessageBox(APL_T("ЁКЛМН!"));
	}

			
	if(bUseCertificateToCheckApproval)
	{
		if(sMethod == APL_CRYPTO_PRO_34_10_2001)   iRes = m_Crypto.csp_CheckSign (signedBuffer, signedBufferLen, sHash, cert_buf, lCertSize,sSignature, addInfo, infoSize, APL_CSP_2001);
		if(sMethod == APL_CRYPTO_PRO_34_10_2012)   iRes = m_Crypto.csp_CheckSign (signedBuffer, signedBufferLen, sHash, cert_buf, lCertSize,sSignature, addInfo, infoSize, APL_CSP_2012);
		else if(sMethod == APL_OPENSSL_34_10_2001) iRes = m_Crypto.ossl_CheckSign(signedBuffer, signedBufferLen, CaplStringAdapter(sHash), cert_buf, lCertSize,CaplStringAdapter(sSignature), addInfo, infoSize);
		else if(sMethod == APL_CRYPT_MGR)          iRes = m_Crypto.rsa_CheckSign (signedBuffer, signedBufferLen, sHash, cert_buf, lCertSize, sSignature, addInfo, infoSize);
	}
	else
	{
		// Тут проверяется подпись без сохраненного в базе сертификата, как следствие, в базе сохранялся
		// открытый ключ, который брался из контейнера, а не из сертификата, как в случае выше. Поэтому 
		// алгоритм проверки подписи - другой.
		//if(bShowResult)MessageBox(NULL,  APL_T("Сертификат не найден. Проверка по открытому ключу."),  APL_T("Проверка подписи"), MB_OK|MB_ICONINFORMATION);

		if(sMethod == APL_CRYPTO_PRO_34_10_2001)   iRes = m_Crypto.csp_CheckSign (signedBuffer, signedBufferLen, sHash, sOpenKey, sSignature, addInfo, infoSize, APL_CSP_2001);
		if(sMethod == APL_CRYPTO_PRO_34_10_2012)   iRes = m_Crypto.csp_CheckSign (signedBuffer, signedBufferLen, sHash, sOpenKey, sSignature, addInfo, infoSize, APL_CSP_2012);
		else if(sMethod == APL_OPENSSL_34_10_2001) iRes = m_Crypto.ossl_CheckSign(signedBuffer, signedBufferLen, CaplStringAdapter(sHash), CaplStringAdapter(sOpenKey), CaplStringAdapter(sSignature), addInfo, infoSize);
		else if(sMethod == APL_CRYPT_MGR) 	       iRes = m_Crypto.rsa_CheckSign (signedBuffer, signedBufferLen, sHash, sOpenKey, sSignature, addInfo, infoSize);
	}

	if(0!=addInfo) {delete addInfo; addInfo=0;}
	
	if(cert_buf) {delete [] cert_buf; cert_buf=0;}
	if(sPath!=_T(""))
	{
		::SetFileAttributes(sPath, FILE_ATTRIBUTE_NORMAL);
		::DeleteFile(sPath);		
	}

	if(bShowResult)
	{
		bool bActualApproval = IsApprovalActual(approval);
		switch (iRes)
		{
			case APL_CRYPT_NO_ERROR:

				if(bActualApproval) MessageBox(NULL,  APL_T("Подпись верна."),  APL_T("Проверка подписи"), MB_OK|MB_ICONINFORMATION);
				else MessageBox(NULL,  APL_T("Подпись верна.\n\n (Реквизитная часть документа изменилась после подписи.)"),  APL_T("Проверка подписи"), MB_OK|MB_ICONINFORMATION);
				break;
			case APL_CRYPT_UNKNOWN_ERROR:
				MessageBox(NULL,  APL_T("Ошибка во время выполнения программы!"),  APL_T("Проверка подписи"), MB_OK|MB_ICONERROR);
				break;
			case APL_CRYPT_INVALID_CERT:
				MessageBox(NULL,  APL_T("Некорректный сертификат открытого ключа. Проверка подписи невозможна!"),  APL_T("Проверка подписи"), MB_OK|MB_ICONERROR);
				break;
			case APL_CRYPT_INVALID_HASH:

				if(bActualApproval) MessageBox(NULL,  APL_T("Данные изменены!\n(неверное значение хэш-функции)"),  APL_T("Проверка подписи"), MB_OK|MB_ICONERROR);
				else MessageBox(NULL,  APL_T("Подпись неверна! (реквизитная часть документа изменена)"),  APL_T("Проверка подписи"), MB_OK|MB_ICONINFORMATION);
				
				if(sSnapShot!=_T(""))
				{
					if(IDYES==MessageBox(NULL,  APL_T(" Для подписи сохранен снимок. Показать изменения ?"),  APL_T("Проверка подписи"), MB_YESNO|MB_ICONQUESTION))
					{
						CString sDiff;
						CreateSnapShotByInventory(sInventory,sNewSnapShot,&sSnapShot,&sDiff);
						aplShowBigMsg(sDiff, APL_T("Различия снимков"));
					}
				}
				break;
			case APL_CRYPT_INVALID_SIGNATURE:
				MessageBox(NULL,  APL_T("Неверная подпись!"),  APL_T("Проверка подписи"), MB_OK|MB_ICONERROR);
				break;
			case APL_ERROR_DO_NOT_SHOW:
				break;
		}
	}

	return iRes;
}

//****************************************************************
bool CaplAutorizationManager::ShowApproval(CaplInstance *appr)
{
	CaplInstance *Note=NULL;

	if(m_data==0) return false;
	if(e_apl_appr_pers_org==0) return false;
	if(appr==0) return false;
	if(appr->GetType()==0) return false;
	if(appr->GetAccessmode()>aplRO)
	{
		aplErrorMessage(S::NoAccessRight(),appr);
		return 0;
	}
	
	CaplSetResourceHandle setres(module_inst);

	CApprovalDlg dlg;
	dlg.m_api=m_api;
	dlg.m_mode=_T("Edit");
	dlg.m_item=0;
	dlg.m_appr=appr;


	dlg.m_pNote = &Note;


	m_data->GetAttrBN(appr,_T("item"),dlg.m_item);
	if(dlg.DoModal()==IDOK)	
	{
/*
		if (dlg.m_bCreateNewNote)
		{
			if(Note!=NULL)
				m_data->PutAttr(Note,m_api->m_appr_mgr.a_note_item,appr);
		}
*/
		if(m_AutoSave) m_data->NET_SaveChanges();

// 		if(dlg.m_appr->GetAccessmode()==aplOWN)
// 		{
// 			aplExtent aet;
// 			aet.Add(dlg.m_appr);
// 			apidata.NET_SetAccessFromPattern(&aet,dlg.m_csAccessString);
// 		}

		return true;
	}
	
	return false;
}

//****************************************************************
CString CaplAutorizationManager::GetOperatorName()
{
	LPCTSTR sEmpty=_T("");
	if(m_data==0) return sEmpty;
	if(m_api==0) return sEmpty;

	CaplInstance *curuser=m_data->GetCurrUser();
	if(0==curuser) return sEmpty;

	CString sResult, buf;

	CaplInstance *pers=GetCurrentPerson();
	if(0!=pers)
	{
		if(pers->GetAccessmode()<=aplRO)
		{
			m_data->GetAttr(pers,a_pers_last_name,sResult);	
			sResult+=buf;
			m_data->GetAttr(pers,a_pers_first_name,buf);
			if(buf!=_T(""))
			{
				if(sResult!=_T("")) sResult+=_T(" ");
				sResult+=buf.Left(1);
				sResult+=_T(".");
			}
			CaplAggr aggr0;
			m_data->GetAttr(pers,a_pers_middle_names,aggr0);
			if(aggr0.GetSize()>0)
			{
				aggr0.GetByIndex(0,buf);
				if(buf!=_T(""))
				{
					if(sResult!=_T("")) sResult+=_T(" ");
					sResult+=buf.Left(1);
					sResult+=_T(".");
				}
			}
		}
	}

	if(sResult!=_T("")) sResult+=_T(" ");

	sResult+=_T("(");
	m_data->GetAttr(curuser,a_apl_user_name,buf);
	sResult+=buf;
	sResult+=_T(")");

	return sResult;
}


//****************************************************************
bool CaplAutorizationManager::GetPersonName(CaplInstance *po, CString &buf,bool is_short,bool reverse_user, int nMaxNameLen)
{
	buf=_T("");
	if(m_data==0) return false;
	if(m_api==0) return false;
	if(po==0) return false;
	if((void*)(-1)==po) return false;
	if(po->GetType()==0) return false;

	CaplInstance *inst;
	CString user=_T(""); 

	if(m_data->IsKindOf(po,e_apl_user))
	{
		m_data->GetAttr(po,a_apl_user_name,user);
		m_data->GetAttr(po,a_apl_user_po,inst);
		if(!inst) 
		{
			buf=user;
			return true;
		}
	}
	else inst=po;
	
	if(m_data->IsKindOf(inst,e_pers_org))	m_data->GetAttr(inst,a_po_the_pers,inst);
	else inst=po;

	if(inst!=0)
	{
		if(m_data->IsKindOf(inst, e_person))
		{
			CaplAggr aggr0;
			CString buf1;
			m_data->GetAttr(inst,a_pers_last_name,buf);	
			if(nMaxNameLen>0 && buf.GetLength()>nMaxNameLen) {buf1=buf.Left(nMaxNameLen); buf=buf1; buf+=_T('.');}
			m_data->GetAttr(inst,a_pers_first_name,buf1);
			if(!buf1.IsEmpty()) {buf+=_T(" ");if(is_short){buf+=buf1[0];buf+=_T(".");}else{buf+=buf1;}}
			m_data->GetAttr(inst,a_pers_middle_names,aggr0);
			aggr0.GetByIndex(0,buf1);
			if(!buf1.IsEmpty()) {/*buf+=_T(" ");*/if(is_short){buf+=buf1[0];buf+=_T(".");}else{buf+=_T(" ");buf+=buf1;}}

			if(m_api->m_show.m_PersonId)
			{
				CString sId;
				m_api->m_data.GetAttr(inst, a_pers_id, sId);
				if(!sId.IsEmpty())
					buf=sId+_T(" : ")+buf;
			}
		}
		else if(m_data->IsKindOf(inst, e_official))
		{
			CaplInstance *pers;
			m_data->GetAttr(inst, a_official_id, buf);	
			m_data->GetAttr(inst, a_official_act_person, pers);	
			if(pers!=0)
			{
				CString buf1; 
				GetPersonName(pers, buf1, is_short);
				if(buf1!=_T("")) { buf+=_T(" ("); buf+=buf1; buf+=_T(")");}
			}
		}
	}
	if(buf.IsEmpty()==TRUE)
	{
		buf=user;
	}
	else if(user.IsEmpty()==FALSE)
	{
		if(reverse_user)
		{
			user+=_T(" (")+buf+_T(")");
			buf=user;
		}
		else
		{
			buf+=_T(" (")+user+_T(")");
		}
	}

	return true;
}

//****************************************************************

bool CaplAutorizationManager::GetPersonOfficials(CaplInstance* person, aplExtent &officials, bool bOwner)
{
	officials.Clear();
	aplExtent ext;
	
	m_data->GetEntityExtent(e_official, ext);

	for(int i= 0; i<ext.GetSize(); i++)
	{
		CaplInstance* inst= NULL;
		if(bOwner)
			m_data->GetAttr(ext[i], a_official_owner, inst);
		else
			m_data->GetAttr(ext[i], a_official_act_person, inst);
		
		if(inst==person) officials.Add(ext[i]);
	}

	return true;
}
//**************************************************************************
bool CaplAutorizationManager::GetPersonOrganizations(CaplInstance* person, aplExtent& organizations, bool bActualOnly)
{
	organizations.Clear();
	if(0==person) return false;

	aplExtent ext;
	CaplInstance *pers, *org;
	CString sEndDate;

	m_data->GetEntityExtent(e_pers_org,ext);
	for(int i= 0; i<ext.GetSize(); i++)
	{
		m_data->GetAttr(ext[i], a_po_the_pers, pers);
		if(0==pers) continue;
		if(m_api->m_data.IsKindOf(pers,m_api->m_appr_mgr.e_official)) // По просьбе ЦКБА 31.10.2022
		{
			m_api->m_data.GetAttr(pers, m_api->m_appr_mgr.a_official_act_person, pers);
		}
		if(pers!=person) continue;
		if(bActualOnly)
		{
			m_data->GetAttr(ext[i], a_po_end_date, sEndDate);
			if(sEndDate!=_T("")) continue;
		}
		m_data->GetAttr(ext[i], a_po_the_org, org);
		if(0!=org) organizations.Add(org);
	}
	return true;
}

//**************************************************************************
void CaplAutorizationManager::ShowOfficialHistory(CaplInstance* official, int hist_type )
{
	if(official==NULL) return;
	CaplSetResourceHandle setres(module_inst);

	COfficialHistDlg dlg;
	dlg.m_pInstance = official;
	dlg.m_data = m_data;
	dlg.m_auth_mgr = this;
	dlg.m_hist_type = hist_type;

	dlg.DoModal();
}

void CaplAutorizationManager::ShowPersonOfficials(CaplInstance* person)
{
	if(person==NULL) return;
	CaplSetResourceHandle setres(module_inst);

	CPersOfficialDlg dlg;
	dlg.m_pInstance = person;
	dlg.m_data = m_data;
	dlg.m_auth_mgr = this;

	dlg.DoModal();
}

CaplInstance *CaplAutorizationManager::CreateOfficial(const TCHAR *id,const TCHAR *descr)
{
	if(!id) return 0;
	CaplInstance *official=FindOfficialById(id);
	if(official)
		return official;
	else
		official=m_data->CreateInstance(e_official);
	if(official)
	{
		m_data->PutAttr(official,a_official_id,id);
		if(descr) m_data->PutAttr(official,a_official_descr,descr);
		return official;
	}
	return 0;
}

CaplInstance *CaplAutorizationManager::FindOfficialById(const TCHAR *id,bool bLoadFromBase)
{
	if(bLoadFromBase)
	{
		CaplLoadData ld(m_data,DEF_SOURCE);
		int j=ld.AddQuery(_T('e'),0,e_official,0,true);
			  ld.AddQuery(_T('d'),j,0,a_official_id,true);
			  ld.LoadEx();
	}
	aplExtent ext;
	m_data->GetEntityExtent(e_official,ext);
	CString buf=_T("");
	CString id_s=id;
	id_s.MakeUpper();
	for(int i=0;i<ext.GetSize();i++)
	{
		if(ext[i]->GetAccessmode()>aplRO) continue;
		m_data->GetAttr(ext[i],a_official_id,buf);
		buf.MakeUpper();
		if(buf==id_s) return ext[i];
	}
	return 0;
}

void CaplAutorizationManager::GetKVZShops( CStringArray &shops ) const
{
	shops.Add(_T("1"));	
	shops.Add(_T("3"));	
// 	shops.Add(_T("6(1)"));
// 	shops.Add(_T("6(2)"));
	shops.Add(_T("6"));
	shops.Add(_T("7"));	
	shops.Add(_T("8"));
	shops.Add(_T("10"));
	shops.Add(_T("11"));
	shops.Add(_T("12"));
	shops.Add(_T("13"));
	shops.Add(_T("14"));
	shops.Add(_T("15"));
	shops.Add(_T("18"));
	shops.Add(_T("21"));
	shops.Add(_T("30"));
	shops.Add(_T("31"));	
	shops.Add(_T("34"));
	shops.Add(_T("35"));
	shops.Add(_T("36"));
	shops.Add(_T("37"));
	shops.Add(_T("42"));
	shops.Add(_T("43"));
	shops.Add(_T("45"));	
}

void CaplAutorizationManager::GetKVZDepartments( CStringArray &departments ) const
{
	departments.Add(_T("104"));
	departments.Add(_T("105"));
	departments.Add(_T("109"));
	departments.Add(_T("110")); 	
	departments.Add(_T("118"));
	departments.Add(_T("123"));	
	departments.Add(_T("132"));	
	departments.Add(_T("133"));
	departments.Add(_T("149"));
// 	departments.Add(_T("160(1)"));
// 	departments.Add(_T("160(2)"));
	departments.Add(_T("158"));
	departments.Add(_T("160"));	
	departments.Add(_T("170"));
	departments.Add(_T("171"));
	departments.Add(_T("172"));
	departments.Add(_T("176"));		// бывшее "ВП"	
	departments.Add(APL_T("Заречье"));
	departments.Add(APL_T("КАИ"));
	departments.Add(APL_T("93(ТМЗ)"));	
	departments.Add(APL_T("ЮТэйр-Инжиниринг"));	
	departments.Add(APL_T("КОМЗ"));
	departments.Add(APL_T("Аэротех"));
	departments.Add(APL_T("Высота"));
	departments.Add(APL_T("КАПП"));
	departments.Add(APL_T("УУАЗ"));
	departments.Add(APL_T("РТИ"));
	departments.Add(APL_T("КВАРТ"));
	departments.Add(APL_T("Рычаг"));	
	departments.Add(APL_T("АО '356 АРЗ'"));
	departments.Add(APL_T("АО '419 АРЗ'"));
	departments.Add(APL_T("АО 'КВЗ-Ремсервис'"));
	departments.Add(APL_T("ПАО 'Роствертол'"));
	departments.Add(APL_T("ОАО 'Красный октябрь'"));
}

CaplInstance *CaplAutorizationManager::CreateApprovalStatus(const TCHAR *name)
{
	if(!name) return 0;
	CaplInstance *status=FindApprovalStatusBN(name);
	if(status)
		return status;
	else
		status=m_data->CreateInstance(e_appr_status);
	if(status)
	{
		m_data->PutAttr(status,a_appr_status_name,name);
		return status;
	}

	return 0;
}

CaplInstance *CaplAutorizationManager::FindApprovalStatusBN(const TCHAR *name,bool bLoadFromBase, bool bCreateIfNotFound)
{
	CString name_s=name;
	if(name_s==_T("")) return 0;
	if(bLoadFromBase && m_api->m_data.IsConnected())
	{
		CaplLoadData ld(m_data,DEF_SOURCE);
		int j=ld.AddQuery(_T('e'),0,e_appr_status,0,true,true);
			  ld.LoadEx();
	}
	aplExtent ext;
	m_data->GetEntityExtent(e_appr_status,ext);
	CString buf=_T("");
	name_s.MakeUpper();
	for(int i=0;i<ext.GetSize();i++)
	{
		if(ext[i]->GetAccessmode()>aplRO) continue;
		m_data->GetAttr(ext[i],a_appr_status_name,buf);
		buf.MakeUpper();
		if(buf==name_s) return ext[i];
	}
	if(!bCreateIfNotFound) return 0;

	CaplInstance *status=m_api->m_data.CreateInstance(e_appr_status);
	m_api->m_data.PutAttr(status,a_appr_status_name,name);

	if(m_AutoSave) m_api->SaveChanges();

	return status;

}

CaplInstance *CaplAutorizationManager::FindRoleBN(const TCHAR *name,bool bLoadFromBase, bool bCreateIfNotFound)
{
	if(bLoadFromBase && m_api->m_data.IsConnected())
	{
		CaplLoadData ld(m_data,DEF_SOURCE);
		int j=ld.AddQuery(_T('e'),0,e_po_role,0,true,true);
		ld.LoadEx();
	}
	aplExtent ext;
	m_data->GetEntityExtent(e_po_role,ext);
	CString buf=_T("");
	CString name_s=name;
	name_s.MakeUpper();
	for(int i=0;i<ext.GetSize();i++)
	{
		if(ext[i]->GetAccessmode()>aplRO) continue;
		m_data->GetAttr(ext[i],a_po_role_name,buf);
		buf.MakeUpper();
		if(buf==name_s) return ext[i];
	}
	if(!bCreateIfNotFound) return 0;

	CaplInstance *role=m_api->m_data.CreateInstance(m_api->m_appr_mgr.e_po_role);
	m_api->m_data.PutAttr(role,a_po_role_name,name);

	if(m_AutoSave) m_api->SaveChanges();

	return role;
}


CaplInstance *CaplAutorizationManager::FindRoleApproval(CaplInstance *item,const TCHAR *role,CaplInstance *status)
{
	if(m_data==0) return 0;
	if(e_apl_appr_pers_org==0) return 0;
	if(item==0) return 0;
	if(item->GetType()==0) return 0;
	if(item->GetAccessmode()>aplRO)
	{
		aplErrorMessage(S::NoAccessRight(),item);
		return 0;
	}
	if(!role) return 0;
	if(!status) return 0;

	aplExtent ext;
	LoadItemApproval(item,ext);
	CaplInstance *c_status=0;
	CString role_s=role,c_role=_T("");
	for(int i=0;i<ext.GetSize();i++)
	{
		if(ext[i]->GetAccessmode()>aplRO) continue;
		m_data->GetAttr(ext[i],a_appr_status,c_status);
		if(c_status==status)
		{
			m_data->GetAttr(ext[i],a_appr_role,c_role);
			if(role_s==c_role) return ext[i];
		}
	}
	return 0;
}

bool CaplAutorizationManager::DeleteApproval(CaplInstance *approval)
{
	if(m_data==0) return false;
	if(e_apl_appr_pers_org==0) return false;
	if(approval==0) return false;
	if(approval->GetType()==0) return false;
	if(approval->GetAccessmode()>=aplRW)
	{
		aplErrorMessage(S::NoAccessRight(),approval);
		return false;
	}

	CString buf;
	apidata.GetAttr(approval,a_appr_dg_sign_cert,buf);

	if(buf!=_T(""))
	{
		m_data->NET_DeleteBlob(approval,a_appr_dg_sign_cert);
	}
	m_data->DeleteInstance(approval);
	if(m_AutoSave) m_api->SaveChanges();
	return true;
}

bool CaplAutorizationManager::ShowItemApprovals(CaplInstance *item)
{
	if(m_data==0) return false;
	if(m_api==0) return false;
	if(item==0) return false;

	if(item->GetType()==0) return false;
	if(item->GetAccessmode()>aplRO)
	{
		aplErrorMessage(S::NoAccessRight(),item);
		return false;
	}

	CaplSetResourceHandle setres(module_inst);

	CShowItemApprovals dlg;
	dlg.m_api = m_api;
	dlg.m_item = item;
	dlg.DoModal();
	return true;
}


bool CaplAutorizationManager::DeleteAllApproval(CaplInstance *item)
{
	if(m_data==0) return false;
	if(e_apl_appr_pers_org==0) return false;
	if(item==0) return false;
	if(item->GetType()==0) return false;
	if(item->GetAccessmode()>aplRO)
	{
		aplErrorMessage(S::NoAccessRight(),item);
		return false;
	}

	aplExtent ext;
	LoadItemApproval(item,ext);
	for(int i=0;i<ext.GetSize();i++)
	{
		if(ext[i]->GetAccessmode()>aplOWN) continue;

		CString buf;
		m_data->GetAttr(ext[i],a_appr_dg_sign_cert,buf);
		if(buf!=_T(""))
		{
			m_data->NET_DeleteBlob(ext[i], a_appr_dg_sign_cert);
		}

		m_data->DeleteInstance(ext[i]);
	}
	if(m_AutoSave) m_api->SaveChanges();
	return true;
}

bool CaplAutorizationManager::DeleteAllApprovalByStatus(CaplInstance *item,aplExtent &ext_status)
{
	if(m_data==0) return false;
	if(e_apl_appr_pers_org==0) return false;
	if(item==0) return false;
	if(item->GetType()==0) return false;
	if(item->GetAccessmode()>aplRO)
	{
		aplErrorMessage(S::NoAccessRight(),item);
		return false;
	}

	aplExtent ext;
	LoadItemApproval(item,ext);
	CaplInstance *status=0;
	for(int i=0;i<ext.GetSize();i++)
	{
		if(ext[i]->GetAccessmode()>aplOWN) continue;
		m_data->GetAttr(ext[i],a_appr_status,status);
		for(int j=0;j<ext_status.GetSize();j++)
		{
			if(status==ext_status[j])
			{
				CString buf;
				m_data->GetAttr(ext[i],a_appr_dg_sign_cert,buf);
				if(buf!=_T(""))
				{
					m_data->NET_DeleteBlob(ext[i], a_appr_dg_sign_cert);
				}
				m_data->DeleteInstance(ext[i]);
			}
		}
	}
	if(m_AutoSave) m_api->SaveChanges();
	return true;
}

bool CaplAutorizationManager::FindPersonOrganizations(CaplInstance *person,aplExtent &ext_out, bool bFromBase)
{
	if(!person) return false;
	if(m_data==0) return false;
	if(person->GetType()==0) return false;
	if(person->GetAccessmode()>aplRO)
	{
		aplErrorMessage(S::NoAccessRight(),person);
		return false;
	}
	aplExtent res;
	CaplAttrValue tst_val;
	int i;
	CaplInstance *inst=0;
	CString buf=_T("");
	aplExtent ext;

	if(bFromBase)
	{
		tst_val.attr = a_po_the_pers;
		tst_val.value.Set(person);
		m_api->m_data.NET_FindInstancesWithAttrValues(e_pers_org, 1, &tst_val, res, false);

		LoadExtentInfo(res);
	}

	m_data->GetEntityExtent(e_pers_org,ext);
	for(i=0;i<ext.GetSize();i++)
	{
		if(ext[i]->GetAccessmode()>aplRO) continue;
		m_data->GetAttr(ext[i],a_po_the_pers,inst);
		if(inst==person) 
		{
			m_data->GetAttr(ext[i],a_po_end_date,buf);
			if(buf==_T(""))	
			{
				m_data->GetAttr(ext[i],a_po_the_org,inst);
				if(inst) ext_out.Add(inst);
			}
		}
	}
	return true;
}

CaplInstance* CaplAutorizationManager::FindOrganizationById(const TCHAR* id, bool bFromBase, bool bLoadAttrs)
{
	if(!m_data || !m_data->IsDictLoad()) return NULL;
	if(!id) return NULL;

	CaplInstance* org= NULL;
	CString buf;
	aplExtent ext;

	if(!bFromBase)
	{
		m_data->GetEntityExtent(e_org, ext);
		for(int i= 0; i<ext.GetSize(); i++)
		{
			if(!ext[i] || !ext[i]->GetType()) continue;
			if(ext[i]->GetAccessmode()>aplRO) continue;
			
			m_data->GetAttr(ext[i], a_org_id, buf);
			if(!buf.Compare(id))
			{
				org= ext[i];
				break;
			}
		}
	}
	else
	{
		CaplAttrValue tst_attr;
		tst_attr.attr = a_org_id;
		tst_attr.value.Set(id);
		if(m_api->m_data.NET_FindInstancesWithAttrValues(e_org, 1, &tst_attr, ext, false)<0) return NULL;
		if(bLoadAttrs)
			m_api->LoadExtentInfo(ext);
		org = ext[0];
	}

	return org;
}

bool CaplAutorizationManager::GetAllSubOrganization(CaplInstance *inst, aplExtent &out, aplExtent *rel)
{
	if(m_data==0) return false;
	if(!m_data->IsDictLoad()) return false;
	out.Clear();
	aplExtent trel;
	m_data->GetEntityExtent(e_org_rel,trel);
	if(rel!=0)
	{
		rel->Clear();
	}
	if(inst==0)
	{
		int i;
		m_data->GetEntityExtent(e_org,out);
		for(i=0; i<trel.Size;i++)
		{
			CaplInstance *related,*relating;

			m_data->GetAttr(trel[i],a_org_rel_relating,relating);
			if(relating==0) continue;
			m_data->GetAttr(trel[i],a_org_rel_related,related);
			if(related!=0)
			{
				out.Remove(out.Find(related));
			}
		}
		CString id;
		for(i=0; i<out.Size;i++)
		{
			CaplInstance *org=out[i];
			id= _T("");
			
			if(org->GetAccessmode()<aplNO)
			{
				m_data->GetAttr(org,a_org_id,id);				
			}

			if(id.IsEmpty())
			{
				out.Remove(i);
				i--;
			}
		}
	}
	else
	{
		CaplInstance *relating;
		for(int i=0; i<trel.Size;i++)
		{
			m_data->GetAttr(trel[i],a_org_rel_relating,relating);
			if(relating==inst)
			{
				CaplInstance *related=0;
				m_data->GetAttr(trel[i],a_org_rel_related,related);
				if(related!=0){
					out.Add(related);
					if(rel!=0)
					{
						rel->Add(trel[i]);
					}

				}
			}
		}
	}
	return true;
}
bool CaplAutorizationManager::GetAllSubOrganization(aplExtent &inExt, aplExtent &out, bool bRecursive)
{
	if(m_data==0) return false;
	if(!m_data->IsDictLoad()) return false;
	out.Clear();
	aplExtent trel;
	m_data->GetEntityExtent(e_org_rel,trel);
	CaplInstance *relating;
	for(int i=0; i<trel.Size;i++)
	{
		m_data->GetAttr(trel[i],a_org_rel_relating,relating);
		if(inExt.Find(relating)>-1)
		{
			CaplInstance *related=0;
			m_data->GetAttr(trel[i],a_org_rel_related,related);
			if(related)
				out.Add(related);
		}
	}
	if(bRecursive && out.Size>0)
	{
		aplExtent ext, ext1;
		ext.Append(out);
		GetAllSubOrganization(ext, ext1, true);
		out.Append(ext1);
	}
	return true;
}

bool CaplAutorizationManager::GetAllSubPerson(CaplInstance *inst, aplExtent &out, aplExtent &pers_org)
{
	if(!m_data) return false;
	if(!m_data->IsDictLoad()) return false;
	aplExtent pers, official, poext;
	m_data->GetEntityExtent(e_person,pers);
	m_data->GetEntityExtent(e_official,official);
	m_data->GetEntityExtent(e_pers_org,poext);
	out.Clear();
	pers_org.Clear();
	if(inst==0)
	{
		out.Append(pers);
		out.Append(official);
		poext.Append(poext);
		CaplInstance *tmp;
		for(int i=0; i<poext.Size;i++)
		{
			m_data->GetAttr(poext[i],a_po_the_pers,tmp);
			if(tmp!=0)
			{
				out.Remove(out.Find(tmp));
				pers_org.Remove(i);
			}
		}
		return true;
	}
	if(inst!=0)
	{
		CaplInstance *tmp;
		CString val;
		for(int i=0; i<poext.Size;i++)
		{
			m_data->GetAttr(poext[i],a_po_the_org,tmp);
			if(tmp==inst)
			{
				m_data->GetAttr(poext[i],a_po_end_date,val);
				if(val!=_T("")) continue;
				m_data->GetAttr(poext[i],a_po_the_pers,tmp);
				if(tmp)
				{
					out.Add(tmp);
					pers_org.Add(poext[i]);
				}
			}
		}
	}

	return true;
}
bool CaplAutorizationManager::ShowPersonProperties(CaplInstance *inst)
{
	if(!m_data->IsDictLoad()) return false;

	CaplSetResourceHandle setres(module_inst);
	
	if(m_data->IsKindOf(inst,e_person))
	{
		CPersonPropDlg dlg;
		dlg.m_person = inst;
		dlg.m_api = m_api;
		dlg.DoModal();
	}
	else if(m_data->IsKindOf(inst,e_official))
	{
		COfficialPropDlg dlg;
		dlg.inst = inst;
		dlg.m_data = m_data;
		dlg.DoModal();
	}
	return true;
}

bool CaplAutorizationManager::GetUserPatterns(CaplInstance *user,aplExtent &patterns)
{
	patterns.Clear();
	if(!m_data->IsDictLoad()) return false;
	if(user==0 || user==(CaplInstance*)-1) return false;
	if(user->GetId()==0) return true;
	CaplLoadData ld(&m_api->m_data,DEF_SOURCE);
	//Чтение шаблонов
	int i;
	aplExtent ext_pat;
	CString str,strd;
	ld.AddQuery(_T('e'),0,e_apl_acc_pat,0,true,true);
	ld.LoadEx(true,&ext_pat);
	strd.Format(_T("%i"),user->GetId());
	for(i=0;i<ext_pat.GetSize();i++){
		m_data->GetAttr(ext_pat[i],a_apl_acc_pat_pattern,str);
		if(str.Find(strd)!=-1){
			patterns.Add(ext_pat[i]);
		}
	}

	return true;
}

bool CaplAutorizationManager::ShowOrganizationProperties(CaplInstance *inst)
{
	if(!m_data->IsDictLoad()) return false;
	CaplSetResourceHandle setres(module_inst);
	COrganizationPropDlg dlg;
	dlg.m_api = m_api;
	dlg.inst = inst;
	dlg.DoModal();
	return true;
}

bool CaplAutorizationManager::GetUserEnveroment(aplExtent &status, aplExtent &doc_types, aplExtent &contexts)
{
	if(!m_api) return false;
	if(!m_api->m_data.IsDictLoad()) return false;
	CaplInstance *person = GetCurrentPerson();
	if(!person) return false;

	CaplEntity *ent;
	aplExtent all_status, all_doc_types, all_contexts;
	if(m_api->m_data.IsConnected())
	{
		CaplLoadData ld(&m_api->m_data,DEF_SOURCE);
		//Чтение ролей;
		ld.AddQuery(_T('e'),0,e_po_role,0,true,true);		
		//all_status
		ent = m_data->GetEntityBN(_T("approval_status"));
		ld.AddQuery(_T('e'),0,ent,0,true, true);		
		//all_contexts
		ent = m_data->GetEntityBN(_T("application_context_element"));
		ld.AddQuery(_T('e'),0,ent,0,true, true);		
		//all_doc_types
		ent = m_data->GetEntityBN(_T("document_type"));
		ld.AddQuery(_T('e'),0,ent,0,true, true);
		ld.LoadEx();
	}
	m_data->GetEntityExtentBN(_T("approval_status"), all_status);
	m_data->GetEntityExtentBN(_T("application_context_element"), all_contexts);
	m_data->GetEntityExtentBN(_T("document_type"), all_doc_types);

	aplExtent roles, user_roles, tmp;
	m_api->m_data.GetEntityExtent(e_po_role, roles);
	ent = m_data->GetEntityBN(_T("person"));
	m_data->GetAttr(person, m_data->GetAttrDefinition(ent,_T("apl_person_roles")),user_roles);
	if(roles.Size==0) return false;
	status.Clear();
	doc_types.Clear();
	contexts.Clear();
	bool all;
	for(int r=0; r<user_roles.Size;r++)
	{
		tmp.Clear();
		m_data->GetAttr(roles[r],a_po_role_specified_contexts_set,all);
		if(!all)
		{
			contexts.Append(all_contexts);
		}
		else 
		{
			m_data->GetAttr(roles[r],a_po_role_contexts,tmp);
			for(int i=0; i<tmp.Size;i++)
				contexts.Add(tmp[i]);
		}
		
		m_data->GetAttr(roles[r],a_po_role_specified_status_set,all);
		if(!all)
		{
			status.Append(all_status);
		}
		else 
		{
			m_data->GetAttr(roles[r],a_po_role_status,tmp);
			for(int i=0; i<tmp.Size;i++)
				status.Add(tmp[i]);
		}
		
		m_data->GetAttr(roles[r],a_po_role_specified_document_types_set,all);
		if(!all)
			doc_types.Append(all_doc_types);
		else 
		{
			m_data->GetAttr(roles[r],a_po_role_document_types,tmp);
			for(int i=0; i<tmp.Size;i++)
				doc_types.Add(tmp[i]);
		}
	}
	return true;
}

bool CaplAutorizationManager::FindPersonById(const TCHAR *id,aplExtent &ext_out,bool is_substring)
{
	if(!id) return false;
	if(m_api->m_data.IsConnected())
	{
		CString query;
		query = _T("SELECT Ext FROM Ext {person_and_organization(");
		if(is_substring) query +=_T(".the_person->person.id LIKE '");
		else query +=_T(".the_person->person.id ='");
		query +=id;
		query +=_T("')} END_SELECT");
		m_data->NET_QueryEditParse(query);
		m_data->NET_QueryExecute(ext_out, APL_T("Поиск сотрудников в БД PSS..."));

		LoadExtentInfo(ext_out);
	}
	else
	{
#ifdef _DEBUG
		AfxMessageBox( APL_T("Не реализовано для работы с файлом!!!"));
		ASSERT(0);
#endif
	}
	
	return ext_out.GetSize()>0;
}

CaplInstance *CaplAutorizationManager::CreatePerson(const TCHAR *id,const TCHAR *last_name,const TCHAR *first_name,CaplAggr *mid_names, bool bTestUnique)
{
	if(!id) return 0;
	CaplInstance *person=0;
	aplExtent ext_persons;
	CaplInstance *person_org=0;
	if(bTestUnique)
		FindPersonById(id,ext_persons);
	if(ext_persons.GetSize())
	{
		return ext_persons[0];
	}
	else
	{
		person_org=m_data->CreateInstance(e_pers_org);
		person=m_data->CreateInstance(e_person);
		if(person_org && person) m_data->PutAttr(person_org,a_po_the_pers,person);
	}
	if(person)
	{
		m_data->PutAttr(person,a_pers_id,id);
		if(last_name) m_data->PutAttr(person,a_pers_last_name,last_name);
		if(first_name) m_data->PutAttr(person,a_pers_first_name,first_name);
		if(mid_names && mid_names->GetSize()) m_data->PutAttr(person,a_pers_middle_names,*mid_names);
	}
	if(m_AutoSave) m_api->SaveChanges();
	return person_org;
}

CaplInstance *CaplAutorizationManager::CreatePerson(const TCHAR *id,const TCHAR *last_name,const TCHAR *first_name, const TCHAR *mid_name, bool bTestUnique)
{
	if(id==NULL) return NULL;

	CaplInstance *person=0;
	aplExtent ext_persons;
	CaplAggr aggr;
	aggr.Add(mid_name);

	if(bTestUnique)
		FindPersonById(id,ext_persons);

	if(ext_persons.GetSize())
	{
		return ext_persons[0];
	}
	else
		person=m_data->CreateInstance(e_person);
	if(person)
	{
		m_data->PutAttr(person, a_pers_id,id);
		m_data->PutAttr(person, a_pers_last_name, last_name);
		m_data->PutAttr(person, a_pers_first_name, first_name);
		m_data->PutAttr(person, a_pers_middle_names, aggr);
	}
	if(m_AutoSave)
		m_api->SaveChanges();

	return person;
}

CaplInstance *CaplAutorizationManager::CreateOrgRel(CaplInstance *relating_org,CaplInstance *related_org)
{
	if(!relating_org || !related_org) return 0;
	if(!relating_org->GetType() || !related_org->GetType()) return 0;

	CaplInstance *rel = FindOrgRel(relating_org, related_org);
	if(rel)
	{
		if(m_api->m_ModeInteractive)
			AfxMessageBox( APL_T("Такая связь уже существует!"));
		return rel;
	}

	//проверка на зацикливания
	if(!m_api->m_data.TestCycleInRelation(e_org_rel, a_org_rel_relating, a_org_rel_related, relating_org, related_org))
	{
		if(m_api->m_ModeInteractive)
			AfxMessageBox( APL_T("Элемент организационной структуры не должен входить сам в себя!"));
		return NULL;
	}


	rel=m_data->CreateInstance(e_org_rel);
	if(rel)
	{
		m_data->PutAttr(rel,a_org_rel_relating,relating_org);
		m_data->PutAttr(rel,a_org_rel_related,related_org);
	}
	if(m_AutoSave) m_api->SaveChanges();
	return rel;
}

CaplInstance* CaplAutorizationManager::CreateOrganization(CaplInstance* org, bool bCanEdit)
{
	if(!m_data->IsConnected()) return 0;
	CaplSetResourceHandle setres(module_inst);
	COrganizationPropDlg dlg;
	dlg.m_api = m_api;
	dlg.inst = org;
	dlg.m_bCanEdit = bCanEdit;
	dlg.DoModal();
	return dlg.inst;
}

CaplInstance* CaplAutorizationManager::CreateOrganizationType(LPCTSTR lpName)
{
	if(lpName==NULL) return 0;
	if(m_api==NULL) return 0;
	if(!m_api->m_data.IsDictLoad()) return 0;

	aplExtent ext;
	CaplInstance* nInst = NULL;
	CaplAttrValue tst_val;

	//проверяем на уникальность
	tst_val.attr = a_apl_org_type_name;
	tst_val.value.Set(lpName);
	if(m_api->m_data.NET_FindInstancesWithAttrValues(e_apl_org_type, 1, &tst_val, ext, false)>0)
		return ext[0];

	nInst = m_api->m_data.CreateInstance(e_apl_org_type);
	ASSERT(nInst);
	m_api->m_data.PutAttr(nInst, a_apl_org_type_name, lpName);
	return nInst;
}

CaplInstance* CaplAutorizationManager::GetOrganizationTypeBN(LPCTSTR lpName)
{
	if(lpName==NULL) return 0;
	if(m_api==NULL) return 0;
	if(!m_api->m_data.IsDictLoad()) return 0;
	
	aplExtent ext;
	CaplAttrValue tst_val;
	
	//проверяем на уникальность
	tst_val.attr = a_apl_org_type_name;
	tst_val.value.Set(lpName);
	if(m_api->m_data.NET_FindInstancesWithAttrValues(e_apl_org_type, 1, &tst_val, ext, false)>0)
		return ext[0];
	
	return NULL;
}

bool CaplAutorizationManager::DeleteOrganization(CaplInstance* nInst)
{
	if(m_api==NULL) return false;
	if(!m_api->m_data.IsDictLoad()) return false;
	if(nInst==NULL) return false;
	if(nInst->GetAccessmode()>aplOWN) return false;
	if(!m_api->m_data.IsKindOf(nInst, e_org)) return false;

	aplExtent rels, tmp;
	CaplAttrValue tst_val;
	int i;
	//Определяем где связь используется
	tst_val.attr = a_org_rel_related;
	tst_val.value.Set(nInst);
	m_api->m_data.NET_FindInstancesWithAttrValues(e_org_rel, 1, &tst_val, rels, false);
	//определяем входящие
	tst_val.attr = a_org_rel_relating;
	tst_val.value.Set(nInst);
	m_api->m_data.NET_FindInstancesWithAttrValues(e_org_rel, 1, &tst_val, tmp, false);
	rels.Append(tmp);
	//проверяем доступ
	for(i=0; i<rels.GetSize(); i++)
	{
		if(rels[i]==NULL) continue;
		if(rels[i]->GetAccessmode()>aplOWN) return false;
	}

	//удаляем все нафиг
	rels.Add(nInst);
	for(i=0; i<rels.GetSize(); i++)
	{
		if(rels[i]==NULL) continue;
		m_api->m_data.DeleteInstance(rels[i]);
	}

	return true;
}

CaplInstance* CaplAutorizationManager::FindOrgRel(CaplInstance *relating_org, CaplInstance *related_org)
{
	if(m_api==NULL) return NULL;
	if(!m_api->m_data.IsDictLoad()) return NULL;
	if(relating_org==NULL) return NULL;
	if(!m_api->m_data.IsKindOf(relating_org, e_org)) return NULL;
	if(related_org==NULL) return NULL;
	if(!m_api->m_data.IsKindOf(related_org, e_org)) return NULL;

	aplExtent res;
	CaplAttrValue tst_val[2];
	tst_val[0].attr = a_org_rel_relating;
	tst_val[0].value.Set(relating_org);
	tst_val[1].attr = a_org_rel_related;
	tst_val[1].value.Set(related_org);
	if(m_api->m_data.NET_FindInstancesWithAttrValues(e_org_rel, 2, &tst_val[0], res, false)>0)
		return res[0];

	return NULL;
}

bool CaplAutorizationManager::WhereUsedOrg(CaplInstance *org, aplExtent &ext, aplExtent *rels, bool bFromBase)
{
	if(m_api==NULL) return false;
	if(!m_api->m_data.IsDictLoad()) return false;
	if(org==NULL) return false;
	if(!m_api->m_data.IsKindOf(org, e_org)) return false;

	//считаем, что все в КЭШе

	ext.Clear();
	if(rels)
		rels->Clear();

	aplExtent res;
	CaplAttrValue tst_val;
	int i;
	CaplInstance *inst;

	tst_val.attr = a_org_rel_related;
	tst_val.value.Set(org);
	m_api->m_data.NET_FindInstancesWithAttrValues(e_org_rel, 1, &tst_val, res, false);

	if(bFromBase)
		LoadExtentInfo(res);

	for(i=0; i<res.GetSize(); i++)
	{
		if(res[i]==NULL) continue;
		if(res[i]->GetAccessmode()>aplRO) continue;

		m_api->m_data.GetAttr(res[i], a_org_rel_relating, inst);
		if(inst)
		{
			ext.Add(inst);
			if(rels)
				rels->Add(res[i]);
		}
	}

	return true;
}

CaplInstance* CaplAutorizationManager::GetActualPersOrg(CaplInstance *pers, bool bReturnOrg)
{
	if(m_api==NULL) return NULL;
	if(!m_api->m_data.IsDictLoad()) return NULL;
	if(pers==NULL) return NULL;

	aplExtent po_ext;
	int i;
	CString buf;
	CaplInstance *tmp;

	m_api->m_data.GetEntityExtent(e_pers_org, po_ext);

	for(i=0; i<po_ext.GetSize(); i++)
	{
		CaplInstance *po=po_ext[i];
		m_api->m_data.GetAttr(po, a_po_the_pers, tmp);
		if(tmp!=pers) continue;
		m_api->m_data.GetAttr(po, a_po_end_date, buf);
		if(buf.IsEmpty())
		{
			if(!bReturnOrg) return po;
			CaplInstance *org;
			m_api->m_data.GetAttr(po, a_po_the_org, org);
			if(0==org) continue;
			return org;
		}
	}

	return NULL;
}

bool CaplAutorizationManager::GetActualPersOrgs(CaplInstance *pers, aplExtent &ext_org, bool bReturnOrg)
{
	ext_org.Clear();
	if(m_api==NULL) return false;
	if(!m_api->m_data.IsDictLoad()) return false;
	if(pers==NULL) return false;

	aplExtent po_ext;
	int i;
	CString buf;
	CaplInstance *tmp;

	m_api->m_data.GetEntityExtent(e_pers_org, po_ext);

	for(i=0; i<po_ext.GetSize(); i++)
	{
		CaplInstance *po=po_ext[i];
		m_api->m_data.GetAttr(po, a_po_the_pers, tmp);
		if(tmp!=pers) continue;
		m_api->m_data.GetAttr(po, a_po_end_date, buf);
		if(buf.IsEmpty())
		{
			if(!bReturnOrg) ext_org.Add(po);
			else
			{
				CaplInstance *org;
				m_api->m_data.GetAttr(po, a_po_the_org, org);
				if(0==org) continue;
				ext_org.Add(org);
			}
		}
	}
	return true;
}

// Возвращает все организации, куда сейчас входит сотрудник и все вышестоящие организации
bool CaplAutorizationManager::GetAllActualPersOrgs(CaplInstance *pers, aplExtent &ext_org, bool bWithOfficials)
{
	ext_org.Clear();
	if(m_api==NULL) return false;
	if(!m_api->m_data.IsDictLoad()) return false;
	if(pers==NULL) return false;

	aplExtent ext_org_rel;
	m_api->m_data.GetEntityExtent(e_org_rel, ext_org_rel);

	aplExtent ext_cur_org, ext_new_org;
	ext_cur_org.Unique=false;

	GetActualPersOrgs(pers,ext_org,true);



	if(bWithOfficials) // По просьбе ЦКБА от 31.10.2022
	{
		aplExtent officials;
		if(GetPersonOfficials(pers, officials, false))
		{
			if(officials.GetSize()>0)
			{
				int i;
				aplExtent ext_org2;
				for(i=0; i<officials.GetSize();i++)
				{
					GetActualPersOrgs(officials[i],ext_org2,true);
					ext_org.Append(ext_org2);
				}
			}
		}
	}

	CSortClass::SortExtentByInst(ext_org);
	ext_cur_org.Append(ext_org);


	while(ext_cur_org.GetSize()>0)
	{
		int i;
		for(i=0;i<ext_org_rel.GetSize();i++)
		{
			CaplInstance *org_ted, *org_ting;
			m_api->m_data.GetAttr(ext_org_rel[i],  m_api->m_appr_mgr.a_org_rel_related, org_ted);
			m_api->m_data.GetAttr(ext_org_rel[i],  m_api->m_appr_mgr.a_org_rel_relating, org_ting);

			int j;
			for(j=0;j<ext_cur_org.GetSize();j++)
			{
				if(org_ted!=ext_cur_org[j]) continue;
				if(aplQFindInstInExtent(ext_org,org_ting,false)>=0) continue;
				ext_org.Add(org_ting); CSortClass::SortExtentByInst(ext_org);
				ext_new_org.Add(org_ting);
			}
		}
		ext_cur_org.Clear();
		ext_cur_org.Append(ext_new_org);
		ext_new_org.Clear();
	}
	return true;
}



bool CaplAutorizationManager::GetUserData(CaplInstance* item, CaplInstance** user, CaplInstance** pers, CaplInstance **po)
{
	if(m_api==NULL) return false;
	if(!m_api->m_data.IsDictLoad()) return false;
	if(item==NULL) return false;
	if(user==NULL) return false;
	if(pers==NULL) return false;
	if(po==NULL) return false;

	if(m_api->m_data.IsKindOf(item, e_apl_user))
	{
		*user = item;
		return GetPersonByUser(item, pers, po);
	}
	else if(m_api->m_data.IsKindOf(item, e_pers_org))
	{
		*po = item;
		return GetUserByPO(item, user, pers);
	}
	else if(m_api->m_data.IsKindOf(item, e_person))
	{
		*pers = item;
		return GetUserByPerson(item, user, pers);
	}

	return false;
}

bool CaplAutorizationManager::GetPersonByUser(CaplInstance* user, CaplInstance** pers, CaplInstance **po)
{
	if(m_api==NULL) return false;
	if(!m_api->m_data.IsDictLoad()) return false;
	if(user==NULL) return false;
	if(pers==NULL) return false;
	if(po==NULL) return false;

	*po = NULL;
	*pers = NULL;

	m_api->m_data.GetAttr(user, a_apl_user_po, *po);
	if(*po==NULL) return false;
	
	if(m_api->m_data.IsKindOf(*po, e_pers_org))
	{
		m_api->m_data.GetAttr(*po, a_po_the_pers, *pers);
	}
	else if(m_api->m_data.IsKindOf(*po, e_person))
	{
		*pers=*po;
		*po=0;
	}
	else return false;

	return true;
}

bool CaplAutorizationManager::GetUserByPerson(CaplInstance* pers, CaplInstance** user, CaplInstance **po)
{
	if(m_api==NULL) return false;
	if(!m_api->m_data.IsDictLoad()) return false;
	if(user==NULL) return false;
	if(pers==NULL) return false;
	if(po==NULL) return false;

	*po = GetActualPersOrg(pers);
	*user = NULL;

	int i;
	aplExtent user_ext;
	CaplInstance *tmp;
	m_api->m_data.GetEntityExtent(e_apl_user, user_ext);
	for(i=0; i<user_ext.GetSize(); i++)
	{
		m_api->m_data.GetAttr(user_ext[i], a_apl_user_po, tmp);
		if((tmp==*po && *po!=NULL) || tmp==pers)
		{
			*user = user_ext[i];
			break;
		}
	}
	
	return true;
}

bool CaplAutorizationManager::GetUserByPO(CaplInstance* po, CaplInstance** user, CaplInstance **pers)
{
	if(m_api==NULL) return false;
	if(!m_api->m_data.IsDictLoad()) return false;
	if(user==NULL) return false;
	if(pers==NULL) return false;
	if(po==NULL) return false;

	*pers = NULL;
	*user = NULL;

	m_api->m_data.GetAttr(po, a_po_the_pers, *pers);

	int i;
	aplExtent user_ext;
	CaplInstance *tmp;
	m_api->m_data.GetEntityExtent(e_apl_user, user_ext);
	for(i=0; i<user_ext.GetSize(); i++)
	{
		m_api->m_data.GetAttr(user_ext[i], a_apl_user_po, tmp);
		if(tmp==po || tmp==*pers)
		{
			*user = user_ext[i];
			break;
		}
	}

	return true;
}

CaplInstance* CaplAutorizationManager::CreateOrganization(LPCTSTR lpszId, LPCTSTR lpszName)
{
	if(m_api==NULL) return 0;
	if(!m_api->m_data.IsDictLoad()) return 0;
	if(lpszId==NULL && lpszName==NULL) return CreateOrganization((CaplInstance*)NULL, true);

	//Проверяем на уникальность и создаем!
	aplExtent ext;
	CaplAttrValue tst_val;
	tst_val.attr = a_org_id;
	tst_val.value.Set(lpszId);
	if(m_api->m_data.NET_FindInstancesWithAttrValues(e_org, 1, &tst_val, ext, false)>0)
		return ext[0];

	CaplInstance *nOrg = NULL;

	nOrg = m_api->m_data.CreateInstance(e_org);
	m_api->m_data.PutAttr(nOrg, a_org_id, lpszId);
	m_api->m_data.PutAttr(nOrg, a_org_name, lpszName);

	return nOrg;
}

ESignMode CaplAutorizationManager::SeSignModeForCryptMgr(ESignMode mode, bool bResetPassword)
{
	if(bResetPassword) m_Crypto.ResetSignTime();
	return m_Crypto.SetSignMode(mode);	
}

bool CaplAutorizationManager::CheckPersonRoleByOption(CaplInstance *person, LPCTSTR option, bool bShowMsg)
{
	if(m_api==NULL) return false;
	if(!m_api->m_data.IsDictLoad()) return false;
	if(0==option) return false;

	CString sRoleName;
	m_api->m_options_mgr.GetOptionValueBN( option, sRoleName, _T(""));
	if(sRoleName==_T("")) return true;

	bool b=CheckPersonRole(person,LPCTSTR(sRoleName));
	if(b) return true;
	if(bShowMsg)
	{
		CString msg=APL_T("Вы не обладаете ролью для выполнения операции!");
		msg+=APL_T("\n\n(Опция: '"); msg+=option;msg+=APL_T("'\nЗначение: '");
		msg+=sRoleName; msg+=_T("')");
		AfxMessageBox(msg, MB_ICONSTOP|MB_OK);
	}
	return false;
}

bool CaplAutorizationManager::CheckPersonRole(CaplInstance *person, LPCTSTR role)
{
	if(m_api==NULL) return false;
	if(!m_api->m_data.IsDictLoad()) return false;
	if(role==0) return false;
	if(person==0)
	{
		CaplInstance *po=0;
		m_api->m_data.GetAttr(m_api->m_data.GetCurrUser(), a_apl_user_po,po);
		
		if (po!=NULL)
		{
			if (m_api->m_data.IsKindOf(po, e_pers_org))
			{
				m_api->m_data.GetAttr(po, a_po_the_pers, person);
			}
			else if (m_api->m_data.IsKindOf(po, e_person))
			{
				person = po;
			}
		}
	}
	if(person==0) return false;
	if(!m_api->m_data.IsKindOf(person,e_person)) return false;

	int i,j;
	aplExtent roles;
	CStringArray sa_roles;
	CString buf, tmp_role, baseroles=role;
	if(baseroles==_T("")) return true;
	baseroles.MakeLower();

	int pos_prev=0;
	int pos=baseroles.Find(_T('|'));
	while(pos>=0)
	{
		if((pos-pos_prev)>1)
		{
			buf=baseroles.Mid(pos_prev,pos-pos_prev);
			if(buf!=_T(""))sa_roles.Add(buf);
		}
		pos_prev=pos+1;
		pos=baseroles.Find(_T('|'),pos+1);
	}
	buf=baseroles.Right(baseroles.GetLength()-pos_prev); 
	if(buf!=_T(""))sa_roles.Add(buf);

	
	m_api->m_data.GetAttr(person, a_pers_roles, roles);
	m_api->LoadExtentInfo(roles);
	for(i=0;i<roles.GetSize();i++)
	{
		m_api->m_data.GetAttr(roles[i], a_po_role_name, tmp_role);
		tmp_role.MakeLower();
		for(j=0;j<sa_roles.GetSize();j++)
		{
			if(sa_roles[j]==tmp_role) return true;

			if(CaplTranslate::IsNeedTranslate())
			{
				CString sTranslatedRole=aplTranslate(sa_roles[j]);
				if(sTranslatedRole==tmp_role) return true;
			}
		}
	}
	return false;

}
//*****************************************************************************************
bool CaplAutorizationManager::GetPersonDocumentTypes(CaplInstance *person, aplExtent &ext_doc_types, bool &bAllDocTypes)
{
	ext_doc_types.Clear();
	bAllDocTypes=false; 

	if(m_api==NULL) return false;
	if(!m_api->m_data.IsDictLoad()) return false;
	if(person==0) person=GetCurrentPerson();
	if(person==0) return true;
	if(!m_api->m_data.IsKindOf(person,e_person)) return false;

	int i;
	aplExtent roles,doc_types;
	m_api->m_data.GetAttr(person, a_pers_roles, roles);
	m_api->LoadExtentInfo(roles);
	for(i=0;i<roles.GetSize();i++)
	{
		CaplInstance *role=roles[i];
		if(0==role) continue;
		if(role->IsDeleted()) continue;

		bool bSpecDocTypeSet;
		m_api->m_data.GetAttr(role, a_po_role_specified_document_types_set,bSpecDocTypeSet);
		if(false==bSpecDocTypeSet)
		{
			bAllDocTypes=true;
			ext_doc_types.Clear();
			return true;
		}
		m_api->m_data.GetAttr(role, a_po_role_document_types,doc_types);
		ext_doc_types.Append(doc_types);
	}
	return true;
}

//*****************************************************************************************
bool CaplAutorizationManager::CheckItemStatus(CaplInstance *inst, CaplInstance *status, LPCTSTR role, aplExtent *ext_approvals)
{
	if(0!=ext_approvals) ext_approvals->Clear();
	if(0==inst || 0==status) return false;
	//проверка уникальности кода
	CaplAttrValue values[5];					
	values[0].value.Set(inst); 
	values[0].attr=a_appr_item;    
	values[1].value.Set(status); 
	values[1].attr=a_appr_status;    
	values[2].value.Set(_T("")); 
	values[2].attr=a_appr_revocation_date_time;   
	int n=3;
	
	if(role!=0)
	{
		if(role[0]!=_T('\0'))
		{
			values[3].value.Set(role); 
			values[3].attr=a_appr_role;    
			n++;
		}
	}

	aplExtent ext;
	n=m_data->NET_FindInstancesWithAttrValues(e_apl_appr_pers_org, n, &values[0], ext,false);
	if(n>0)
	{
		if(0!=ext_approvals) ext_approvals->Append(ext);
		return true;
	}
	return false;
}


bool CaplAutorizationManager::SelectOrganization(CaplInstance **inst, LPCTSTR lpszTitle, aplExtent *RootItems)
{
	if(m_api==NULL) return false;
	if(!m_api->m_data.IsDictLoad()) return false;

	if(!m_api->m_bLoadedOrgstruct)m_api->m_appr_mgr.LoadOrgStruct();

	bool isFind=false;
	CaplSetResourceHandle setres(module_inst);
	COrgStrDlg dlg(m_api,*inst);
	if(lpszTitle)
		dlg.m_sTitle = lpszTitle;
	if(RootItems)
		dlg.SetRootInst(*RootItems);
	if(dlg.DoModal()==IDOK)
	{
		*inst=dlg.m_inst;
		isFind=true;
	}
	return isFind;
}

bool CaplAutorizationManager::ShowCertificateProperties(CaplInstance *ciCert)
{	
	if(!ciCert) return false;

	CaplCertificateDlg dlg(m_api, ciCert);
	dlg.DoModal();

	return true;
}


bool CaplAutorizationManager::LoadHolydaysInCash()
{
	if(m_api==NULL) return false;
	if(!m_api->m_data.IsDictLoad()) return false;

	m_holydays_map.bAutoSort=false;

	CaplLoadData ld(m_data,DEF_SOURCE);

	ld.AddQuery(_T('e'), 0, e_calendar_holyday, 0, true, true);
	if(!ld.LoadEx()) return false;

	aplExtent ext;
	m_api->m_data.GetEntityExtent(e_calendar_holyday,ext);
	int i,j,k;
	CString buf,buf1;
	for(i=0;i<ext.GetSize();i++)
	{
		m_api->m_data.GetAttr(ext[i],a_calendar_holyday_day,buf1);
		buf=buf1.Left(8);
		m_holydays_map.Add(_atoi(buf),0);
	}

	if(m_holydays_map.Size<1)
	{
		m_bHolydeysLoaded=true;
		return false;
	}
	m_holydays_map.SortIn();


	//Добавляем метки в виде несуществующих дат чтобы было проще искать начало месяца в массиве
	int startyear=m_holydays_map.Data[0].in;
	startyear=startyear/10000;
	int endyear=m_holydays_map.Data[m_holydays_map.Size-1].in;
	endyear=endyear/10000;

	for(i=startyear;i<=endyear;i++)
	{
		for(j=1;j<12;j++)
		{
			k=startyear*10000+j*100;
			m_holydays_map.Add(k,-1);
		}
	}
	m_holydays_map.SortIn();
	m_bHolydeysLoaded=true;
	return true;
}

// Определяет является ли день выходным. day  в формате ГГГГММДД (можно ГГГГММДДЧЧММСС)
bool CaplAutorizationManager::IsDayHolyday(CString &day)
{
	if(day==_T("") || day.GetLength()<8) return false;
	if(!m_bHolydeysLoaded)
	{
		if(!LoadHolydaysInCash()) return false;
	}
	if(m_holydays_map.Size<1) return false;

	CString buf=day.Left(8);
	int d=_atoi(buf);
	int i=m_holydays_map.QFindByIn(d);
	if(i>=0) return true;
	return false;
}

// Определяет является ли день выходным. day 
bool CaplAutorizationManager::IsDayHolyday(COleDateTime day)
{
	if(day.GetStatus() != COleDateTime::valid) return false;
	if(!m_bHolydeysLoaded)
	{
		if(!LoadHolydaysInCash()) return false;
	}
	if(m_holydays_map.Size<1) return false;

	int d=day.GetYear()*10000 + day.GetMonth()*100+day.GetDay();
	int i=m_holydays_map.QFindByIn(d);
	if(i>=0) return true;
	return false;
}


// Определяет количество выходных между 2-мя датами (включая первую дату и не включая посленюю)
bool CaplAutorizationManager::GetHolydayCount(COleDateTime day_start,COleDateTime day_end, int &day_count)
{
	day_count=0;
	if((day_start.GetStatus() != COleDateTime::valid) || (day_end.GetStatus() != COleDateTime::valid)) return false;
	if(!m_bHolydeysLoaded)
	{
		if(!LoadHolydaysInCash()) return false;
	}

	if(m_holydays_map.Size<1) { day_count=0; return true;}

	if(day_start>day_end)
	{
		COleDateTime dt_temp=day_start;
		day_start=day_end;
		day_end=dt_temp;
	}
	int ds=day_start.GetYear()*10000 + day_start.GetMonth()*100+day_start.GetDay();
	int de=day_end.GetYear()*10000 + day_end.GetMonth()*100+day_end.GetDay();
	
	int d0=day_start.GetYear()*10000 + day_start.GetMonth()*100;

	int i=m_holydays_map.QFindByIn(d0); //находим метку начала месяца
	
	if(i<0) i=0; // начала месяца не нашлось, почему-то

	int dc=0;

	while(i<m_holydays_map.Size)
	{
		int d=m_holydays_map.Data[i].in;
		int l=m_holydays_map.Data[i].out;
		i++;
		if(d<ds) continue;
		if(d>de) break;
		if(l>=0) dc++;// это не метка
	}
	day_count=dc;
	return true;
}

// Определяет количество рабочих дней между 2-мя датами (включая первую дату и не включая посленюю)
bool CaplAutorizationManager::GetWorkdayCount(COleDateTime day_start,COleDateTime day_end, int &day_count)
{
	day_count=0;
	if((day_start.GetStatus() != COleDateTime::valid) || (day_end.GetStatus() != COleDateTime::valid)) return false;
	if(day_start>day_end)
	{
		COleDateTime dt_temp=day_start;
		day_start=day_end;
		day_end=dt_temp;
	}
	int hd=0;
	if(!GetHolydayCount(day_start,day_end,hd)) return false;
	COleDateTimeSpan dts=day_end-day_start;
	day_count=dts.GetDays()+1-hd;
	return true;
}

int FindNextHolyday(CaplMap &m_holydays_map, int &i, int step) //возвращает следующий/предыдущий выходной день
{
	if(step==0) return 0;
	while(true)
	{
		i+=step;
		if(i<0) return 0;
		if( i>=m_holydays_map.Size) return 99999999;
		if(m_holydays_map.Data[i].out>=0)  return m_holydays_map.Data[i].in;
	}
}

bool CaplAutorizationManager::AddWorkdayToDate(COleDateTime first_date, int iWorkDayCount, COleDateTime &new_date)
{
	double d=iWorkDayCount;
	return AddWorkdayToDate(first_date,d,new_date);
}

bool CaplAutorizationManager::AddWorkdayToDate(COleDateTime first_date, double dWorkDayCount, COleDateTime &new_date)
{
	new_date.SetStatus(COleDateTime::invalid);
	if(first_date.GetStatus() != COleDateTime::valid) return false;
	if(0==dWorkDayCount) {new_date=first_date; return true;}

	int iWorkDayCount=(int)dWorkDayCount;
	double dDayPart=dWorkDayCount-iWorkDayCount;

	if(m_holydays_map.Size<1)
	{
		COleDateTimeSpan dts(dWorkDayCount);
		new_date=first_date+dts;
		return true;
	}

	int df=first_date.GetYear()*10000 + first_date.GetMonth()*100+first_date.GetDay();

	int step=1;  if(iWorkDayCount<0) {step=-1; dDayPart*=-1;}
	COleDateTimeSpan dts(step,0,0,0);
	COleDateTime dt=first_date;

	//Считаем что кол-во добавляемых дней обычно будет небольшим, поэтому тупо обрабатываем по одному.

	int d;
	if(step>0)d=first_date.GetYear()*10000 + first_date.GetMonth()*100; // пред метка
	else 
	{
		// след. метка
		if(first_date.GetMonth()<12) d=first_date.GetYear()*10000 + (first_date.GetMonth()+1)*100; 
		else d=(first_date.GetYear()+1)*10000; 
	}

	int hi=m_holydays_map.QFindByIn(d); //находим метку начала месяца
	if(hi<0) // начала месяца не нашлось, почему-то
	{
		if(step>0) hi=0;
		else hi=m_holydays_map.Size;
	}

	//Находим индекс первого выходного после указанной даты
	while(true)
	{
		d=FindNextHolyday(m_holydays_map,hi,step);
		if(0==d) break;
		if(step>0)
		{
			if(d>df) break;
		}
		else
		{
			if(d<df) break;
		}
	}

	COleDateTime nextholyday;
	int year,month,day;
	year=d/10000; month=(d-(year*10000))/100; day=(d-(year*10000))-(month*100);
	nextholyday.SetDate(year,month,day);

	int iWorkDayCountLeft=iWorkDayCount;
	if(iWorkDayCountLeft<0)iWorkDayCountLeft*=-1;

	while(iWorkDayCountLeft>0 || dDayPart!=0)
	{
		if(dDayPart!=0) {dt+=COleDateTimeSpan(dDayPart); dDayPart=0; iWorkDayCountLeft++;}
		else dt+=dts;

		if((int)(dt.m_dt)==(int)(nextholyday.m_dt))
		{
			d=FindNextHolyday(m_holydays_map,hi,step);
			year=d/10000; month=(d-(year*10000))/100; day=(d-(year*10000))-(month*100);
			nextholyday.SetDate(year,month,day);
		}
		else iWorkDayCountLeft--;
	}
	
	
	new_date=dt;
	return true;
}


// Проверяет вхождение сотрудника в ту-же рабочую группу, что и человек поставивший на item подпись "Разработал"
bool CaplAutorizationManager::CheckPersonInWgApproval(CaplInstance *person, CaplInstance *item, LPCTSTR status_name, LPCTSTR role_name )
{
	if(0==item || 0== m_api) return false;
	if(0==person) person=m_api->m_appr_mgr.GetCurrentPerson();

	aplExtent ext_appr_razrab;
	CaplInstance *razrab_status=m_api->m_appr_mgr.FindApprovalStatusBN(status_name);
	if(0==razrab_status) return false;
	m_api->m_appr_mgr.CheckItemStatus(item,razrab_status,role_name,&ext_appr_razrab);
	if(ext_appr_razrab.GetSize()<=0) return true;

	m_api->m_appr_mgr.LoadExtentInfo(ext_appr_razrab);
	aplExtent ext_persons;
	int i;
	CString buf,subquery;
	CaplInstance *inst;
	for(i=0;i<ext_appr_razrab.GetSize();i++)
	{
		m_api->m_data.GetAttr(ext_appr_razrab[i],m_api->m_appr_mgr.a_appr_pers_org,inst);
		if(0==inst) continue;
		if(subquery!=_T("")) subquery+=_T(" OR ");
		buf.Format(_T(".the_person = #%i"),inst->GetId());
		subquery+=buf;
	}
	if(subquery==_T("")) return false;

	CString sSql =_T("SELECT Ext FROM Ext_org {person_and_organization (.end_date = '' AND (%s))}.the_organization ")
		_T("Ext {person_and_organization ( .the_person = #%i AND .end_date = '' AND .the_organization IN #Ext_org )} 	END_SELECT");

	buf.Format(_T("%i"),person->GetId());
	sSql.Replace(_T("%i"), LPCTSTR(buf));
	sSql.Replace(_T("%s"),LPCTSTR(subquery));
	if(m_api->m_data.NET_QueryEditParse(sSql, false) == false) return false;
	aplExtent ext;
	m_api->m_data.NET_QueryExecute(ext);
	if(ext.GetSize()>0) return true;
	return false;
}

//*******************************************************************************************
//*******************************************************************************************
//*******************************************************************************************

CaplInstance *CaplAutorizationManager::CreateDigSignCert4Person(CaplInstance *person, CaplCryptographicManager::TCertInfo &certInfo, bool bSaveKeyInBase)
{
	if(0==person) return 0;
	if(person->IsDeleted()) return 0;
	if(!m_api->m_data.IsKindOf(person,e_person)) return 0;

	if(certInfo.bCheckRootKey)
	{
		aplExtent aeCerts;
		CString sOpenKey;

		CString sSql = _T("SELECT Ext_1 FROM Ext_1 { apl_digital_sign_open_key(.revocation_date = '' AND .cert_type = 'root') } END_SELECT");
		if(m_api->m_data.NET_QueryEditParse(sSql, false) == false) return 0;
		m_api->m_data.NET_QueryExecute(aeCerts);				

		for(int i=0; i<aeCerts.Size; i++)
		{
			m_api->m_data.GetAttr(aeCerts[i], a_apl_digital_sign_open_key_open_key, sOpenKey);
			if(sOpenKey!=_T("")) certInfo.saConfidentOpenKeys.Add(sOpenKey); 
		}
	}

	//Записываем данные сотрудник
	if(certInfo.sSurName==_T("") && 0!=person)	m_api->m_data.GetAttr(person,a_pers_last_name,certInfo.sSurName);
	
	if(certInfo.sGivenName==_T("") && 0!=person)
	{
		m_api->m_data.GetAttr(person,a_pers_first_name,certInfo.sGivenName);
		CaplAggr aggr;
		m_api->m_data.GetAttr(person, a_pers_middle_names, aggr);
		CString buf;
		if(aggr.GetSize() > 0) buf = aggr.aggr[0]->sval;
		if(buf!=_T("")) {certInfo.sGivenName+=_T(" "); certInfo.sGivenName+=buf;}
	}

	CaplCryptographicManager m_Crypto;
	if(!m_Crypto.CreateKey(certInfo)) return 0;

	// получаем данные о созданном сертификате и сохраняем его в базу
	COleDateTime dNotBefore, dNotAfter;
	CString sNotBefor, sNotAfter, sSubject, sOpenKey, sAlg, sIssuer, sSerialNum;
	long blob;

	if(!m_Crypto.GetDataFromCertFile(certInfo.sCertFilePath, sSubject, sOpenKey, dNotBefore, dNotAfter, sIssuer, sSerialNum, sAlg)) return 0;

	aplDate2String(dNotBefore,sNotBefor);
	aplDate2String(dNotAfter,sNotAfter);

	CaplInstance*ciOpenKey = m_api->m_data.CreateInstance(m_api->m_appr_mgr.e_apl_digital_sign_open_key);
	if(!ciOpenKey)
	{
		MessageBox(0, APL_T("Не удалось создать запись о сертификате в базе данных!"), APL_T("Ошибка создания инстанса"), MB_ICONSTOP);
		return 0;
	}

	m_api->m_data.PutAttr(ciOpenKey,a_apl_digital_sign_open_key_confidential, false);
	m_api->m_data.PutAttr(ciOpenKey,a_apl_digital_sign_open_key_open_key_metod, certInfo.sSystem);
	m_api->m_data.PutAttr(ciOpenKey,a_apl_digital_sign_open_key_person, person);
	m_api->m_data.PutAttr(ciOpenKey,a_apl_digital_sign_open_key_open_key, sOpenKey);
	m_api->m_data.PutAttr(ciOpenKey,a_apl_digital_sign_open_key_open_key_cert_subject, sSubject);
	m_api->m_data.PutAttr(ciOpenKey,a_apl_digital_sign_open_key_open_key_cert_issuer, sIssuer);
	m_api->m_data.PutAttr(ciOpenKey,a_apl_digital_sign_open_key_open_key_cert_serial_num, sSerialNum);
	m_api->m_data.PutAttr(ciOpenKey,a_apl_digital_sign_open_not_before, sNotBefor);
	m_api->m_data.PutAttr(ciOpenKey,a_apl_digital_sign_open_not_after, sNotAfter);
	m_api->m_data.PutAttr(ciOpenKey,a_apl_digital_sign_cert_type, _T(""));
	m_api->m_data.PutAttr(ciOpenKey,a_apl_digital_sign_open_key_author, GetCurrentPerson());
	m_api->m_data.NET_SaveBlob(ciOpenKey,a_apl_digital_sign_open_key_open_key_cert_blob,certInfo.sCertFilePath, blob);

	// по желанию сохраняем и контейнер тоже
	if(bSaveKeyInBase == 1)
		m_api->m_data.PutAttr(ciOpenKey, a_apl_digital_sign_open_key_container, certInfo.sNewContainer);

	m_api->SaveChanges();

	return ciOpenKey;
}

bool CaplAutorizationManager::CreateDigSignCert4CurrentPerson()
{
	if(!m_api->m_data.IsConnected()){AfxMessageBox(APL_T("Соединение с БД не установлено!"),MB_ICONSTOP); return false;}

	CaplInstance *person=m_api->m_appr_mgr.GetCurrentPerson();
	if(0==person){AfxMessageBox(APL_T("Для текущего пользователя не указан сотрудник!"),MB_ICONSTOP); return false;}

	CString buf, sSql, sCurDate;
	COleDateTime cur_odt;//=COleDateTime::GetCurrentTime();
	//aplDate2String(cur_odt,sCurDate);
	sCurDate=m_api->m_data.NET_GetServerDateTime();
	aplString2Date(sCurDate,cur_odt);

	sSql.Format(_T("SELECT Ext FROM ")
		_T("Ext {apl_digital_sign_open_key(.the_person =#%i AND .revocation_date='' AND .not_after >'%s') } ")
		_T("END_SELECT"), person->GetId(), LPCTSTR(sCurDate));

	if(!m_api->m_data.NET_QueryEditParse(sSql)) return false;

	aplExtent ext0;
	m_api->m_data.NET_QueryExecute(ext0);

	if(0!=ext0.GetSize()) {AfxMessageBox(APL_T("У Вас уже есть действующие сертификаты!"),MB_ICONWARNING); return false;}

	// Формирование данных для генерацтт

	CString sCACertSN,sCACertPsw,sCACertContainer;
	m_api->m_options_mgr.GetOptionValueBN(APL_NO_T("ЭЦП\\Генерация сертификата пользователем\\Серийный номер сертификата УЦ"),sCACertSN,_T(""));
	if(sCACertSN==_T(""))  {AfxMessageBox(APL_T("В настройках отсутствует сертификат УЦ!"),MB_ICONWARNING); return false;}

	m_api->m_options_mgr.GetOptionValueBN(APL_NO_T("ЭЦП\\Генерация сертификата пользователем\\Пароль сертификата УЦ"),sCACertPsw,_T(""));
	if(sCACertPsw==_T(""))  {AfxMessageBox(APL_T("В настройках отсутствует пароль сертификата УЦ!"),MB_ICONWARNING); return false;}

	sCACertSN.Replace(_T(" "),_T(""));
	
	// Переворачиваем строку
	int i=sCACertSN.GetLength()-2;
	buf=_T("");
	while(i>=0)
	{
		buf+=sCACertSN[i];
		buf+=sCACertSN[i+1];
		i-=2;
	}
	sCACertSN=buf;

	// Ищем контейнер в БД
	sSql.Format(_T("SELECT Ext FROM ")
		_T("Ext {apl_digital_sign_open_key(.cert_serial_number ='%s' AND .revocation_date='' AND .not_after >'%s') } ")
		_T("END_SELECT"), LPCTSTR(sCACertSN), LPCTSTR(sCurDate));

	if(!m_api->m_data.NET_QueryEditParse(sSql)) return false;

	m_api->m_data.NET_QueryExecute(ext0);
	if(0==ext0.GetSize()) {AfxMessageBox(APL_T("Не найден действующий сертификат УЦ с заданным номером!"),MB_ICONWARNING); return false;}

	m_api->m_data.GetAttr(ext0[0],a_apl_digital_sign_open_key_container, sCACertContainer);		


	CGetPasswordDialog psw_dlg;
	psw_dlg.m_sHeader=APL_T("Ввелите пароль для нового\r\n контейнера закрытого ключа");

	if(psw_dlg.DoModal()!=IDOK) return false;


	// Генерирем сертификат
	CaplCryptographicManager::TCertInfo certInfo;

	certInfo.sSystem = APL_CRYPT_MGR;
	certInfo.dNotBefor = cur_odt;
	COleDateTime after_dt;
	certInfo.dNotAfter.SetDateTime(cur_odt.GetYear()+2, cur_odt.GetMonth(), cur_odt.GetDay(), 23, 59, 59);
	GetPersonName(person,buf,false);
	certInfo.sFullName = buf;
	certInfo.sCommonName = buf;
	certInfo.sUserRoles = _T("");

	m_api->m_data.GetAttr(person, m_api->m_appr_mgr.a_pers_last_name, certInfo.sSurName);
	m_api->m_data.GetAttr(person, m_api->m_appr_mgr.a_pers_first_name, certInfo.sGivenName);
	CaplAggr aggr;
	m_api->m_data.GetAttr(person, m_api->m_appr_mgr.a_pers_middle_names, aggr);
	buf=_T("");
	if(aggr.GetSize() > 0) buf = aggr.aggr[0]->sval;
	if(buf!=_T("")) {certInfo.sGivenName+=_T(" "); certInfo.sGivenName+=buf;}

	m_api->m_data.GetAttr(person,a_pers_e_mail,certInfo.sMail);

	m_api->m_options_mgr.GetOptionValueBN(APL_NO_T("ЭЦП\\Генерация сертификата пользователем\\Организация"),certInfo.sOrganization,_T(""));
	if(certInfo.sOrganization==_T("")) {AfxMessageBox(APL_T("В настройках не задана организация!"),MB_ICONWARNING); return false;}

	certInfo.sOrganizationUnit = _T("");

	m_api->m_options_mgr.GetOptionValueBN(APL_NO_T("ЭЦП\\Генерация сертификата пользователем\\Адрес"),certInfo.sStreet,_T(""));
	if(certInfo.sStreet==_T("")) {AfxMessageBox(APL_T("В настройках не задан адрес!"),MB_ICONWARNING); return false;}

	m_api->m_options_mgr.GetOptionValueBN(APL_NO_T("ЭЦП\\Генерация сертификата пользователем\\Город"),certInfo.sLocality,_T(""));
	if(certInfo.sLocality==_T("")) {AfxMessageBox(APL_T("В настройках не задан город!"),MB_ICONWARNING); return false;}

	m_api->m_options_mgr.GetOptionValueBN(APL_NO_T("ЭЦП\\Генерация сертификата пользователем\\Регион"),certInfo.sRegion,_T(""));
	if(certInfo.sRegion==_T("")) {AfxMessageBox(APL_T("В настройках не задан регион!"),MB_ICONWARNING); return false;}

	m_api->m_options_mgr.GetOptionValueBN(APL_NO_T("ЭЦП\\Генерация сертификата пользователем\\Страна"),certInfo.sCountry,_T(""));
	if(certInfo.sCountry==_T("")) {AfxMessageBox(APL_T("В настройках не задана страна!"),MB_ICONWARNING); return false;}

	GetPersonName(person,certInfo.sCommonName,false);

	certInfo.sNewContainerPassword = psw_dlg.m_sPassword;

	buf=certInfo.sCommonName;
	buf.Replace(_T(" "),_T("_"));
	buf.Replace(_T("."),_T("_"));

	if(!aplGetTempFileName((LPCTSTR)buf, _T("prk"), certInfo.sNewContainerPath)) return false;

	//certInfo.sNewContainerPath = _T("C:\\tesr.prk");


	certInfo.sContainerCA =  _T(""); 
	certInfo.sPasswordCA = sCACertPsw;
	certInfo.sContentContainerCA = sCACertContainer;

	certInfo.bCheckRootKey = true;

	CaplInstance *ciOpenKey=CreateDigSignCert4Person(person,certInfo,true);

	::DeleteFile(certInfo.sNewContainerPath);

	if(0==ciOpenKey) {AfxMessageBox(APL_T("Ошибка при создании сертификата!"),MB_ICONSTOP|MB_OK); return false;}
	
	AfxMessageBox(APL_T("Сертификат успешно создан!"),MB_ICONINFORMATION|MB_OK);

	return true;
}