// ApprovalDlg.cpp : implementation file
//

#include "stdafx.h"
#include "dictionary.h"
#include "apl_api.h"
#include "ApprovalDlg.h"
#include "ApprNoteDlg.h"

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

const CString glSection = _T("Settings");
const CString glLastStatusAssigned = _T("LastStatusAssigned");

/////////////////////////////////////////////////////////////////////////////
// CApprovalDlg dialog

void CApprovalDlg::PrpareSignOwnerToShow(CString &owner)
{
	int i=owner.Find(_T("CN="));
	if(i<0) return;

	i+=3;
	int j=owner.Find(_T(','),i);

	if(j<0) j=owner.GetLength()-1;

	CString buf=owner.Mid(i,j-1);
	
	if(buf==_T("")) return;

	buf+=_T(" ("); buf+=owner; buf+=_T(")");
	owner=buf;	
}


CApprovalDlg::CApprovalDlg(CWnd* pParent /*=NULL*/)
	: CaplResizableDialog(CApprovalDlg::IDD, pParent)
{
	//{{AFX_DATA_INIT(CApprovalDlg)
	m_sNotes = _T("");
	//}}AFX_DATA_INIT
	m_api=0; 
	m_item=0;
	m_appr=0;
	m_status_inst= NULL;
	m_person_inst=0;
	//m_Buffer=0;
	m_lBufferLen= 0;
	del_files.Clear();
	m_person_inst = NULL;

	m_DefRole= NULL;
	m_ciCert = 0;
	m_bMultiItemsMode = false ;
	m_MultiItemsExtent = NULL ;
//	m_prov.Synchronize();
	m_bNoCheckRepeatStatus=false;
	m_bCheckStatusForRole = true;
}


void CApprovalDlg::DoDataExchange(CDataExchange* pDX)
{
	CaplResizableDialog::DoDataExchange(pDX);
	//{{AFX_DATA_MAP(CApprovalDlg)
	DDX_Control(pDX, IDC_SHOW_CERT, m_show_cert_button);
	DDX_Control(pDX, IDC_RICHEDIT_ANOTE, m_rtfANote);
	DDX_Control(pDX, IDC_TAB2_FILES_OR_NOTE, m_tcFilesOrNote);
	DDX_Control(pDX, IDC_ST_APPR_ICO, m_appr_ico);
	DDX_Control(pDX, IDC_EDIT1, m_cNote);
	DDX_Control(pDX, IDC_CD_ADD_FILE, m_cAddFile);
	DDX_Control(pDX, IDC_CD_VIEW_FILE, m_cViewFile);
	DDX_Control(pDX, IDC_CD_SAVE_FILE, m_cSaveFile);
	DDX_Control(pDX, IDC_CD_FILE_LIST, m_cFileList);
	DDX_Control(pDX, IDC_CD_DELETE_FILE, m_cDelFile);
	DDX_Control(pDX, IDCANCEL, m_cancel_btn);
	DDX_Control(pDX, IDC_SIGNATURE, m_signature);
	DDX_Control(pDX, IDC_CHECK_SIGN, m_check_sign_btn);
	DDX_Control(pDX, IDC_SIGN, m_sign_btn);
	DDX_Control(pDX, IDC_CRYPT_SYSTEM, m_system);
	DDX_Control(pDX, IDC_ST_APPR_NAME, m_st_appr_name);
	DDX_Control(pDX, IDC_PERSON, m_person);
	DDX_Control(pDX, IDOK, m_ok_btn);
	DDX_Control(pDX, IDC_PO_ROLE, m_po_role);
	DDX_Control(pDX, IDC_DATE, m_date_ctrl);
	DDX_Control(pDX, IDC_TIME, m_time_ctrl);
	DDX_Control(pDX, IDC_STATUS, m_status);
	DDX_Control(pDX, IDC_LEVEL, m_level);
	DDX_Text(pDX, IDC_EDIT1, m_sNotes);
	DDX_Text(pDX, IDC_CRYPT_SYSTEM, m_sMethid);
	DDX_Control(pDX, IDC_FORMAT, m_format_ctrl);
	DDX_Control(pDX, IDC_NUM_LIST, m_list_count_ctrl);
	DDX_Control(pDX, IDC_NUM_LIST_A4, m_num_list_a4_ctrl);
	DDX_Control(pDX, IDC_T_DESCR, m_st_descr_ctrl);
	//}}AFX_DATA_MAP
}


BEGIN_MESSAGE_MAP(CApprovalDlg, CaplResizableDialog)
	ON_BN_CLICKED(IDC_SIGN, OnSign)
	ON_BN_CLICKED(IDC_CHECK_SIGN, OnCheckSign)
	ON_CBN_SELCHANGE(IDC_CRYPT_SYSTEM, OnSelchangeCryptSystem)
	ON_BN_CLICKED(IDC_ST_APPR_NAME, OnStApprName)
	ON_WM_DESTROY()
	ON_BN_CLICKED(IDC_CD_ADD_FILE, OnCdAddFile)
	ON_BN_CLICKED(IDC_CD_DELETE_FILE, OnCdDeleteFile)
	ON_BN_CLICKED(IDC_CD_VIEW_FILE, OnCdViewFile)
	ON_CBN_SELCHANGE(IDC_PO_ROLE, OnSelchangePoRole)
	ON_NOTIFY(NM_DBLCLK, IDC_CD_FILE_LIST, OnDblclkCdFileList)
	ON_BN_CLICKED(IDC_CD_SAVE_FILE, OnCdSaveFile)
	ON_NOTIFY(TCN_SELCHANGE, IDC_TAB2_FILES_OR_NOTE, OnSelchangeTab2FilesOrNote)
	ON_NOTIFY(EN_SELCHANGE, IDC_RICHEDIT1_ANOTE, OnSelchangeRichedit1Anote)
	ON_NOTIFY(TCN_SELCHANGING, IDC_TAB2_FILES_OR_NOTE, OnSelchangingTab2FilesOrNote)
	ON_BN_CLICKED(IDC_SHOW_CERT, OnShowCert)
	ON_CBN_EDITCHANGE(IDC_FORMAT, &CApprovalDlg::OnCbnEditchangeFormat)
	ON_CBN_EDITUPDATE(IDC_FORMAT, &CApprovalDlg::OnCbnEditupdateFormat)
	ON_EN_CHANGE(IDC_NUM_LIST, &CApprovalDlg::OnEnChangeNumList)
	ON_CBN_SELCHANGE(IDC_FORMAT, &CApprovalDlg::OnCbnSelchangeFormat)
END_MESSAGE_MAP()

BOOL CApprovalDlg::SetAnchors(void)
{
	AddAnchor(IDC_ST_APPR_ICO,TOP_CENTER);
	AddAnchor(IDC_ST_APPR_NAME,TOP_CENTER);

	AddAnchor(IDC_GRP_APPR,TOP_LEFT,TOP_RIGHT);
		AddAnchor(IDC_T_APPR,TOP_LEFT);
		AddAnchor(IDC_STATUS,TOP_LEFT,TOP_RIGHT);

		AddAnchor(IDC_T_LEVEL,TOP_RIGHT);
		AddAnchor(IDC_LEVEL,TOP_RIGHT);
		
		AddAnchor(IDC_T_PERSON,TOP_LEFT);
		AddAnchor(IDC_PERSON,TOP_LEFT,TOP_RIGHT);
		
		AddAnchor(IDC_T_ROLE,TOP_LEFT);
		AddAnchor(IDC_PO_ROLE,TOP_LEFT,TOP_RIGHT);
		
		AddAnchor(IDC_T_DATE,TOP_RIGHT);
		AddAnchor(IDC_DATE,TOP_RIGHT);
		AddAnchor(IDC_T_TIME,TOP_RIGHT);
		AddAnchor(IDC_TIME,TOP_RIGHT);

		AddAnchor(IDC_ST_NUM_LIST,TOP_RIGHT);
		AddAnchor(IDC_NUM_LIST,TOP_RIGHT);
		AddAnchor(IDC_FORMAT,TOP_RIGHT);
		AddAnchor(IDC_ST_FORMAT,TOP_RIGHT);
		AddAnchor(IDC_ST_NUM_LIST_A4,TOP_RIGHT);
		AddAnchor(IDC_NUM_LIST_A4,TOP_RIGHT);

		AddAnchor(IDC_T_DESCR,TOP_LEFT);
		AddAnchor(IDC_EDIT1,TOP_LEFT,TOP_RIGHT);

	AddAnchor(IDC_GRP_EL_SIGN,TOP_LEFT,TOP_RIGHT);
		AddAnchor(IDC_T_SYSTEM,TOP_LEFT);
		AddAnchor(IDC_CRYPT_SYSTEM,TOP_LEFT,TOP_RIGHT);
		AddAnchor(IDC_SIGN,TOP_RIGHT);

		AddAnchor(IDC_T_SIGN,TOP_LEFT);
		AddAnchor(IDC_SIGNATURE,TOP_LEFT,TOP_RIGHT);
		AddAnchor(IDC_CHECK_SIGN,TOP_RIGHT);
		AddAnchor(IDC_SHOW_CERT,TOP_RIGHT);

	AddAnchor(IDC_ASSOC_FILES,TOP_LEFT);
//////////////////////////////////////////////////////////////////////////
	AddAnchor(IDC_CD_ADD_FILE,TOP_RIGHT);
	AddAnchor(IDC_CD_DELETE_FILE,TOP_RIGHT);
	AddAnchor(IDC_CD_VIEW_FILE,TOP_RIGHT);
	AddAnchor(IDC_CD_SAVE_FILE,TOP_RIGHT);
	
	AddAnchor(IDC_CD_FILE_LIST,TOP_LEFT,BOTTOM_RIGHT);
//////////////////////////////////////////////////////////////////////////
	AddAnchor(IDOK,BOTTOM_RIGHT);
	AddAnchor(IDCANCEL,BOTTOM_RIGHT);


	// Sams tab control
	AddAnchor(IDC_TAB2_FILES_OR_NOTE,TOP_LEFT,BOTTOM_RIGHT);
	AddAnchor(IDC_RICHEDIT1_ANOTE,TOP_LEFT,BOTTOM_RIGHT);
	
	return TRUE;
}

/////////////////////////////////////////////////////////////////////////////
// CApprovalDlg message handlers

BOOL CApprovalDlg::OnInitDialog() 
{
	CaplResizableDialog::OnInitDialog();

	ModifyStyleEx(0, WS_EX_DLGMODALFRAME | WS_EX_WINDOWEDGE | WS_EX_CONTROLPARENT);   
	ModifyStyle(0, WS_MAXIMIZEBOX);   

	if(m_api==0) 
		return FALSE;

	// предотвращаем потерю модальности после диалога с бочками из aplSocketTransport
	CORRECT_LOOSE_MODAL_ON_CLASS(&(m_api->m_data));
	
	int i;
	COLORMAP  cm;
	cm.from=RGB(192,192,192);
	cm.to=GetSysColor(COLOR_BTNFACE);

	if(aplGetBitPerPixel(this)>8)
		m_name_bmp.LoadMappedBitmap(IDB_APPR_NAME,0,&cm,1);
	else	
		m_name_bmp.LoadMappedBitmap(IDB_APPR_NAME_16,0,&cm,1);

	HBITMAP hBmpOld=m_st_appr_name.SetBitmap(HBITMAP(m_name_bmp));	
	::DeleteObject(hBmpOld);


	m_ico_bmp.LoadMappedBitmap(IDB_APPR_ICO,0,&cm,1);
	hBmpOld=m_appr_ico.SetBitmap(HBITMAP(m_ico_bmp));	
	::DeleteObject(hBmpOld);

	m_cancel_btn.SetIcon(GetAplStdIco16(APLSTDICO_CANCEL));
	m_cancel_btn.SetFlat(FALSE);
	m_ok_btn.SetIcon(GetAplStdIco16(APLSTDICO_OK));
	m_ok_btn.SetFlat(FALSE);	

	m_cAddFile.SetTooltipText( APL_T("Добавить файл..."));
	m_cAddFile.SetIcon(GetAplTableIco(APL_TABLE_NEW));
	m_cDelFile.SetTooltipText( APL_T("Удалить файл..."));
	m_cDelFile.SetIcon(GetAplTableIco(APL_TABLE_DEL));
	m_cSaveFile.SetIcon(GetAplTableIco(APL_TABLE_SAVE));
	m_cSaveFile.SetTooltipText( APL_T(" Сохранить файл..."));
	m_cViewFile.SetTooltipText( APL_T("Просмотреть файл"));
	m_cViewFile.SetIcon(GetAplTableIco(APL_TABLE_VIEW));


	m_cFileList.InsertColumn(0,_T(""),LVCFMT_LEFT,900);

	SetAnchors();

/////////SAMS/////////////////////////////////////////////////////////////////
	CreateTabPage(m_noteDlg.IDD,  (TCHAR*)APL_T("Примечание"), &m_noteDlg);
	m_tcFilesOrNote.InsertItem(1, APL_T("Ассоциированные файлы"));
	ShowFileControls(SW_HIDE);

	
	m_tcFilesOrNote.SetCurSel(0);
/*
	if (m_mode==_T("Edit"))
	{
		m_noteDlg.m_bNewNote=false;
	}
	else
	{
		m_noteDlg.m_bNewNote=true;
		
	}
*/
	m_noteDlg.m_richedit = &m_rtfANote;
	m_noteDlg.m_api=m_api;
	m_noteDlg.m_appr= m_appr;
	m_noteDlg.m_item= m_item;

	m_noteDlg.m_pNote = m_pNote;
	m_noteDlg.m_mode  = m_mode;

	m_noteDlg.AddFonts();

	m_bCreateNewNote=m_noteDlg.GetLastNote();

//	AddAnchor(m_noteDlg.m_hWnd,TOP_LEFT,BOTTOM_RIGHT);

//////////////////////////////////////////////////////////////////////////

	//Чтение установленных криптографических систем

	bool bforsign=false;
	if(m_appr==0) bforsign=true;
	
	CStringArray array;
	CaplCryptographicManager::GetAllCSP(array,bforsign);
	if(array.GetSize()>0)
	{
		for(i=0; i<array.GetSize(); i++)
		{
			int n= m_system.AddString(array[i]);
		}
			
		CString sDefCSPName;
		sDefCSPName = CaplCryptographicManager::GetDefaultCSP();

		int iPos= m_system.FindString(-1, sDefCSPName);
		if(CB_ERR!=iPos)
			m_system.SetCurSel(iPos);
		else
			m_system.SetCurSel(-1);
	}
	else
	{
		int n= m_system.AddString( APL_T("Системы не установлены"));
		m_system.SetCurSel(n);
		m_system.EnableWindow(FALSE);
	}

	
	//Статус присваивается не версии документа или
	//не установлены криптографические системы
	//if(!bNoSystem)m_system.EnableWindow(FALSE);
		
	m_sign_btn.ShowWindow(SW_HIDE);		
	m_check_sign_btn.ShowWindow(SW_HIDE);
	m_show_cert_button.ShowWindow(SW_HIDE);

	COleDateTime odt;

	aplExtent ext0;
	CaplAggr aggr0;
	CString buf,buf1;
	CaplInstance *inst,*inst1;

	if(m_appr==0)
	{
		CWinApp *app=AfxGetApp(); // При вызове из ActiveX возвращает 0
		CString sLastRole;
		if(0!=app) sLastRole=app->GetProfileString(_T("ApprovalDlg"),_T("LastRole"),_T(""));

		if(0==m_person_inst)
		{
			m_person_inst=m_api->m_appr_mgr.GetCurrentPerson();
		}
		if(m_sFormat!=_T(""))	m_format_ctrl.SelectString(0,m_sFormat);

		if(m_person_inst==0) AfxMessageBox( APL_T("Анонимный пользователь не может присваивать электронные подписи !!!"),MB_OK|MB_ICONSTOP);
		else if(-2!=(long)m_person_inst)
		{
			//m_person.SetSelID((long)inst);

			// Чтение ролей
			if(m_DefRole==NULL)
			{
				bool bval;
				inst = m_person_inst;
				int index_cur_role=-1;
				apidata.GetAttrBN(inst,_T("apl_person_roles"),aggr0);
				for(i=0;i<aggr0.GetSize();i++)
				{
					aggr0.GetByIndex(i,inst);
					if(inst==0) continue;
					apidata.GetAttrBN(inst,_T("system"),bval);
					if(bval) continue; // Системные роли не показываем
					apidata.GetAttrBN(inst,_T("name"),buf);
					if(m_sRole!=_T(""))
					{
						if(buf!=m_sRole)continue;  // В списке должна получится одна роль
						int ind = m_po_role.AddString(buf);
						m_po_role.SetItemData(ind,(DWORD)inst);
						m_po_role.SetCurSel(ind);
						break;
					}
					int ind = m_po_role.AddString(buf);
					if(buf==m_sRole) index_cur_role=ind;
					m_po_role.SetItemData(ind,(DWORD)inst);
				}

				if(sLastRole!=_T("") && m_sRole==_T(""))
				{
					// Устанавливаем запомненную роль
					m_po_role.SelectString(0,sLastRole);
				}
			}
			else
			{
				apidata.GetAttrBN(m_DefRole, _T("name"), buf);
				int ind = m_po_role.AddString(buf);
				m_po_role.SetItemData(ind,(DWORD)m_DefRole);				
			}
			if(1==m_po_role.GetCount()&&m_sRole==_T("")) m_po_role.SetCurSel(0);

			// Чтение статусов
			OnSelchangePoRole();

			
			if(m_dt.IsEmpty())
			{
				apidata.NET_GetServerDateTime(odt);
				aplDate2String(odt,m_dt);
			}
			else
			{
				aplString2Date(m_dt, odt);				
			}
			
			m_date_ctrl.SetTime(odt);
			m_time_ctrl.SetTime(odt);

			int allowChangeDate=0;
			m_api->m_options_mgr.GetOptionValueBN( APL_NO_T("Разрешить изменение даты при подписи"), allowChangeDate, 0);
			if(allowChangeDate>0)
			{
				m_date_ctrl.EnableWindow(TRUE);
				m_time_ctrl.EnableWindow(TRUE);
			}

			if (m_bMultiItemsMode)
			{
				bool bShowSignButton = false ;
				bool bEnambleSystem = true;
				for (int i = 0 ; i < m_MultiItemsExtent->Size ; i++ )
				{
					CaplInstance* pItem = m_MultiItemsExtent->GetAt(i);
					if(apidata.IsKindOf(pItem, m_api->m_doc_mgr.e_apl_doc_rev))
					{
						bShowSignButton = true ;
					}
					else if( apidata.IsKindOf(pItem, m_api->m_prd_mgr.e_pdf)  ||
						apidata.IsKindOf(pItem, m_api->m_bp_mgr.e_bp) ||
						apidata.IsKindOf(pItem, m_api->m_bp_mgr.e_apl_bp_ver))
					{
						bShowSignButton = true ;
					}
					else
					{
						bShowSignButton = false ;
						break ;
					}
				}
			
					
				if (bShowSignButton)
				{
					m_sign_btn.ShowWindow(SW_SHOW);
				}
				else
				{
					m_system.EnableWindow(FALSE);
				}
			}
			else
			{
				if(apidata.IsKindOf(m_item, m_api->m_doc_mgr.e_apl_doc_rev) ||
					apidata.IsKindOf(m_item, m_api->m_prd_mgr.e_pdf)||
					apidata.IsKindOf(m_item, m_api->m_change_mgr.e_chng)||
					apidata.IsKindOf(m_item, m_api->m_bp_mgr.e_bp) ||
					apidata.IsKindOf(m_item, m_api->m_bp_mgr.e_apl_bp_ver) ||
					apidata.IsKindOf(m_item, m_api->m_bp_mgr.e_apl_bp_inst) ||
					apidata.IsKindOf(m_item, m_api->m_bp_mgr.e_bp_res) ||
					apidata.IsKindOf(m_item, m_api->m_charact_mgr.e_apl_charact_value) ||
					apidata.IsKindOf(m_item, m_api->m_charact_mgr.e_apl_charact_value_ver) 
					)
				{
					m_sign_btn.ShowWindow(SW_SHOW);
				}
				else
				{
					m_system.EnableWindow(FALSE);
				}
			}
		}
	}
	else
	{
		bool isRO=true;
		m_system.EnableWindow(FALSE);
		apidata.GetAttrBN(m_appr,_T("person_organization"),inst);
		m_person_inst=inst;
		//m_person.SetSelID((long)inst);
		inst1=apidata.GetCurrUser();
		apidata.GetAttrBN(inst1,_T("personality"),inst1);
		
		// может быть разносратица
		if(inst1!=0 && inst!=0	)
		{
			if(inst->GetType()!=inst1->GetType())
			{
				if(m_api->m_data.IsKindOf(inst1, m_api->m_appr_mgr.e_pers_org))
					apidata.GetAttrBN(inst1,_T("the_person"),inst1);
				if(m_api->m_data.IsKindOf(inst, m_api->m_appr_mgr.e_pers_org))
					apidata.GetAttrBN(inst,_T("the_person"),inst);
			}
		}
		/*if(inst==inst1)
		{
			// Чтение ролей
			if(m_api->m_data.IsKindOf(inst, m_api->m_appr_mgr.e_pers_org))
				apidata.GetAttrBN(inst,_T("the_person"),inst);
			apidata.GetAttrBN(inst,_T("apl_person_roles"),aggr0);
			for(i=0;i<aggr0.GetSize();i++)
			{
				aggr0.GetByIndex(i,inst);
				if(inst==0) continue;
				apidata.GetAttrBN(inst,_T("name"),buf);
				int ind = m_po_role.AddString(buf);
				m_po_role.SetItemData(ind,(DWORD)inst);
			}
		} else isRO=true;*/	
		

		apidata.GetAttrBN(m_appr,_T("level"),buf);
		m_level.SetWindowText(buf);
		apidata.GetAttrBN(m_appr,_T("status"),inst);
		if(inst!=0)
		{
			apidata.GetAttrBN(inst,S::name,buf);
			m_status.SelectString(0,buf);
		}
		
		apidata.GetAttrBN(m_appr,_T("role"),buf);
		m_po_role.AddString(buf);
		m_po_role.SetCurSel(0);
		m_po_role.EnableWindow(FALSE);

		if(m_api->m_options_mgr.CheckInstallCode(_T("grpz"))) // только для ГРПЗ
		{
			if(m_api->m_data.IsKindOf(m_item,m_api->m_change_mgr.e_chng))
			{
				CString sRoleName=buf;
				CString sFieldName=APL_T("Описание");
				sRoleName.MakeLower();
				if(sRoleName.Find(_T("180"))>=0)  sFieldName=APL_T("Срок\nдоработки\nТО");
				else if(sRoleName.Find(_T("103"))>=0  || sRoleName.Find(_T("119"))>=0 ||
					 sRoleName.Find(_T("122"))>=0 || sRoleName.Find(_T("123"))>=0)  sFieldName=APL_T("Номер\nкомплекта\nвнедрения");
				m_st_descr_ctrl.SetWindowText(sFieldName);
			}
		}


		//Чтение статусов
		CaplInstance *status;
		apidata.GetAttrBN(m_appr,_T("status"),status);
		m_status.ResetContent();

		buf=_T("");
		if(status!=0) 	apidata.GetAttrBN(status,S::name,buf);
		int k= m_status.AddString(buf);
		m_status.SetItemData(k, (DWORD)status);
		m_status.SetCurSel(k);
		m_status.EnableWindow(FALSE);


		apidata.GetAttrBN(m_appr,_T("approval_date_time_s"),m_dt);
		if(!aplString2Date(m_dt,odt))odt.SetDateTime(1900,1,1,0,0,0);
		m_date_ctrl.SetTime(odt);
		m_time_ctrl.SetTime(odt);


		CString sFormat,sNumList,sNumListA4;

		apidata.GetAttr(m_appr,m_api->m_appr_mgr.a_appr_format,sFormat);
		apidata.GetAttr(m_appr,m_api->m_appr_mgr.a_appr_total_sheets_count,sNumList);
		apidata.GetAttr(m_appr,m_api->m_appr_mgr.a_appr_total_sheets_count_a4,sNumListA4);

		//m_format_ctrl.SetWindowText(sFormat);
		m_format_ctrl.SelectString(0,sFormat);
		m_list_count_ctrl.SetWindowText(sNumList);
		m_num_list_a4_ctrl.SetWindowText(sNumListA4);

		
		buf= _T("");
		apidata.GetAttrBN(m_appr, _T("digital_sign_metdod"), buf);

		if(!buf.IsEmpty())
		{
			int iPos= m_system.FindString(-1, buf);
			if(iPos!=CB_ERR)
			{
				m_system.SelectString(-1, buf);
				if(apidata.IsKindOfBN(m_item, _T("apl_document_revision")))
					m_check_sign_btn.EnableWindow(TRUE);
				m_system.EnableWindow(FALSE);
			}
			else
			{
				iPos= m_system.AddString(buf);
				m_system.SetCurSel(iPos);
				m_system.EnableWindow(FALSE);
				m_sign_btn.EnableWindow(FALSE);
				m_sign_btn.ShowWindow(SW_SHOW);
			}
		}
		else
			m_system.SetCurSel(-1);
	
	
		CString sign_text;

		apidata.GetAttrBN(m_appr, _T("digital_sign_open_key"), m_sOpenKey);
		apidata.GetAttrBN(m_appr, _T("digital_sign_hash"), m_sHash);
		apidata.GetAttrBN(m_appr, _T("digital_sign"), m_sSign);
		apidata.GetAttr(m_appr, m_api->m_appr_mgr.a_appr_dg_sign_author, m_sSignOwner);

		if(m_sSign!=_T(""))
		{
			buf=m_sSignOwner;
			PrpareSignOwnerToShow(buf);
			sign_text+= APL_T("Владелец ключа: "); sign_text+=buf; sign_text+=_T("\r\n");
			sign_text+= APL_T("Ключ проверки ЭЦП: "); sign_text+=m_sOpenKey; sign_text+=_T("\r\n");
			sign_text+= APL_T("Хэш:     "); sign_text+=m_sHash; sign_text+=_T("\r\n");
			sign_text+= APL_T("Подпись: "); sign_text+=m_sSign; sign_text+=_T("\r\n");

			sign_text+= APL_T("Сертификат: ");
			apidata.GetAttr(m_appr,m_api->m_appr_mgr.a_appr_dg_sign_cert,buf);
			if(buf!=_T("")) sign_text+= APL_T("Есть (в подписи)");
			else
			{
				// если есть ЭЦП, то ищем сертификат в базе
				CString pers_cert_blob;
				GetCertificateInBase();
				if(m_ciCert!=0) m_api->m_data.GetAttr(m_ciCert,m_api->m_appr_mgr.a_apl_digital_sign_open_key_open_key_cert_blob, pers_cert_blob);
				if(pers_cert_blob!=_T(""))	sign_text+= APL_T("Есть (у сотрудника)");
				else sign_text+= APL_T("Нет");
			}
		}
		else sign_text= APL_T("Простая электронная подпись");

		m_signature.SetWindowText(sign_text);
		m_signature.SetSel(0,0);

		if(m_sSign!=_T(""))
		{
			m_check_sign_btn.ShowWindow(SW_SHOW);
			m_show_cert_button.ShowWindow(SW_SHOW);
		}

		//Чтение имен файлов.
		aplExtent ext;
		CString str;
		
		m_api->m_data.GetAttr(m_appr,m_api->m_appr_mgr.a_appr_attachment, ext);
		
		for(int f=0;f<ext.Size;f++)
		{
			m_api->GetItemName(ext[f], str);
			int ind = m_cFileList.InsertItem(f, str);		
			m_cFileList.SetItemData(ind,(DWORD)ext[f]);
		}
		apidata.GetAttrBN(m_appr,_T("notes"),m_sNotes);


		//  Блокировка кнопок
		if((m_appr->GetAccessmode()>aplRW)||isRO)
		{
			m_level.SetReadOnly(TRUE);
			m_status.EnableWindow(FALSE);
			m_po_role.EnableWindow(FALSE);
			//m_person.SetReadOnly(TRUE);
			m_date_ctrl.EnableWindow(FALSE);
			m_time_ctrl.EnableWindow(FALSE);

			m_format_ctrl.EnableWindow(FALSE);
			m_list_count_ctrl.SetReadOnly(TRUE);
			m_num_list_a4_ctrl.SetReadOnly(TRUE);

			
			if(m_lBufferLen)
			{
				m_system.EnableWindow(FALSE);
				m_sign_btn.EnableWindow(FALSE);
			}

			m_ok_btn.EnableWindow(FALSE);

			m_cAddFile.EnableWindow(FALSE);
			m_cDelFile.EnableWindow(FALSE);
			//m_cViewFile.EnableWindow(FALSE);
			//m_cSaveFile.EnableWindow(FALSE);
			
			m_cNote.SetReadOnly();
		}
	}

	if(m_person_inst!=0 && -2!=(long)m_person_inst)
	{
		m_api->m_appr_mgr.GetPersonName(m_person_inst, buf);
		//apidata.GetAttrBN(ext0[i],_T("the_organization"),inst1);
		m_person.SetWindowText(buf);
	}
	else m_person.SetWindowText(APL_T("Сотрудник не задан. (Некорректная подпись!)"));

	UpdateData(FALSE);

//#ifndef _DEMO
//	m_person.SetReadOnly(TRUE);
//#endif
	

//	m_rtfANote.SetParent(&m_tcFilesOrNote);	


	// устанавливаем предыдущий проставленный статус
	SelectPrevStatus();

	return TRUE;
}

void CApprovalDlg::SelectPrevStatus()
{
	// берем id инстанса
	int statusId = 0;
	CWinApp *app=AfxGetApp(); // При вызове из ActiveX возвращает 0
	if(0!=app) statusId = app->GetProfileInt(glSection, glLastStatusAssigned, 0);

	if(0 != statusId)
	{
		const int itemsCount = m_status.GetCount();

		// выделяем статус в комбо-боксе
		for(int i=0; i<itemsCount; ++i)
		{
			CaplInstance *statusInst = reinterpret_cast<CaplInstance*>(m_status.GetItemData(i));
			if(0 == statusInst) continue;

			if(statusInst->GetId() == statusId)
			{
				m_status.SetCurSel(i);
				break;
			}
		}
	}
}

void CApprovalDlg::GetCertificateInBase()
{
	if(m_sSign==_T("")) return;
	
	CString sSql;
	aplExtent aeCert;
	sSql.Format(_T("SELECT Ext_1 FROM Ext_1 { apl_digital_sign_open_key.digital_sign_open_key = '%s' } END_SELECT"), m_sOpenKey);
	m_api->m_data.NET_QueryEditParse(sSql);
	m_api->m_data.NET_QueryExecute(aeCert);
	if(aeCert.Size) m_ciCert = aeCert[0];
}

void CApprovalDlg::OnOK() 
{
	int i;
	CaplAggr aggr;
	CString buf,sval;
	CaplInstance *inst,*po, *inst1, *inst2;
	COleDateTime odt,odt0,odt1, odt_old; 
	
	CaplLoadData ld(&apidata,DEF_SOURCE);
	aplExtent ext;
	long aplError= 0;
	bool bNoError= false;
	int n, iVal;
	int iNumList,iNumListA4;

	UpdateData();

	m_status_inst=(CaplInstance*)m_status.GetItemData(m_status.GetCurSel());
	if(m_status_inst==(CaplInstance*)-1)
		m_status_inst=0;
	if(m_status_inst==0)
	{
		AfxMessageBox( APL_T("Статус не указан !!!"),MB_OK|MB_ICONSTOP);
		return;
	}
	m_po_role.GetWindowText(m_sRole);
	if(m_sRole.IsEmpty())
	{
		AfxMessageBox( APL_T("Роль не указана !!!"),MB_OK|MB_ICONSTOP);
		return;
	}

	CString sStatusName;
	m_api->m_data.GetAttr(m_status_inst,m_api->m_appr_mgr.a_appr_status_name,sStatusName);
	CWinApp *app=AfxGetApp(); // При вызове из ActiveX возвращает 0
	if(0!=app)
	{
		app->WriteProfileString(_T("ApprovalDlg"),_T("LastStatus"),sStatusName);
		app->WriteProfileString(_T("ApprovalDlg"),_T("LastRole"),m_sRole);
	}


	po=m_person_inst;
	//po=(CaplInstance*)m_person.GetSelId();
	if(po==0)
	{
		AfxMessageBox( APL_T("Сотрудник не указан !!!"),MB_OK|MB_ICONSTOP);
		return;
	}

	bool bNeedDescription = false;
	m_api->m_data.GetAttr(m_status_inst, m_api->m_appr_mgr.a_appr_status_need_description, bNeedDescription);
	if(bNeedDescription)
	{
		m_cNote.GetWindowText(buf); buf.TrimRight(); buf.TrimLeft();
		
		if(buf==_T(""))
		{
			AfxMessageBox( APL_T("Установка этого статуса требует обязательного обоснования (в поле \"Описание\") !!!"),MB_OK|MB_ICONSTOP);
			return;
		}
	}

	m_format_ctrl.GetWindowText(m_sFormat);
	m_list_count_ctrl.GetWindowText(m_sNumList);
	m_num_list_a4_ctrl.GetWindowText(m_sNumListA4);


	if(m_api->m_options_mgr.CheckInstallCode(_T("grpz"))) // только для ГРПЗ
	{
		CString sStatusName;
		m_api->m_data.GetAttr(m_status_inst,m_api->m_appr_mgr.a_appr_status_name,sStatusName);
		sStatusName.MakeLower();

		if(m_sRole==APL_T("Нормоконтролер"))
		{
			if(m_sFormat==_T("")){AfxMessageBox(APL_T("Формат не задан!"),MB_OK|MB_ICONSTOP); m_format_ctrl.SetFocus(); return;}
			iNumList=_atoi(m_sNumList);
			if(iNumList<1){AfxMessageBox(APL_T("Не задано 'количество листов всего'!"),MB_OK|MB_ICONSTOP); m_list_count_ctrl.SetFocus(); return;}
			iNumListA4=_atoi(m_sNumListA4);
			if(iNumListA4<1){AfxMessageBox(APL_T("Не задано 'количество листов приведенных к формату А4'!"),MB_OK|MB_ICONSTOP); m_num_list_a4_ctrl.SetFocus(); return;}

			if(sStatusName==APL_T("отклонено"))
			{
				if(!bCheckGrpzNormokontrolNotesFormat()) return;
			}
		}

		CString buf=m_sRole; buf.MakeLower();
		if(sStatusName==APL_T("согласовано"))
		{
			CString sNote;
			m_cNote.GetWindowText(sNote);
			if(sNote==_T(""))
			{
				if(buf.Find(_T("180"))>=0) 
				{
					if(IDYES!=AfxMessageBox(APL_T("Не указан срок доработки ТО!\n\n Поставить подпись ?"),MB_YESNO|MB_ICONEXCLAMATION)) return; 	
				}
				else if(buf.Find(_T("103"))>=0 || buf.Find(_T("119"))>=0 || buf.Find(_T("122"))>=0 || buf.Find(_T("123"))>=0) 
				{
					if(IDYES!=AfxMessageBox(APL_T("Не указан номер комплекта внедрения!\n\n Поставить подпись ?"),MB_YESNO|MB_ICONEXCLAMATION)) return; 	
				}
			}
		}

		// Аннулируем пркдыдущие подписи, если такие есть
		if(buf.Find(_T("180"))>=0 || buf.Find(_T("103"))>=0 || buf.Find(_T("119"))>=0 || buf.Find(_T("122"))>=0 || buf.Find(_T("123"))>=0 || buf.Find(APL_T("пдб"))>=0 )
		{
			CaplAttrValue tst_values[5];
			tst_values[0].value.Set(m_status_inst);
			tst_values[0].attr=m_api->m_appr_mgr.a_appr_status;
			tst_values[1].value.Set(m_item);
			tst_values[1].attr=m_api->m_appr_mgr.a_appr_item;
			tst_values[2].value.Set(LPCTSTR(m_sRole));
			tst_values[2].attr=m_api->m_appr_mgr.a_appr_role;
			tst_values[3].attr=m_api->m_appr_mgr.a_appr_revocation_date_time;
			tst_values[3].value.Set(_T(""));
			aplExtent ext;
			apidata.NET_FindInstancesWithAttrValues( m_api->m_appr_mgr.e_apl_appr_pers_org, 4, &tst_values[0], ext, false);
			if(ext.Size>0)
			{
				if(IDOK!=AfxMessageBox(APL_T("У объекта уже есть подпись с таким-же статусом и такой-же ролью!\n\nСуществующая подпись будет аннулирована!\n\nПродолжить?"),MB_OKCANCEL|MB_ICONSTOP)) return;
			
				COleDateTime odt;
				CString sDate;
				m_api->m_data.NET_GetServerDateTime(odt);
				aplDate2String(odt, sDate);

				CaplAdminModeProvider adminmode(&(m_api->m_data),-1, -1,DEF_SOURCE);
				for(i=0;i<ext.Size;i++)
				{
					m_api->m_data.PutAttr(ext[i], m_api->m_appr_mgr.a_appr_revocation_date_time, sDate);
				}
			}
			m_bNoCheckRepeatStatus=true;
		}
	}
	
	//Формируем екстент обрабатываемых инстансов
	aplExtent Items ;
	aplExtent* pItems = &Items ;
	if (!m_bMultiItemsMode)
	{
		Items.Add (m_item);
	}
	else
	{
		pItems = m_MultiItemsExtent ;
	}
	int iDenyDubleStatus=0;
	m_api->m_options_mgr.GetOptionValueBN( APL_NO_T("Статус\\Запретить дублировать подпись другим сотрудником"),iDenyDubleStatus,0);
	if(0!=iDenyDubleStatus)
	{
		for (int i = 0 ; i < pItems->Size ; i++)
		{
			CaplInstance* pItem = pItems->GetAt (i);

			// Проверяем уникальность комбинации статуса и роли
			CaplAttrValue tst_values[5];
			tst_values[0].value.Set(m_status_inst);
			tst_values[0].attr=m_api->m_appr_mgr.a_appr_status;
			tst_values[1].value.Set(pItem);
			tst_values[1].attr=m_api->m_appr_mgr.a_appr_item;
			tst_values[2].value.Set(LPCTSTR(m_sRole));
			tst_values[2].attr=m_api->m_appr_mgr.a_appr_role;
			tst_values[3].attr=m_api->m_appr_mgr.a_appr_revocation_date_time;
			tst_values[3].value.Set(_T(""));

			if(!apidata.NET_TestUniqueAttrValues(m_api->m_appr_mgr.e_apl_appr_pers_org,m_appr,4,&tst_values[0],false))
			{
				AfxMessageBox( APL_T("Электронная подпись с такими статусом и ролью \nуже есть у этого объекта !!!"));
				return;
			}
		}
	}


	if(!m_bNoCheckRepeatStatus)
	{
		for (int i = 0 ; i < pItems->Size ; i++)
		{
			CaplInstance* pItem = pItems->GetAt (i);

			// Проверяем уникальность
			// Проверяем уникальность
			if(m_bCheckStatusForRole)
			{
				CaplAttrValue tst_values[5];
				tst_values[0].value.Set(m_status_inst);
				tst_values[0].attr=m_api->m_appr_mgr.a_appr_status;
				tst_values[1].value.Set(pItem);
				tst_values[1].attr=m_api->m_appr_mgr.a_appr_item;
				tst_values[2].value.Set(LPCTSTR(m_sRole));
				tst_values[2].attr=m_api->m_appr_mgr.a_appr_role;
				tst_values[3].value.Set(po);
				tst_values[3].attr=m_api->m_appr_mgr.a_appr_pers_org;
				tst_values[4].attr=m_api->m_appr_mgr.a_appr_revocation_date_time;
				tst_values[4].value.Set(_T(""));

				if(!apidata.NET_TestUniqueAttrValues(m_api->m_appr_mgr.e_apl_appr_pers_org,m_appr,5,&tst_values[0],false))
				{
					AfxMessageBox( APL_T("Электронная подпись этого сотрудника с таким статусом и с такой ролью \nуже есть у этого объекта !!!"));
					return;
				}
			}else
			{
				CaplAttrValue tst_values[2];
				tst_values[0].value.Set(m_status_inst);
				tst_values[0].attr=m_api->m_appr_mgr.a_appr_status;
				tst_values[1].value.Set(pItem);
				tst_values[1].attr=m_api->m_appr_mgr.a_appr_item;


				if(!apidata.NET_TestUniqueAttrValues(m_api->m_appr_mgr.e_apl_appr_pers_org,m_appr,2,&tst_values[0],false))
				{
					AfxMessageBox( APL_T("Электронная подпись с таким статусом уже есть у этого объекта !!!"));
					return;
				}
			}
		}
	}

	
	m_level.GetWindowText(m_sLevel);

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

		// последние проверки ЭЦП
		bool bNeedDigSign=false;
		if(m_sSign==_T("") )
		{
			if(m_api->m_data.IsKindOf(pItem, m_api->m_doc_mgr.e_apl_doc_rev))
			{
				m_api->m_options_mgr.GetOptionValueBN( APL_NO_T("Настройка документов\\Всегда подписывать документы ЭЦП"), iVal, 0);
				if(0!=iVal)bNeedDigSign=true;
			}
			else if(m_api->m_data.IsKindOf(pItem, m_api->m_change_mgr.e_chng))
			{
				m_api->m_options_mgr.GetOptionValueBN( APL_NO_T("Изменения\\Всегда подписывать изменения ЭЦП"), iVal, 0);
				if(0!=iVal)bNeedDigSign=true;
			}
		}
			
			
		if(bNeedDigSign)
		{
			CString sSelectedSystem,sHash, sOpenKey, sSignature, sUser, sCert,sInventory,sSnapShot;

			int iPos= m_system.GetCurSel();
			if(iPos!=CB_ERR) m_system.GetLBText(iPos, sSelectedSystem);

			if(sSelectedSystem==_T(""))
			{
				AfxMessageBox( APL_T("Требуется ЭЦП! Система ЭЦП не выбрана!"));
				return;
			}

			if(!m_api->m_appr_mgr.SignObject(pItem, sSelectedSystem, 
				sSignature, sHash, sOpenKey,sUser,sCert,sInventory,sSnapShot))
			{
				AfxMessageBox( APL_T("Ошибка при присвоении ЭЦП!!!"),MB_OK|MB_ICONSTOP);				
				return;			
			}

			m_sSign= sSignature;
			m_sHash= sHash;
			m_sOpenKey= sOpenKey;
			m_sSignOwner=sUser;
			m_sSignCert=sCert;
			m_sInventory=sInventory;
			m_sSnapShot=sSnapShot;
		}
	}
	

	// дата подписи не должна выходить за рамки действия выбранного сертификата
	if(m_sOpenKey != _T(""))
	{
		aplExtent aeCert;
		COleDateTime time;
		CString sSql, sAfter, sBefore, sTime;

		sSql.Format(_T("SELECT Ext_1 FROM Ext_1 { apl_digital_sign_open_key.digital_sign_open_key = '%s' } END_SELECT"), m_sOpenKey);
		if(m_api->m_data.NET_QueryEditParse(sSql, false))
		{
			m_api->m_data.NET_QueryExecute(aeCert);		
			if(aeCert.Size == 1)
			{
				m_api->m_data.GetAttr(aeCert[0], m_api->m_appr_mgr.a_apl_digital_sign_open_not_after, sAfter);
				m_api->m_data.GetAttr(aeCert[0], m_api->m_appr_mgr.a_apl_digital_sign_open_not_before, sBefore);

				if(!sAfter.IsEmpty() && !sBefore.IsEmpty())
				{
					m_date_ctrl.GetTime(time);
					aplDate2String(time, sTime);

					if( !(sTime>=sBefore && sTime<=sAfter) )
					{
						MessageBox( APL_T("Указанная дата подписи выходит за рамки действия ключа пользователя!"),  APL_T("Ошибка ЭЦП"), MB_ICONSTOP);
						return;
					}
				}
			}
			else
			{
				MessageBox( APL_T("В базе данных не найдено записи о ключе пользователя"),  APL_T("Ошибка ЭЦП"), MB_ICONSTOP);
				return;
			}
		}
	}
	
	int iPos= m_system.GetCurSel();
	if(iPos!=CB_ERR && !m_sOpenKey.IsEmpty() && !m_sMethid.IsEmpty())
	{
		//m_system.GetLBText(iPos, m_sMethid);
		
		//Проверка принадлежности ключа
		if(po)
		{
			//пользователь, который подписал документ
			if(m_api->m_data.IsKindOf(po, m_api->m_appr_mgr.e_pers_org))
				apidata.GetAttr(po, m_api->m_appr_mgr.a_po_the_pers, inst2);
			else if(m_api->m_data.IsKindOf(po, m_api->m_appr_mgr.e_person))
				inst2= po;
		}
		else
			return;//Сотрудник не выбран
		
		CString buf1, buf2;
		if(inst2)
		{
			//ent= apidata.GetEntityBN(_T("apl_digital_sign_open_key"));
			//attr= apidata.GetAttrDefinition(e_apl_digital_sign_open_key, _T("the_person"));
		n= 	ld.AddQuery(_T('b'), inst2->GetId(), m_api->m_appr_mgr.e_apl_digital_sign_open_key, m_api->m_appr_mgr.a_apl_digital_sign_open_key_person, true);
			ld.AddQuery(_T('d'), n, 0, m_api->m_appr_mgr.a_apl_digital_sign_open_key_person, true);
			ld.AddQuery(_T('d'), n, 0, m_api->m_appr_mgr.a_apl_digital_sign_open_key_open_key, true);
			if(!ld.LoadEx()){
				if(apidata.GetLastAplError()!=APL_SOCK_OPERATION_IN_PROGRESS){
					AfxMessageBox(S::ErrorLoadDataMgr(),MB_OK|MB_ICONSTOP);
				}
			}

			apidata.GetEntityExtent(m_api->m_appr_mgr.e_apl_digital_sign_open_key, ext);

			for(i=0; i<ext.GetSize(); i++)
			{
				apidata.GetAttr(ext[i], m_api->m_appr_mgr.a_apl_digital_sign_open_key_open_key, buf2);
				//01ae... == 01AE...
				if(!buf2.CompareNoCase(m_sOpenKey))
				{
					//пользователь, на которого занесен ключ
					apidata.GetAttr(ext[i], m_api->m_appr_mgr.a_apl_digital_sign_open_key_person, inst1);
					if(inst1==inst2)
					{
						bNoError= true;
						break;
					}
				}
			}
		}

		// закомментил акуленко. все проверки делались уже до этого момента
// 		if(!bNoError/* && !buf1.IsEmpty()*/)
// 		{
// 			MessageBox(APL_T("Данный ключ не является открытым криптографическим\nключом пользователя, утвердившего статус."), 
// 				APL_T("Проверка ключа"), MB_OK|MB_ICONERROR);
// 			return;
// 		}
		// Конец проверки принадлежности ключа
	}

	//////////////////////////////////////////////////////////////////////////
//	AfxMessageBox(_T("Create Note"));
	m_noteDlg.SaveNote();
	//////////////////////////////////////////////////////////////////////////
	
	m_date_ctrl.GetTime(odt0);
	m_time_ctrl.GetTime(odt1);
	odt.SetDateTime(odt0.GetYear(),odt0.GetMonth(),odt0.GetDay(),
		odt1.GetHour(),odt1.GetMinute(),odt1.GetSecond());

	if(m_appr==0) 	
	{
/*		m_appr=apidata.CreateInstanceBN(_T("apl_approval_person_organization"));
		apidata.PutAttrBN(m_appr,_T("item"),m_item);*/
		aplDate2String(odt,m_dt);
		
		m_newFiles.RemoveAll();
		
		CString fname;
		int cnt = m_cFileList.GetItemCount();
		for(i=0; i<cnt;i++)
		{
			fname = m_cFileList.GetItemText(i,0);
			m_newFiles.Add(fname);
		}
	}
	else
	{
		aplDate2String(odt,buf);
		if(buf!=m_dt) apidata.PutAttrBN(m_appr,_T("approval_date_time_s"),buf);	
		aplString2Date(buf,odt1);

		apidata.GetAttrBN(m_appr,_T("status"),inst);
		if(inst!=m_status_inst) apidata.PutAttrBN(m_appr,_T("status"),m_status_inst);
		
		apidata.GetAttrBN(m_appr,_T("level"),sval);
		if(sval!=m_sLevel)apidata.PutAttrBN(m_appr,_T("level"),m_sLevel);

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

		apidata.GetAttrBN(m_appr,_T("role"), sval);
		if(sval!=m_sRole)	apidata.PutAttrBN(m_appr,_T("role"),m_sRole);

		apidata.GetAttrBN(m_appr,_T("person_organization"),inst);
		if(inst!=po)apidata.PutAttrBN(m_appr,_T("person_organization"),po);

		buf=_T(""); sval=_T("");
		apidata.GetAttr(m_appr, m_api->m_appr_mgr.a_appr_dg_sign_met, sval);
		if(sval!=m_sMethid) apidata.PutAttr(m_appr, m_api->m_appr_mgr.a_appr_dg_sign_met, m_sMethid);
		
		buf=_T(""); sval=_T("");
		apidata.GetAttr(m_appr, m_api->m_appr_mgr.a_appr_dg_sign, sval);
		if(sval!=m_sSign) apidata.PutAttr(m_appr, m_api->m_appr_mgr.a_appr_dg_sign, m_sSign);
		
		buf=_T(""); sval=_T("");
		apidata.GetAttr(m_appr, m_api->m_appr_mgr.a_appr_dg_sign_open_key, sval);
		if(sval!=m_sOpenKey) apidata.PutAttr(m_appr, m_api->m_appr_mgr.a_appr_dg_sign_open_key, m_sOpenKey);
		
		buf=_T(""); sval=_T("");
		apidata.GetAttr(m_appr, m_api->m_appr_mgr.a_appr_dg_sign_hash, sval);
		if(sval!=m_sHash) apidata.PutAttr(m_appr, m_api->m_appr_mgr.a_appr_dg_sign_hash, m_sHash);

		buf=_T(""); sval=_T("");
		apidata.GetAttr(m_appr, m_api->m_appr_mgr.a_appr_dg_sign_author, sval);
		if(sval!=m_sSignOwner) apidata.PutAttr(m_appr, m_api->m_appr_mgr.a_appr_dg_sign_author, m_sSignOwner);

		apidata.GetAttr(m_appr, m_api->m_appr_mgr.a_appr_dg_sign_snapshot, sval);
		if(sval!=m_sSnapShot) apidata.PutAttr(m_appr, m_api->m_appr_mgr.a_appr_dg_sign_snapshot, m_sSnapShot);

		apidata.GetAttr(m_appr, m_api->m_appr_mgr.a_appr_dg_sign_inventory, sval);
		if(sval!=m_sInventory) apidata.PutAttr(m_appr, m_api->m_appr_mgr.a_appr_dg_sign_inventory, m_sInventory);

	
		int cnt = m_cFileList.GetItemCount();
	
		aplExtent files;
		CString fname;
		CaplInstance *inst;
		files.Clear();
		
		for(i=0; i<cnt;i++)
		{
			fname= m_cFileList.GetItemText(i,0);
			inst= (CaplInstance*)m_cFileList.GetItemData(i);
			
			if(inst==0)
			{
				inst = m_api->m_doc_mgr.CreateFile(fname);				
				if(!inst)
				{
					AfxMessageBox( APL_T("Не могу создать файл ")+fname, MB_ICONERROR|MB_OK);
					return;
				}
			}
			files.Add(inst);
		}

		apidata.PutAttrBN(m_appr,_T("attachment"),files);
		apidata.PutAttrBN(m_appr,_T("notes"),m_sNotes);
		
		for(i=0; i<del_files.Size;i++)
			if(del_files[i]!=NULL) m_api->m_data.NET_DeleteBlobBN(del_files[i],_T("source"));
		
		m_api->SaveChanges();
	}

	CaplCryptographicManager::SetDefaultCSP(m_sMethid);

	DeleteCeratedFiels();
	if(0!=app) app->WriteProfileInt(glSection, glLastStatusAssigned, m_status_inst->GetId());

	CaplResizableDialog::OnOK();
}


void CApprovalDlg::OnSign()
{
	CString buf,sSelectedSystem;
	int iPos= m_system.GetCurSel();
	if(iPos!=CB_ERR)	m_system.GetLBText(iPos, sSelectedSystem);
	
	if(sSelectedSystem==_T(""))
	{
		AfxMessageBox( APL_T("Система ЭЦП не выбрана!"));
		return;
	}

	m_sSign=_T(""); m_sHash=_T(""); m_sOpenKey=_T(""); m_sSignOwner=_T(""); m_sSignCert=_T(""); m_sInventory=_T(""); m_sSnapShot=_T("");

	CaplInstance *sign_pers=m_person_inst;

	if(m_api->m_appr_mgr.SignObject(m_item, sSelectedSystem, m_sSign, m_sHash, m_sOpenKey,m_sSignOwner,m_sSignCert,m_sInventory,m_sSnapShot,&sign_pers))
	{
		if(sign_pers!=m_person_inst) // для случая определения пользователя по ключу
		{
			m_person_inst=sign_pers;
			m_api->m_appr_mgr.GetPersonName(m_person_inst, buf);
			m_person.SetWindowText(buf);
		}

		CString sign_text, sKey;
		buf=m_sSignOwner;
		PrpareSignOwnerToShow(buf);
		sign_text+= APL_T("Владелец ключа: ");
		sign_text+=buf; 
		sign_text+=_T("\r\n");
		sign_text+= APL_T("Открытый ключ: ");

		// так сделано специально, не убирать!!!!!
		sKey.Format(_T("%s"), m_sOpenKey);

		sign_text += sKey; 		
		sign_text+=_T("\r\n");
		sign_text+= APL_T("Хэш:     "); 
		sign_text+=m_sHash; 
		sign_text+=_T("\r\n");
		sign_text+= APL_T("Подпись: "); 
		sign_text+=m_sSign; sign_text+=_T("\r\n");
		
		sign_text+= APL_T("Сертификат: ");
		if(m_sSignCert==_T("")) sign_text+= APL_T("Нет");
		else
		{
			sign_text+= APL_T("Есть");
			//m_saCreatedFiles.Add(m_sSignCert);
		}
 

		m_signature.SetWindowText(sign_text);
		m_signature.SetSel(0,0);
		m_show_cert_button.ShowWindow(SW_SHOW);

		GetCertificateInBase();

//			m_check_sign_btn.EnableWindow();
	}
	else
	{
		sSelectedSystem=_T("");
		m_sSign=_T("");
		m_sHash=_T("");
		m_sOpenKey=_T("");
		m_sSignOwner=_T("");
		m_sSignCert=_T("");
		m_signature.SetWindowText(_T(""));
	}
}

