Article ID: 172551
Article Last Modified on 3/7/2005
APPLIES TO
- Microsoft Foundation Class Library 4.2, when used with:
- Microsoft Visual C++ 5.0 Enterprise Edition
- Microsoft Visual C++ 5.0 Professional Edition
- Microsoft Visual C++ 6.0 Enterprise Edition
- Microsoft Visual C++ 6.0 Professional Edition
- Microsoft Visual C++ 6.0 Standard Edition
This article was previously published under Q172551
SYMPTOMS
CInternetSession::OpenURL() fails if you use a URL that specifies a file that contains spaces or other unsafe characters. For example, the following will fail:
CMyInternetSession s(""); CStdioFile* p = s.OpenURL("file://c:/temp/Text Document.txt");
As a result, a File Exception is thrown and the following message appears:
CAUSE
The specifications for a URL designate certain characters that must be escaped when they are present in a URL. The space character is one of the characters that must be escaped.
The function CInternetSession::OpenURL() calls a function that converts unsafe characters in the URL to their escape sequences before processing the URL further. If the URL is using the file protocol it creates a CStdioFile and returns a pointer to this object. However, CStdioFile does not understand the escaped path and, as a result, an exception is thrown.
RESOLUTION
When you use the file protocol, you must not convert unsafe characters to their escape sequences. The following code demonstrates how to do this by writing a CInternetSession derived class to override OpenURL().
// class definition class CMyInternetSession : CInternetSession { public: CMyInternetSession::CMyInternetSession(LPCTSTR pstrAgent = NULL, DWORD dwContext = 1, DWORD dwAccessType = PRE_CONFIG_INTERNET_ACCESS, LPCTSTR pstrProxyName = NULL, LPCTSTR pstrProxyBypass = NULL, DWORD dwFlags = 0); CStdioFile* CMyInternetSession::OpenURL(LPCTSTR pstrURL, DWORD dwContext = 1, DWORD dwFlags = INTERNET_FLAG_TRANSFER_ASCII, LPCTSTR pstrHeaders = NULL, DWORD dwHeadersLength = 0); }; // CMyInternetSession constructor CMyInternetSession::CMyInternetSession(LPCTSTR pstrAgent, DWORD dwContext, DWORD dwAccessType, LPCTSTR pstrProxyName, LPCTSTR pstrProxyBypass, DWORD dwFlags) { CInternetSession(pstrAgent, dwContext, dwAccessType, pstrProxyName, pstrProxyBypass, dwFlags); } CStdioFile* CMyInternetSession::OpenURL(LPCTSTR pstrURL, DWORD dwContext, DWORD dwFlags, LPCTSTR pstrHeaders, DWORD dwHeadersLength) { ASSERT(pstrURL != NULL); ASSERT(dwHeadersLength == 0 || pstrHeaders != NULL); // must have TRANSFER_BINARY or TRANSFER_ASCII but not both #define _AFX_TRANSFER_MASK (INTERNET_FLAG_TRANSFER_BINARY \ | INTERNET_FLAG_TRANSFER_ASCII) ASSERT((dwFlags & _AFX_TRANSFER_MASK) != 0); ASSERT((dwFlags & _AFX_TRANSFER_MASK) != _AFX_TRANSFER_MASK); DWORD dwServiceType; CString strServer; CString strObject; INTERNET_PORT nPort; BOOL bParsed = AfxParseURL(pstrURL, dwServiceType, strServer, strObject, nPort); // if it turns out to be a file... if (bParsed && dwServiceType == AFX_INET_SERVICE_FILE) { CString userName; CString password; // Get the normalized file name with out converting // unsafe characters to escape sequence. AfxParseURLEx(pstrURL, dwServiceType, strServer, strObject, nPort, userName, password, ICU_NO_ENCODE); int nMode = CFile::modeRead | CFile::shareCompat; if (dwFlags & INTERNET_FLAG_TRANSFER_BINARY) nMode |= CFile::typeBinary; else nMode |= CFile::typeText; return new CStdioFile(strObject, nMode); } return CInternetSession::OpenURL(pstrURL, dwContext, dwFlags, pstrHeaders, dwHeadersLength); }
REFERENCES
The specification for URL's are published by The World Wide Web Consortium (W3C). The specifications define the escape sequences and unsafe characters. Its URL is:
NOTE: Web links may change without notice.
Additional query words: 4.20b space file OpenURL filename
Keywords: kbprb KB172551