// aplpacket.h: interface for the CaplPacket class.
//
//////////////////////////////////////////////////////////////////////
#ifndef AFX_APLapl_packet_H__D13DB883_42AD_48CC_9E77_6416CCB5EDBD__INCLUDED_
#define AFX_APLapl_packet_H__D13DB883_42AD_48CC_9E77_6416CCB5EDBD__INCLUDED_

#if _MSC_VER > 1000
#pragma once
#endif // _MSC_VER > 1000

#include "StdAfx.h"
#include <apl_gui.h>
#include <aplCryptManager.h>


#ifdef APL_WIN_ETD_EXPIMP
#define APL_WIN_ETD_CLASS_EXPORT __declspec(dllexport)
#else
#define APL_WIN_ETD_CLASS_EXPORT __declspec(dllimport)
#ifdef _DEBUG
#ifdef UNICODE
#pragma comment (lib,"apl_packet_ud.lib")
#else
#pragma comment (lib,"apl_packet_d.lib")
#endif
#else
#ifdef UNICODE
#pragma comment (lib,"apl_packet_u.lib")
#else
#pragma comment (lib,"apl_packet.lib")
#endif
#endif
#endif

#define APL_WIN_ETD	"ETD BIN "					// заголовок в начале файла всегда должен быть в кодировке ANSI
#define APL_WIN_ETD_VER	"1.0"					// заголовок в начале файла всегда должен быть в кодировке ANSI
#define APL_WIN_ETD_HEADER "<ETD BIN 1.0>"		// заголовок в начале файла всегда должен быть в кодировке ANSI

#define APL_WIN_ETD_U	"ETD BINu"				// заголовок в начале файла всегда должен быть в кодировке ANSI
#define APL_WIN_ETD_HEADER_U "<ETD BINu1.0>"	// заголовок в начале файла всегда должен быть в кодировке ANSI

//Ошибки
#define APL_LOAD_DATASETSIGN_FROM_BUF_ERROR		1
#define APL_LOAD_DATASETSIGN_FROM_FILE_ERROR	2
#define APL_SAVE_DATASETSIGN_TO_FILE_ERROR		3
#define APL_SAVE_DATASETSIGN_TO_BUF_ERROR		4
#define APL_LOAD_DATASETPARAM_FROM_BUF_ERROR	5
#define APL_LOAD_DATASETPARAM_FROM_FILE_ERROR	6
#define APL_SAVE_DATASETPARAM_TO_FILE_ERROR		7
#define APL_SAVE_DATASETPARAM_TO_BUF_ERROR		8
#define APL_LOAD_FOLDERDATASET_FROM_FILE_ERROR	9
#define APL_SAVE_FOLDERDATASET_TO_FILE_ERROR	10
#define APL_LOAD_FILERDATASET_FROM_FILE_ERROR	11
#define APL_SAVE_FILERDATASET_TO_FILE_ERROR		12
#define APL_LOAD_PACKET_FROM_FILE_ERROR			13
#define APL_SAVE_PACKET_TO_FILE_ERROR			14
#define APL_UNKNOWN_FILE_FORMAT					15
#define APL_CRC32_ERROR							16
#define APL_INCORRECT_FILE_VERSION				17
#define APL_INCOMPATIBLE_FILE_FORMAT			18
#define APL_UNKNOWN_ERROR						19



class CaplPacket;
class CaplCryptographicManager;
class CaplSignBuf;

class APL_WIN_ETD_CLASS_EXPORT CBinaryFile : public CFile
{
protected:
	//идет работа с файлом ansi (true) или unicode (false)
	bool m_bANSI;

public:
	CBinaryFile(bool bANSI = true);

	bool Read(CString &str);
	bool Read(UINT32 &i);
	bool Read(TCHAR& c);
	BYTE Read();

	void Write(CString str);
	void Write(UINT32 i);
	void Write(char c);
	void Write(wchar_t wc);

	bool WriteFromFile(LPCTSTR sFileName);  // Дописывает содержимое файла в текущий файл 

	bool WriteToFile(LPCTSTR sFileName, UINT nCount);  // Записывает файл из текущего файла (nCount байт)

	virtual void Write( const void* lpBuf, UINT nCount ){CFile::Write(lpBuf, nCount);};
	virtual UINT Read(void *lpBuf, UINT nCount)	{return CFile::Read(lpBuf, nCount);};

	bool IsANSI() { return m_bANSI; }
	void SetANSI(bool bANSI) { m_bANSI = bANSI; }
};

class APL_WIN_ETD_CLASS_EXPORT CDataSetParam
{
protected:
	//идет работа с файлом ansi (true) или unicode (false)
	bool m_bANSI;

public:
	CDataSetParam(LPCTSTR sName, LPCTSTR sValue, bool bANSI = true);
	CDataSetParam();
	virtual ~CDataSetParam();

	CString		m_sName;
	CString		m_sValue;

