DOCUMENT:Q172551 03-MAY-2001 [visualc] TITLE :PRB: CInternetSession::OpenURL() Fails with File Protocol PRODUCT :Microsoft C Compiler PROD/VER:winnt:5.0,6.0 OPER/SYS: KEYWORDS:kbInternet kbMFC kbVC kbVC500 kbVC600 kbVS97 kbVS600 kbGrpDSMFCATL ====================================================================== ------------------------------------------------------------------------------- The information in this article applies to: - The Microsoft Foundation Classes (MFC), used with: - Microsoft Visual C++, 32-bit Enterprise Edition, version 5.0 - Microsoft Visual C++, 32-bit Professional Edition, version 5.0 - Microsoft Visual C++, 32-bit Enterprise Edition, version 6.0 - Microsoft Visual C++, 32-bit Professional Edition, version 6.0 - Microsoft Visual C++, 32-bit Learning Edition, version 6.0 ------------------------------------------------------------------------------- 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: c:\temp\Text%20Document.txt was not found. 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: http://www.w3.org/ NOTE: Web links may change without notice. Additional query words: 4.20b space file OpenURL filename ====================================================================== Keywords : kbInternet kbMFC kbVC kbVC500 kbVC600 kbVS97 kbVS600 kbGrpDSMFCATL Technology : kbAudDeveloper kbMFC Version : winnt:5.0,6.0 Issue type : kbprb ============================================================================= THE INFORMATION PROVIDED IN THE MICROSOFT KNOWLEDGE BASE IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY KIND. MICROSOFT DISCLAIMS ALL WARRANTIES, EITHER EXPRESS OR IMPLIED, INCLUDING THE WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. IN NO EVENT SHALL MICROSOFT CORPORATION OR ITS SUPPLIERS BE LIABLE FOR ANY DAMAGES WHATSOEVER INCLUDING DIRECT, INDIRECT, INCIDENTAL, CONSEQUENTIAL, LOSS OF BUSINESS PROFITS OR SPECIAL DAMAGES, EVEN IF MICROSOFT CORPORATION OR ITS SUPPLIERS HAVE BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. SOME STATES DO NOT ALLOW THE EXCLUSION OR LIMITATION OF LIABILITY FOR CONSEQUENTIAL OR INCIDENTAL DAMAGES SO THE FOREGOING LIMITATION MAY NOT APPLY. Copyright Microsoft Corporation 2001.