添加自定义加密方法
CRC32.h
#pragma once
class CRC32
{
public:
CRC32(void);
public:
~CRC32(void);
static unsigned GetDataCRC32( const void*pData, unsigned dwSize, unsigned dwDefaultCRC );
};
CRC32.cpp
#include "CRC32.h"
//CRC表提取自zlib, crc32.h
static const unsigned long CRCTable32[256] =
{
0x00000000UL, 0x77073096UL, 0xee0e612cUL, 0x990951baUL, 0x076dc419UL,
0x706af48fUL, 0xe963a535UL, 0x9e6495a3UL, 0x0edb8832UL, 0x79dcb8a4UL,
0xe0d5e91eUL, 0x97d2d988UL, 0x09b64c2bUL, 0x7eb17cbdUL, 0xe7b82d07UL,
0x90bf1d91UL, 0x1db71064UL, 0x6ab020f2UL, 0xf3b97148UL, 0x84be41deUL,
0x1adad47dUL, 0x6ddde4ebUL, 0xf4d4b551UL, 0x83d385c7UL, 0x136c9856UL,
0x646ba8c0UL, 0xfd62f97aUL, 0x8a65c9ecUL, 0x14015c4fUL, 0x63066cd9UL,
0xfa0f3d63UL, 0x8d080df5UL, 0x3b6e20c8UL, 0x4c69105eUL, 0xd56041e4UL,
0xa2677172UL, 0x3c03e4d1UL, 0x4b04d447UL, 0xd20d85fdUL, 0xa50ab56bUL,
0x35b5a8faUL, 0x42b2986cUL, 0xdbbbc9d6UL, 0xacbcf940UL, 0x32d86ce3UL,
0x45df5c75UL, 0xdcd60dcfUL, 0xabd13d59UL, 0x26d930acUL, 0x51de003aUL,
0xc8d75180UL, 0xbfd06116UL, 0x21b4f4b5UL, 0x56b3c423UL, 0xcfba9599UL,
0xb8bda50fUL, 0x2802b89eUL, 0x5f058808UL, 0xc60cd9b2UL, 0xb10be924UL,
0x2f6f7c87UL, 0x58684c11UL, 0xc1611dabUL, 0xb6662d3dUL, 0x76dc4190UL,
0x01db7106UL, 0x98d220bcUL, 0xefd5102aUL, 0x71b18589UL, 0x06b6b51fUL,
0x9fbfe4a5UL, 0xe8b8d433UL, 0x7807c9a2UL, 0x0f00f934UL, 0x9609a88eUL,
0xe10e9818UL, 0x7f6a0dbbUL, 0x086d3d2dUL, 0x91646c97UL, 0xe6635c01UL,
0x6b6b51f4UL, 0x1c6c6162UL, 0x856530d8UL, 0xf262004eUL, 0x6c0695edUL,
0x1b01a57bUL, 0x8208f4c1UL, 0xf50fc457UL, 0x65b0d9c6UL, 0x12b7e950UL,
0x8bbeb8eaUL, 0xfcb9887cUL, 0x62dd1ddfUL, 0x15da2d49UL, 0x8cd37cf3UL,
0xfbd44c65UL, 0x4db26158UL, 0x3ab551ceUL, 0xa3bc0074UL, 0xd4bb30e2UL,
0x4adfa541UL, 0x3dd895d7UL, 0xa4d1c46dUL, 0xd3d6f4fbUL, 0x4369e96aUL,
0x346ed9fcUL, 0xad678846UL, 0xda60b8d0UL, 0x44042d73UL, 0x33031de5UL,
0xaa0a4c5fUL, 0xdd0d7cc9UL, 0x5005713cUL, 0x270241aaUL, 0xbe0b1010UL,
0xc90c2086UL, 0x5768b525UL, 0x206f85b3UL, 0xb966d409UL, 0xce61e49fUL,
0x5edef90eUL, 0x29d9c998UL, 0xb0d09822UL, 0xc7d7a8b4UL, 0x59b33d17UL,
0x2eb40d81UL, 0xb7bd5c3bUL, 0xc0ba6cadUL, 0xedb88320UL, 0x9abfb3b6UL,
0x03b6e20cUL, 0x74b1d29aUL, 0xead54739UL, 0x9dd277afUL, 0x04db2615UL,
0x73dc1683UL, 0xe3630b12UL, 0x94643b84UL, 0x0d6d6a3eUL, 0x7a6a5aa8UL,
0xe40ecf0bUL, 0x9309ff9dUL, 0x0a00ae27UL, 0x7d079eb1UL, 0xf00f9344UL,
0x8708a3d2UL, 0x1e01f268UL, 0x6906c2feUL, 0xf762575dUL, 0x806567cbUL,
0x196c3671UL, 0x6e6b06e7UL, 0xfed41b76UL, 0x89d32be0UL, 0x10da7a5aUL,
0x67dd4accUL, 0xf9b9df6fUL, 0x8ebeeff9UL, 0x17b7be43UL, 0x60b08ed5UL,
0xd6d6a3e8UL, 0xa1d1937eUL, 0x38d8c2c4UL, 0x4fdff252UL, 0xd1bb67f1UL,
0xa6bc5767UL, 0x3fb506ddUL, 0x48b2364bUL, 0xd80d2bdaUL, 0xaf0a1b4cUL,
0x36034af6UL, 0x41047a60UL, 0xdf60efc3UL, 0xa867df55UL, 0x316e8eefUL,
0x4669be79UL, 0xcb61b38cUL, 0xbc66831aUL, 0x256fd2a0UL, 0x5268e236UL,
0xcc0c7795UL, 0xbb0b4703UL, 0x220216b9UL, 0x5505262fUL, 0xc5ba3bbeUL,
0xb2bd0b28UL, 0x2bb45a92UL, 0x5cb36a04UL, 0xc2d7ffa7UL, 0xb5d0cf31UL,
0x2cd99e8bUL, 0x5bdeae1dUL, 0x9b64c2b0UL, 0xec63f226UL, 0x756aa39cUL,
0x026d930aUL, 0x9c0906a9UL, 0xeb0e363fUL, 0x72076785UL, 0x05005713UL,
0x95bf4a82UL, 0xe2b87a14UL, 0x7bb12baeUL, 0x0cb61b38UL, 0x92d28e9bUL,
0xe5d5be0dUL, 0x7cdcefb7UL, 0x0bdbdf21UL, 0x86d3d2d4UL, 0xf1d4e242UL,
0x68ddb3f8UL, 0x1fda836eUL, 0x81be16cdUL, 0xf6b9265bUL, 0x6fb077e1UL,
0x18b74777UL, 0x88085ae6UL, 0xff0f6a70UL, 0x66063bcaUL, 0x11010b5cUL,
0x8f659effUL, 0xf862ae69UL, 0x616bffd3UL, 0x166ccf45UL, 0xa00ae278UL,
0xd70dd2eeUL, 0x4e048354UL, 0x3903b3c2UL, 0xa7672661UL, 0xd06016f7UL,
0x4969474dUL, 0x3e6e77dbUL, 0xaed16a4aUL, 0xd9d65adcUL, 0x40df0b66UL,
0x37d83bf0UL, 0xa9bcae53UL, 0xdebb9ec5UL, 0x47b2cf7fUL, 0x30b5ffe9UL,
0xbdbdf21cUL, 0xcabac28aUL, 0x53b39330UL, 0x24b4a3a6UL, 0xbad03605UL,
0xcdd70693UL, 0x54de5729UL, 0x23d967bfUL, 0xb3667a2eUL, 0xc4614ab8UL,
0x5d681b02UL, 0x2a6f2b94UL, 0xb40bbe37UL, 0xc30c8ea1UL, 0x5a05df1bUL,
0x2d02ef8dUL
};
CRC32::CRC32(void)
{
}
CRC32::~CRC32(void)
{
}
unsigned CRC32::GetDataCRC32( const void*pData, unsigned dwSize, unsigned dwDefaultCRC )
{
if( !pData )
{
return 0;
}
const unsigned char*pByteData = ( const unsigned char*)pData;
unsigned dwCRC = dwDefaultCRC;
for( unsigned i=0; i<dwSize; i++ )
{
dwCRC = ( dwCRC << 8 ) ^ CRCTable32[ (dwCRC >> 24) ^ (*pByteData++) ];
}
return dwCRC;
}
QuickCryptor.h
#pragma once
#include <stdio.h>
class CQuickCryptor
{
public:
CQuickCryptor(void);
public:
~CQuickCryptor(void);
//初始化加密器
void Init( const char*szPassword );
//加密
void Encrypt( void*pData, size_t Size );
//解密
void Decrypt( void*pData, size_t Size );
private:
int NextValue( int & Seed );
private:
int m_SeedValue; //加密种子
};
QuickCryptor.cpp
#include "QuickCryptor.h"
#include "CRC32.h"
#include <string.h>
CQuickCryptor::CQuickCryptor(void)
{
m_SeedValue = 0;
}
CQuickCryptor::~CQuickCryptor(void)
{
}
void CQuickCryptor::Init(const char*szPassword )
{
m_SeedValue = 0;
if( szPassword )
{
m_SeedValue = CRC32::GetDataCRC32( szPassword, strlen( szPassword ), 0 );
}
}
int CQuickCryptor::NextValue( int &Seed )
{
//模拟一下C运行库的rand这个算法
//保证我们用固定的种子生成固定的下一个值
return ( ( ( Seed = Seed * 214013L + 2531011L) >> 16) & 0xffff );
}
void CQuickCryptor::Encrypt(void*pData, size_t Size )
{
//加密处理,我们把种子生成的值不断的去做变换
int Seed = m_SeedValue;
unsigned char*pByteData = (unsigned char*)pData;
for( size_t i=0; i<Size; i++ )
{
int Value = pByteData[i] + ( NextValue( Seed ) & 0xFF );
//加上一个种子生成的值(0-255)
if( Value > 255 )
{
Value -= 256;
}
pByteData[i] = Value;
}
}
void CQuickCryptor::Decrypt(void*pData, size_t Size )
{
//解密处理,我们把种子生成的值不断的去做变换
int Seed = m_SeedValue;
unsigned char*pByteData = (unsigned char*)pData;
for( size_t i=0; i<Size; i++ )
{
//由于加密我们做加法,解密我们就做减法
int Value = pByteData[i] - ( NextValue( Seed ) & 0xFF );
if( Value < 0 )
{
Value += 256;
}
pByteData[i] = Value;
}
}
NewPackage.h
#ifndef NEWPACKAGE_H_
#define NEWPACKAGE_H_
#include <stdio.h>
#include <errno.h>
#include <stdlib.h>
#include <string.h>
#include <vector>
#include <string>
#include "QuickCryptor.h"
class CFileBuffer
{
public:
CFileBuffer():m_pBuffer(nullptr),m_nSize(0)
{
}
~CFileBuffer()
{
Destroy();
}
//创建一块内存
bool Create(size_t Size)
{
Destroy();
m_pBuffer = malloc(Size);
if(!m_pBuffer)
{
return false;
}
m_nSize = Size;
return true;
}
//销毁一块内存
void Destroy()
{
if(m_pBuffer)
{
free(m_pBuffer);
m_pBuffer = nullptr;
}
m_nSize = 0;
}
//获取申请内存地址
void* GetBuffer()const
{
return m_pBuffer;
}
//获取申请内存大小
size_t GetSize()const
{
return m_nSize;
}
//将内存写入到磁盘文件
bool Save(const char* szFileName)
{
//检查m_pBuffer是否为空,如果为空,表示当前指针没有指向任何数据,不需要写入
if(!m_pBuffer)
return false;
//以二进制写的方式打开文件,准备写入文件
FILE* fp = fopen(szFileName, "wb");
if(!fp)
{
fprintf(stderr, "fopen %s error : %s \n",szFileName, strerror(errno));
}
//开始写入文件
if(m_nSize != fwrite(m_pBuffer, 1, m_nSize, fp))
{
fclose(fp);
return false;
}
fclose(fp);
return true;
}
private:
void* m_pBuffer;
size_t m_nSize;
};
struct NewPackageItem
{
size_t FileNameLen; //文件名的长度
size_t FileSize; //文件的大小
size_t OffsetPackage; //文件在包裹的偏移位置
char FileName[0]; //可变文件名
};
//我们定义一个标识,表示这个是我们的包裹格式
static const char MY_PACKAGE_FLAG[] = "NewPackage";
static const size_t MY_ENCRYPT_METHOD_XOR = 0; //xor加密
static const size_t MY_ENCRYPT_METHOD_EASY = 0; //自定义的简单的快速加密
struct PackageInfo
{
size_t EncryptMethod; //加密算法
};
class CNewPackage
{
public:
CNewPackage();
~CNewPackage();
//重置一个包裹
void ResetPackage( );
//读取一个包裹
bool OpenPackage( const char*szPackageName, const char*szPassword);
//添加一个文件,忽略大小写
bool AddFile( const char*szFileName );
//删除一个文件,忽略大小写
bool RemoveFile( const char*szFileName );
//重复性检查,忽略大小写
bool HasFile( const char*szFileName );
//保存包裹到指定文件名
bool SavePackage( const char*szPackageName, const char*szPassword);
//导出文件数据到FileBuffer里面
bool ExportPackageItem( const char*szFileName, CFileBuffer & FileBuffer );
private:
FILE* m_fpPackage; //包裹文件指针
CQuickCryptor m_Cryptor; //操作加密解密的对象
std::vector<std::string> m_AddFiles; //待添加到包裹的文件
std::vector<NewPackageItem*> m_PackageItems; //已经打包到包裹的文件信息
};
#endif // !NEWPACKAGE_H_
NewPackage.cpp
#include "NewPackage.h"
/*
┌------------┬-------------┬-------------┬------┬--------┬-------┬-------┐
├ size_t n │ Item │ Item │. . . │ FILE1 │ FILE1 │ . . . │
└------------┴-------------┴-------------┴------┴--------┴-------┴-------┘
┌-----------┬-----------┬--------┬-----------┬-----------┬------┬--------┬-------┬-------┐
├ size_t n │PackageItem│FileName│PackageItem│ FileName │. . . │ FILE1 │ FILE1 │ . . . │
└-----------┴-----------┴--------┴-----------┴-----------┴------┴--------┴-------┴-------┘
*/
struct FileItemForWrite
{
FILE *fp; //要打包的文件的文件指针
size_t FileOffset; //在文件中的偏移位置
size_t FileSize; //要读取的文件的大小
std::string FileName; //要读取的文件的文件名
NewPackageItem *pPackageItem; //要读取的文件基本信息
};
CNewPackage::CNewPackage()
{
m_fpPackage = nullptr;
}
CNewPackage::~CNewPackage()
{
ResetPackage();
}
void CNewPackage::ResetPackage()
{
for (size_t i = 0; i < m_PackageItems.size(); i++)
{
NewPackageItem *pItem = m_PackageItems[i];
free(pItem);
}
//clear是为了清除vector内部的index,size;如果不清除,这两个值会一直增加
m_PackageItems.clear();
//关闭包裹文件指针
if (m_fpPackage)
{
fclose(m_fpPackage);
m_fpPackage = nullptr;
}
//清理待添加的文件容器
m_AddFiles.clear();
}
bool CNewPackage::AddFile(const char *szFileName)
{
//如果有同名的,做替换处理
RemoveFile(szFileName);
m_AddFiles.push_back(szFileName);
return true;
}
bool CNewPackage::RemoveFile(const char *szFileName)
{
//从待添加的文件查找
for (size_t i = 0; i < m_AddFiles.size(); i++)
{
if (strcasecmp(m_AddFiles[i].c_str(), szFileName) == 0)
{
m_AddFiles.erase(m_AddFiles.begin() + i);
return true;
}
}
//从包裹文件中查找
for (size_t i = 0; i < m_PackageItems.size(); i++)
{
NewPackageItem *pItem = m_PackageItems[i];
if (strcasecmp(pItem->FileName, szFileName))
{
m_PackageItems.erase(m_PackageItems.begin() + i);
return true;
}
}
}
bool CNewPackage::HasFile(const char *szFileName)
{
//从待添加的文件查找
for (size_t i = 0; i < m_AddFiles.size(); i++)
{
if (strcasecmp(m_AddFiles[i].c_str(), szFileName) == 0)
{
return true;
}
}
//从包裹文件中查找
for (size_t i = 0; i < m_PackageItems.size(); i++)
{
NewPackageItem *pItem = m_PackageItems[i];
if (strcasecmp(pItem->FileName, szFileName) == 0)
{
return true;
}
}
}
inline size_t NewPackageEncryptWrite( CQuickCryptor & Cryptor, const void*pBuffer, size_t Size, FILE*fp )
{
unsigned char*pByteBuffer = (unsigned char*)malloc( Size );
if( !pByteBuffer )
{
return 0;
}
memcpy( pByteBuffer, pBuffer, Size );
Cryptor.Encrypt( pByteBuffer, Size );
size_t WriteSize = fwrite( pByteBuffer, 1, Size, fp );
free( pByteBuffer );
return WriteSize;
}
inline size_t NewPackageDecryptRead( CQuickCryptor & Cryptor, void*pBuffer, size_t Size, FILE*fp )
{
size_t ReadSize = fread( pBuffer, 1, Size, fp );
Cryptor.Decrypt( pBuffer, ReadSize );
return ReadSize;
}
bool CNewPackage::SavePackage(const char *szPackageName, const char*szPassword)
{
FILE *fpPackage = fopen(szPackageName, "wb");
if (!fpPackage)
{
fprintf(stderr, " fopen %s error %s \n", szPackageName, strerror(errno));
return false;
}
CQuickCryptor Crptor;
Crptor.Init(szPassword);
//写入文件头标识
if( sizeof( MY_PACKAGE_FLAG ) != NewPackageEncryptWrite(Crptor, MY_PACKAGE_FLAG, sizeof( MY_PACKAGE_FLAG ), fpPackage ) )
{
fprintf(stderr, " 写入文件头信息失败 error %s \n", strerror(errno));
return false;
}
PackageInfo Info;
Info.EncryptMethod = MY_ENCRYPT_METHOD_XOR;
if( sizeof( Info ) != NewPackageEncryptWrite(Crptor, &Info, sizeof( Info ), fpPackage ) )
{
fprintf(stderr, " 写入文件信息 error %s \n", strerror(errno));
return false;
}
//将包裹中原有的文件 和 待添加的文件 全部放入这个WriteItems中
std::vector<FileItemForWrite> WriteItems;
//预留一个sizeof(size_t)的大小,TotalHeadIndexSize是n个PackageItem所占的字节数
size_t TotalHeadIndexSize = sizeof(size_t);
//处理待添加的文件
for (size_t i = 0; i < m_AddFiles.size(); i++)
{
FILE *fpRead = fopen(m_AddFiles[i].c_str(), "rb");
if (!fpRead)
{
fprintf(stderr, "fopen %s error %s \n", m_AddFiles[i].c_str(), strerror(errno));
return false;
}
fseek(fpRead, 0, SEEK_END);
//填充FileItemForWrite信息
FileItemForWrite Item;
Item.fp = fpRead;
Item.FileOffset = 0;
Item.FileSize = ftell(fpRead);
Item.FileName = m_AddFiles[i];
size_t FileNameLen = Item.FileName.length() + 1;
//申请一块内存存放文件的头部信息
NewPackageItem *pNewItem = (NewPackageItem *)malloc(sizeof(NewPackageItem) + FileNameLen);
if (!pNewItem)
{
continue;
}
Item.pPackageItem = pNewItem;
//填充文件的头部信息
pNewItem->FileNameLen = FileNameLen;
pNewItem->FileSize = Item.FileSize;
strcpy(pNewItem->FileName, m_AddFiles[i].c_str());
//更新TotalHeadIndexSize的大小
TotalHeadIndexSize += sizeof(NewPackageItem) + FileNameLen;
//将待写入的文件添加到容器中
WriteItems.push_back(Item);
}
//处理原来包裹中已经存在的文件
for (size_t i = 0; i < m_PackageItems.size(); i++)
{
NewPackageItem *pItem = m_PackageItems[i];
FileItemForWrite Item;
Item.fp = m_fpPackage;
Item.FileOffset = pItem->OffsetPackage;
Item.FileSize = pItem->FileSize;
Item.FileName = pItem->FileName;
size_t FileNameLen = Item.FileName.length();
NewPackageItem *pNewItem = (NewPackageItem *)malloc(sizeof(NewPackageItem) + FileNameLen);
if (!pNewItem)
{
continue;
}
Item.pPackageItem = pNewItem;
pNewItem->FileNameLen = FileNameLen;
pNewItem->FileSize = Item.FileSize;
strcpy(pNewItem->FileName, Item.FileName.c_str());
TotalHeadIndexSize += sizeof(NewPackageItem) + pNewItem->FileNameLen;
WriteItems.push_back(Item);
}
//有多少个PackageItem
size_t TotalPackageItems = WriteItems.size();
//开始写入文件
if( sizeof( TotalPackageItems ) != NewPackageEncryptWrite(Crptor, &TotalPackageItems, sizeof( TotalPackageItems ), fpPackage ) )
{
fprintf(stderr, "fwrite %lu error %s \n ", TotalPackageItems, strerror(errno));
return false;
}
//记录当前的文件指针位置
size_t IndexOffset = ftell(fpPackage);
//预留TotalHeadIndexSize的空间供索引写入
fseek(fpPackage, TotalHeadIndexSize, SEEK_SET);
//先写入文件
bool bError = false;
size_t CurOffset = TotalHeadIndexSize;
for (size_t i = 0; i < WriteItems.size(); i++)
{
FileItemForWrite &Item = WriteItems[i];
if (bError == false)
{
//填充偏移信息
Item.pPackageItem->OffsetPackage = CurOffset;
//更新偏移信息
CurOffset += Item.FileSize;
//将要写入的文件的文件指针移动到文件头
fseek(Item.fp, Item.FileOffset, SEEK_SET);
char szBuffer[65536];
size_t LeftSize = Item.FileSize;
while (1)
{
//实际要读取的大小
size_t ReadSize = LeftSize;
//如果大于缓冲区,我们就只读取缓冲区大小的内容,剩余的下次读取
if (ReadSize > sizeof(szBuffer))
{
ReadSize = sizeof(szBuffer);
}
//读取文件
size_t nReadBytes = fread(szBuffer, 1, ReadSize, Item.fp);
//ReadSize必须要等于nReadBytes
if (ReadSize != nReadBytes)
{
fprintf(stderr, "读取 %s 失败 %s\n",Item.FileName.c_str(), strerror(errno));
bError = true;
break;
}
//写入包裹
if( nReadBytes != NewPackageEncryptWrite(Crptor, szBuffer, nReadBytes, fpPackage ) )
{
fprintf(stderr, "读取 %s 失败 %s\n",szPackageName, strerror(errno));
bError = true;
break;
}
LeftSize -= nReadBytes;
//如果剩余大小为0,就读取完成了
if (LeftSize == 0)
{
break;
}
}
}
//关闭需要打包的文件
if (Item.fp != m_fpPackage)
{
fclose(Item.fp);
Item.fp = NULL;
}
}
//如果没错误,写入索引
if (!bError)
{
fseek(fpPackage, IndexOffset, SEEK_SET);
for (size_t i = 0; i < WriteItems.size(); i++)
{
FileItemForWrite &Item = WriteItems[i];
NewPackageItem *pItem = Item.pPackageItem;
if (!bError)
{
//加密写入,我们先写入文件名长度
if( sizeof( pItem->FileNameLen ) != NewPackageEncryptWrite( Crptor, &pItem->FileNameLen, sizeof( pItem->FileNameLen ), fpPackage ) )
{
printf( "写入%s失败,打包失败\n", szPackageName );
bError = true;
}
if( !bError )
{
//写入剩余的内容
int WriteSize = sizeof( NewPackageItem ) + pItem->FileNameLen - sizeof( pItem->FileNameLen );
if( WriteSize != NewPackageEncryptWrite( Crptor, ((unsigned char*)pItem) + sizeof( pItem->FileNameLen ), WriteSize, fpPackage ) )
{
printf( "写入%s失败,打包失败\n", szPackageName );
bError = true;
}
}
}
free(pItem);
}
}
fclose(fpPackage);
return !bError;
}
bool CNewPackage::OpenPackage(const char *szPackageName, const char*szPassword)
{
ResetPackage();
m_Cryptor.Init( szPassword );
m_fpPackage = fopen(szPackageName, "rb");
if (!m_fpPackage)
{
fprintf(stderr, "打开 %s 失败 %s\n",szPackageName, strerror(errno));
return false;
}
//读入文件头标识
char FileFlag[ sizeof( MY_PACKAGE_FLAG ) ];
if( sizeof( MY_PACKAGE_FLAG ) != NewPackageDecryptRead(m_Cryptor, FileFlag, sizeof( FileFlag ), m_fpPackage ) )
{
fprintf(stderr, "读取文件头标识失败 %s\n", strerror(errno));
return false;
}
//判断一下我们读取到的文件头是否是我们定义的,做个最简单的格式判断
if( memcmp( FileFlag, MY_PACKAGE_FLAG, sizeof( FileFlag ) ) != 0 )
{
fprintf( stderr, "包裹%s格式错误\n", szPackageName );
return false;
}
PackageInfo Info;
if( sizeof( Info ) != NewPackageDecryptRead(m_Cryptor, &Info, sizeof( Info ), m_fpPackage ) )
{
fprintf( stderr, "读取%s失败 %s\n", szPackageName, strerror(errno));
return false;
}
if( Info.EncryptMethod != MY_ENCRYPT_METHOD_XOR )
{
fprintf( stderr, "无法识别%s的加密格式\n", szPackageName );
return false;
}
//先读取包裹中Item的个数
size_t PackageItemCount = 0;
if( sizeof( PackageItemCount ) != NewPackageDecryptRead(m_Cryptor, &PackageItemCount, sizeof( PackageItemCount ), m_fpPackage ) )
{
fprintf(stderr, "读取%s失败 %s\n", szPackageName, strerror(errno));
return false;
}
//根据读到的Item的个数遍历,把所有包裹中的文件放入m_PackageItems中
for (size_t i = 0; i < PackageItemCount; i++)
{
//先读取文件名的长度,因为文件名是变长的,方便后面申请内存
size_t FileNameLen = 0;
if( sizeof( FileNameLen ) != NewPackageDecryptRead(m_Cryptor, &FileNameLen, sizeof( FileNameLen ), m_fpPackage ) )
{
fprintf(stderr, "读取%s失败 %s\n", szPackageName, strerror(errno));
return false;
}
char *pBuffer = (char *)malloc(sizeof(NewPackageItem) + FileNameLen);
if (!pBuffer)
{
fprintf(stderr, "读取%s失败 %s\n", szPackageName, strerror(errno));
return false;
}
NewPackageItem *pItem = (NewPackageItem *)pBuffer;
pItem->FileNameLen = FileNameLen;
//我们已经读取FileNameLen了,所以剩余读取的部分减掉FileNameLen
size_t ReadSize = sizeof(NewPackageItem) + FileNameLen - sizeof(FileNameLen);
if( ReadSize != NewPackageDecryptRead(m_Cryptor, pBuffer + sizeof( FileNameLen ), ReadSize, m_fpPackage ) )
{
fprintf(stderr, "读取%s失败 %s\n", szPackageName, strerror(errno));
return false;
}
m_PackageItems.push_back(pItem);
}
return true;
}
bool CNewPackage::ExportPackageItem(const char *szFileName, CFileBuffer &FileBuffer)
{
//先从待添加的文件查找
for (size_t i = 0; i < m_AddFiles.size(); i++)
{
if (strcasecmp(m_AddFiles[i].c_str(), szFileName) == 0)
{
FILE *fp = fopen(szFileName, "rb");
if (!fp)
{
return false;
}
fseek(fp, 0, SEEK_END);
size_t Size = ftell(fp);
fseek(fp, 0, SEEK_SET);
//申请内存
if (!FileBuffer.Create(Size))
{
fclose(fp);
return false;
}
//把文件读入内存中
if (Size != fread(FileBuffer.GetBuffer(), 1, Size, fp))
{
fclose(fp);
return false;
}
return true;
}
}
//再从包裹文件中查找
for (size_t i = 0; i < m_PackageItems.size(); i++)
{
NewPackageItem *pItem = m_PackageItems[i];
if (strcasecmp(pItem->FileName, szFileName) == 0)
{
if (!FileBuffer.Create(pItem->FileSize))
{
return false;
}
fseek(m_fpPackage, pItem->OffsetPackage, SEEK_SET);
if( pItem->FileSize != NewPackageDecryptRead(m_Cryptor,FileBuffer.GetBuffer(), pItem->FileSize, m_fpPackage ) )
{
return false;
}
return true;
}
}
return false;
}
main.cpp
#include "NewPackage.h"
int main(void)
{
CNewPackage pkg;
pkg.AddFile( "test1.txt" );
pkg.AddFile( "test2.txt" );
pkg.AddFile( "test3.txt" );
pkg.SavePackage( "test.pkg","abcd");
pkg.RemoveFile( "test2.txt" );
pkg.SavePackage( "test1.pkg","abcd");
pkg.OpenPackage( "test1.pkg","abcd");
CFileBuffer bf;
pkg.ExportPackageItem( "test3.txt", bf );
bf.Save( "testout.txt" );
return 0;
}
来源:https://www.cnblogs.com/s3320/p/11935112.html