void CApprovalDlg::OnCheckSign() 
{
	m_api->m_appr_mgr.CheckApproval(m_appr);
}


void CApprovalDlg::OnSelchangeCryptSystem() 
{
	int iPos= m_system.GetCurSel();
	//if(iPos!=m_iSelSystem)
	{
		m_signature.SetWindowText(_T(""));

		m_sSignOwner=_T("");
		m_sSignCert=_T("");
		m_sSign=_T("");
		m_sHash=_T("");
		m_sMethid=_T("");

		m_check_sign_btn.EnableWindow(FALSE);
		m_sign_btn.ShowWindow(SW_SHOW);
		m_sign_btn.EnableWindow();
	}

	UpdateData();
}

void CApprovalDlg::OnStApprName() 
{
	// TODO: Add your control notification handler code here
	CString text,buf;
//	if(((GetKeyState(VK_LMENU) & 0xff00)!=0)&&((GetKeyState(VK_RMENU) & 0xff00)!=0))
	if(((GetKeyState(VK_LMENU) )!=0)&&((GetKeyState(VK_RMENU) )!=0))
		{
		text.Format( APL_T("Режим %s;\n"),m_mode);
		if(m_appr!=0){buf.Format(_T("m_appr->id %i;\n"),m_appr->GetId());text+=buf;}else{buf.Format(_T("m_appr==0;\n"));}
		if(m_item!=0){buf.Format(_T("m_item->id %i;\n"),m_item->GetId());text+=buf;}else{buf.Format(_T("m_item==0;\n"));}
		if(m_person_inst!=0){buf.Format(_T("m_person_inst->GetId() %i;\n"),m_person_inst->GetId());text+=buf;}else{buf.Format(_T("m_person_inst==0;\n"));}
		COleDateTime dt;
		if(aplString2Date(m_dt,dt)){buf.Format(_T("m_dt = %s;\n"),LPCTSTR(m_dt));text+=buf;}
		AfxMessageBox(text);
	}	
}

void CApprovalDlg::OnDestroy() 
{
	//if(m_Buffer!=0) delete m_Buffer;
	CaplResizableDialog::OnDestroy();
}

void CApprovalDlg::OnCdAddFile() 
{
	CFileDialog dlg(true,_T("*"),_T("*.*"),OFN_ALLOWMULTISELECT|OFN_HIDEREADONLY|OFN_OVERWRITEPROMPT
		|OFN_ENABLESIZING|OFN_EXPLORER, APL_T("Все файлы (*.*)|*.*||"),this);
	if(dlg.DoModal()==IDOK)
	{
		POSITION pos = dlg.GetStartPosition();
		CString path=_T("");
		while(pos>0)
		{
			path = dlg.GetNextPathName(pos);
			LVFINDINFO /*fInfo1, */fInfo2;
			//fInfo1.psz = dlg.GetFileName();
			//fInfo1.flags = LVFI_STRING;
			fInfo2.psz = path;
			fInfo2.flags = LVFI_STRING;
			//if(m_cFileList.FindItem(&fInfo1)<0 && m_cFileList.FindItem(&fInfo2)<0)
			if(m_cFileList.FindItem(&fInfo2)<0)
			{
				int i = m_cFileList.InsertItem(m_cFileList.GetItemCount(),path);
				m_cFileList.SetItemData(i,0);
				
			}
		}
	}
}

void CApprovalDlg::OnCdDeleteFile() 
{
	int count = m_cFileList.GetSelectedCount();
	
	if(count<=0) return;
	if(MessageBox( APL_T("Вы действительно желаете удалить выбранные файлы?"), APL_T("Удаление"),MB_ICONQUESTION|MB_YESNO|MB_DEFBUTTON2)==IDNO)
		return;
	int pos=-1;
	while((pos = m_cFileList.GetNextItem(pos,LVIS_SELECTED))>-1)
	
	{
		CaplInstance *file = (CaplInstance*)m_cFileList.GetItemData(pos);
	
		del_files.Add(file);
		m_cFileList.DeleteItem(pos);
	
		pos--;
	}
}


void CApprovalDlg::OnCdViewFile() 
{
	int count = m_cFileList.GetSelectedCount();
	
	if(count<1) return;
	if(count>1)
		if(MessageBox( APL_T("Выбрано более одного файла. Желаете просмотреть все?"), APL_T("Просмотр"),MB_YESNO|MB_ICONQUESTION|MB_DEFBUTTON1)==IDNO)
			return;
	int pos=-1;
	while((pos = m_cFileList.GetNextItem(pos,LVIS_SELECTED))>-1)
	
	{
		CString fname;
		fname = m_cFileList.GetItemText(pos,0);
		CaplInstance *inst = (CaplInstance*)m_cFileList.GetItemData(pos);
		
		if(inst)
		{
			m_api->GetItemName(inst, fname);
			TCHAR tmp[1024];
			GetTempPath(1024,tmp);
			CString str(tmp);
			m_api->m_doc_mgr.LoadRevision(inst,str+_T("\\")+fname);
			aplShellExecute(this->m_hWnd,_T("open"),str+_T("\\")+fname,NULL,NULL,SW_SHOW);
		}
		else
			aplShellExecute(this->m_hWnd,_T("open"),fname,NULL,NULL,SW_SHOW);
	}
}

void CApprovalDlg::OnSelchangePoRole() 
{
	m_status.ResetContent();
	int cur = m_po_role.GetCurSel();
	if(cur<0) return;
	aplExtent ext;
	CString buf;
	int k;
	CaplInstance *status=0;
	if(m_appr!=0) apidata.GetAttr(m_appr,m_api->m_appr_mgr.a_appr_status,status);
	
	/*Подписывается или нет объект WF*/
	if(m_status_ext.GetSize()==0)
	{
		CaplInstance *inst = (CaplInstance*)m_po_role.GetItemData(cur);
		if(!inst) return;
		apidata.GetAttrBN(inst,_T("approval_status"),ext);
		bool all=true;
		apidata.GetAttrBN(inst,_T("specified_approval_status_set"),all);
		if(!all) apidata.GetEntityExtent(m_api->m_appr_mgr.e_appr_status,ext);
	}
	else
	{
		ext.Append(m_status_ext);
	}

	for(int i=0;i<ext.Size;i++)
	{
		bool insertStatus = true;

		// возможно, не все статусы стоит отображать в комбобоксе
		for(int j=0; j<m_statusesToHide.Size; ++j)
		{
			if(m_statusesToHide[j] == ext[i])
			{
				insertStatus = false;
				break;
			}
		}

		if(false == insertStatus)
			continue;

		apidata.GetAttrBN(ext[i], S::name, buf);
		k=m_status.AddString(buf);
		m_status.SetItemData(k, (long)ext[i]);
		if(status!=0 && status==ext[i]) m_status.SetCurSel(k);
	}

	if(0==m_appr)
	{
		CString sLastStatus;
		CWinApp *app=AfxGetApp(); // При вызове из ActiveX возвращает 0
		if(0!=app) sLastStatus=app->GetProfileString(_T("ApprovalDlg"),_T("LastStatus"),_T(""));
		if(sLastStatus!=_T(""))m_status.SelectString(0,sLastStatus);
	}


	if(m_api->m_options_mgr.CheckInstallCode(_T("grpz"))) // только для ГРПЗ
	{
		if(m_api->m_data.IsKindOf(m_item,m_api->m_change_mgr.e_chng))
		{
			CString sRoleName;
			CString sFieldName=APL_T("Описание");
			m_po_role.GetLBText(cur,sRoleName);
			sRoleName.MakeLower();
			if(sRoleName.Find(_T("180"))>=0)  sFieldName=APL_T("Срок\nдоработки\nТО");
			else if(sRoleName.Find(_T("103"))>=0  || sRoleName.Find(_T("119"))>=0 || sRoleName.Find(_T("122"))>=0 || sRoleName.Find(_T("123"))>=0)  sFieldName=APL_T("Номер\nкомплекта\nвнедрения");

			m_st_descr_ctrl.SetWindowText(sFieldName);
		}
	}
}

void CApprovalDlg::OnDblclkCdFileList(NMHDR* pNMHDR, LRESULT* pResult) 
{
	// TODO: Add your control notification handler code here
	if(m_cViewFile.IsWindowEnabled())
		OnCdViewFile();
	
	*pResult = 0;
}


void CApprovalDlg::OnCdSaveFile() 
{
	int count = m_cFileList.GetSelectedCount();
	
	if(count<1) return;
	if(count>1)
	{
		MessageBox( APL_T("Выбрано более одного файла."), APL_T("Ошибка"),MB_OK|MB_ICONERROR);
		return;
	}
	int pos=-1;
	pos = m_cFileList.GetNextItem(pos,LVIS_SELECTED);
	
	if(pos<0) return;
	CString fname;
	fname = m_cFileList.GetItemText(pos,0);

	CaplInstance *inst = (CaplInstance*)m_cFileList.GetItemData(pos);


	CFileDialog dlg(false,_T("*.*"),fname,OFN_HIDEREADONLY|OFN_OVERWRITEPROMPT
			|OFN_ENABLESIZING|OFN_EXPLORER, APL_T("Все файлы (*.*)|*.*||"),this);
	if(dlg.DoModal()==IDOK)
	if(inst)
		m_api->m_doc_mgr.LoadRevision(inst,dlg.GetPathName());
	else
		CopyFile(fname,dlg.GetPathName(),true);
}


void CApprovalDlg::ShowFileControls(int show)
{
	int arr[]= {IDC_ASSOC_FILES,	IDC_CD_ADD_FILE,	IDC_CD_DELETE_FILE,
				IDC_CD_VIEW_FILE,	IDC_CD_SAVE_FILE,	IDC_CD_FILE_LIST};
	for (int i=0;i<6;i++)
		GetDlgItem(arr[i])->ShowWindow(show);
}

void CApprovalDlg::CreateTabPage(UINT nID, const LPTSTR sTitle, CDialog* pDlg)
{
	TC_ITEM tci;
     
    tci.mask = TCIF_TEXT;
    tci.pszText = sTitle;
    int ind = m_tcFilesOrNote.InsertItem(m_tcFilesOrNote.GetItemCount(), &tci);
    tci.mask = TCIF_PARAM;
    tci.lParam = (LPARAM)pDlg;
    m_tcFilesOrNote.SetItem(ind, &tci);
    pDlg->Create(nID, &m_tcFilesOrNote);
    pDlg->ShowWindow(SW_SHOW);
 	m_rtfANote.ShowWindow(SW_SHOW);
    
    CRect rect, iRect;
     
    m_tcFilesOrNote.GetItemRect(0, &iRect);
    m_tcFilesOrNote.GetClientRect(&rect);
    rect.DeflateRect(2, 2);
    rect.top+=iRect.Height()+1;
     
    pDlg->MoveWindow(rect);
}

void CApprovalDlg::OnSelchangingTab2FilesOrNote(NMHDR* pNMHDR, LRESULT* pResult) 
{
	int iTab = m_tcFilesOrNote.GetCurSel();
	if(iTab==0)
	{
		TC_ITEM tci;
		tci.mask = TCIF_PARAM;
		m_tcFilesOrNote.GetItem(iTab, &tci);
		CWnd* pWnd = (CWnd *)tci.lParam;
		pWnd->ShowWindow(SW_HIDE);
		m_rtfANote.ShowWindow(SW_HIDE);
	}
	else
	{
		ShowFileControls(SW_HIDE);
	}
     
	*pResult = 0;
}

void CApprovalDlg::OnSelchangeTab2FilesOrNote(NMHDR* pNMHDR, LRESULT* pResult) 
{
	int iTab = m_tcFilesOrNote.GetCurSel();
	if(iTab==0)
	{
		TC_ITEM tci;
		tci.mask = TCIF_PARAM;
		m_tcFilesOrNote.GetItem(iTab, &tci);
		CWnd* pWnd = (CWnd *)tci.lParam;
		pWnd->ShowWindow(SW_SHOW); 
		m_rtfANote.ShowWindow(SW_SHOW);
	}
	else
	{
		ShowFileControls(SW_SHOW);
	}
	*pResult = 0;
}

void CApprovalDlg::OnSelchangeRichedit1Anote(NMHDR* pNMHDR, LRESULT* pResult) 
{
	m_noteDlg.SelChangeRE(pNMHDR, pResult);
	
	*pResult = 0;
}


void CApprovalDlg::OnShowCert() 
{
	if(m_appr==0) return;	
	if(m_sSign==_T(""))return;	

	CString buf;
	apidata.GetAttr(m_appr,m_api->m_appr_mgr.a_appr_dg_sign_cert,buf);
	if(buf!=_T(""))
	{
		//Открываем сертификат, сохраненный в статусе
		m_api->m_appr_mgr.ShowCertificateProperties(m_appr);
	}
	else
	{
		//Открываем сертификат, сохраненный в статусе
		//GetCertificateInBase();// если есть ЭЦП, то ищем сертификат в базе
		if(m_ciCert==0) AfxMessageBox( APL_T("Сертификат не сохранен!")) ;
		else m_api->m_appr_mgr.ShowCertificateProperties(m_ciCert);
	}
	return;
}

void CApprovalDlg::OnCancel()
{
	DeleteCeratedFiels();

	if(!m_sSignCert.IsEmpty())
	{
		::SetFileAttributes(m_sSignCert, FILE_ATTRIBUTE_NORMAL);
		::DeleteFile(m_sSignCert);
	}

	CaplResizableDialog::OnCancel();
}

void CApprovalDlg::DeleteCeratedFiels()
{
	for(int i=0; i<m_saCreatedFiles.GetSize(); ++i)
	{
		::SetFileAttributes(m_saCreatedFiles[i], FILE_ATTRIBUTE_NORMAL);
		::DeleteFile(m_saCreatedFiles[i]);
	}	
}

void CApprovalDlg::OnCbnEditchangeFormat(){	OnEnChangeNumList();}
void CApprovalDlg::OnCbnEditupdateFormat(){	OnEnChangeNumList();}
void CApprovalDlg::OnCbnSelchangeFormat() {	OnEnChangeNumList();}

void CApprovalDlg::OnEnChangeNumList()
{
	CString sFormat,sCount,sA4Count;
	m_format_ctrl.GetWindowText(sFormat);
	m_list_count_ctrl.GetWindowText(sCount);
	m_api->m_doc_mgr.CalcA4SheetsCount(sFormat,sCount,sA4Count);
	m_num_list_a4_ctrl.SetWindowText(sA4Count);
}


bool CApprovalDlg::bCheckGrpzNormokontrolNotesFormat()
{
	CString buf,sNote;

	m_cNote.GetWindowText(sNote);
	if(sNote==_T(""))
	{
		AfxMessageBox(APL_T("Не задано описание ошибок!"),MB_ICONSTOP|MB_OK);
		m_cNote.SetFocus();
		return false;
	}
	int i,j,k,len=sNote.GetLength();
	//Проверка на символы
	for(i=0;i<len;i++)
	{
		TCHAR c=sNote[i];
		if(c==_T('(') || c==_T(')') || (c>=_T('0') && c<=_T('9'))) continue;
		buf.Format(APL_T("Недопустимый символ в позиции %i"),i);
		AfxMessageBox(buf,MB_ICONSTOP|MB_OK);
		m_cNote.SetFocus();
		m_cNote.SetSel(i,i+1);
		return false;
	}

	i=0;
	int iType,iCount;
	while(true)
	{
		while(sNote[i]==_T(' ')) i++;
		if(i>=len) break;
		j=sNote.Find(_T('('),i);
		if(j<0) {buf.Format(APL_T("Отсутствует '(' с позиции %i"),i);	AfxMessageBox(buf,MB_ICONSTOP|MB_OK); m_cNote.SetFocus();	m_cNote.SetSel(i,i);	return false;};
		if(j==0) {buf.Format(APL_T("Отсутствует шифр ошибки с позиции %i"),i);	AfxMessageBox(buf,MB_ICONSTOP|MB_OK); 	m_cNote.SetFocus(); m_cNote.SetSel(i,i);	return false;};

		buf=sNote.Mid(i,j-i); 
		iType=_atoi(buf);

		k=sNote.Find(_T(')'),j+1);
		if(k<0) {buf.Format(APL_T("Отсутствует ')' после позиции %i"),j+1);	AfxMessageBox(buf,MB_ICONSTOP|MB_OK); m_cNote.SetFocus();	m_cNote.SetSel(j+1,j+1);	return false;};
		if(k==j+1){buf.Format(APL_T("Отсутствует количество ошибок после позиции %i"),j+1);	AfxMessageBox(buf,MB_ICONSTOP|MB_OK); m_cNote.SetFocus();	m_cNote.SetSel(j+1,j+1);	return false;};
		
		buf=sNote.Mid(j+1,k-(j+1));
		iCount=_atoi(buf);
		
		i=k+1;
		//TRACE("\n   %i  -- %i",iType,iCount);
	}
	return true;
}