recognizer.cpp
上传用户:dangjiwu
上传日期:2013-07-19
资源大小:42019k
文件大小:12k
- #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_RESULT
- CHXFileRecognizer::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, "377330377340", 4, "image/jpeg" },
- { 0, "BM", 2, "image/bmp" },
- { 0, "355253356333", 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_RESULT
- CHXFileRecognizer::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 03", 4) == 0)
- {
- bID3 = TRUE;
- }
- }
- if (bMPA || bID3)
- {
- res = HXR_OK;
- pMimeType = "audio/mp3";
- }
- return res;
- }
- HX_RESULT
- CHXFileRecognizer::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, "nr")) // 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_RESULT
- CHXFileRecognizer::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, "nr")) // 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)
- BOOL
- CHXFileRecognizer::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;
- }
- void
- CHXFileRecognizer::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);
- }