	bool Load(CBinaryFile &file);
	bool Save(CBinaryFile &file);
	UINT64 GetBufSize(bool bUseAdditionalParam = true);
	bool SaveToBuf(CaplSignBuf &signBuf, bool bUseAdditionalParam = true);
	virtual bool LoadFromBuf(BYTE *pBuf, int &index);

	bool IsANSI() { return m_bANSI; }
	void SetANSI(bool bANSI) { m_bANSI = bANSI; }
};

class APL_WIN_ETD_CLASS_EXPORT CDataSet
{
protected:
	CaplPacket	*m_pPacket;

	//идет работа с файлом ansi (true) или unicode (false)
	bool m_bANSI;

public:
	HTREEITEM	m_item;//Проще добавить нужный только WinETD атрибут чем переписать все!!!

	CDataSet(CaplPacket *pPacket, CDataSet *pParent = NULL, bool bANSI = true);
	virtual ~CDataSet();

	CArray<CDataSetParam*, CDataSetParam*>	m_Parametrs;
	CString		m_sName;
	CString		m_sCompress_method;
	CString		m_sCrypt_method;

	CDataSet*	m_pParent;

	virtual void Clear();
	virtual bool Load(CBinaryFile &file){return false;};
	virtual bool Save(CBinaryFile &file){return false;};
	virtual UINT64 GetBufSize(bool bUseAdditionalParam = true){return 0;};
	virtual bool SaveToBuf(CaplSignBuf &signBuf, bool bUseAdditionalParam = true){return false;};
	virtual bool LoadFromBuf(BYTE *pBuf, int &index){return false;};
	virtual bool IsFolder(){return false;};
	virtual bool View(CString &sPathName, HANDLE &hProc){return false;};
	virtual bool SaveFiles(LPCTSTR lpszPathName = NULL){return false;};
	virtual bool LoadItem(LPCTSTR lpszPath, bool addFileParam = true){return false;};	

	int CheckSigns(bool bShowMessages);
	bool GetParamValueBN(LPCTSTR lpName, CString &sValue);
	bool SetParamValueBN(LPCTSTR lpName, LPCTSTR sValue);

	bool IsANSI() { return m_bANSI; }
	void SetANSI(bool bANSI);
};

class APL_WIN_ETD_CLASS_EXPORT CFolderDataSet : public CDataSet
{
public:
	CFolderDataSet(CaplPacket *pPacket, CDataSet *pParent = NULL, bool bANSI = true);
	virtual ~CFolderDataSet();

	CArray<CDataSet*, CDataSet*>	m_Content;

	virtual void Clear();
	virtual bool Load(CBinaryFile &file);
	virtual bool Save(CBinaryFile &file);
	virtual bool IsFolder(){return true;};
	virtual bool LoadItem(LPCTSTR lpszPath, bool addFileParam = true);
	virtual UINT64 GetBufSize(bool bUseAdditionalParam = true);
	virtual bool SaveToBuf(CaplSignBuf &signBuf, bool bUseAdditionalParam = true);
	virtual bool LoadFromBuf(BYTE *pBuf, int &index);
	virtual bool SaveFiles(LPCTSTR lpszPathName = NULL);
};

class APL_WIN_ETD_CLASS_EXPORT CFileDataSet : public CDataSet
{
public:
	CFileDataSet(CaplPacket *pPacket, CDataSet *pParent = NULL, bool bANSI = true);
	virtual ~CFileDataSet();

	char*	m_pData;   // При хранении данных во временном файле равен нулю, но m_DataSize>0
	UINT32	m_DataSize;

	// Большие файлы хранятся не в памяти, а во временных файлах.
	
	CString m_sTempDataFile; // Полное имя временного файла с данными
	
	virtual void Clear();
	virtual bool Load(CBinaryFile &file);
	virtual bool Save(CBinaryFile &file);
	virtual bool View(CString &sPathName, HANDLE &hProc);
	virtual bool LoadItem(LPCTSTR lpszPath, bool addFileParam = true);
	virtual UINT64 GetBufSize(bool bUseAdditionalParam = true);
	virtual bool SaveToBuf(CaplSignBuf &signBuf, bool bUseAdditionalParam = true); // Сохраняет в буфер для ЭЦП
	virtual bool LoadFromBuf(BYTE *pBuf, int &index);
	virtual bool SaveFiles(LPCTSTR lpszPathName = NULL);	
	virtual bool SaveContentToFile(LPCTSTR lpszPathName); // Сохраняет в конкретный файл. lpszPathName не должно быть пустым
};

class APL_WIN_ETD_CLASS_EXPORT CSignSert
{
protected:
	CaplPacket	*m_pPacket;
public:
	CSignSert(CaplPacket	*pPacket);
	virtual ~CSignSert();

	CString m_sPersonName;
	CString m_sCertBS;
	CString m_sCertSN;	

