📄 recognizer.cpp
字号:
#include "ihxpckts.h"#include "hxbuffer.h"#include "hlxclib/ctype.h" /* for isspace() */#include "hxmarsh.h" /* for getshort() */#include "recognizer.h"#define REALMEDIA_MIME_TYPE "application/x-pn-realmedia"#define REALAUDIO_MIME_TYPE "audio/x-pn-realaudio"#define FLASH_MIME_TYPE "application/x-shockwave-flash"#define REALAUDIO_METAFILE_MIME_TYPE "audio/x-pn-realaudio"#define REALAUDIO_PLUGIN_MIME_TYPE "audio/x-pn-realaudio-plugin"#define SMIL_MIME_TYPE "application/smil"// length of buffer read from file and passed to recognizer#if defined(_UNIX) && !defined(_MAC_UNIX)// we want a little more data, since we need to try to detect smil, ram and mp3#define RECOG_LEN 4096#else#define RECOG_LEN 512#endif #if !defined (_SYMBIAN)HX_RESULT CHXFileRecognizer::GetMimeType(const char* pFileName, IHXBuffer* pBuffer, REF(IHXBuffer*) pMimeType){ HX_RESULT res = HXR_FAIL; const char* pMimeTypeStr = NULL;#if defined(_UNIX) && !defined(_MAC_UNIX) do { res = GetMimeTypeFromMagic(pBuffer, pMimeTypeStr); if (SUCCEEDED(res)) break; res = TestSMILFile(pBuffer, pFileName, pMimeTypeStr); if (SUCCEEDED(res)) break; res = TestRAMFile(pBuffer, pFileName, pMimeTypeStr); if (SUCCEEDED(res)) break; res = TestMP3File(pBuffer, pFileName, pMimeTypeStr); } while (0);#else // #if defined(_UNIX) && !defined(_MAC_UNIX) if (IsSDPFile(pBuffer)) { pMimeTypeStr = "application/sdp"; res = HXR_OK; }#endif // #if defined(_UNIX) && !defined(_MAC_UNIX) if (pMimeTypeStr) { // convert mime type to IHXBuffer pMimeType = new CHXBuffer; if (pMimeType) { pMimeType->AddRef(); int len = strlen(pMimeTypeStr); res = pMimeType->Set((const UCHAR*)pMimeTypeStr, len + 1); if (FAILED(res)) { HX_RELEASE(pMimeType); } } else { res = HXR_OUTOFMEMORY; } } return res;}#endif#if defined(_UNIX) && !defined(_MAC_UNIX)HX_RESULTCHXFileRecognizer::GetMimeTypeFromMagic(IHXBuffer* pBuffer, REF(const char*) pMimeType){ HX_RESULT res = HXR_FAIL; pMimeType = NULL; HX_ASSERT(pBuffer); if (pBuffer && pBuffer->GetSize()) { UCHAR* pData = pBuffer->GetBuffer(); UINT32 uLength = pBuffer->GetSize(); // map magic data to a mime type typedef struct { UINT32 uOffset; const char* pMagic; UINT32 uLength; const char* pMimeType; } magic_data; // these are the magic tricks we know const magic_data kMagicMap[] = { { 0, "v=", 2, "application/sdp" }, { 0, ".RA ", 4, REALAUDIO_MIME_TYPE }, { 0, ".RMF", 4, REALMEDIA_MIME_TYPE }, { 0, ".RMS", 4, REALMEDIA_MIME_TYPE }, { 0, "OggS", 4, "audio/x-ogg", }, { 0, "#!AMR", 5, "audio/amr" }, { 0, "WAVE", 4, "audio/x-wav" }, { 0, "GIF89a", 6, "image/gif" }, { 0, "GIF87a", 6, "image/gif" }, { 0, "\211PNG", 4, "image/png" }, { 0, "\377\330\377\340", 4, "image/jpeg" }, { 0, "BM", 2, "image/bmp" }, { 0, "\355\253\356\333", 4, "application/x-rpm" }, { 0, "FWS", 3, FLASH_MIME_TYPE }, { 0, "CWS", 3, FLASH_MIME_TYPE }, { 0, "#EXTM3U", 7, "audio/scpls" }, { 0, NULL, 0, NULL } // null terminator }; // find a matching magic string for (const magic_data* pCursor = kMagicMap; pCursor->pMagic; ++pCursor) { if (pCursor->uOffset + pCursor->uLength < uLength && memcmp(pData + pCursor->uOffset, pCursor->pMagic, pCursor->uLength) == 0) { pMimeType = pCursor->pMimeType; res = HXR_OK; break; } } } return res;}HX_RESULTCHXFileRecognizer::TestMP3File(IHXBuffer* pBuffer, const char* pFileName, REF(const char*) pMimeType){ HX_RESULT res = HXR_FAIL; HX_ASSERT(pBuffer); BOOL bMPA = FALSE; BOOL bID3 = FALSE; if (pBuffer->GetSize() >= 4) { const char* pBegin = (const char*)pBuffer->GetBuffer(); // XXXNH: I stole this from /usr/share/misc/magic and it seems to // do a good job of guessing mp3 UINT16 uShort = getshort((UINT8*)pBegin); if ((uShort & 0xffe0) == 0xffe0 && (uShort & 0x0018) != 0x0008 && (uShort & 0x0006) != 0x0000) { bMPA = TRUE; } else if (memcmp(pBegin, "ID3\003", 4) == 0) { bID3 = TRUE; } } if (bMPA || bID3) { res = HXR_OK; pMimeType = "audio/mp3"; } return res;}HX_RESULTCHXFileRecognizer::TestSMILFile(IHXBuffer* pBuffer, const char* pFileName, REF(const char*) pMimeType){ HX_RESULT res = HXR_FAIL; HX_ASSERT(pBuffer); const char* pExt = strrchr(pFileName, '.'); BOOL bValidExt = pExt && (strcasecmp(pExt, ".smi") == 0 || strcasecmp(pExt, ".smil") == 0); const char* pBegin = (const char*)pBuffer->GetBuffer(); UINT32 uLen = pBuffer->GetSize(); const char* pEnd = (const char*)((UINT32)pBegin + uLen); BOOL bSMILFound = FALSE; BOOL bBodyFound = FALSE; for (const char* pCursor = pBegin; (!bSMILFound || !bBodyFound) && pCursor && pCursor < pEnd; pCursor = strpbrk(pCursor+1, "\n\r")) // next line { // eat whitespace while (isspace(*pCursor) && pCursor < pEnd) ++pCursor; const char* pTag = strchr(pCursor, '<'); while (pTag && (!bSMILFound || !bBodyFound)) { if (!bSMILFound && strncasecmp(pTag, "<smil", 5) == 0) { bSMILFound = TRUE; } else if (!bBodyFound && strncasecmp(pTag, "<body", 5) == 0) { bBodyFound = TRUE; } pTag = strchr(pTag+1, '<'); } } if (bSMILFound && (bBodyFound || bValidExt)) { // very likely a SMIL file pMimeType = SMIL_MIME_TYPE; res = HXR_OK; } return res;}HX_RESULTCHXFileRecognizer::TestRAMFile(IHXBuffer* pBuffer, const char* pFileName, REF(const char*) pMimeType){ HX_RESULT res = HXR_FAIL; HX_ASSERT(pBuffer); const char* pBegin = (const char*)pBuffer->GetBuffer(); UINT32 uLen = pBuffer->GetSize(); const char* pEnd = (const char*)((UINT32)pBegin + uLen); BOOL bProtocolFound = FALSE; BOOL bHTML = FALSE; for (const char* pCursor = pBegin; pCursor && pCursor < pEnd; pCursor = strpbrk(pCursor+1, "\n\r")) // next line { // eat whitespace while (isspace(*pCursor) && pCursor < pEnd) ++pCursor; if (pCursor && pCursor < pEnd && *pCursor != '#') // skip comments { // do we have an html tag? const char* pTag = strchr(pCursor, '<'); if (pTag && strncasecmp(pCursor, "<html", 5) == 0) { bHTML = TRUE; break; } // find a protocol? if (strncasecmp(pCursor, "rtsp://", 7) == 0 || strncasecmp(pCursor, "http://", 7) == 0 || strncasecmp(pCursor, "file://", 7) == 0 || strncasecmp(pCursor, "pnm://", 6) == 0) { bProtocolFound = TRUE; break; } } } if (!bHTML && bProtocolFound) { // this is probably a RAM file const char* pExt = strrchr(pFileName, '.'); if (pExt && strcasecmp(pExt, ".rpm") == 0) { pMimeType = REALAUDIO_PLUGIN_MIME_TYPE; } else { pMimeType = REALAUDIO_METAFILE_MIME_TYPE; } res = HXR_OK; } return res;}#else // #if defined(_UNIX) && !defined(_MAC_UNIX)BOOLCHXFileRecognizer::IsSDPFile(IHXBuffer* pBuffer){ BOOL bResult = FALSE; if (pBuffer && pBuffer->GetSize()) { if (0 == strncmp((const char*)pBuffer->GetBuffer(), "v=", 2)) { bResult = TRUE; } } return bResult;}#endif // #if defined(_UNIX) && !defined(_MAC_UNIX)CHXFileRecognizer::CHXFileRecognizer() : m_lRefCount(0), m_pFile(NULL), m_pResponse(NULL), m_pBuffer(NULL), m_bGetMimeTypeDone(FALSE){}CHXFileRecognizer::~CHXFileRecognizer(){ HX_RELEASE(m_pBuffer); HX_RELEASE(m_pResponse); HX_RELEASE(m_pFile);}STDMETHODIMP CHXFileRecognizer::QueryInterface(REFIID riid, void** ppvObj){ HX_RESULT ret = HXR_OK; if (IsEqualIID(riid, IID_IHXFileRecognizer)) { AddRef(); *ppvObj = (IHXFileRecognizer*)this; } else if (IsEqualIID(riid, IID_IHXFileResponse)) { AddRef(); *ppvObj = (IHXFileResponse*)this; } else if (IsEqualIID(riid, IID_IUnknown)) { AddRef(); *ppvObj = this; } else { *ppvObj = NULL; ret = HXR_NOINTERFACE; } return ret;}STDMETHODIMP_(ULONG32) CHXFileRecognizer::AddRef(){ return InterlockedIncrement(&m_lRefCount);}STDMETHODIMP_(ULONG32) CHXFileRecognizer::Release(){ if (InterlockedDecrement(&m_lRefCount) > 0) { return m_lRefCount; } delete this; return 0;}STDMETHODIMP CHXFileRecognizer::GetMimeType(IHXFileObject* /*IN*/ pFile, IHXFileRecognizerResponse* /*IN*/ pRecognizerResponse){ HX_RESULT ret = HXR_FAIL; if (pRecognizerResponse) { m_pResponse = pRecognizerResponse; m_pResponse->AddRef(); } // get our own IHXFileResponse interface IHXFileResponse* pFileResponse = NULL; ret = QueryInterface(IID_IHXFileResponse, (void**) &pFileResponse); if (SUCCEEDED(ret) && pFileResponse && pFile != NULL) { m_pFile = pFile; m_pFile->AddRef(); ret = m_pFile->Init(HX_FILE_READ | HX_FILE_BINARY, pFileResponse); } if (FAILED(ret) && m_pResponse) { m_pResponse->GetMimeTypeDone(ret, NULL); } HX_RELEASE(pFileResponse); return ret;}STDMETHODIMP CHXFileRecognizer::InitDone(HX_RESULT status){ if (SUCCEEDED(status)) { status = m_pFile->Read(RECOG_LEN); } if (FAILED(status) && m_pResponse) { m_pResponse->GetMimeTypeDone(status, NULL); } return status;}STDMETHODIMP CHXFileRecognizer::SeekDone(HX_RESULT /* status */){ if (!m_bGetMimeTypeDone) { DoFileRecognize(); HX_RELEASE(m_pBuffer); } return HXR_OK;}STDMETHODIMP CHXFileRecognizer::ReadDone(HX_RESULT status, IHXBuffer* pBuffer){ if (FAILED(status) && m_pResponse) { m_pResponse->GetMimeTypeDone(HXR_FAIL, NULL); } else { HX_ASSERT(!m_pBuffer); m_pBuffer = pBuffer; HX_ADDREF(m_pBuffer); // seek back to the beginning of the file // since the same file object will be passed to the file format if (HXR_OK != m_pFile->Seek(0, FALSE) && !m_bGetMimeTypeDone) { DoFileRecognize(); HX_RELEASE(m_pBuffer); } } return HXR_OK;}STDMETHODIMP CHXFileRecognizer::WriteDone(HX_RESULT /* status */){ return HXR_OK;}STDMETHODIMP CHXFileRecognizer::CloseDone(HX_RESULT /* status */){ return HXR_OK;}voidCHXFileRecognizer::DoFileRecognize(void){ HX_RESULT ret = HXR_OK; IHXBuffer* pMimeType = NULL; const char* pFileName = NULL; m_bGetMimeTypeDone = TRUE; if (m_pFile) m_pFile->GetFilename(pFileName); ret = GetMimeType(pFileName, m_pBuffer, pMimeType); if (SUCCEEDED(ret) && pMimeType && pMimeType->GetSize() > 0 && m_pResponse) { m_pResponse->GetMimeTypeDone(HXR_OK, pMimeType); } else { m_pResponse->GetMimeTypeDone(HXR_FAIL, NULL); } HX_RELEASE(pMimeType);}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -