1.改进了频繁打开文件造成的资源浪费
CCEBFileEngine::CCEBFileEngine(LPCTSTR pszFileName)
{
if (!m_cebFile.Open(pszFileName, CFile::modeRead | CFile::shareDenyWrite))
return;
// CreateFileMapping
m_hMapFile = CreateFileMapping((HANDLE)(m_cebFile.m_hFile),0,PAGE_WRITECOPY,0,0,NULL);
if (m_hMapFile == NULL ||m_hMapFile == INVALID_HANDLE_VALUE)
{
return ;
}
m_pbFile = (LPBYTE)MapViewOfFile(m_hMapFile,FILE_MAP_COPY,0,0,0);
if (m_pbFile == NULL)
{
CloseHandle(m_hMapFile);
return ;
}
m_dwOriginFileSize = (DWORD)m_cebFile.GetLength();
memcpy(&m_cfh,m_pbFile,sizeof(CEBFILEHEADER));
char szCopyright[20];
memcpy(szCopyright, m_cfh.szHeaderInfo, 11);
szCopyright[11] = '\0';
if (strcmp(szCopyright, CEB_FILEHEADER_COPYRIGHT) != 0)
{
ASSERT(FALSE);
return;
}
m_strCopyright = szCopyright;
if (m_cfh.szHeaderInfo[11] == 0 && m_cfh.szHeaderInfo[12] == 0 && m_cfh.szHeaderInfo[13] == 0)
{
// 表明这是CEB 3.0或更高的版本。
m_nMajorVer = m_cfh.szHeaderInfo[CEBHEADER_MAJORVER_OFFSETPOS];
m_nMinorVer = m_cfh.szHeaderInfo[CEBHEADER_MINORVER_OFFSETPOS];
}
else
{
// 否则为CEB 3.0以前的版本。
char szVer[20];
memcpy(szVer, m_cfh.szHeaderInfo, 16);
szVer[16] = '\0';
CString strVer = szVer;
strVer = strVer.Right(4);
CString strMajor = strVer.Left(1);
CString strMinor = strVer.Right(2);
m_nMajorVer = (BYTE)_ttoi(strMajor);
m_nMinorVer = (BYTE)_ttoi(strMinor);
// 这里防止一些老版本的CEB却写着3.0的版本号而导致后续的错误。
if (m_nMajorVer >= 3)
m_nMajorVer = 2;
}
CEBINDEXITEM item;
for (int i = 0; i < m_cfh.wIndexCount; i++)
{
memcpy(&item,
m_pbFile + sizeof(CEBFILEHEADER) + i*sizeof(CEBINDEXITEM),
sizeof(CEBINDEXITEM));
m_aIndex.Add(item);
}
m_strFileName = pszFileName;
}
2.采用了PDFLib的dll的DLL2LIB后的静态库,整合到一个exe中,避免了发布程序的臃肿.
BOOL CEyueteuApp::InitInstance()
{
// const
// unsigned char sSource [13] = {
// 0x26, 0x22, 0x08, 0x77, 0x32, 0xC5, 0x00, 0x43, 0xF9, 0x74, 0x81, 0xEB, 0xB9
// };
// BYTE* pOutBuffer = NULL;
// long nBufLen = 0;
// DWORD dwRet = Base64Encode((const BYTE*)(LPCSTR)sSource, 13,0,
// &pOutBuffer, &nBufLen);
// free(pOutBuffer);
// SKINMAGICTRIAL_DllMain(GetModuleHandle(NULL), DLL_PROCESS_ATTACH, NULL);
// VERIFY( 1 == InitSkinMagicLib( AfxGetInstanceHandle(), "" ,
// NULL,
// NULL ) );
// VERIFY( 1 == LoadSkinFromResource(m_hInstance,MAKEINTRESOURCE(xpblue),_T("SKIN")));
// SetDialogSkin("Dialog");
PDFLIB_DllMain(GetModuleHandle(NULL), DLL_PROCESS_ATTACH, NULL);
3.界面采用XT12.0.0的静态库,挂接一个VISTA的皮肤,同样把皮肤内嵌进exe
CEyueteuDlg::CEyueteuDlg(CWnd* pParent /*=NULL*/)
: CDialog(CEyueteuDlg::IDD, pParent)
{
//{{AFX_DATA_INIT(CEyueteuDlg)
m_Range = 0;
m_Pos = 0;
m_strJobInfo = _T("0个文件已转换/0个文件待转换");
m_bBookName = TRUE;
m_strSavePath = _T("");
m_bLocal = TRUE;
m_bNoEncrypt = FALSE;
m_bOnline = FALSE;
m_bBookMake = TRUE;
m_bWater = TRUE;
m_bDemo = FALSE;
//}}AFX_DATA_INIT
// Note that LoadIcon does not require a subsequent DestroyIcon in Win32
m_hIcon = AfxGetApp()->LoadIcon(IDR_MAINFRAME);
m_pdwThreadId = NULL;
m_phThread = NULL;
m_arrStrFileName.RemoveAll();
m_dwJobCount = 0;
m_dwEndJobCount = 0;
#ifdef CEB2PDF
// 释放为临时文件加载
TCHAR szTempPath[_MAX_PATH];
GetTempPath(_MAX_PATH, szTempPath);
CString strSkinName = szTempPath;
strSkinName += _T("\\Vista.cjstyles");
// Load the user-defined resource.
HMODULE m_hInstance = AfxGetApp()->m_hInstance;
HRSRC hExeFile = ::FindResource(m_hInstance,MAKEINTRESOURCE(VISTA),_T("SKIN"));
HGLOBAL hRes = ::LoadResource(m_hInstance, hExeFile);
DWORD dwSize = ::SizeofResource(m_hInstance, hExeFile);
if (hRes != NULL)
{
UINT FAR* lpnRes = (UINT FAR*)::LockResource(hRes);
CFile file(strSkinName, CFile::modeCreate | CFile::modeWrite);
file.WriteHuge(lpnRes, dwSize);
file.Flush();
::FreeResource(hRes);
}
XTPSkinManager()->LoadSkin(strSkinName);
DeleteFile(strSkinName);
#endif
}
4.采用多线程解码以及更新界面现实
void CEyueteuDlg::OnOK()
{
VIRTUALIZER_MUTATE1_START
#ifndef CEB2PDF
::MessageBox(0,
"\n\n\nDemo版本只能转换部分未加密的ceb, . \n\n",
"注意",
MB_OK|MB_ICONWARNING);
#endif
UpdateData();
VIRTUALIZER_END
if (m_btnNew.GetCheck() == 1)
{
HANDLE hFile = NULL;
if (m_strSavePath.IsEmpty() ||
(hFile = CreateFile(m_strSavePath + "\\temp",
GENERIC_WRITE,
FILE_SHARE_WRITE,
NULL,
CREATE_ALWAYS,
FILE_ATTRIBUTE_NORMAL,
NULL)) == INVALID_HANDLE_VALUE)
{
MessageBox("保存路径错误,请重新选择或者输入!","错误");
m_strSavePath.Empty();
m_ctlEdit.SetFocus();
UpdateData(FALSE);
return;
}
else
{
CloseHandle(hFile);
DeleteFile(m_strSavePath + "\\temp");
}
}
m_strJobInfo = _T("0个文件已转换/0个文件待转换");
m_dwJobCount = 0;
m_dwEndJobCount = 0;
CString strFilter;
strFilter.LoadString(IDS_OPENFILE_FILTER);
CFileDialog *dlgFileOpen = new CFileDialog(TRUE,
_T("*.ceb"),
NULL,
OFN_ALLOWMULTISELECT|OFN_HIDEREADONLY|OFN_EXPLORER|OFN_FILEMUSTEXIST,
strFilter);
TCHAR *pszFileList = new TCHAR[MAXLENGTH_FILENAMEBUFFER];
dlgFileOpen->m_ofn.lpstrFile = pszFileList;
dlgFileOpen->m_ofn.lpstrFile[0] = _T('\0');
dlgFileOpen->m_ofn.nMaxFile = MAXLENGTH_FILENAMEBUFFER;
dlgFileOpen->m_ofn.lStructSize = sizeof(OPENFILENAME);
dlgFileOpen->m_ofn.Flags |= OFN_SHOWHELP;
if (dlgFileOpen->DoModal() == IDOK)
{
CString strFileName;
POSITION posFile = dlgFileOpen->GetStartPosition();
int nCount =0;
m_arrStrFileName.RemoveAll();
while (posFile)
{
strFileName = dlgFileOpen->GetNextPathName(posFile);
m_arrStrFileName.Add(strFileName);
nCount++;
}
m_dwJobCount = nCount;
m_dwEndJobCount = 0;
m_pdwThreadId = new DWORD[nCount];
m_phThread = new HANDLE[nCount];
PTHREADARG m_pArg;
for (int i = 0; i < nCount;i++)
{
m_pArg = new THREADARG;
m_pArg->dwThreadId = i;
m_pArg->pThis = this;
m_pArg->strFileName = m_arrStrFileName[i];
m_phThread[i] = CreateThread(
NULL, // default security attributes
0, // use default stack size
ThreadProc, // thread function
m_pArg, // argument to thread function
CREATE_SUSPENDED, // use default creation flags
&m_pdwThreadId[i]); // returns the thread identifier
// Check the return value for success.
if (m_phThread[i] == NULL)
{
ExitProcess(i);
}
SetThreadPriority(m_phThread[i],THREAD_PRIORITY_LOWEST);
ResumeThread(m_phThread[i]);
}
GetDlgItem(IDOK)->EnableWindow(FALSE);
GetDlgItem(IDCANCEL)->EnableWindow(FALSE);
m_Range = (short)m_dwJobCount;
m_ctlProgress.SetRange(0,m_Range);
m_strJobInfo.Format("%d个文件已转换/%d个文件待转换",m_dwEndJobCount,m_dwJobCount);
}
m_ctlProgress.SetStep(1);
m_ctlProgress.SetPos(0);
delete[] pszFileList;
delete dlgFileOpen;
UpdateData(FALSE);
Invalidate(FALSE);
}
DWORD WINAPI CEyueteuDlg::ThreadProc( LPVOID lpParam )
{
PTHREADARG pArg = (PTHREADARG)lpParam;
CString strFileName = pArg->strFileName;
CEyueteuDlg *pThis = pArg->pThis;
if(!pThis->OpenDoc(strFileName))
{
pThis->PostMessage(WM_ENDJOB,1,(LPARAM)lpParam);
}
else
pThis->PostMessage(WM_ENDJOB,0,(LPARAM)lpParam);
return 0;
}
LRESULT CEyueteuDlg::OnEndJobMessage(WPARAM wParam, LPARAM lParam)
{
PTHREADARG pArg = NULL;
switch(wParam)
{
case -2:
{
m_Pos = (int)lParam;
for (int i = 0; i < m_Pos;i++)
{
m_ctlProgress.StepIt();
}
return 0;
}
case -1:
m_Range += (short)lParam;
m_ctlProgress.SetRange(0,m_Range);
return 0;
case 1:
{
pArg = (PTHREADARG)lParam;
MessageBox(pArg->strFileName,"转换错误!",MB_OK|MB_ICONERROR);
}
break;
case 2:
{
CString str = (LPCSTR)lParam;
MessageBoxA(str,"创建文件失败!",MB_OK|MB_ICONERROR);
return 0;
}
case 3:
{
m_strJobInfo = "解码原始ceb数据......";
UpdateData(FALSE);
}
return 0;
case 4:
{
m_strJobInfo = " 生成pdf书签 ......";
UpdateData(FALSE);
}
return 0;
default:
break;
}
pArg = (PTHREADARG)lParam;
if (pArg)
{
CloseHandle(m_phThread[pArg->dwThreadId]);
delete pArg;
}
if(++m_dwEndJobCount == m_dwJobCount)
{
delete [] m_phThread;
m_phThread = NULL;
delete [] m_pdwThreadId;
m_pdwThreadId = NULL;
GetDlgItem(IDOK)->EnableWindow(TRUE);
GetDlgItem(IDCANCEL)->EnableWindow(TRUE);
}
m_strJobInfo.Format("%d个文件已转换/%d个文件待转换",m_dwEndJobCount,m_dwJobCount);
m_ctlProgress.StepIt();
UpdateData(FALSE);
// Invalidate(FALSE);
return 0;
}
5.手工增加水印和书签,这部分尤其自豪,曾经请教一个pdf高手,跟我要5万,经过长达15天的不断尝试各类pdf的sdk和lib,最终采用PDFLib的sdk完成.
// 添加书签和水印以及文档信息,采用PDFLib 7.0.3 注册版
/* create a new PDFlib object */
PDF *p = NULL;
char optlist[256] = {0};
char BookMakerName[256] = {0};
HGLOBAL hRes = 0;
unsigned char * imagedata;
int image;
if ((p = PDF_new()) == (PDF *) 0)
{
printf("Couldn't create PDFlib object (out of memory)!\n");
return(2);
}
PDF_TRY(p)
{
if (PDF_begin_document(p, (LPSTR)(LPCSTR)strPDFFileName, 0, ""/*compatibility=1.5*/) == -1)
{
printf("Error: %s\n", PDF_get_errmsg(p));
PDF_delete(p);
return(2);
}
// 设置文档 信息
if (m_strBookName.IsEmpty())
{
int nTemp = strPDFFileName.ReverseFind('\\');
nTemp = strPDFFileName.GetLength() - nTemp;
m_strBookName = strPDFFileName.Right(nTemp-1);
}
PDF_set_info(p, "Title", m_strBookName);
PDF_set_info(p, "Keywords", "此文档由ceb2pdf专业版3.9生成,详细信息请联系QQ:694285177");
PDF_create_pvf(p,
"ceb2pdf",
0,pBuffer,dwPDFDataLength,0);
// 添加水印
if (m_bWater)
{
HRSRC hExeFile = ::FindResource(AfxGetApp()->m_hInstance,MAKEINTRESOURCE(IDR_LOG),_T("log"));
hRes = ::LoadResource(AfxGetApp()->m_hInstance, hExeFile);
DWORD dwSize = ::SizeofResource(AfxGetApp()->m_hInstance, hExeFile);
if (hRes != NULL)
{
imagedata = (PBYTE)::LockResource(hRes);
}
PDF_create_pvf(p, "/pvf/image", 0, imagedata, dwSize, "");
/* Load the image from the PVF */
image = PDF_load_image(p, "auto", "/pvf/image", 0, "");
if (image == -1)
{
printf("Error: %s\n", PDF_get_errmsg(p));
PDF_delete(p);
if (imagedata)
{
free((void *) imagedata);
}
return(2);
}
}
int manual = PDF_open_pdi_document(p, "ceb2pdf", 0, "");
if (manual == -1)
{
printf("Error: %s\n", PDF_get_errmsg(p));
return(2);
}
/* Get the number of pages in the input document */
VMProtectBegin
UINT endpage = (int) PDF_pcos_get_number(p, manual, "/Root/Pages/Count");
if (m_bDemo)
{
endpage /= 5;
}
VMProtectEnd
UINT NodeID = 0; //
int ParentNodeID = 0;
PDF_set_parameter(p, "pdiwarning", "true");
if (pNodeList)
{
if (m_bBookMake)
{
#ifdef CEB2PDF
PostMessage(WM_ENDJOB,(WPARAM)-1,dwNodeCount);
#endif
PostMessage(WM_ENDJOB,(WPARAM)4,0);
}
}
for ( UINT pageno= 1; pageno <= endpage; pageno++)
{
int page = PDF_open_pdi_page(p, manual, pageno, "");
if (page == -1)
{
fprintf(stderr, "Error: %s\n", PDF_get_errmsg(p));
}
/* Dummy page size; will be adjusted later */
PDF_begin_page_ext(p, 10, 10, "");
// 添加水印
if (m_bWater)
{
PDF_fit_image(p, image, 0, 0, "scale 0.5");
}
// 添加书签
if (pNodeList)
{
if (m_bBookMake)
{
/* Create a bookmark with the file name */
while ((pNodeList+NodeID)->dwDestPage == pageno)
{
#ifdef CEB2PDF
PostMessage(WM_ENDJOB,(WPARAM)-2,1);
#endif
int ParentNodeID = (pNodeList+NodeID)->wParentNodeID;
sprintf(BookMakerName,"%s",(pNodeList+NodeID)->szText);
sprintf(optlist,
"parent=%d destination {type fixed} textcolor {rgb 0 0 0}",
ParentNodeID);
strPDFFileName = optlist;
if (!ParentNodeID)
{
strPDFFileName += " fontstyle=bold";
}
PDF_create_bookmark(p, BookMakerName, 0,(LPSTR)(LPCSTR)strPDFFileName);
NodeID++;
if (NodeID == dwNodeCount)
{
break;
}
}
}
}
/* Place the imported page on the output page, and
* adjust the page size
*/
PDF_fit_pdi_page(p, page, 0, 0, "adjustpage");
PDF_end_page_ext(p, "");
PDF_close_pdi_page(p, page);
}
if (m_bWater)
{
/* Delete the virtual file to free the allocated memory */
PDF_delete_pvf(p, "/pvf/image", 0);
::FreeResource(hRes);
}
PDF_close_pdi_document(p, manual);
PDF_end_document(p, "");
PDF_delete(p);
}
PDF_CATCH(p)
{
printf("PDFlib exception occurred in pdflib_cs2 sample:\n");
printf("[%d] %s: %s\n",
PDF_get_errnum(p), PDF_get_apiname(p), PDF_get_errmsg(p));
PDF_delete(p);
return(2);
}
delete [] pNodeList;
PostMessage(WM_ENDJOB,(WPARAM)-2,dwPDFDataLength/(1024*100) - nTemp);
bRet = TRUE;
}
BOOL CEyueteuDlg::OpenDoc(LPCTSTR pszFileName)
{
CATALOGNODE *pNodeList = FALSE;
DWORD dwNodeCount = 0;
BOOL bKeyExist = FALSE;
BOOL bAlgorithmIDExist = FALSE;
BOOL bRet = FALSE;
BYTE m_pPDFContentStreamKey[32] = {0};
int m_nPDFContentStreamKeyLength = 24;
DWORD m_dwPDFContentStreamAlgorithmID = 0;
VIRTUALIZER_MUTATE1_START
CCEBFileEngine cfe(pszFileName);
if (cfe.GetIndexCount() <= 0)
return FALSE;
// 查找PDF内容流stream的加密key和加密算法
CEBINDEXITEM itemEncryptKey;
CEBINDEXITEM itemEncryptAlgorithmID;
bKeyExist = cfe.FindIndexItem(CEB_INDEXTYPE_CSENCRYPTKEY, NULL, itemEncryptKey);
bAlgorithmIDExist = cfe.FindIndexItem(CEB_INDEXTYPE_CSENCRYPTALGORITHMID, NULL, itemEncryptAlgorithmID);
if (bKeyExist && bAlgorithmIDExist)
{
bRet = SetKeyFromCEBFile(cfe,
itemEncryptAlgorithmID,
itemEncryptKey,
m_nPDFContentStreamKeyLength,
m_dwPDFContentStreamAlgorithmID,
m_pPDFContentStreamKey);
}
else if (!bKeyExist && !bAlgorithmIDExist)
{
CEBINDEXITEM itemDRM;
BOOL bItemExist = FALSE;
bItemExist = cfe.FindIndexItem(CEB_INDEXTYPE_DRMMETHOD, NULL, itemDRM);
if (m_bOnline) // 在线浏览
bRet = SetKeyFromCEBVoucher_3(pszFileName,
m_nPDFContentStreamKeyLength,
m_dwPDFContentStreamAlgorithmID,
m_pPDFContentStreamKey);
else
{
BYTE* pDate = new BYTE[itemDRM.dwDataBlockLength];
memcpy(pDate,cfe.m_pbFile + itemDRM.dwOffsetPos,itemDRM.dwDataBlockLength);
if ((int)(*pDate) == 1) // 购买的图书
{
bRet = SetKeyFromCEBVoucher_1(pszFileName,
m_nPDFContentStreamKeyLength,
m_dwPDFContentStreamAlgorithmID,
m_pPDFContentStreamKey);
}
else if((int)(*pDate) == 2) // 借阅的图书
{
bRet = SetKeyFromCEBVoucher_2(pszFileName,
m_nPDFContentStreamKeyLength,
m_dwPDFContentStreamAlgorithmID,
m_pPDFContentStreamKey);
}
delete[] pDate;
}
}
if (!bRet)
{
cfe.Close();
return FALSE;
}
CEBINDEXITEM itemIndex;
DWORD dwPDFDataLength(0), dwPDFDataOffset(0);
DWORD dwRC4KeyLength(0), dwRC4KeyOffset(0);
BOOL bPDFDataExist = FALSE;
BOOL bRC4KeyExist = FALSE;
if (cfe.FindIndexItem(CEB_INDEXTYPE_PDFDATA, NULL, itemIndex))
{
dwPDFDataOffset = itemIndex.dwOffsetPos;
dwPDFDataLength = itemIndex.dwDataBlockLength;
bPDFDataExist = TRUE;
}
if (cfe.FindIndexItem(CEB_INDEXTYPE_RC4KEY, NULL, itemIndex))
{
dwRC4KeyOffset = itemIndex.dwOffsetPos;
dwRC4KeyLength = itemIndex.dwDataBlockLength;
bRC4KeyExist = TRUE;
}
// CreatePDFFile
bRet = FALSE;
if (bPDFDataExist && bRC4KeyExist)
{
CFile pdffile;
CString strPDFFileName = pszFileName;
// strPDFFileName.MakeLower();
// 保存到自定义目录
if (!m_strSavePath.IsEmpty())
{
int nTemp = strPDFFileName.GetLength() - strPDFFileName.ReverseFind('\\');
strPDFFileName = strPDFFileName.Right(nTemp);
strPDFFileName = m_strSavePath + strPDFFileName;
}
// 用ceb的内部书名替代原文件名
if (m_bBookName)
{
CEBBOOKINFOA bi;
if (cfe.GetBookInfo(bi))
{
if (lstrlen(bi.szBookTitle))
{
CString strTemp(bi.szBookTitle);
strTemp.Replace(0x2f,'_');
strTemp.Replace('\\','_');
strTemp.Replace(0x0a,'_');
strTemp.Replace(0x0d,'_');
m_strBookName = strTemp;
int nTemp = strPDFFileName.ReverseFind('\\');
strPDFFileName = strPDFFileName.Left(nTemp+1);
strPDFFileName += strTemp;
}
}
}
if (m_bNoEncrypt)
{
if (bKeyExist && bAlgorithmIDExist)
{
TCHAR szBuf[80];
wsprintf(szBuf,
"要转换的文件已经是未加密的!");
SendMessage(WM_ENDJOB,2,(LPARAM)(szBuf));
return TRUE;
}
strPDFFileName.Insert(strPDFFileName.ReverseFind('\\') + 1,"未加密_");
strPDFFileName += ".ceb";
}
else
{
strPDFFileName.TrimRight(".ceb");
strPDFFileName += ".pdf";
}
// strPDFFileName += ".pdf";
// 修改文件打开方式为禁止写!防止有的ceb内部文件名一样,创建同名文件而出现错误!
DeleteFile(strPDFFileName);
if (!pdffile.Open(strPDFFileName,
CFile::modeReadWrite|CFile::shareDenyWrite|CFile::modeCreate))
{
TCHAR szBuf[80];
LPVOID lpMsgBuf;
DWORD dw = GetLastError();
FormatMessage(
FORMAT_MESSAGE_ALLOCATE_BUFFER |
FORMAT_MESSAGE_FROM_SYSTEM,
NULL,
dw,
MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
(LPTSTR) &lpMsgBuf,
0, NULL );
wsprintf(szBuf,
"创建%s的PDF文件发生错误!\r错误号: %d\r错误信息: %s",
pszFileName,dw, lpMsgBuf);
LocalFree(lpMsgBuf);
SendMessage(WM_ENDJOB,2,(LPARAM)(szBuf));
cfe.Close();
return TRUE;
}
DWORD dwFileSize = cfe.m_cebFile.GetLength();
// #ifndef CEB2PDF
// if (dwFileSize > 1024*10000)
// {
// return FALSE;
// }
// #endif
// 转成未加密的ceb
if (m_bNoEncrypt)
{
#ifdef CEB2PDF
if (bKeyExist && bAlgorithmIDExist)
return FALSE;
// ceb Head
pdffile.Write(cfe.m_pbFile,16);
// 插件数据的新长度
DWORD dwTemp = DWORD(*(cfe.m_pbFile + 16));
dwTemp += 0x22;
pdffile.Write(&dwTemp,4);
// 插件的新数目
dwTemp = WORD(*(cfe.m_pbFile + 16 + 4));
dwTemp += 2;
pdffile.Write(&dwTemp,2);
// 插件数据,新增17 * 2 个字节,
// RC4 Key
ZeroMemory(&itemIndex,sizeof(itemIndex));
itemIndex.byIndexType = 4;
itemIndex.dwOffsetPos = dwFileSize + 17*2;
itemIndex.dwDataBlockLength = 64;
pdffile.Write(&itemIndex,17);
// 加密方法
ZeroMemory(&itemIndex,sizeof(itemIndex));
itemIndex.byIndexType = 5;
itemIndex.dwOffsetPos = dwFileSize + 17*2 + 64;
itemIndex.dwDataBlockLength = 4;
pdffile.Write(&itemIndex,17);
dwTemp = DWORD(*(cfe.m_pbFile + 16 + 4));
for (DWORD n = 0; n < dwTemp; n++)
{
memcpy(&itemIndex,cfe.m_pbFile + 22 +n*17,17);
itemIndex.dwOffsetPos += 17*2;
if (itemIndex.byIndexType ==0x0a)// 去掉DRM标识
{
itemIndex.byIndexType =0xFE;
}
pdffile.Write(&itemIndex,17);
}
// 原来的pdf内核数据
pdffile.Write(cfe.m_pbFile + 22 + dwTemp*17,dwFileSize- 22 - dwTemp*17 );
// 必须将密钥加密,否则不能在Reader中打印!
BYTE *pDecryptKey = NULL;
int nLen = 0;
if (!EncryptKey(m_pPDFContentStreamKey, 24, pDecryptKey, nLen))
{
// 加密出错
TCHAR szBuf[80];
wsprintf(szBuf,
"加密Key错误!");
SendMessage(WM_ENDJOB,2,(LPARAM)(szBuf));
return TRUE;
}
pdffile.Write(pDecryptKey,nLen);
m_dwPDFContentStreamAlgorithmID += 0x80000000;
pdffile.Write(&m_dwPDFContentStreamAlgorithmID,4);
free(pDecryptKey);
pdffile.Close();
cfe.Close();
return TRUE;
#endif
}
if (dwFileSize < dwRC4KeyOffset + dwRC4KeyLength
||dwFileSize < dwPDFDataOffset + dwPDFDataLength)
{
cfe.Close();
return FALSE;
}
VIRTUALIZER_END
BYTE* pRC4Key = NULL;
// 得到RC4密钥
pRC4Key = cfe.m_pbFile + dwRC4KeyOffset;
CRC4CryptoEngine objTmpRC4;
objTmpRC4.InitialRC4Crypto(pRC4Key, (BYTE)dwRC4KeyLength);
CRC4CryptoEngine objRC4;
int nTemp = dwPDFDataLength/(1024*100);
SendMessage(WM_ENDJOB,(WPARAM)-1,nTemp);
nTemp = 0;
LPBYTE pBuffer = cfe.m_pbFile + dwPDFDataOffset;
DWORD dwLen = 0,dwPDFLen = dwPDFDataLength;
int nCount = 0;
while (dwPDFLen > 0)
{
dwLen = 65536;
if (dwPDFLen < 65536)
{
dwLen = dwPDFLen;
}
memcpy(&objRC4, &objTmpRC4, sizeof(CRC4CryptoEngine));
objRC4.RC4Decrypt(pBuffer + nCount*65536, dwLen);
if (dwPDFDataLength < 65536)
{
break;
}
dwPDFLen -= dwLen;
nCount++;
}
// #if defined(_DEBUG)
// pdffile.Write(cfe.m_pbFile + dwPDFDataOffset,dwPDFDataLength);
// CString strTempFileName = pdffile.GetFileName();
// CopyFile(strTempFileName,strTempFileName + ".temp",0);
// #endif
// 解密stream和endstream之间的内容
PostMessage(WM_ENDJOB,(WPARAM)3,0);
DWORD dwStream = 0;
DWORD dwEndStream = 0;
BYTE *pDeCode = new BYTE[256];
while (1)
{
for (DWORD i = dwStream; i < dwPDFDataLength; i++)
{
if (pBuffer[i] == 's' && !memcmp(&pBuffer[i],"stream",6) &&
pBuffer[i-1] != 'd')
{
break;
}
}
if (i >= dwPDFDataLength)
{
break;
}
if (!i)
{
return FALSE;
}
dwStream = i;
for (i = dwStream; i < dwPDFDataLength; i++)
{
if (pBuffer[i] == 'e' && !memcmp(&pBuffer[i],"endstream",9) )
{
break;
}
}
if (!i)
{
return FALSE;
}
if (i >= dwPDFDataLength)
{
break;
}
dwEndStream = i;
while(1)
{
if(pBuffer[dwStream++ +6] == 0x0a)
{
break;
}
}
int nBufLen = dwEndStream-dwStream;
nBufLen -= 6;
DWORD m =0;
while(nBufLen>0)
{
int n=0;
if (nBufLen>256)
{
n = 256;
}
else
n = nBufLen;
EN_EncryptData(0,
m_dwPDFContentStreamAlgorithmID,
m_pPDFContentStreamKey,
m_nPDFContentStreamKeyLength,
&(pBuffer[dwStream+6+m*256]),
n,
pDeCode,
m_pPDFContentStreamKey,
m_nPDFContentStreamKeyLength);
memcpy(&(pBuffer[dwStream+6+m*256]),pDeCode,n);
nBufLen -= 256;
m++;
}
dwStream = dwEndStream+9;
DWORD nTemp1 = dwStream/(1024*100);
DWORD nTemp2 = nTemp1-nTemp;
nTemp = nTemp1;
if (nTemp2)
{
PostMessage(WM_ENDJOB,(WPARAM)-2,nTemp2);
}
}
delete[] pDeCode;
// 去掉PDF中的加密标示
dwPDFLen = dwPDFDataLength;
while (dwPDFLen--)
{
if (pBuffer[dwPDFLen]=='E'&&pBuffer[dwPDFLen+1]=='n')
{
dwPDFLen --;
break;
}
}
DWORD nEN_Start = dwPDFLen;
while (pBuffer[dwPDFLen++] != 0x0D)
{
;
}
DWORD nEN_End = dwPDFLen;
memcpy(&pBuffer[nEN_Start],&pBuffer[nEN_End],dwPDFDataLength-nEN_End);
dwPDFDataLength = dwPDFDataLength - nEN_End+nEN_Start;
// pdffile.SetLength(dwPDFDataLength);
// PDF 降版本,供后续程序操作
// pBuffer[7] = '4';
// pdffile.Seek(0,CFile::begin);
// pdffile.Write(pBuffer,dwPDFDataLength);
pdffile.Close();
[注意]传递专业知识、拓宽行业人脉——看雪讲师团队等你加入!