/* * This is a part of the BugTrap package. * Copyright (c) 2005-2009 IntelleSoft. * All rights reserved. * * Description: Text format analyzer. * Author: Maksim Pyatkovskiy. * * This source code is only intended as a supplement to the * BugTrap package reference and related electronic documentation * provided with the product. See these sources for detailed * information regarding the BugTrap package. */ #include "StdAfx.h" #include "TextFormat.h" #include "BugTrapUtils.h" #ifdef _DEBUG #define new DEBUG_NEW #endif /** * @brief Detect file format and encoding. * @param pszFileName - file name. * @param hFile - file handle. * @param bTextFile - true if file contains text and false for binary files. * @param eEncoding - text encoding. * @return sizeof of encoding signature. */ DWORD DetectFileFormat(PCTSTR pszFileName, HANDLE hFile, BOOL& bTextFile, TEXT_ENCODING& eEncoding) { _ASSERTE(hFile != INVALID_HANDLE_VALUE); BYTE arrBuffer[100]; DWORD dwNumRead = 0; if (! ReadFile(hFile, arrBuffer, sizeof(arrBuffer), &dwNumRead, NULL)) { bTextFile = FALSE; eEncoding = TXTENC_ANSI; SetFilePointer(hFile, 0, NULL, FILE_BEGIN); return 0; } static const TCHAR szXmlFileExt[] = _T(".xml"); const size_t nXmlFileExtLength = countof(szXmlFileExt) - 1; size_t nFileNameLength = _tcslen(pszFileName); BOOL bIsXmlFile = nFileNameLength >= nXmlFileExtLength && _tcsicmp(pszFileName + nFileNameLength - nXmlFileExtLength, szXmlFileExt) == 0; bTextFile = TRUE; DWORD dwStartPos, dwCharSize, dwOffsetFromStart; if (dwNumRead >= sizeof(g_arrUTF16LEPreamble) && memcmp(arrBuffer, g_arrUTF16LEPreamble, sizeof(g_arrUTF16LEPreamble)) == 0) { eEncoding = TXTENC_UTF16LE; dwStartPos = sizeof(g_arrUTF16LEPreamble); dwCharSize = sizeof(WCHAR); dwOffsetFromStart = 0; } else if (dwNumRead >= sizeof(g_arrUTF16BEPreamble) && memcmp(arrBuffer, g_arrUTF16BEPreamble, sizeof(g_arrUTF16BEPreamble)) == 0) { eEncoding = TXTENC_UTF16BE; dwStartPos = sizeof(g_arrUTF16BEPreamble); dwCharSize = sizeof(WCHAR); dwOffsetFromStart = 1; } else if (dwNumRead >= sizeof(g_arrUTF8Preamble) && memcmp(arrBuffer, g_arrUTF8Preamble, sizeof(g_arrUTF8Preamble)) == 0) { eEncoding = TXTENC_UTF8; dwStartPos = sizeof(g_arrUTF8Preamble); dwCharSize = sizeof(CHAR); dwOffsetFromStart = 0; } else if (bIsXmlFile) { static const CHAR szXmlProcessingInstruction[] = "= dwXmlProcessingInstructionLength && _memicmp(arrBuffer, szXmlProcessingInstruction, dwXmlProcessingInstructionLength) == 0) { DWORD dwBytePos = dwXmlProcessingInstructionLength; while (dwBytePos < dwNumRead) { while (dwBytePos < dwNumRead && IsSpace(arrBuffer[dwBytePos])) ++dwBytePos; if (dwBytePos >= dwNumRead || arrBuffer[dwBytePos] == '?') break; DWORD dwWordStart = dwBytePos; while (dwBytePos < dwNumRead && IsAlpha(arrBuffer[dwBytePos])) ++dwBytePos; DWORD dwWordLength = dwBytePos - dwWordStart; if (dwWordLength == 0) break; while (dwBytePos < dwNumRead && IsSpace(arrBuffer[dwBytePos])) ++dwBytePos; if (dwBytePos < dwNumRead && arrBuffer[dwBytePos] == '=') ++dwBytePos; else break; while (dwBytePos < dwNumRead && IsSpace(arrBuffer[dwBytePos])) ++dwBytePos; if (dwBytePos < dwNumRead && IsQuotation(arrBuffer[dwBytePos])) ++dwBytePos; else break; if (dwBytePos < dwNumRead) { DWORD dwValueStart = dwBytePos; while (dwBytePos < dwNumRead && ! IsQuotation(arrBuffer[dwBytePos])) ++dwBytePos; DWORD dwValueLength = dwBytePos - dwValueStart; if (dwBytePos < dwNumRead) ++dwBytePos; if (dwWordLength == dwEncodingAttributeLength && _memicmp(arrBuffer + dwWordStart, szEncodingAttribute, dwWordLength) == 0) { if (dwValueLength != dwUTF8EncodingLength || _memicmp(arrBuffer + dwValueStart, szUTF8Encoding, dwUTF8EncodingLength) != 0) eEncoding = TXTENC_ANSI; break; } } } } } else { eEncoding = TXTENC_ANSI; dwStartPos = dwOffsetFromStart = 0; dwCharSize = sizeof(CHAR); } for (DWORD dwBytePos = dwStartPos + dwOffsetFromStart; dwBytePos < dwNumRead; dwBytePos += dwCharSize) { if (arrBuffer[dwBytePos] == 0) { bTextFile = FALSE; eEncoding = TXTENC_ANSI; dwStartPos = 0; break; } } return dwStartPos; }