1875 lines
42 KiB
C
1875 lines
42 KiB
C
static KVMemoryStream g_MemoryAllocator =
|
|
{
|
|
NULL, myMalloc, myFree, myRealloc, myCalloc
|
|
};
|
|
|
|
|
|
/*******************************************************************************
|
|
*
|
|
* function: AutoDetectFile()
|
|
*
|
|
* summary: Print out the format informaton for a file.
|
|
*
|
|
******************************************************************************/
|
|
KVErrorCode AutoDetectFile(void *pContext, char *szFile)
|
|
{
|
|
ADDOCINFO DocInfo;
|
|
KVErrorCode eErr = KVERR_Success;
|
|
BOOL bVal;
|
|
string filename(szFile);
|
|
|
|
bVal = FilterFunc.fpGetDocInfoFile(pContext, szFile, &DocInfo);
|
|
|
|
if (!bVal || (DocInfo.eClass == AutoDetFail) ||
|
|
(DocInfo.eClass == AutoDetNoFormat))
|
|
{
|
|
if (DocInfo.eClass == AutoDetFail)
|
|
{
|
|
eErr = KVERR_AutoDetFail;
|
|
}
|
|
else
|
|
{
|
|
eErr = KVERR_AutoDetNoFormat;
|
|
}
|
|
goto slammer;
|
|
}
|
|
|
|
const size_t last_slash_idx = filename.find_last_of("\\/");
|
|
if (std::string::npos != last_slash_idx)
|
|
{
|
|
filename.erase(0, last_slash_idx + 1);
|
|
}
|
|
|
|
char metaVal[512] = { 0 };
|
|
sprintf(metaVal, "C:\\Program Files\\Tocsg\\eCrmHome\\conf\\ECRMHOMEDB\\tmp\\%s.meta", filename.c_str());
|
|
|
|
FILE *logfile = NULL;
|
|
char ctemp[MAX_PATH];
|
|
|
|
fopen_s(&logfile, metaVal, "a+");
|
|
|
|
if (NULL != logfile)
|
|
{
|
|
char buff[2 * 1024] = { 0 };
|
|
sprintf(buff, "%d_tocLine_%d_tocLine_\n", DocInfo.eClass, DocInfo.eFormat);
|
|
fwrite(buff, sizeof(char), strlen(buff), logfile);
|
|
fclose(logfile);
|
|
}
|
|
|
|
/*
|
|
printf("The file %s \n", szFile);
|
|
printf("Class ID: %d\n", DocInfo.eClass);
|
|
printf("Format ID: %d\n", DocInfo.eFormat);
|
|
printf("Major Version: %ld\n", DocInfo.lVersion);
|
|
printf("Attributes: %u\n", DocInfo.ulAttributes);
|
|
|
|
printf("\n");
|
|
*/
|
|
slammer:
|
|
return(eErr);
|
|
}
|
|
|
|
KVErrorCode AutoDetectStream(void *pContext, char *szFile)
|
|
{
|
|
ADDOCINFO DocInfo;
|
|
KVErrorCode eErr = KVERR_Success;
|
|
KVInputStream inputStream = { 0 };
|
|
MyOpenInfo o = { 0 };
|
|
BOOL bVal = TRUE;
|
|
|
|
|
|
o.pszName = szFile;
|
|
|
|
inputStream.pInputStreamPrivateData = (void*)&o;
|
|
inputStream.fpOpen = myOpen;
|
|
inputStream.fpRead = myRead;
|
|
inputStream.fpSeek = mySeek;
|
|
inputStream.fpTell = myTell;
|
|
inputStream.fpClose = myClose;
|
|
|
|
bVal = FilterFunc.fpGetDocInfoStream(pContext, &inputStream, &DocInfo);
|
|
|
|
if (!bVal || (DocInfo.eClass == AutoDetFail) ||
|
|
(DocInfo.eClass == AutoDetNoFormat))
|
|
{
|
|
if (DocInfo.eClass == AutoDetFail)
|
|
{
|
|
eErr = KVERR_AutoDetFail;
|
|
}
|
|
else
|
|
{
|
|
eErr = KVERR_AutoDetNoFormat;
|
|
}
|
|
goto slammer;
|
|
}
|
|
|
|
/*
|
|
printf("The stream %s \n", szFile);
|
|
printf("Class ID: %d\n", DocInfo.eClass);
|
|
printf("Format ID: %d\n", DocInfo.eFormat);
|
|
printf("Major Version: %ld\n", DocInfo.lVersion);
|
|
printf("Attributes: %u\n", DocInfo.ulAttributes);
|
|
|
|
printf("\n");
|
|
*/
|
|
slammer:
|
|
return(eErr);
|
|
}
|
|
|
|
|
|
/*******************************************************************************
|
|
*
|
|
* function: DoSummaryInfo()
|
|
*
|
|
*
|
|
******************************************************************************/
|
|
static void pascal DoSummaryInfo(void *pKVFilter,
|
|
KVFltInterfaceEx *pInterface,
|
|
char *pszFileIn,
|
|
char *pszFileOut)
|
|
{
|
|
KVSummaryInfoEx si;
|
|
FILE *fo = NULL;
|
|
|
|
fo = fopen(pszFileOut, "wb");
|
|
|
|
if (!fo)
|
|
{
|
|
fprintf(fo, "Error opening target file for summary information\n");
|
|
return; /* error */
|
|
}
|
|
|
|
memset(&si, 0, sizeof(si));
|
|
|
|
if (KVERR_Success != (*pInterface->fpGetOLESummaryInfoFile)(pKVFilter, pszFileIn, &si))
|
|
{
|
|
fprintf(fo, "Error obtaining summary information\n");
|
|
goto slammer;
|
|
}
|
|
|
|
if (si.nElem == 0)
|
|
{
|
|
fprintf(fo, "No summary information\n");
|
|
}
|
|
else
|
|
{
|
|
PrintSummaryInfo(&si, fo);
|
|
}
|
|
|
|
(*pInterface->fpFreeOLESummaryInfo)(pKVFilter, &si);
|
|
|
|
slammer:
|
|
if (fo) fclose(fo);
|
|
}
|
|
|
|
/*******************************************************************************
|
|
*
|
|
* function: DoSummaryInfoStream()
|
|
*
|
|
*
|
|
******************************************************************************/
|
|
static void pascal DoSummaryInfoStream(void *pKVFilter,
|
|
KVFltInterfaceEx *pInterface,
|
|
KVInputStream *pInput,
|
|
FILE *fpOut)
|
|
{
|
|
KVSummaryInfoEx si;
|
|
|
|
memset(&si, 0, sizeof(si));
|
|
if (KVERR_Success != (*pInterface->fpGetOLESummaryInfo)(pKVFilter, pInput, &si))
|
|
{
|
|
fprintf(fpOut, "Error obtaining summary information\n");
|
|
return;
|
|
}
|
|
|
|
if (si.nElem == 0)
|
|
{
|
|
fprintf(fpOut, "No summary information\n");
|
|
goto theend;
|
|
}
|
|
|
|
PrintSummaryInfo(&si, fpOut);
|
|
|
|
theend:
|
|
(*pInterface->fpFreeOLESummaryInfo)(pKVFilter, &si);
|
|
}
|
|
|
|
|
|
/*******************************************************************************
|
|
*
|
|
* function: PrintXmpnfo()
|
|
*
|
|
*
|
|
******************************************************************************/
|
|
void printXmpInfo(KVXmpInfo xi, FILE *fo, DWORD dwXmpOptions)
|
|
{
|
|
|
|
int i = 0, j = 0;
|
|
|
|
if (dwXmpOptions & 2) { // print raw xmp only
|
|
|
|
// print UPacket Data if exists
|
|
// but what is a good way to print UTF16 and UTF32 string into a file?
|
|
if (xi.usXpacketData.cbSize > 0 && xi.usXpacketData.pcString != 0) {
|
|
for (i = 0; i < xi.usXpacketData.cbSize; i++) {
|
|
fputc((int)xi.usXpacketData.pcString[i], fo);
|
|
}
|
|
}
|
|
fputc('\n', fo);
|
|
|
|
}
|
|
else {
|
|
|
|
fprintf(fo, "*** Keyview XMP Information ***\n");
|
|
|
|
// print encoding
|
|
fprintf(fo, "\nEncoding = %d\n", xi.encoding);
|
|
|
|
// print byteOrder
|
|
fprintf(fo, "\nByte Order = %d\n\n", xi.bIsLittleEndian);
|
|
|
|
// print UPacket Data if exists
|
|
// but what is a good way to print UTF16 and UTF32 string into a file?
|
|
if (xi.usXpacketData.cbSize > 0 && xi.usXpacketData.pcString != 0) {
|
|
for (i = 0; i < xi.usXpacketData.cbSize; i++) {
|
|
fputc((int)xi.usXpacketData.pcString[i], fo);
|
|
}
|
|
}
|
|
fprintf(fo, "\n\n");
|
|
|
|
// print nNoOfElements
|
|
fprintf(fo, "No of XMP elements = %d\n\n", xi.nNoOfElements);
|
|
|
|
// print XmpInfoElements
|
|
if (xi.nNoOfElements > 0 && xi.pXmpInfoElems) {
|
|
for (i = 0; i < (int)xi.nNoOfElements; i++) {
|
|
fprintf(fo, "KVXmpInfoElem number %d:\n", i);
|
|
|
|
// printf xpath
|
|
fprintf(fo, "xpath = \"");
|
|
if (xi.pXmpInfoElems[i].usXPathToElement.cbSize) {
|
|
for (j = 0; j < xi.pXmpInfoElems[i].usXPathToElement.cbSize; j++)
|
|
fputc(xi.pXmpInfoElems[i].usXPathToElement.pcString[j], fo);
|
|
}
|
|
fprintf(fo, "\"\n");
|
|
|
|
// printf value
|
|
fprintf(fo, "value = \"");
|
|
if (xi.pXmpInfoElems[i].usValue.cbSize > 0 && xi.pXmpInfoElems[i].usValue.pcString) {
|
|
for (j = 0; j < xi.pXmpInfoElems[i].usValue.cbSize; j++)
|
|
fputc(xi.pXmpInfoElems[i].usValue.pcString[j], fo);
|
|
}
|
|
fprintf(fo, "\"\n\n");
|
|
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
|
|
//#define enumFileMode 0x1
|
|
//#define enumStreamMode 0x2
|
|
|
|
// ******************************************************************************
|
|
// Function: DoXmpInfoStream()
|
|
// Description:
|
|
// Process the stream or file mode request by using the getXmpInfo API
|
|
// in kvfilter.dll
|
|
//
|
|
// ******************************************************************************
|
|
static void pascal DoXmpInfo(void * pKVFilter,
|
|
KVFltInterfaceEx * pInterface,
|
|
char * pszFileIn,
|
|
char * pszFileOut,
|
|
KVInputStream * pInput,
|
|
FILE * fpOut,
|
|
DWORD dwXmpOptions,
|
|
UINT uiMode // to determine if we are using file mode or stream mode
|
|
)
|
|
{
|
|
int ret = KVERR_General;
|
|
KVXmpInfo xi;
|
|
|
|
if (uiMode == enumFileMode) {
|
|
fpOut = fopen(pszFileOut, "wb");
|
|
if (!fpOut)
|
|
{
|
|
fprintf(fpOut, "Error opening target file for Xmp information\n");
|
|
goto CATCH;
|
|
}
|
|
}
|
|
|
|
memset(&xi, 0, sizeof(xi));
|
|
|
|
if (uiMode == enumFileMode) {
|
|
if (*pInterface->fpGetXmpInfoFile != NULL) {
|
|
ret = (*pInterface->fpGetXmpInfoFile)(pKVFilter, pszFileIn, &xi, dwXmpOptions);
|
|
}
|
|
}
|
|
else if (uiMode == enumStreamMode) {
|
|
if (*pInterface->fpGetXmpInfoFile != NULL) {
|
|
ret = (*pInterface->fpGetXmpInfo)(pKVFilter, pInput, &xi, dwXmpOptions);
|
|
}
|
|
}
|
|
else {
|
|
goto CATCH;
|
|
}
|
|
|
|
if (KVERR_Success != ret) {
|
|
fprintf(fpOut, "Error obtaining Xmp information\n");
|
|
goto CATCH;
|
|
}
|
|
|
|
if (xi.nNoOfElements == 0 && xi.usXpacketData.cbSize == 0) {
|
|
// fprintf( fpOut, "No Xmp information\n" ); // output empty file
|
|
}
|
|
else {
|
|
printXmpInfo(xi, fpOut, dwXmpOptions);
|
|
}
|
|
|
|
CATCH:
|
|
|
|
(*pInterface->fpFreeXmpInfo)(pKVFilter, &xi);
|
|
|
|
if (uiMode == enumFileMode) {
|
|
if (fpOut) fclose(fpOut);
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// ******************************************************************************
|
|
// Function: DoXmpInfoFile()
|
|
// Description:
|
|
// A proxy to forward the file mode request to the function DoXmpInfo()
|
|
//
|
|
// ******************************************************************************
|
|
static void pascal DoXmpInfoFile(void * pKVFilter,
|
|
KVFltInterfaceEx * pInterface,
|
|
char * pszFileIn,
|
|
char * pszFileOut,
|
|
DWORD dwXmpOptions)
|
|
{
|
|
DoXmpInfo(pKVFilter, pInterface, pszFileIn, pszFileOut, NULL, NULL, dwXmpOptions, enumFileMode);
|
|
}
|
|
|
|
|
|
|
|
// ******************************************************************************
|
|
// Function: DoXmpInfoStream()
|
|
// Description:
|
|
// A proxy to forward the stream mode request to the function DoXmpInfo()
|
|
//
|
|
// ******************************************************************************
|
|
static void pascal DoXmpInfoStream(void * pKVFilter,
|
|
KVFltInterfaceEx * pInterface,
|
|
KVInputStream * pInput,
|
|
FILE * fpOut,
|
|
DWORD dwXmpOptions)
|
|
{
|
|
DoXmpInfo(pKVFilter, pInterface, NULL, NULL, pInput, fpOut, dwXmpOptions, enumStreamMode);
|
|
}
|
|
|
|
|
|
|
|
|
|
/*******************************************************************************
|
|
*
|
|
* function: PrintSummaryInfo()
|
|
*
|
|
*
|
|
******************************************************************************/
|
|
void pascal PrintSummaryInfo(KVSummaryInfoEx *pSI, FILE *fpOut)
|
|
{
|
|
int n;
|
|
|
|
for (n = 0; n < pSI->nElem; ++n)
|
|
{
|
|
fprintf(fpOut, "%d %d ", pSI->pElem[n].isValid, pSI->pElem[n].type);
|
|
|
|
switch (pSI->pElem[n].type)
|
|
{
|
|
case KV_String:
|
|
{
|
|
fprintf(fpOut, "\"%s\"", pSI->pElem[n].data);
|
|
}
|
|
break;
|
|
|
|
case KV_Int4:
|
|
{
|
|
fprintf(fpOut, "%d", pSI->pElem[n].data);
|
|
}
|
|
break;
|
|
|
|
case KV_DateTime:
|
|
{
|
|
|
|
LONGLONG rtnValue = 0;
|
|
|
|
memcpy(&rtnValue, pSI->pElem[n].data, 8);
|
|
|
|
if (n == 9)
|
|
{
|
|
#if defined (KV_BIG_ENDIAN)
|
|
|
|
/* if it is big endian, swap bytes */
|
|
LONGLONG NN = 0;
|
|
unsigned char *a, *b, *c;
|
|
a = (unsigned char *)&rtnValue;
|
|
b = a + sizeof(LONGLONG)-1;
|
|
c = (unsigned char *)&NN;
|
|
|
|
while (a <= b)
|
|
{
|
|
*c = *b;
|
|
b--;
|
|
c++;
|
|
}
|
|
rtnValue = NN;
|
|
#endif
|
|
fprintf(fpOut, "%ld Minutes", (long)(rtnValue / 600000000));
|
|
}
|
|
else
|
|
{
|
|
time_t timer;
|
|
char * timeStr = NULL;
|
|
char * linefeed = NULL;
|
|
char buffer[40] = { 0 };
|
|
|
|
FileTimeToUnixTime(rtnValue, &timer);
|
|
#if defined (_WINDOWS)
|
|
timeStr = ctime(&timer);
|
|
if (timeStr)
|
|
{
|
|
strncpy(buffer, timeStr, 40);
|
|
}
|
|
#elif defined (KV_CTIME_R_40)
|
|
timeStr = ctime_r(&timer, buffer, 40);
|
|
#else
|
|
timeStr = ctime_r(&timer, buffer);
|
|
#endif
|
|
if (buffer[0] != 0)
|
|
{
|
|
linefeed = strchr(buffer, '\012');
|
|
if (linefeed != NULL)
|
|
{
|
|
*linefeed = '\0';
|
|
}
|
|
fprintf(fpOut, "%s", timeStr);
|
|
}
|
|
}
|
|
}
|
|
break;
|
|
|
|
case KV_ClipBoard:
|
|
{
|
|
fprintf(fpOut, "Clipboard data");
|
|
}
|
|
break;
|
|
|
|
case KV_Bool:
|
|
{
|
|
fprintf(fpOut, "%s", pSI->pElem[n].data ? "true" : "false");
|
|
}
|
|
break;
|
|
|
|
case KV_Unicode:
|
|
{
|
|
int len = 0;
|
|
BYTE *p = (BYTE *)pSI->pElem[n].data;
|
|
|
|
if (p)
|
|
{
|
|
for (; *p != 0 || *(p + 1) != 0; p += 2, len += 2);
|
|
}
|
|
|
|
fprintf(fpOut, "\"");
|
|
if (p)
|
|
{
|
|
fwrite(pSI->pElem[n].data, 1, len + 2, fpOut);
|
|
}
|
|
fprintf(fpOut, "\"");
|
|
|
|
}
|
|
break;
|
|
|
|
case KV_IEEE8:
|
|
{
|
|
fprintf(fpOut, "%lf", *((double *)pSI->pElem[n].data));
|
|
}
|
|
break;
|
|
|
|
case KV_Other:
|
|
{
|
|
fprintf(fpOut, "other");
|
|
}
|
|
break;
|
|
|
|
default:
|
|
{
|
|
if (pSI->pElem[n].isValid)
|
|
{
|
|
fprintf(fpOut, "Bad element type!");
|
|
}
|
|
}
|
|
break;
|
|
}
|
|
|
|
fprintf(fpOut, " %s\n", pSI->pElem[n].isValid ? pSI->pElem[n].pcType : "(null)");
|
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
/*******************************************************************************
|
|
*
|
|
* function: FilterFile()
|
|
*
|
|
* summary: Takes an input file specification and filters the output to an output file
|
|
* using the KeyView filtering API.
|
|
*
|
|
******************************************************************************/
|
|
static int pascal FilterFile(void *pFilter, char *pszFileIn, char *pszFileOut, FilterLsv *lsv)
|
|
{
|
|
ADDOCINFO DocInfo;
|
|
BOOL bAutoRec = FALSE;
|
|
KVErrorCode kvstatus = KVERR_Success;
|
|
KVErrorCode nRet = KVERR_Success;
|
|
|
|
/**************************************************************************/
|
|
/* Call the KeyView auto-recognition on this file.
|
|
*/
|
|
bAutoRec = FilterFunc.fpGetDocInfoFile(pFilter, pszFileIn, &DocInfo);
|
|
|
|
|
|
if (!bAutoRec || (DocInfo.eClass == AutoDetFail) ||
|
|
(DocInfo.eClass == AutoDetNoFormat))
|
|
{
|
|
fprintf(stderr, "Error: fpGetDocInfoFile returned %d in %s\n", DocInfo.eClass, pszFileIn);
|
|
if (DocInfo.eClass == AutoDetFail)
|
|
nRet = KVERR_AutoDetFail;
|
|
else
|
|
nRet = KVERR_AutoDetNoFormat;
|
|
return (nRet);
|
|
}
|
|
|
|
|
|
|
|
/* Check if KeyView can filter this file.
|
|
*/
|
|
kvstatus = (*FilterFunc.fpCanFilterFile)(pFilter, pszFileIn);
|
|
nRet = kvstatus;
|
|
|
|
if (KVERR_Success == kvstatus)
|
|
{
|
|
if (lsv->gbSummary)
|
|
{
|
|
DoSummaryInfo(pFilter, &FilterFunc, pszFileIn, pszFileOut);
|
|
}
|
|
else if (lsv->gbXmp)
|
|
{
|
|
DoXmpInfoFile(pFilter, &FilterFunc, pszFileIn, pszFileOut, lsv->gbXmp);
|
|
}
|
|
else
|
|
{
|
|
kvstatus = (*FilterFunc.fpFilterFile)(pFilter, pszFileIn, pszFileOut, NULL);
|
|
nRet = kvstatus;
|
|
|
|
if (kvstatus != KVERR_Success)
|
|
{
|
|
fprintf(stderr, "Filter error, value returned is %d\n", kvstatus);
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
lsv->pszSrcFile = pszFileIn;
|
|
lsv->pszTrgFile = pszFileOut;
|
|
}
|
|
return (nRet);
|
|
}
|
|
|
|
|
|
/*******************************************************************************
|
|
*
|
|
* function: FilterStream()
|
|
*
|
|
* summary: Takes an input file specification and filters the output to an output file
|
|
* using the KeyView filtering API.
|
|
* Uses stream-based filtering instead of file-based.
|
|
*
|
|
******************************************************************************/
|
|
static int pascal FilterStream(void *pFilter, char *pszFileIn, char *pszFileOut, FilterLsv *lsv)
|
|
{
|
|
adDocDesc DocDesc = { 0 };
|
|
KVErrorCode nRet = KVERR_Success;
|
|
KVInputStream IO = { 0 };
|
|
MyOpenInfo o = { 0 };
|
|
FILE *fo = NULL;
|
|
void *pStream = NULL;
|
|
KVFilterOutput filterOut = { 0 };
|
|
BOOL bStreamOpen = FALSE;
|
|
|
|
|
|
/**************************************************************************/
|
|
|
|
lsv->pszSrcFile = pszFileIn;
|
|
lsv->pszTrgFile = pszFileOut;
|
|
|
|
fo = fopen(pszFileOut, "wb");
|
|
|
|
if (!fo)
|
|
{
|
|
printf("Error opening target file for filtering\n");
|
|
nRet = KVERR_CreateOutputFileFailed;
|
|
return(nRet);
|
|
}
|
|
|
|
/* Initialize the input stream
|
|
*/
|
|
o.pszName = pszFileIn;
|
|
|
|
IO.pInputStreamPrivateData = (void *)&o;
|
|
IO.fpOpen = myOpen;
|
|
IO.fpRead = myRead;
|
|
IO.fpSeek = mySeek;
|
|
IO.fpTell = myTell;
|
|
IO.fpClose = myClose;
|
|
|
|
|
|
/* Open this stream for filtering.
|
|
*/
|
|
|
|
/* if you need to change the BITWISE flags on the fly then call the Ex2 function
|
|
* This is just a test as the flags are set in the fpInit
|
|
*/
|
|
if (lsv->AddInputFileName)
|
|
{
|
|
if (lsv->fpKV_FilterConfig)
|
|
lsv->fpKV_FilterConfig(pFilter, 0, 0, pszFileIn);
|
|
}
|
|
|
|
|
|
pStream = (*FilterFunc.fpOpenStream)(pFilter, &IO);
|
|
|
|
|
|
if (!pStream)
|
|
{
|
|
fprintf(stderr, "Error opening input stream on -> %s\n", pszFileIn);
|
|
nRet = KVERR_badInputStream;
|
|
goto slammer;
|
|
}
|
|
|
|
bStreamOpen = TRUE;
|
|
|
|
/* Check if KeyView can filter this stream.
|
|
*/
|
|
nRet = (*FilterFunc.fpCanFilterStream)(pFilter, pStream);
|
|
|
|
if (nRet != KVERR_Success)
|
|
{
|
|
if (bStreamOpen)
|
|
{
|
|
if (!(*FilterFunc.fpCloseStream)(pFilter, pStream))
|
|
{
|
|
fprintf(stderr, "Error: Unable to filter %s (fpCanFilterStream returns %d)\n", pszFileIn, nRet);
|
|
fprintf(stderr, "Error in KVCloseStream(): %s\n", pszFileIn);
|
|
nRet = KVERR_General;
|
|
|
|
}
|
|
}
|
|
|
|
if (fo)
|
|
{
|
|
fclose(fo);
|
|
}
|
|
if (nRet == KVERR_General)
|
|
{
|
|
/* stop, get out! */
|
|
_unlink(pszFileOut);
|
|
return(nRet);
|
|
}
|
|
|
|
if (nRet != KVERR_Success) {
|
|
_unlink(pszFileOut);
|
|
}
|
|
|
|
return(nRet);
|
|
}
|
|
|
|
if (lsv->gbSummary)
|
|
{
|
|
/*
|
|
* Do summary extraction.
|
|
*/
|
|
DoSummaryInfoStream(pFilter, &FilterFunc, &IO, fo);
|
|
}
|
|
else if (lsv->gbXmp)
|
|
{
|
|
/*
|
|
* Do XMP Info extraction.
|
|
*/
|
|
DoXmpInfoStream(pFilter, &FilterFunc, &IO, fo, lsv->gbXmp);
|
|
}
|
|
else
|
|
{
|
|
while (1)
|
|
{
|
|
nRet = (*FilterFunc.fpFilterStream)(pFilter, pStream, &filterOut, NULL);
|
|
|
|
if (nRet != KVERR_Success)
|
|
{
|
|
fprintf(stderr, "Error filtering stream: %s\n", pszFileIn);
|
|
goto slammer;
|
|
}
|
|
|
|
/*
|
|
** Check if we're done filtering...
|
|
*/
|
|
|
|
if (filterOut.cbText == 0)
|
|
{
|
|
break;
|
|
}
|
|
|
|
/*
|
|
** Write this buffer out to stdout...
|
|
*/
|
|
|
|
fwrite(filterOut.pcText, 1, filterOut.cbText, fo);
|
|
|
|
/* The caller is responsible for free'ing the memory allocated
|
|
* by the KVFilterStream() function. The KeyView filtering API used
|
|
* our g_MemoryAllocator to allocate the memory...
|
|
*/
|
|
(*g_MemoryAllocator.fpFree)(&g_MemoryAllocator, filterOut.pcText);
|
|
}
|
|
}
|
|
|
|
slammer:
|
|
|
|
/*
|
|
** Load KVCloseStream
|
|
*/
|
|
if (pStream)
|
|
{
|
|
if (!(*FilterFunc.fpCloseStream)(pFilter, pStream))
|
|
{
|
|
fprintf(stderr, "Error closing stream: %s\n", pszFileIn);
|
|
nRet = KVERR_General;
|
|
}
|
|
}
|
|
|
|
if (fo)
|
|
{
|
|
fclose(fo);
|
|
}
|
|
|
|
return (nRet);
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/*******************************************************************************
|
|
*
|
|
* Installable file system layer: the next 5 functions provide basic file
|
|
* manipulation.
|
|
*
|
|
******************************************************************************/
|
|
|
|
BOOL pascal myOpen(struct tag_InputStream *p)
|
|
{
|
|
MyOpenInfo *po = (MyOpenInfo *)p->pInputStreamPrivateData;
|
|
po->fp = fopen(po->pszName, "rb");
|
|
return (po->fp != NULL);
|
|
}
|
|
|
|
UINT pascal myRead(struct tag_InputStream *p, BYTE *pc, UINT cb)
|
|
{
|
|
MyOpenInfo *po = (MyOpenInfo *)p->pInputStreamPrivateData;
|
|
return (fread(pc, 1, cb, po->fp));
|
|
}
|
|
|
|
BOOL pascal mySeek(struct tag_InputStream *p, long l, int w)
|
|
{
|
|
MyOpenInfo *po = (MyOpenInfo *)p->pInputStreamPrivateData;
|
|
if (!po->fp) return(1);
|
|
return(!fseek(po->fp, l, w));
|
|
}
|
|
|
|
long pascal myTell(struct tag_InputStream *p)
|
|
{
|
|
MyOpenInfo *po = (MyOpenInfo *)p->pInputStreamPrivateData;
|
|
if (!po->fp) return(-1);
|
|
return (ftell(po->fp));
|
|
}
|
|
|
|
BOOL pascal myClose(struct tag_InputStream *p)
|
|
{
|
|
MyOpenInfo *po = (MyOpenInfo *)p->pInputStreamPrivateData;
|
|
if (po->fp)
|
|
{
|
|
fclose(po->fp);
|
|
po->fp = NULL;
|
|
}
|
|
return (TRUE);
|
|
}
|
|
|
|
|
|
|
|
/*******************************************************************************
|
|
*
|
|
* Memory abstraction: the variable g_MemoryAllocator is passed into all KeyView
|
|
* filtering API entry points requiring it.
|
|
*
|
|
******************************************************************************/
|
|
void * pascal myMalloc(struct tag_MemoryStream *pX, size_t cb)
|
|
{
|
|
return (malloc(cb));
|
|
}
|
|
|
|
void pascal myFree(struct tag_MemoryStream *pX, void *ptr)
|
|
{
|
|
free(ptr);
|
|
}
|
|
|
|
void * pascal myRealloc(struct tag_MemoryStream *pX, void *ptr, size_t cb)
|
|
{
|
|
return (realloc(ptr, cb));
|
|
}
|
|
|
|
void * pascal myCalloc(struct tag_MemoryStream *pX, size_t ne, size_t s)
|
|
{
|
|
return (calloc(ne, s));
|
|
}
|
|
|
|
|
|
|
|
|
|
/* szDir is the directory where the filter dlls are */
|
|
int filterText(char *szDir, char *szSrc, char *szTarget, FilterLsv *lsv)
|
|
{
|
|
void *pFilter = NULL;
|
|
char szDllName[1024];
|
|
//void *pKVFILTER;
|
|
HINSTANCE pKVFILTER;
|
|
KVErrorCode nRet = KVERR_Success;
|
|
KVErrorCode(pascal *fpGetFilterInterfaceEx)(KVFltInterfaceEx*, int);
|
|
|
|
strcpy(szDllName, szDir);
|
|
|
|
strcat(szDllName, "kvfilter");
|
|
pKVFILTER = myLoadLibrary(szDllName);
|
|
if (!pKVFILTER)
|
|
{
|
|
WriteLog("filterlocation err");
|
|
fprintf(stderr, "Can't load kvfilter!\n");
|
|
fprintf(stderr, "This executable must be in the same directory as the Filter binaries.\n");
|
|
nRet = KVERR_DLLNotFound;
|
|
goto jail;
|
|
}
|
|
|
|
fpGetFilterInterfaceEx = (KVErrorCode(pascal *)(KVFltInterfaceEx *, int))
|
|
myGetProcAddress(pKVFILTER, (char*)"KV_GetFilterInterfaceEx");
|
|
|
|
if (fpGetFilterInterfaceEx == NULL)
|
|
{
|
|
WriteLog("Can't get interface function!");
|
|
fprintf(stderr, "Can't get interface function!\n");
|
|
nRet = KVERR_General;
|
|
goto jail;
|
|
}
|
|
|
|
nRet = (*fpGetFilterInterfaceEx)(&FilterFunc, KVFLTINTERFACE_REVISION);
|
|
if (KVERR_Success != nRet)
|
|
{
|
|
WriteLog("interface");
|
|
fprintf(stderr, "Can't get Filter interface functions!\n");
|
|
goto jail;
|
|
}
|
|
|
|
/*
|
|
* if the BITWISE flags don't need to be see on the fly, set the gdwFlags here.
|
|
* pFilter = (*FilterFunc.fpInit)( &g_MemoryAllocator, NULL , szDir, KVCS_UTF8, gdwFLAGS );
|
|
*/
|
|
lsv->fpKV_GetKvErrorCodeEx = (KVErrorCodeEx(pascal *)(void *))myGetProcAddress(pKVFILTER, (char*)"KV_GetKvErrorCodeEx");
|
|
lsv->fpKV_FilterConfig = (BOOL(pascal *)(void *, int, int, void *))myGetProcAddress(pKVFILTER, (char*)"KV_FilterConfig");
|
|
|
|
pFilter = (*FilterFunc.fpInit)(&g_MemoryAllocator, NULL, szDir, KVCS_UTF8, lsv->dwFlags);
|
|
|
|
|
|
if (pFilter == NULL)
|
|
{
|
|
WriteLog("Error Init");
|
|
fprintf(stderr, "Error initializing filter!\n");
|
|
nRet = KVERR_General;
|
|
goto jail;
|
|
}
|
|
|
|
if (lsv->fpKV_FilterConfig)
|
|
{
|
|
|
|
if (lsv->bInclRMark)
|
|
{
|
|
lsv->fpKV_FilterConfig(pFilter, KVFLT_INCLREVISIONMARK, TRUE, NULL);
|
|
|
|
}
|
|
|
|
if (lsv->bNoComments)
|
|
{
|
|
lsv->fpKV_FilterConfig(pFilter, KVFLT_NOCOMMENTS, TRUE, NULL);
|
|
}
|
|
|
|
if (lsv->bShowHiddenText)
|
|
{
|
|
lsv->fpKV_FilterConfig(pFilter, KVFLT_SHOWHIDDENTEXT, TRUE, NULL);
|
|
|
|
}
|
|
|
|
if (lsv->szXMLConfigFile[0])
|
|
{
|
|
KVXConfigInfo xinfo;
|
|
BOOL bDone = FALSE;
|
|
int n = 0;
|
|
|
|
/* get config info for Verity-recognized formats */
|
|
while (!bDone)
|
|
{
|
|
memset(&xinfo, 0, sizeof(KVXConfigInfo));
|
|
if (GetKVXConfigInfo(lsv, &xinfo, n))
|
|
{
|
|
lsv->fpKV_FilterConfig(pFilter, KVFLT_SETXMLCONFIGINFO, 0, &xinfo);
|
|
FreeKVXConfigInfo(&xinfo);
|
|
n++;
|
|
}
|
|
else
|
|
{
|
|
bDone = TRUE;
|
|
}
|
|
}
|
|
|
|
/* get customized config info for other formats */
|
|
bDone = FALSE;
|
|
n = 100;
|
|
while (!bDone)
|
|
{
|
|
memset(&xinfo, 0, sizeof(KVXConfigInfo));
|
|
if (GetKVXConfigInfo(lsv, &xinfo, n))
|
|
{
|
|
lsv->fpKV_FilterConfig(pFilter, KVFLT_SETXMLCONFIGINFO, 0, &xinfo);
|
|
FreeKVXConfigInfo(&xinfo);
|
|
n++;
|
|
}
|
|
else
|
|
{
|
|
bDone = TRUE;
|
|
}
|
|
}
|
|
}
|
|
if (lsv->szTempDir[0])
|
|
{
|
|
lsv->fpKV_FilterConfig(pFilter, KVFLT_SETTEMPDIRECTORY, 0, lsv->szTempDir);
|
|
}
|
|
if (lsv->szSrcPassword[0])
|
|
{
|
|
lsv->fpKV_FilterConfig(pFilter, KVFLT_SETSRCPASSWORD,
|
|
strlen(lsv->szSrcPassword), lsv->szSrcPassword);
|
|
}
|
|
if (lsv->lpdfDirection >= LPDF_RAW)
|
|
{
|
|
lsv->fpKV_FilterConfig(pFilter, KVFLT_LOGICALPDF,
|
|
lsv->lpdfDirection, NULL);
|
|
}
|
|
}
|
|
#if 0
|
|
if (_access(szSrc, 0))
|
|
{
|
|
fprintf(stderr, "Cannot locate input file.\n");
|
|
nRet = KVERR_badInputStream;
|
|
goto jail;
|
|
}
|
|
#endif
|
|
//TODO JKim
|
|
AutoDetectFile(pFilter, szSrc);
|
|
if (lsv->gbKWAD)
|
|
{
|
|
if (lsv->gbStreamBased)
|
|
{
|
|
nRet = AutoDetectStream(pFilter, szSrc);
|
|
}
|
|
else
|
|
{
|
|
nRet = AutoDetectFile(pFilter, szSrc);
|
|
}
|
|
}
|
|
else if (lsv->gbStreamBased)
|
|
{
|
|
FilterStream(pFilter, szSrc, szTarget, lsv);
|
|
}
|
|
else
|
|
{
|
|
FilterFile(pFilter, szSrc, szTarget, lsv);
|
|
}
|
|
nRet = KVERR_Success;
|
|
|
|
|
|
jail:
|
|
if (nRet == KVERR_General)
|
|
{
|
|
int kvErrorEx;
|
|
if (lsv->fpKV_GetKvErrorCodeEx)
|
|
{
|
|
kvErrorEx = (*lsv->fpKV_GetKvErrorCodeEx)(pFilter);
|
|
if (kvErrorEx != KVError_Last)
|
|
printf("KvErrorCodeEx = %d \n ", kvErrorEx);
|
|
else
|
|
printf("No more KvErrorCodeEx \n");
|
|
}
|
|
}
|
|
|
|
if (pFilter)
|
|
(*FilterFunc.fpShutdown)(pFilter);
|
|
|
|
FreeLibrary((HINSTANCE)pKVFILTER);
|
|
|
|
return (nRet);
|
|
}
|
|
|
|
/******************************************************************
|
|
*
|
|
* Porting Load library function to different platforms
|
|
*
|
|
*******************************************************************/
|
|
|
|
HINSTANCE myLoadLibrary(char *filename)
|
|
{
|
|
char szFileNameWithExtension[_MAX_PATH];
|
|
|
|
strcpy(szFileNameWithExtension, filename);
|
|
|
|
#if defined(_WINDOWS)
|
|
strcat(szFileNameWithExtension, ".dll");
|
|
return LoadLibraryA(szFileNameWithExtension);
|
|
|
|
#elif defined(_HPUX11)
|
|
strcat(szFileNameWithExtension, ".sl");
|
|
return shl_load(szFileNameWithExtension, BIND_DEFERRED, 0L);
|
|
|
|
#elif defined (HPUX_R64)
|
|
strcat(szFileNameWithExtension, ".sl");
|
|
return dlopen(szFileNameWithExtension, RTLD_LAZY);
|
|
|
|
#elif defined (_RS6K43) || defined (AIX_P64)
|
|
strcat(szFileNameWithExtension, ".a");
|
|
return dlopen(szFileNameWithExtension, RTLD_LAZY);
|
|
|
|
#else
|
|
strcat(szFileNameWithExtension, ".so");
|
|
return dlopen(szFileNameWithExtension, RTLD_LAZY);
|
|
|
|
#endif
|
|
}
|
|
|
|
|
|
/******************************************************************
|
|
*
|
|
* Porting Free library function to different platforms
|
|
*
|
|
*******************************************************************
|
|
void myFreeLibrary(void * hKVFILTER)
|
|
{
|
|
#if defined(_WINDOWS)
|
|
FreeLibrary((HINSTANCE)hKVFILTER);
|
|
#elif defined(_HPUX11)
|
|
shl_unload((shl_t)hKVFILTER);
|
|
#else
|
|
dlclose(hKVFILTER);
|
|
#endif
|
|
}
|
|
*/
|
|
|
|
void PrintFilterErrMsg(char *szTitle, KVErrorCode error)
|
|
{
|
|
char szError[40];
|
|
|
|
*szError = '\0';
|
|
switch (error)
|
|
{
|
|
case KVERR_Success:
|
|
//wsprintfA(szError, "KVERR_Success");
|
|
return;
|
|
|
|
case KVERR_DLLNotFound:
|
|
wsprintfA(szError, "KVERR_DLLNotFound");
|
|
break;
|
|
|
|
case KVERR_processCancelled:
|
|
wsprintfA(szError, "KVERR_processCancelled");
|
|
break;
|
|
|
|
case KVERR_OutOfCore:
|
|
wsprintfA(szError, "KVERR_OutOfCore");
|
|
break;
|
|
|
|
case KVERR_badInputStream:
|
|
wsprintfA(szError, "KVERR_badInputStream");
|
|
break;
|
|
|
|
case KVERR_badOutputType:
|
|
wsprintfA(szError, "KVERR_badOutputType");
|
|
break;
|
|
|
|
case KVERR_General:
|
|
wsprintfA(szError, "KVERR_General");
|
|
return;
|
|
|
|
case KVERR_FormatNotSupported:
|
|
wsprintfA(szError, "KVERR_FormatNotSupported");
|
|
break;
|
|
|
|
case KVERR_PasswordProtected:
|
|
wsprintfA(szError, "KVERR_PasswordProtected");
|
|
break;
|
|
|
|
case KVERR_ADSNotFound:
|
|
wsprintfA(szError, "KVERR_ADSNotFound");
|
|
break;
|
|
|
|
case KVERR_AutoDetFail:
|
|
wsprintfA(szError, "KVERR_AutoDetFail");
|
|
break;
|
|
|
|
case KVERR_AutoDetNoFormat:
|
|
wsprintfA(szError, "KVERR_AutoDetNoFormat");
|
|
break;
|
|
|
|
case KVERR_ReaderInitError:
|
|
wsprintfA(szError, "KVERR_ReaderInitError");
|
|
break;
|
|
|
|
case KVERR_NoReader:
|
|
wsprintfA(szError, "KVERR_NoReader");
|
|
break;
|
|
|
|
case KVERR_CreateOutputFileFailed:
|
|
wsprintfA(szError, "KVERR_CreateOutputFileFailed");
|
|
break;
|
|
|
|
case KVERR_CreateTempFileFailed:
|
|
wsprintfA(szError, "KVERR_CreateTempFileFailed");
|
|
break;
|
|
|
|
case KVERR_ErrorWritingToOutputFile:
|
|
wsprintfA(szError, "KVERR_ErrorWritingToOutputFile");
|
|
break;
|
|
|
|
case KVERR_CreateProcessFailed:
|
|
wsprintfA(szError, "KVERR_CreateProcessFailed");
|
|
break;
|
|
|
|
case KVERR_WaitForChildFailed:
|
|
wsprintfA(szError, "KVERR_WaitForChildFailed");
|
|
break;
|
|
|
|
case KVERR_ChildTimeOut:
|
|
wsprintfA(szError, "KVERR_ChildTimeOut");
|
|
break;
|
|
|
|
case KVERR_ArchiveFileNotFound:
|
|
wsprintfA(szError, "KVERR_ArchiveFileNotFound");
|
|
break;
|
|
|
|
case KVERR_ArchiveFatalError:
|
|
wsprintfA(szError, "KVERR_ArchiveFatalError");
|
|
break;
|
|
|
|
default:
|
|
wsprintfA(szError, "%d", error);
|
|
}
|
|
|
|
WriteLog("%s: error code returned is %s\n", szTitle, szError);
|
|
}
|
|
|
|
/******************************************************************
|
|
*
|
|
* Porting GetProcAddress for different platforms *
|
|
*
|
|
* *****************************************************************/
|
|
|
|
void * myGetProcAddress(HINSTANCE hInst, char *funcName)
|
|
{
|
|
#if defined(_WINDOWS)
|
|
return GetProcAddress(hInst, funcName);
|
|
#elif defined (_HPUX11)
|
|
int result = 0;
|
|
void *fp = NULL;
|
|
shl_findsym((shl_t*)&hInst, funcName, TYPE_UNDEFINED, &fp);
|
|
if (result) fp = NULL;
|
|
return fp;
|
|
#else
|
|
return dlsym(hInst, funcName);
|
|
#endif
|
|
}
|
|
|
|
|
|
|
|
|
|
/*******************************************************************************
|
|
*
|
|
* function: filterArchive()
|
|
*
|
|
* summary: Takes an input file specification and extract archive file to a
|
|
* directory.
|
|
*
|
|
******************************************************************************/
|
|
int filterArchive(void *pFilter, char *pszFileIn, char *pszFileOut)
|
|
{
|
|
|
|
void *pArchiveContext = NULL;
|
|
int nFilesInArch;
|
|
int nIndex;
|
|
char acExtractFile[250];
|
|
char acPathFile[250];
|
|
|
|
int rcMkdir;
|
|
void *vpKVUtilLib = NULL;
|
|
int error = 0;
|
|
KVErrorCode nRet = KVERR_Success;
|
|
|
|
/* Open Archive File */
|
|
if ((pArchiveContext = (void *)(*FilterFunc.fpOpenArchiveFile)
|
|
(pFilter, pszFileIn)) == NULL)
|
|
{
|
|
fprintf(stderr, "Error: can't openning archive file %s.\n", pszFileIn);
|
|
nRet = KVERR_badInputStream;
|
|
|
|
/* Shut Down Archive */
|
|
/* Don't need to shut down again, because it is already shut down when
|
|
* fpOpenArchiveFile fails */
|
|
/*if( !(*FilterFunc.fpCloseArchiveFile)( pArchiveContext ) )
|
|
{
|
|
fprintf(stderr, "Error: shutting down archive file %s.\n", pszFileIn );
|
|
nRet = KVERR_General;
|
|
}*/
|
|
return (nRet);
|
|
}
|
|
|
|
/* Get Number of Files In Archive */
|
|
if ((nFilesInArch = (*FilterFunc.fpGetNumFilesInArchiveFile)
|
|
(pArchiveContext)) < 0)
|
|
{
|
|
fprintf(stderr, "Error: getting number of files in archive failed.\n");
|
|
nRet = KVERR_ArchiveFatalError;
|
|
|
|
/* Shut Down Archive */
|
|
if (!(*FilterFunc.fpCloseArchiveFile)(pArchiveContext))
|
|
{
|
|
fprintf(stderr, "Error: shutting down archive file.\n");
|
|
nRet = KVERR_General;
|
|
}
|
|
|
|
return (nRet);
|
|
}
|
|
|
|
|
|
/* create directory if not exist */
|
|
if (_access(pszFileOut, 0) == -1)
|
|
{
|
|
#ifdef _WINDOWS
|
|
rcMkdir = _mkdir(pszFileOut);
|
|
#else
|
|
rcMkdir = _mkdir(pszFileOut, 511);
|
|
#endif
|
|
if (rcMkdir)
|
|
{
|
|
fprintf(stderr, "Error: creating output directories %s\n", pszFileOut);
|
|
nRet = KVERR_CreateOutputFileFailed;
|
|
|
|
/* Shut Down Archive */
|
|
if (!(*FilterFunc.fpCloseArchiveFile)(pArchiveContext))
|
|
{
|
|
fprintf(stderr, "Error: shutting down archive file\n");
|
|
nRet = KVERR_General;
|
|
}
|
|
|
|
return (nRet);
|
|
}
|
|
}
|
|
|
|
for (nIndex = 0; nIndex < nFilesInArch; nIndex++)
|
|
{
|
|
TPArchiveFileInfo archiveInfo;
|
|
|
|
/* Get Archive File Info */
|
|
if ((nRet = (*FilterFunc.fpGetArchiveFileInfo)
|
|
(pArchiveContext, nIndex, &archiveInfo)) != KVERR_Success)
|
|
{
|
|
continue;
|
|
}
|
|
|
|
if (archiveInfo.bIsDir || archiveInfo.bNeedPwd)
|
|
{
|
|
nRet = KVERR_PasswordProtected;
|
|
continue;
|
|
}
|
|
|
|
/* assume no problem in creating directory... */
|
|
sprintf(acExtractFile, "%s/%s", pszFileOut, archiveInfo.szFilename);
|
|
|
|
/* create directory */
|
|
{
|
|
char *pBeginDir, *pEndDir, *pDir;
|
|
int length;
|
|
|
|
length = strlen(pszFileOut);
|
|
|
|
pBeginDir = acExtractFile + length + 1;
|
|
pEndDir = strrchr(acExtractFile, '/') + 1;
|
|
|
|
pDir = pBeginDir;
|
|
for (; pDir != pEndDir; pDir++)
|
|
{
|
|
switch ((char)*pDir)
|
|
{
|
|
case '/':
|
|
{
|
|
memcpy(acPathFile, acExtractFile, pDir - acExtractFile);
|
|
acPathFile[pDir - acExtractFile] = '\0';
|
|
#ifdef _WINDOWS
|
|
rcMkdir = _mkdir(acPathFile);
|
|
#else
|
|
rcMkdir = _mkdir(acPathFile, 511);
|
|
#endif
|
|
break;
|
|
}
|
|
default:
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
/* Extract Files In Archive */
|
|
nRet = (*FilterFunc.fpExtractArchiveFile)(pArchiveContext, nIndex, acExtractFile);
|
|
if (nRet != KVERR_Success)
|
|
{
|
|
fprintf(stderr, "Error: extracting files in archive...\n");
|
|
}
|
|
}
|
|
|
|
/* Shut Down Archive */
|
|
if (!(*FilterFunc.fpCloseArchiveFile)(pArchiveContext))
|
|
{
|
|
fprintf(stderr, "Error: shutting down archive file\n");
|
|
nRet = KVERR_General;
|
|
|
|
return (nRet);
|
|
}
|
|
|
|
/* return ok */
|
|
return(nRet);
|
|
|
|
}
|
|
|
|
|
|
|
|
/* ----------------------------------------------------------------------
|
|
* This function checks to see if the INI file exists by making a call
|
|
* to GetPrivateProfileString(). If the file is found, no further
|
|
* action is required. If the entry returns a blank, the path of the
|
|
* INI file is adjusted to match the current working directory and
|
|
* another attempt is made to read the first entry in the file. If this
|
|
* also fails, a warning message is output, indicating the INI file was
|
|
* not found but that the input file will be converted using the internal
|
|
* defaults.
|
|
* ---------------------------------------------------------------------*/
|
|
void LocateINIFile(char *szExecutable, char *szINIFile)
|
|
{
|
|
char szINIPath[_MAX_PATH];
|
|
char szINIFileName[_MAX_PATH];
|
|
char *pszINI = NULL;
|
|
char *pszPath = NULL;
|
|
char szReturnedString[GPPSTRINGMAXSIZE];
|
|
|
|
/* Attempt to find the first entry in the ini file */
|
|
GetPrivateProfileStringA("config0", "eKVFormat", "Not found", szReturnedString, GPPSTRINGMAXSIZE, szINIFile);
|
|
if (strcmp(szReturnedString, "Not found") == 0)
|
|
{
|
|
/* entry not found, try further */
|
|
char *pcTmp;
|
|
|
|
for (pcTmp = szExecutable; *pcTmp != '\0'; pcTmp++)
|
|
{
|
|
*pcTmp = (char)tolower((int)((char)(*pcTmp)));
|
|
}
|
|
|
|
/* Determine the directory of the executable, if we can */
|
|
strcpy(szINIPath, szExecutable);
|
|
pszPath = strstr(szExecutable, "filter");
|
|
szINIPath[pszPath - szExecutable] = '\0';
|
|
|
|
strcpy(szINIFileName, szINIFile);
|
|
pszINI = strrchr(szINIFileName, '/');
|
|
if (pszINI == NULL)
|
|
{
|
|
pszINI = strrchr(szINIFileName, '\\');
|
|
}
|
|
if (pszINI)
|
|
{
|
|
strcpy(szINIFileName, &pszINI[1]);
|
|
|
|
if (szINIFileName != NULL)
|
|
{
|
|
pszINI = szINIFileName;
|
|
}
|
|
}
|
|
strcat(szINIPath, szINIFileName);
|
|
|
|
#ifdef _WINDOWS
|
|
GetCurrentDirectoryA(_MAX_PATH, szINIPath);
|
|
strcat(szINIPath, "\\");
|
|
#else
|
|
strcpy(szINIPath, "./");
|
|
#endif
|
|
strcat(szINIPath, szINIFileName);
|
|
|
|
/* Attempt to find the first entry in the ini file */
|
|
GetPrivateProfileStringA("config0", "eKVFormat", "Not found", szReturnedString, GPPSTRINGMAXSIZE, szINIPath);
|
|
if (strcmp(szReturnedString, "Not found") != 0)
|
|
{
|
|
strcpy(szINIFile, szINIPath);
|
|
}
|
|
else
|
|
{
|
|
#if !defined (__mac_os)
|
|
printf("File <%s> not found or is not formatted as expected!\n", szINIPath);
|
|
printf("Conversion will proceed with internal defaults.\n");
|
|
#endif
|
|
}
|
|
}
|
|
}
|
|
|
|
/*----------------------------------------------------------------------
|
|
*
|
|
* SaveINIFileString
|
|
*
|
|
*---------------------------------------------------------------------*/
|
|
char* SaveINIFileString(char *szINIString)
|
|
{
|
|
char *psz = NULL;
|
|
int nLength = strlen(szINIString);
|
|
if (nLength == 0)
|
|
{
|
|
return NULL;
|
|
}
|
|
|
|
psz = (char *)malloc(nLength + 1);
|
|
|
|
#ifdef _WINDOWS
|
|
assert(psz != 0);
|
|
#endif
|
|
|
|
strcpy(psz, szINIString);
|
|
return psz;
|
|
}
|
|
|
|
/*----------------------------------------------------------------------
|
|
*
|
|
*---------------------------------------------------------------------*/
|
|
ENdocFmt FindFormatID(char *szInputString)
|
|
{
|
|
if (strcmp(szInputString, "MS_Word_XML_Fmt") == 0)
|
|
return MS_Word_XML_Fmt;
|
|
if (strcmp(szInputString, "MS_Excel_XML_Fmt") == 0)
|
|
return MS_Excel_XML_Fmt;
|
|
if (strcmp(szInputString, "MS_Visio_XML_Fmt") == 0)
|
|
return MS_Visio_XML_Fmt;
|
|
if (strcmp(szInputString, "SO_Text_XML_Fmt") == 0)
|
|
return SO_Text_XML_Fmt;
|
|
if (strcmp(szInputString, "SO_Spreadsheet_XML_Fmt") == 0)
|
|
return SO_Spreadsheet_XML_Fmt;
|
|
if (strcmp(szInputString, "SO_Presentation_XML_Fmt") == 0)
|
|
return SO_Presentation_XML_Fmt;
|
|
|
|
return Unknown_Fmt;
|
|
}
|
|
|
|
/*----------------------------------------------------------------------
|
|
*
|
|
*---------------------------------------------------------------------*/
|
|
BOOL GetKVXConfigInfo(FilterLsv *lsv, KVXConfigInfo *pXInfo, int n)
|
|
{
|
|
BOOL bRet = TRUE;
|
|
char szSection[16];
|
|
char szReturnedString[GPPSTRINGMAXSIZE];
|
|
|
|
sprintf(szSection, "config%d", n);
|
|
GetPrivateProfileStringA(szSection, "eKVFormat", "Not found", szReturnedString, GPPSTRINGMAXSIZE, lsv->szXMLConfigFile);
|
|
if (strcmp(szReturnedString, "Not found") == 0)
|
|
{
|
|
bRet = FALSE;
|
|
}
|
|
else
|
|
{
|
|
pXInfo->eKVFormat = FindFormatID(szReturnedString);
|
|
|
|
GetPrivateProfileStringA(szSection, "szRoot", "", szReturnedString, GPPSTRINGMAXSIZE, lsv->szXMLConfigFile);
|
|
pXInfo->pszRoot = SaveINIFileString(szReturnedString);
|
|
|
|
GetPrivateProfileStringA(szSection, "szInMetaElement", "", szReturnedString, GPPSTRINGMAXSIZE, lsv->szXMLConfigFile);
|
|
pXInfo->pszInMeta = SaveINIFileString(szReturnedString);
|
|
|
|
GetPrivateProfileStringA(szSection, "szExMetaElement", "", szReturnedString, GPPSTRINGMAXSIZE, lsv->szXMLConfigFile);
|
|
pXInfo->pszExMeta = SaveINIFileString(szReturnedString);
|
|
|
|
GetPrivateProfileStringA(szSection, "szInContentElement", "", szReturnedString, GPPSTRINGMAXSIZE, lsv->szXMLConfigFile);
|
|
pXInfo->pszInContent = SaveINIFileString(szReturnedString);
|
|
|
|
GetPrivateProfileStringA(szSection, "szExContentElement", "", szReturnedString, GPPSTRINGMAXSIZE, lsv->szXMLConfigFile);
|
|
pXInfo->pszExContent = SaveINIFileString(szReturnedString);
|
|
|
|
GetPrivateProfileStringA(szSection, "szInAttribute", "", szReturnedString, GPPSTRINGMAXSIZE, lsv->szXMLConfigFile);
|
|
pXInfo->pszInAttribute = SaveINIFileString(szReturnedString);
|
|
}
|
|
return bRet;
|
|
}
|
|
|
|
/*----------------------------------------------------------------------
|
|
*
|
|
*---------------------------------------------------------------------*/
|
|
BOOL FreeKVXConfigInfo(KVXConfigInfo *pXInfo)
|
|
{
|
|
BOOL bRet = TRUE;
|
|
|
|
if (!pXInfo) return bRet;
|
|
|
|
if (pXInfo->pszRoot)
|
|
free(pXInfo->pszRoot);
|
|
if (pXInfo->pszInMeta)
|
|
free(pXInfo->pszInMeta);
|
|
if (pXInfo->pszExMeta)
|
|
free(pXInfo->pszExMeta);
|
|
if (pXInfo->pszInContent)
|
|
free(pXInfo->pszInContent);
|
|
if (pXInfo->pszExContent)
|
|
free(pXInfo->pszExContent);
|
|
if (pXInfo->pszInAttribute)
|
|
free(pXInfo->pszInAttribute);
|
|
|
|
return bRet;
|
|
}
|
|
|
|
/******************************************************************************
|
|
******************************************************************************/
|
|
void FileTimeToUnixTime(LONGLONG pft, time_t* t)
|
|
{
|
|
LONGLONG ll = 0;
|
|
#if defined (KV_BIG_ENDIAN)
|
|
{
|
|
int i;
|
|
for (i = 0; i < 64; i += 8) {
|
|
ll |= (LONGLONG)((BYTE)(pft >> i)) << (56 - i);
|
|
}
|
|
}
|
|
#else
|
|
ll = pft;
|
|
#endif
|
|
|
|
#if defined (_WINDOWS)
|
|
if (ll >= 116444736000000000)
|
|
{
|
|
ll = ll - 116444736000000000;
|
|
}
|
|
#else
|
|
if (ll >= 116444736000000000LL)
|
|
{
|
|
ll = ll - 116444736000000000LL;
|
|
}
|
|
#endif
|
|
|
|
else
|
|
{
|
|
ll = 0;
|
|
}
|
|
#if defined (KV_SIZEOF_LONG_IS_64_BITS)
|
|
*t = (unsigned int)(ll / 10000000L);
|
|
#else
|
|
*t = (unsigned long)(ll / 10000000L);
|
|
#endif
|
|
}
|
|
|
|
int encodeutf8(unsigned long u, unsigned char *buf, size_t maxbytes)
|
|
{
|
|
static const struct {
|
|
int nbytes;
|
|
unsigned long max;
|
|
} tab[] = {
|
|
{ 1, 0x0000007F },
|
|
{ 2, 0x000007FF },
|
|
{ 3, 0x0000FFFF },
|
|
{ 4, 0x001FFFFF },
|
|
{ 5, 0x03FFFFFF },
|
|
{ 6, 0x7FFFFFFF },
|
|
};
|
|
static const int ntab = sizeof(tab) / sizeof(tab[0]);
|
|
int i, j;
|
|
|
|
if (u > tab[ntab - 1].max)
|
|
return -1;
|
|
|
|
for (i = 0; i < ntab; ++i) {
|
|
if (u <= tab[i].max)
|
|
break;
|
|
}
|
|
assert(i < ntab);
|
|
|
|
if (tab[i].nbytes > maxbytes)
|
|
return -1;
|
|
|
|
if (tab[i].nbytes == 1) { /* Special case */
|
|
buf[0] = u;
|
|
}
|
|
else {
|
|
for (j = tab[i].nbytes - 1; j > 0; --j) {
|
|
buf[j] = 0x80 | (u & 0x3f);
|
|
u >>= 6;
|
|
}
|
|
|
|
unsigned char mask = ~(0xFF >> tab[i].nbytes);
|
|
buf[0] = mask | u;
|
|
}
|
|
|
|
return tab[i].nbytes;
|
|
}
|
|
|
|
int high_ones(int c) {
|
|
int n;
|
|
|
|
for (n = 0; (c & 0x80) == 0x80; c <<= 1)
|
|
++n;
|
|
return n;
|
|
}
|
|
|
|
|
|
unsigned long decodeutf8(unsigned char *buf, int nbytes)
|
|
{
|
|
unsigned long u;
|
|
int i, j;
|
|
|
|
if (nbytes <= 0)
|
|
return INVALID_CHAR;
|
|
|
|
if (nbytes == 1) {
|
|
if (buf[0] >= 0x80)
|
|
return INVALID_CHAR;
|
|
return buf[0];
|
|
}
|
|
|
|
i = high_ones(buf[0]);
|
|
if (i != nbytes)
|
|
return INVALID_CHAR;
|
|
u = buf[0] & (0xff >> i);
|
|
for (j = 1; j < nbytes; ++j) {
|
|
if ((buf[j] & 0xC0) != 0x80)
|
|
return INVALID_CHAR;
|
|
u = (u << 6) | (buf[j] & 0x3f);
|
|
}
|
|
|
|
/* Conforming UTF-8 cannot contain codes 0xd800쭯0xdfff (UTF-16
|
|
surrogates) as well as 0xfffe and 0xffff. */
|
|
if (u >= 0xD800 && u <= 0xDFFF)
|
|
return INVALID_CHAR;
|
|
if (u == 0xFFFE || u == 0xFFFF)
|
|
return INVALID_CHAR;
|
|
|
|
return u;
|
|
}
|
|
|
|
|
|
int is_utf8_byte_stream(FILE *file, int quiet) {
|
|
enum { MAX_UTF8_BYTES = 6 };
|
|
unsigned char buf[MAX_UTF8_BYTES];
|
|
unsigned char buf2[MAX_UTF8_BYTES];
|
|
int nbytes, nbytes2;
|
|
int c;
|
|
unsigned long code;
|
|
unsigned long line, col, byteoff;
|
|
|
|
nbytes = 0;
|
|
line = 1;
|
|
col = 1;
|
|
byteoff = 0;
|
|
|
|
for (;;) {
|
|
c = getc(file);
|
|
|
|
if (c == EOF || c < 0x80 || (c & 0xC0) != 0x80) {
|
|
/* New char starts, deal with previous one. */
|
|
if (nbytes > 0) {
|
|
code = decodeutf8(buf, nbytes);
|
|
if (code == INVALID_CHAR)
|
|
goto error;
|
|
nbytes2 = encodeutf8(code, buf2,
|
|
MAX_UTF8_BYTES);
|
|
if (nbytes != nbytes2 ||
|
|
memcmp(buf, buf2, nbytes) != 0)
|
|
goto error;
|
|
++col;
|
|
}
|
|
nbytes = 0;
|
|
/* If it's UTF8, start collecting again. */
|
|
if (c != EOF && c >= 0x80)
|
|
buf[nbytes++] = c;
|
|
}
|
|
else {
|
|
/* This is a continuation byte, append to buffer. */
|
|
if (nbytes == MAX_UTF8_BYTES)
|
|
goto error;
|
|
buf[nbytes++] = c;
|
|
}
|
|
|
|
if (c == EOF)
|
|
break;
|
|
else if (c == '\n') {
|
|
++line;
|
|
byteoff = 0;
|
|
col = 1;
|
|
}
|
|
else
|
|
++byteoff;
|
|
}
|
|
|
|
if (nbytes != 0)
|
|
goto error;
|
|
|
|
return 1;
|
|
|
|
error:
|
|
if (!quiet) {
|
|
printf("line %lu, char %lu, byte offset %lu: "
|
|
"invalid UTF-8 code\n", line, col, byteoff);
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
int JudgeUtf8File(TCHAR * FileName)
|
|
{
|
|
int ok = 1;
|
|
FILE *file = NULL;
|
|
|
|
file = _tfopen(FileName, _T("r"));
|
|
if (file == NULL)
|
|
{
|
|
// should never occur
|
|
ok = -1;
|
|
}
|
|
else
|
|
{
|
|
if (!is_utf8_byte_stream(file))
|
|
ok = 0;
|
|
|
|
fclose(file);
|
|
}
|
|
|
|
return ok;
|
|
}
|
|
|
|
int ConvertAnsi2Utf8(TCHAR *szSrcAnsi, TCHAR *szDesUtf8)
|
|
{
|
|
HANDLE hFile = CreateFile(szSrcAnsi,
|
|
GENERIC_READ,
|
|
FILE_SHARE_READ,
|
|
NULL,
|
|
OPEN_EXISTING,
|
|
FILE_ATTRIBUTE_NORMAL,
|
|
NULL);
|
|
|
|
if (INVALID_HANDLE_VALUE == hFile)
|
|
{
|
|
return -1;
|
|
}
|
|
DWORD dwFileSize = GetFileSize(hFile, NULL);
|
|
if (INVALID_FILE_SIZE == dwFileSize)
|
|
{
|
|
CloseHandle(hFile);
|
|
hFile = NULL;
|
|
|
|
return -2;
|
|
}
|
|
|
|
char * szAnsiBuf = new char[dwFileSize + 1];
|
|
if (NULL == szAnsiBuf)
|
|
{
|
|
CloseHandle(hFile);
|
|
hFile = NULL;
|
|
return -3;
|
|
}
|
|
|
|
memset(szAnsiBuf, 0, dwFileSize + 1);
|
|
|
|
DWORD dwBytesRead = 0;
|
|
if (!ReadFile(hFile, szAnsiBuf, dwFileSize, &dwBytesRead, NULL))
|
|
{
|
|
if (NULL != szAnsiBuf)
|
|
{
|
|
delete[] szAnsiBuf;
|
|
szAnsiBuf = NULL;
|
|
}
|
|
|
|
CloseHandle(hFile);
|
|
hFile = NULL;
|
|
|
|
|
|
return -4;
|
|
}
|
|
|
|
CloseHandle(hFile);
|
|
hFile = NULL;
|
|
|
|
|
|
wchar_t *szUnicodeBuf = new wchar_t[dwFileSize + 1];
|
|
memset(szUnicodeBuf, 0, sizeof(wchar_t)*(dwFileSize + 1));
|
|
|
|
int nWCHAR = MultiByteToWideChar(CP_ACP, 0, szAnsiBuf, dwFileSize, szUnicodeBuf, dwFileSize);
|
|
|
|
int nUTF8 = WideCharToMultiByte(CP_UTF8, 0, szUnicodeBuf, nWCHAR, NULL, 0, NULL, NULL);
|
|
|
|
char *szUTF8Buf = new char[nUTF8 + 1];
|
|
memset(szUTF8Buf, 0, nUTF8 + 1);
|
|
|
|
|
|
WideCharToMultiByte(CP_UTF8, 0, szUnicodeBuf, nWCHAR, szUTF8Buf, nUTF8, NULL, NULL);
|
|
|
|
int iRet = 0;
|
|
FILE * fo = _tfopen(szDesUtf8, _T("wb"));
|
|
|
|
if (!fo)
|
|
{
|
|
|
|
iRet = -5;
|
|
}
|
|
else
|
|
{
|
|
if (nUTF8 != fwrite(szUTF8Buf, 1, nUTF8, fo))
|
|
{
|
|
iRet = -6;
|
|
}
|
|
}
|
|
|
|
if (fo)
|
|
{
|
|
fclose(fo);
|
|
}
|
|
|
|
delete[]szAnsiBuf;
|
|
delete[]szUnicodeBuf;
|
|
delete[]szUTF8Buf;
|
|
|
|
return iRet;
|
|
} |