	virtual bool Load(CBinaryFile &file);
	virtual void Save(CBinaryFile &file);
	virtual UINT64 GetBufSize(bool bUseAdditionalParam = true);
	virtual bool SaveToBuf(CaplSignBuf &signBuf, bool bUseAdditionalParam = true);
	virtual bool LoadFromBuf(BYTE *pBuf, int &index);
};

class APL_WIN_ETD_CLASS_EXPORT CDataSetSign
{
protected:
	CaplPacket	*m_pPacket;
public:
	CDataSetSign(CaplPacket *pPacket);
	~CDataSetSign();
	
	CDataSet	*m_pDataSet;
	CSignSert	*m_pSertificate;
	
	CString		m_sStatus;
	CString		m_sRole;
	CString		m_sDate;
	CString		m_sComment;
	
	CString		m_sHashSystem;
	CString		m_sHashBS;
	
	CString		m_sSignSystem;
	CString		m_sSignBS;

	bool		m_bNewSign;

	bool Load(CBinaryFile &file, int ds_offset = 0, int sert_offset = 0);
	bool Save(CBinaryFile &file);
	virtual UINT64 GetBufSize(bool bUseAdditionalParam = true);
	virtual bool SaveToBuf(CaplSignBuf &signBuf, bool bUseAdditionalParam = true);
	virtual bool LoadFromBuf(BYTE *pBuf, int &index, int ds_offset = 0, int sert_offset = 0);
};

class APL_WIN_ETD_CLASS_EXPORT CaplPacket  
{
	friend class CDataSet;
	friend class CFolderDataSet;
	friend class CFileDataSet;
	friend class CDataSetSign;
protected:
	CArray<CDataSet*, CDataSet*>	m_DataSets;

	//идет работа с файлом ansi (true) или unicode (false)
	bool m_global_ansi_string;

public:
	void Clear();
	CaplPacket();
	virtual ~CaplPacket();

	UINT Load(LPCTSTR lpszPathName);
	bool Save(LPCTSTR lpszPathName);
	bool SaveAsFiles(LPCTSTR lpszPathName, CStringArray *sFiles);
	int CheckSigns(bool bShowMessages);
	int GetDSCount() {return m_DataSets.GetSize();};

	CDataSet	*m_pRootDataSet;
	CString		m_sId;
	CString		m_sDescr;
	CString		m_sProviderCode;
	CString		m_sLoadState;

	CArray<CSignSert*, CSignSert*>	m_Sertificates;
	CArray<CDataSetSign*,CDataSetSign*> m_DataSetSigns;

	bool IsANSI() { return m_global_ansi_string; }
	void SetANSI(bool bANSI);
};


// Класс предназначен для подготовки буфера для подписи
// До определенного момента данные накапливаются в памяти и возвращает адрес в памяти
// При превышении лимита данные пишутся в файл и возвращает имя файла 
// (так как это надо для функций ЭЦП
// Даже при использовании файла, данные всё равно накапливаются в памяти,
// И записываются в файл помере заполнения буфера.

class APL_WIN_ETD_CLASS_EXPORT CaplSignBuf
{
public:
	CaplSignBuf();
	virtual ~CaplSignBuf();
	void Clear();  // Очистка буфера

	// Функции для ипользования при подписи
	UINT32 GetDataSize(); // Возвращает размер буфера, если буфер в памяти, и 0, если в файле
	BYTE *GetData();     // Возвращает указатель на буфер с данными или именем

	UINT64 GetAllDataSize(); // Возвращаетр размер всех данных

	// Функции добавления в буфер
	bool Add(char c);   // Добавляет в буфер символ
	bool Add(UINT32 i); // Добавляет в буфер число
	bool Add(CString &str,  bool bANSI = true);  // Добавляет в буфер строку

	//inline bool Add(int i){return Add((UINT32)i);};  

	bool Add(BYTE *addData, UINT32 addDataSize); // Основная функция добавления массива данных
	bool AddFile(LPCTSTR sFilePath);      // Добавляет в буфер содержимое файла

protected:

	UINT64 m_DataAllSize;  // Текущий размер данных (память + данные в файле)
	
	BYTE *m_pBuf;       // Текущий буффер
	UINT32 m_BufSize;   // Текущий размер буфера в памяти
	UINT32 m_DataInBufSize;  // Текущий размер данных в буфере (без файла равен m_DataSize);
	
	bool m_bFileMode;    // Режим хранения данных в файле. Вклчается при превышении лимита памяти.
	CString m_sDataFile; // Полный путь к файлу с данными

	bool Flush();  // Скидыает текущий буфер в памяти в файл. Вызывает SaveDataToFile

	bool SaveDataToFile(BYTE *addData, UINT32 addDataSize); // Записывает данные в файл, который создает если надо

};


#endif // !defined(AFX_APLapl_packet_H__D13DB883_42AD_48CC_9E77_6416CCB5EDBD__INCLUDED_)
