📄 datafsys.cpp
字号:
if (m_pFileResponse) { AddRef(); IHXFileResponse* pResponse = m_pFileResponse; m_pFileResponse = 0; pResponse->CloseDone(HXR_OK); pResponse->Release(); Release(); } return HXR_OK;}/************************************************************************ * Method: * IHXFileObject::Read * Purpose: * Reads a buffer of data of the specified length from the file * and asynchronously returns it to the caller via the * IHXFileResponse interface passed in to Init. */STDMETHODIMP DataFileObject::Read(ULONG32 ulCount){ HX_RESULT hResult = HXR_OK; IHXBuffer* pBuffer = NULL; CHXNestedBuffer* pNestedBuffer = NULL; if (!m_pDataURL || m_ulFilePointer == m_pDataURL->GetSize()) { m_pFileResponse->ReadDone(HXR_FAIL, 0); return HXR_OK; } // Don't read off the end of the buffer ulCount = min(ulCount, (m_pDataURL->GetSize() - m_ulFilePointer)); // Create a nested buffer object hResult = CHXNestedBuffer::CreateObject(&pNestedBuffer); if (FAILED(hResult)) { m_pFileResponse->ReadDone(hResult, 0); return HXR_OK; } // AddRef the object pNestedBuffer->AddRef(); // Init the object hResult = pNestedBuffer->Init(m_pDataURL, m_ulFilePointer, ulCount); if (FAILED(hResult)) { HX_RELEASE(pNestedBuffer); m_pFileResponse->ReadDone(hResult, 0); return HXR_OK; } // Query for the IHXBuffer interface hResult = pNestedBuffer->QueryInterface(IID_IHXBuffer, (void**)&pBuffer); HX_ASSERT(SUCCEEDED(hResult)); m_ulFilePointer += ulCount; m_pFileResponse->ReadDone(HXR_OK, pBuffer); HX_RELEASE(pNestedBuffer); HX_RELEASE(pBuffer); return HXR_OK;}/************************************************************************ * Method: * IHXFileObject::Write * Purpose: * Writes a buffer of data to the file and asynchronously notifies * the caller via the IHXFileResponse interface passed in to Init, * of the completeness of the operation. */STDMETHODIMP DataFileObject::Write(IHXBuffer* pBuffer){ return HXR_UNEXPECTED;}/************************************************************************ * Method: * IHXFileObject::Seek * Purpose: * Seeks to an offset in the file and asynchronously notifies * the caller via the IHXFileResponse interface passed in to Init, * of the completeness of the operation. */STDMETHODIMP DataFileObject::Seek(ULONG32 ulOffset, BOOL bRelative){ HX_RESULT pnr = HXR_OK; if (!m_pDataURL) { m_pFileResponse->SeekDone(HXR_FAIL); return HXR_OK; } if (bRelative && ulOffset <= m_pDataURL->GetSize() - m_ulFilePointer) { m_ulFilePointer += ulOffset; } else if (!bRelative && ulOffset <= m_pDataURL->GetSize()) { m_ulFilePointer = ulOffset; } else { pnr = HXR_FAIL; } m_pFileResponse->SeekDone(pnr); return pnr;}/************************************************************************ * Method: * IHXFileObject::Stat * Purpose: * Collects information about the file that is returned to the * caller in an IHXStat object */STDMETHODIMP DataFileObject::Stat(IHXFileStatResponse* pFileStatResponse){ HX_RESULT hResult = HXR_OK; if (!m_pDataURL) { hResult = HXR_FAIL; pFileStatResponse->StatDone(HXR_FAIL, 0, 0, 0, 0, 0); } else { pFileStatResponse->StatDone(HXR_OK, m_pDataURL->GetSize(), 0, 0, 0, 0); } return hResult;}/************************************************************************ * Method: * IHXFileObject::Advise * Purpose: * To pass information to the File Object */STDMETHODIMP DataFileObject::Advise(ULONG32 ulInfo){ return HXR_UNEXPECTED;}// IHXFileExists interface/************************************************************************ * Method: * IHXFileExists::DoesExist * Purpose: */STDMETHODIMP DataFileObject::DoesExist( const char* pPath, IHXFileExistsResponse* pFileResponse){ pFileResponse->DoesExistDone(m_pDataURL ? TRUE : FALSE); return HXR_OK;}STDMETHODIMP DataFileObject::SetRequest( IHXRequest* pRequest){ HX_RESULT hresult = HXR_OK; HX_RELEASE(m_pRequest); m_pRequest = pRequest; if (m_pRequest) { m_pRequest->AddRef(); } const char* pURL; IHXValues* pHeaders = 0; IHXBuffer* pBuffer0 = 0; hresult = m_pRequest->GetURL(pURL); if (hresult != HXR_OK) { goto RequestError; } hresult = m_pClassFactory->CreateInstance(CLSID_IHXBuffer, (void**)&pBuffer0); hresult = ParseURL(pURL, m_MediaType, pBuffer0); if (SUCCEEDED(hresult)) { m_pDataURL = pBuffer0; pBuffer0 = NULL; } /* * Now set the Response Headers */ hresult = m_pClassFactory->CreateInstance(CLSID_IHXValues, (void**)&pHeaders); if (HXR_OK != hresult) { goto RequestError; } hresult = m_pClassFactory->CreateInstance(CLSID_IHXBuffer, (void**)&pBuffer0); if (HXR_OK != hresult) { goto RequestError; } pBuffer0->Set((Byte*)"no-cache", 9); pHeaders->SetPropertyCString("Pragma", pBuffer0); HX_RELEASE(pBuffer0); hresult = m_pClassFactory->CreateInstance(CLSID_IHXBuffer, (void**)&pBuffer0); if (HXR_OK != hresult) { goto RequestError; } pBuffer0->Set((Byte*)(const char*)m_MediaType, m_MediaType.GetLength()+1); pHeaders->SetPropertyCString("Content-Type", pBuffer0); HX_RELEASE(pBuffer0); m_pRequest->SetResponseHeaders(pHeaders);RequestError: HX_RELEASE(pHeaders); HX_RELEASE(pBuffer0); return hresult;}STDMETHODIMP DataFileObject::GetRequest( REF(IHXRequest*) pRequest){ pRequest = m_pRequest; if (pRequest) { pRequest->AddRef(); } return HXR_OK;}/************************************************************************ * Method: * IHXFileMimeMapper::FindMimeType * Purpose: */STDMETHODIMPDataFileObject::FindMimeType( const char* /*IN*/ pURL, IHXFileMimeMapperResponse* /*IN*/ pMimeMapperResponse){ HX_RESULT status = HXR_OK; CHXString mimeString; pMimeMapperResponse->AddRef(); status = ParseURL(pURL, mimeString, NULL); status = pMimeMapperResponse->MimeTypeFound(status, (const char*)mimeString); pMimeMapperResponse->Release(); return status;}/* * Syntax * * dataurl := "data:" [ mediatype ] [ ";base64" ] "," data * mediatype := [ type "/" subtype ] *( ";" parameter ) * - Matching of media type and subtype is ALWAYS * case-insensitive. * type := token * subtype := token * parameter := attribute "=" value * attribute := token * - Matching of attributes is ALWAYS case-insensitive. * value := token | quoted-string * token := (alphanum | untspecials)? * quoted-string * := """ (token | tspecials)? """ * tspecials := ";" | "/" | "?" | ":" | "@" | "=" | "(" | ")" | * "<" | ">" | "," | "\" | """ | "[" | "]" * untspecials:= "-" | "_" | "." | "!" | "#" | "$" | "%" | "*" | "+" * "|" | "`" | "~" | "'" * data := *urlchar * urlchar := reserved | unreserved | escaped * reserved := ";" | "/" | "?" | ":" | "@" | "&" | "=" | "+" | * "$" | "," * unreserved := alphanum | mark * mark := "-" | "_" | "." | "!" | "~" | "*" | "'" | * "(" | ")" * escaped = "%" hex hex * hex := digit | "A" | "B" | "C" | "D" | "E" | "F" | * "a" | "b" | "c" | "d" | "e" | "f" * alphanum := alpha | digit * alpha := lowalpha | upalpha * lowalpha := "a" | "b" | "c" | "d" | "e" | "f" | "g" | "h" | "i" | * "j" | "k" | "l" | "m" | "n" | "o" | "p" | "q" | "r" | * "s" | "t" | "u" | "v" | "w" | "x" | "y" | "z" * upalpha := "A" | "B" | "C" | "D" | "E" | "F" | "G" | "H" | "I" | * "J" | "K" | "L" | "M" | "N" | "O" | "P" | "Q" | "R" | * "S" | "T" | "U" | "V" | "W" | "X" | "Y" | "Z" * digit := "0" | "1" | "2" | "3" | "4" | "5" | "6" | "7" | * "8" | "9" * * Attribute values in [RFC2045] are allowed to be either represented as * tokens or as quoted strings. However, within a "data" URL, the * "quoted-string" representation would be awkward, since the quote mark * is itself not a valid urlchar. For this reason, parameter values * should use the URL Escaped encoding instead of quoted string if the * parameter values contain any "tspecial". * * The ";base64" extension is distinguishable from a content-type * parameter by the fact that it doesn't have a following "=" sign. */const char DATA_SCHEME[] = "data:";#define DATA_SCHEME_SIZE (sizeof(DATA_SCHEME) - 1)const char BASE64_TOKEN[] = ";base64";#define BASE64_TOKEN_SIZE (sizeof(BASE64_TOKEN) - 1)STDMETHODIMP DataFileObject::ParseURL(const char* pURL, CHXString& mimeString, IHXBuffer* pBuffer){ HX_RESULT pnr = HXR_OK; UINT32 ulDataURLSize = strlen(pURL); const char* pCurrentChar = pURL; BOOL bBase64 = FALSE; UINT32 ulDataLength = 0; char* pMimeString = NULL; const char* pMimeStringStart = NULL; const char* pMimeStringEnd = NULL; BOOL bHasMimeString = TRUE; // Skip any leading whitespace while (*pCurrentChar && *pCurrentChar < 0x20) { pCurrentChar++; } // pURL must begin with data scheme // dataurl := "data:" [ mediatype ] [ ";base64" ] "," data if (strncasecmp(pCurrentChar, DATA_SCHEME, DATA_SCHEME_SIZE)) { pnr = HXR_FAIL; goto exit; } else { pCurrentChar += DATA_SCHEME_SIZE; } // The URL may begin with "data:", "data:/", or "data://" if (*pCurrentChar == '/') { pCurrentChar++; } if (*pCurrentChar == '/') { pCurrentChar++; } if (*pCurrentChar == ';' || *pCurrentChar == ',') { bHasMimeString = FALSE; } else { if (strncasecmp(pCurrentChar, BASE64_TOKEN, BASE64_TOKEN_SIZE)) { pMimeStringStart = pCurrentChar; pMimeStringEnd = pCurrentChar; // parse past mediatype // mediatype := [ type "/" subtype ] *( ";" parameter ) // walk past type while (tokenChars[*pCurrentChar]) { pCurrentChar++; } // this better be a '/' if (*pCurrentChar != '/') { pnr = HXR_FAIL; goto exit; } else { pCurrentChar++; } // walk past subtype while (tokenChars[*pCurrentChar]) { pCurrentChar++; } pMimeStringEnd = pCurrentChar; if (*pCurrentChar == ';') { while (*pCurrentChar == ';') { // check for base64 if (strncasecmp(pCurrentChar, BASE64_TOKEN, BASE64_TOKEN_SIZE)) { pCurrentChar++; // step past the ';' // walk past the attribute while(tokenChars[*pCurrentChar]) {pCurrentChar++;} // this better be a '=' if (*pCurrentChar != '=') { pnr = HXR_FAIL; goto exit; } else { pCurrentChar++; } // walk past value // XXXJEFFA need to handle quoted-string while(tokenChars[*pCurrentChar]) { pCurrentChar++; } pMimeStringEnd = pCurrentChar; } else { bBase64 = TRUE; pCurrentChar += BASE64_TOKEN_SIZE; break; } } } } else { bBase64 = TRUE; bHasMimeString = FALSE; pCurrentChar += BASE64_TOKEN_SIZE; } } if (bHasMimeString) { // copy the mime string into the parameter ulDataLength = (pMimeStringEnd - pMimeStringStart); pMimeString = mimeString.GetBuffer(ulDataLength + 1); strncpy(pMimeString, pMimeStringStart, ulDataLength); /* Flawfinder: ignore */ pMimeString[ulDataLength] = '\0'; mimeString.ReleaseBuffer(ulDataLength); } else { mimeString = "text/plain"; } // should be a comma between mediatype and data if (*pCurrentChar != ',') { pnr = HXR_FAIL; goto exit; } else { pCurrentChar++; } if (pBuffer != NULL) { BYTE* pOutput = NULL; INT32 nLength = 0; // The rest is the data. It needs to be un-escaped and possibly // un-base64 encoded. if (bBase64) { // Un-base64 encode the data pBuffer->SetSize(ulDataURLSize - (pCurrentChar - pURL)); pOutput = (BYTE*)pBuffer->GetBuffer(); nLength = BinFrom64(pCurrentChar, pBuffer->GetSize(), pOutput); if (nLength == -1) { pBuffer->SetSize(0); } else { pBuffer->SetSize(nLength); } } else { // Un-escape the data pBuffer->SetSize(ulDataURLSize - (pCurrentChar - pURL)); pOutput = (BYTE*)pBuffer->GetBuffer(); nLength = URLUnescapeBuffer(pCurrentChar, ulDataURLSize - (pCurrentChar - pURL), (char*)pOutput); if (nLength == -1) { pBuffer->SetSize(0); } else { pBuffer->SetSize(nLength); } } }exit: return pnr;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -