Microsoft KB Archive/172551

= PRB: CInternetSession::OpenURL Fails with File Protocol =

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</li></ul>

 Microsoft Visual C++ 6.0 Standard Edition</li></ul> </li></ul>

-

<div class="notice_section">

This article was previously published under Q172551

<div class="symptoms_section">

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.

<div class="cause_section">

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.

<div class="resolution_section">

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); }

<div class="references_section">