📄 smlffpln.cpp
字号:
//
STDMETHODIMP CSmilFileFormat::ReadDone
(
HX_RESULT status,
IHXBuffer* pBuffer
)
{
HX_RESULT result = HXR_OK;
if ( SUCCEEDED(status) )
{
HX_ASSERT(pBuffer);
// /For determining what type file this is (via namespace URI), we'll
// hold onto the first pBuffer for later when we handle stream header:
if (!m_pStartOfFile)
{
pBuffer->AddRef();
m_pStartOfFile = pBuffer;
}
BreakUpBuffer(pBuffer);
// recurse...
m_pFileObject->Read(FileChunkSize);
}
else
{
// check see if we have a packet that needs added to the array.
if ( m_pCurrentPacketData )
{
UCHAR* pCb = m_pCurrentPacketData->pBuffer->GetBuffer();
pCb[m_ulCurrentBufferPos++] = '\"';
pCb[m_ulCurrentBufferPos++] = ')';
pCb[m_ulCurrentBufferPos++] = '\0';
m_pCurrentPacketData->pBuffer->SetSize(m_ulCurrentBufferPos);
m_pArrayOfPackets->Add((void*)m_pCurrentPacketData);
m_pCurrentPacketData = NULL;
m_ulCurrentBufferPos = 0;
}
// finished reading, calculate the number of packets to send:
m_ulPacketCount = m_ulCurrentPacket;
m_ulCurrentPacket = 0;
m_state = Ready;
m_pFFResponse->InitDone(result);
}
return result;
}
/////////////////////////////////////////////////////////////////////////
// Method:
// GetSMILFileVersion
// Purpose:
// This Function will break the buffer into packets.
//
// This function maintains a state, such that multiple buffers should
// Be able to be passed into it at any point...
//
HX_RESULT
CSmilFileFormat::GetSMILFileVersion()
{
HX_RESULT pnreslt = HXR_OK;
const char* pSmilTag = NULL;
const char* pCloseOfSmilTag = NULL;
const char* pXmlns = NULL;
const char* pXmlnsOpenQuotationMark = NULL;
const char* pBuf = NULL;
ULONG32 ulBufLen = 0;
const char* pEqualsSign = NULL;
const char* pTmp = NULL;
char* pTmp2 = NULL;
char* pszStartOfFile = NULL;
ULONG32 ulCount = 0;
LONG32 lNumCommentsOpen = 0;
if (!m_pStartOfFile)
{
pnreslt = HXR_BUFFERTOOSMALL;
goto cleanup;
}
// /Fixes PR 59282: m_pStartOfFile is not necessarily NULL-terminated,
// so we have to limit our access of it to the size of the buffer (duh!):
ulBufLen = m_pStartOfFile->GetSize();
pBuf = (const char*)m_pStartOfFile->GetBuffer();
if (!pBuf || !ulBufLen)
{
pnreslt = HXR_BUFFERTOOSMALL;
goto cleanup;
}
pszStartOfFile = new char[ulBufLen+1];
if (!pszStartOfFile)
{
pnreslt = HXR_OUTOFMEMORY;
goto cleanup;
}
// /Now, walk through and copy each character from non-NULL terminated buf:
pTmp = pBuf;
pTmp2 = pszStartOfFile;
while (*pTmp && ulCount<ulBufLen)
{
*pTmp2 = *pTmp;
pTmp++;
pTmp2++;
ulCount++;
}
pszStartOfFile[ulCount] = '\0'; // /NULL-terminate it.
// /Now, let's walk through the start of pszStartOfFile looking for
// namespace declaration(s) inside the <smil ...> tag, and make sure that
// the smil tag is NOT inside of a comment:
pTmp = pszStartOfFile;
while (*pTmp)
{
if (0==strncmp(pTmp, "<!--", 4) )
{
lNumCommentsOpen++;
pTmp+=4;
}
else if (0==strncmp(pTmp, "-->", 3) )
{
lNumCommentsOpen--;
pTmp+=3;
}
else if (lNumCommentsOpen<=0 && 0==strncmp(pTmp, "<smil", 5) )
{
pSmilTag = pTmp; // /We found the smil tag outside of a comment.
break;
}
else
{
pTmp++;
}
}
if (!pSmilTag || ulBufLen-(pSmilTag-pszStartOfFile) < 6) // /6==min size: "<smil>"
{
// /There had better be a <smil...> tag!
pnreslt = HXR_UNEXPECTED;
goto cleanup;
}
pCloseOfSmilTag = strchr(pSmilTag, '>');
// /Add 6 so that we don't allow "<smilxmlns ..." (which is invalid):
pXmlns = strstr(pSmilTag+6, "xmlns");
if (pXmlns && isspace(*(pXmlns-1)) ) // /"xmlns" must follow a space.
{
pEqualsSign = strchr(pXmlns, '=');
if (pEqualsSign)
{
pXmlnsOpenQuotationMark = strchr(pXmlns, '\"');
}
}
if (pXmlns && pEqualsSign && pXmlnsOpenQuotationMark &&
(!pCloseOfSmilTag || pXmlns<pCloseOfSmilTag))
{
BOOL bIsValidNamespaceDeclaration = TRUE;
// /First, make sure there is nothing but whitespace between
// the "xmlns" and the '=' as well as between the '=' and the
// quotation mark:
char* pTmp = (char*)(pXmlns + strlen("xmlns"));
while (pTmp<pEqualsSign)
{
if (!isspace(*pTmp))
{
bIsValidNamespaceDeclaration = FALSE;
break;
}
pTmp++;
}
pTmp = (char*)(pEqualsSign+1);
while(pTmp<pXmlnsOpenQuotationMark)
{
if (!isspace(*pTmp))
{
bIsValidNamespaceDeclaration = FALSE;
break;
}
pTmp++;
}
if (bIsValidNamespaceDeclaration)
{
// /Note: SMIL 1.0 namespace is default and is:
// "http://www.w3.org/TR/REC-smil". Note that if this is
// tagged (first) with a SMIL 1.0 namespace followed by
// another namespace, then this is a 1.0 file and we'll let
// the 1.0 renderer get it and do what it can with the 2.0
// stuff (namely ignore it):
const char* pSMIL10Namespace = strstr(pXmlnsOpenQuotationMark,
"http://www.w3.org/TR/REC-smil\"");
// /This in the final SMIL 2.0 rec:
const char* pSMIL20Namespace = strstr(pXmlnsOpenQuotationMark,
"http://www.w3.org/2001/SMIL20/Language\"");
const char* pSMIL20NamespaceCandidateRec = strstr(
pXmlnsOpenQuotationMark,
"http://www.w3.org/2000/SMIL20/CR/Language\"");
// /Fixes PR 55749: allow new PR namespace:
const char* pSMIL20NamespaceProposedRec = strstr(
pXmlnsOpenQuotationMark,
"http://www.w3.org/2001/SMIL20/PR/Language\"");
const char* pSMIL20NamespaceLastCall = strstr(
pXmlnsOpenQuotationMark,
"http://www.w3.org/TR/REC-smil/2000/SMIL20/LC/\"");
// /If the SMIL 1.0 namespace is declared prior to any other
// version of SMIL's namespace, then this is a SMIL 1.0 doc:
if (pSMIL10Namespace && (!pSMIL20Namespace ||
pSMIL10Namespace < pSMIL20Namespace) &&
(!pSMIL20NamespaceCandidateRec ||
pSMIL10Namespace < pSMIL20NamespaceCandidateRec) &&
(!pSMIL20NamespaceProposedRec ||
pSMIL10Namespace < pSMIL20NamespaceProposedRec) &&
(!pSMIL20NamespaceLastCall ||
pSMIL10Namespace < pSMIL20NamespaceLastCall) )
{
m_smilFileVersion = SMILFileVersionSmil10Strict;
}
else if (pSMIL20NamespaceCandidateRec && (!pSMIL20Namespace ||
pSMIL20NamespaceCandidateRec < pSMIL20Namespace))
{
m_smilFileVersion = SMILFileVersionSmil20PreRec;
}
else if (pSMIL20NamespaceProposedRec && (!pSMIL20Namespace ||
pSMIL20NamespaceProposedRec < pSMIL20Namespace))
{
m_smilFileVersion = SMILFileVersionSmil20PreRec;
}
// /Treat both LC (Last Call) and CR (Candidate Rec) as "PreRec":
else if (pSMIL20NamespaceLastCall && (!pSMIL20Namespace ||
pSMIL20NamespaceLastCall < pSMIL20Namespace))
{
m_smilFileVersion = SMILFileVersionSmil20PreRec;
}
else if (pSMIL20Namespace)
{
m_smilFileVersion = SMILFileVersionSmil20;
}
else
{
m_smilFileVersion = SMILFileVersionUnknown;
}
}
}
cleanup:
if (pszStartOfFile)
{
HX_VECTOR_DELETE(pszStartOfFile);
}
return pnreslt;
}
/////////////////////////////////////////////////////////////////////////
// Method:
// BreakUpBuffer
// Purpose:
// This Function will break the buffer into packets.
//
// This function maintains a state, such that multiple buffers should
// Be able to be passed into it at any point...
//
// XXX jhug
// This doesn't allow text between tags... Future versions of SMIL might
// support this... this will need a bit of a modification.
HX_RESULT
CSmilFileFormat::BreakUpBuffer(IHXBuffer* pBuffer)
{
// walk through the buffer and escape all \"s
// also forget about all white space and comments...
// also break the buffer up into packets for easy access.
HX_RESULT result = HXR_OK;
UCHAR* pCb = NULL;
if ( m_pCurrentPacketData )
{
pCb = m_pCurrentPacketData->pBuffer->GetBuffer();
}
const UCHAR* pData = pBuffer->GetBuffer();
UINT32 ulSize = pBuffer->GetSize();
for ( UINT32 ulPos = 0; ulPos < ulSize && pData[ulPos]; ++ulPos )
{
// three for the end of the packet structure, and 1 in case we have
// to escape a char...
if ( m_ulCurrentBufferPos >= MaxPacketSize - 4 )
{
pCb[m_ulCurrentBufferPos++] = '\"';
pCb[m_ulCurrentBufferPos++] = ')';
pCb[m_ulCurrentBufferPos++] = '\0';
m_pCurrentPacketData->pBuffer->SetSize(m_ulCurrentBufferPos);
m_pArrayOfPackets->Add((void*)m_pCurrentPacketData);
m_pCurrentPacketData = NULL;
m_ulCurrentBufferPos = 0;
pCb = NULL;
}
if ( !m_pCurrentPacketData )
{
m_pCurrentPacketData = new PacketData;
if ( m_pCurrentPacketData == NULL )
{
result = HXR_OUTOFMEMORY;
}
else
{
m_pCurrentPacketData->pBuffer = NULL;
m_pCurrentPacketData->pNumPos = NULL;
result = m_pCommonClassFactory->CreateInstance(CLSID_IHXBuffer,
(void**)&m_pCurrentPacketData->pBuffer);
}
if ( SUCCEEDED(result) )
{
result = m_pCurrentPacketData->pBuffer->SetSize(MaxPacketSize);
}
if ( SUCCEEDED(result) )
{
pCb = m_pCurrentPacketData->pBuffer->GetBuffer();
//memset(pCb, 0xef, MaxPacketSize);
sprintf((char*)pCb, "(smil-document (ver %s)(npkt %ld)"
"(ttlpkt 0 )(doc \"",
RMA_DRIVER_VERSION, ++m_ulCurrentPacket);
m_ulCurrentBufferPos = strlen((char*)pCb);
// back up to the begining of the total number position.
// 13 is position back in header...
m_pCurrentPacketData->pNumPos = (char*)pCb +
m_ulCurrentBufferPos - 13;
}
}
if ( FAILED(result) )
{
break;
}
switch ( m_fileState )
{
case InContent:
{
if ( pData[ulPos] == '\"' )
{
pCb[m_ulCurrentBufferPos++] = '\\';
pCb[m_ulCurrentBufferPos++] = '\"';
}
else if ( pData[ulPos] == '\\' )
{
pCb[m_ulCurrentBufferPos++] = '\\';
pCb[m_ulCurrentBufferPos++] = '\"';
}
else if ( pData[ulPos] == '<' )
{
if ( pData[ulPos+1] == '!' )
{
if ( pData[ulPos+2] == '-'
&& pData[ulPos+3] == '-' )
{
ulPos += 3;
m_fileState = InComment;
}
else if ( pData[ulPos+2] == '[' &&
pData[ulPos+3] == 'C' &&
pData[ulPos+4] == 'D' &&
pData[ulPos+5] == 'A' &&
pData[ulPos+6] == 'T' &&
pData[ulPos+7] == 'A' &&
pData[ulPos+8] == '[' )
{
pCb[m_ulCurrentBufferPos++] = pData[ulPos++];
pCb[m_ulCurrentBufferPos++] = pData[ulPos++];
pCb[m_ulCurrentBufferPos++] = pData[ulPos++];
pCb[m_ulCurrentBufferPos++] = pData[ulPos++];
pCb[m_ulCurrentBufferPos++] = pData[ulPos++];
pCb[m_ulCurrentBufferPos++] = pData[ulPos++];
pCb[m_ulCurrentBufferPos++] = pData[ulPos];
m_fileState = InCDATA;
}
else if ( pData[ulPos+2] == 'D' &&
pData[ulPos+3] == 'O' &&
pData[ulPos+4] == 'C' &&
pData[ulPos+5] == 'T' &&
pData[ulPos+6] == 'Y' &&
pData[ulPos+7] == 'P' &&
pData[ulPos+8] == 'E' )
{
pCb[m_ulCurrentBufferPos++] = pData[ulPos++];
pCb[m_ulCurrentBufferPos++] = pData[ulPos++];
pCb[m_ulCurrentBufferPos++] = pData[ulPos++];
pCb[m_ulCurrentBufferPos++] = pData[ulPos++];
pCb[m_ulCurrentBufferPos++] = pData[ulPos++];
pCb[m_ulCurrentBufferPos++] = pData[ulPos++];
pCb[m_ulCurrentBufferPos++] = pData[ulPos];
m_fileState = InDTD;
}
}
else
{
pCb[m_ulCurrentBufferPos++] = pData[ulPos];
m_fileState = InTagName;
}
}
// preserve all lines so line number error reporting is
// accurate
else if ( isspace(pData[ulPos]) && pData[ulPos] != '\n' &&
pData[ulPos] != '\r')
{
//continue...
}
//If we find \rx where x is not \n, then keep it else let
// the next char (\n) be kept in the next iteration of
// this loop. This accomodates Mac-authored '\r'-only
// text. Think Different (pain is "different").
else if (isspace(pData[ulPos]) && ('\r' == pData[ulPos] &&
(ulPos+1 < ulSize && pData[ulPos+1]) &&
'\n' == pData[ulPos+1]) )
{
//continue...
}
else
{
if ('\r' == pData[ulPos])
{
pCb[m_ulCurrentBufferPos++] = '\n';
}
else
{
pCb[m_ulCurrentBufferPos++] = pData[ulPos];
}
}
}
break;
case InDTD:
{
if ( pData[ulPos] == '[' )
{
m_fileState = InDTDMarkup;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -