October 24, 2014
Hot Topics:
RSS RSS feed Download our iPhone app

Mastering Internet Programming on Mobile Devices: An Asynchronous Data Exchange

  • November 17, 2004
  • By Alex Gusev
  • Send Email »
  • More Articles »

Connecting to Secure Sites

In some cases, Web servers require some kind of authentication and secure connections. Windows CE supports various security protocols such as TSL, SSL, and so forth. WinInet is the simplest way to use these protocols during communication sessions. The basic scheme here is really simple:

  • Use the required protocol in the URL; for example. https://server:port.
  • Use the required port number, as in INTERNET_DEFAULT_HTTPS_PORT for HTTPS.
  • Call HttpOpenRequest with the INTERNET_FLAG_SECURE flag set.
  • If the remote host requires authentication, set INTERNET_FLAG_KEEP_CONNECTION while calling HttpOpenRequest to allow connection maintenance until the authentication process is completed. This flag is also required to keep security options between a number of requests.

If the server requires authentication, error 401 is returned after sending the request. You have several methods to deal with such a situation. First, the application may use InternetErrorDlg to retrieve additional information:

DWORD InternetErrorDlg(
  HWND hWnd,
  HINTERNET hRequest,
  DWORD dwError,
  DWORD dwFlags,
  LPVOID* lppvData
);

This function is smart enough, and depending on passed flags, it may check request headers for any hidden errors and then display dialog boxes if needed. Thus, a sample call is as the following:

...
if( HttpSendRequest(hRequest,0,0,0,0) )
{
    DWORD dwErrorCode = GetLastError();
    
    DWORD dwError = InternetErrorDlg(hWnd,hRequest,dwErrorCode,
                            FLAGS_ERROR_UI_FILTER_FOR_ERRORS |
                            FLAGS_ERROR_UI_FLAGS_CHANGE_OPTIONS |
                            FLAGS_ERROR_UI_FLAGS_GENERATE_DATA,
                            NULL);
    if ( dwError == ERROR_INTERNET_FORCE_RETRY )
    {
       // resend request
       ...
    }
    
    if ( dwError == ERROR_SUCCESS )
    {
       // read response data
       ...
    }
    ...
}

You will find a detailed description of this function in the online help. Here, we'll just note that displaying GUI dialogs is not always a desired behavior. In many cases, your application can know the user and password for authentication, so there is no need to prompt it at all. Instead, you can use an InternetSetOption call. This function is a way to set up different properties of HHTP requests, not just the user and password:

  • INTERNET_OPTION_CONTEXT_VALUE
  • INTERNET_OPTION_CONNECT_TIMEOUT
  • INTERNET_OPTION_CONNECT_RETRIES
  • INTERNET_OPTION_CONNECT_BACKOFF
  • INTERNET_OPTION_CONTROL_SEND_TIMEOUT
  • INTERNET_OPTION_CONTROL_RECEIVE_TIMEOUT
  • INTERNET_OPTION_DATA_SEND_TIMEOUT
  • INTERNET_OPTION_DATA_RECEIVE_TIMEOUT
  • INTERNET_OPTION_READ_BUFFER_SIZE
  • INTERNET_OPTION_WRITE_BUFFER_SIZE
  • INTERNET_OPTION_USERNAME
  • INTERNET_OPTION_PASSWORD
  • INTERNET_OPTION_PROXY
  • INTERNET_OPTION_USER_AGENT

Its usage is demonstrated in the following code snippet:

DWORD dwStatus, dwStatusSize = sizeof(DWORD);
if ( HttpQueryInfo(hRequest, HTTP_QUERY_FLAG_NUMBER |
                             HTTP_QUERY_STATUS_CODE, &dwStatus,
                             &dwSTatusSize) )
{
    if ( dwStatusCode == HTTP_STATUS_DENIED )
    {
        InternetSetOption(hRequest, INTERNET_OPTION_USERNAME,
                          lpszUserName, _tcslen(lpszUserName) + 1);
        InternetSetOption(hRequest, INTERNET_OPTION_PASSWORD,
                          lpszPassword, _tcslen(lpszPassword) + 1);
    }
}

In the same manner, you can define timeout values, proxies, and other request parameters. The HttpQueryInfo API is used to get request status information along with all sorts of header variables. Your application should call it after each HttpSendRequest to verify transmission status.

Finally, remote hosts may support or require cookies. Cookies are used to track data settings or data for a particular Web site. The client can save them on a handheld device and then send them to the Web server along with a request. Windows CE provides the following functions to manage a cookie database:

  • InternetSetCookie
  • InternetSetCookieEx
  • InternetGetCookie

The first two functions are pretty similar. The "Ex" version extends InternetSetCookie by dealing with so-called third-party cookies. InternetGetCookie retrieves cookie data from the local database. The Web server exchanges cookie information through the HTTP header. Thus, your application can set/get it from there. The general format is represented below:

Request:
Cookie: <name>=<value>[; <name>=<value>]...

Response:
Set-Cookie: <name>=<value>[; <name>=<value>]...
[; expires=<date>][; domain=<domain_name>]
[; path=<some_path>][; secure][; httponly]

So, speaking C/C++, you might code something like this:

TCHAR szCookie[] = _T("Cookie: datasrc=maindb;");
HttpAddRequestHeaders(hResuest,szCookie,_tcslen(szCookie),
                      HTTP_ADDREQ_FLAG_ADD);

When using cookies, you should keep in mind a couple of flags that influence cookies' behavior:

  • INTERNET_FLAG_NO_COOKIES—does not automatically add cookie headers to requests and save them into the local database on response
  • INTERNET_FLAG_NO_UI—disables the cookie dialog box that can pop up in some cases to prompt for cookie acceptance

The Compact Framework does not support cookies directly, but you can precede all required items via a Header collection of HttpWebRequest or HttpWebResponse classes:

string strCookie = null;
...
// Sending cookie
req = (HttpWebRequest)WebRequest.Create(strURL);
req.Headers["Cookie"] = strCookie;
req.Credentials = new NetworkCredential(...);
...

// Receving cookie
HttpWebResponse resp = null;
string strCookie = null;
try
{
   resp = req.GetResponse() as HttpWebResponse;
}
catch(WebException e)
{
   if(e.Status == WebExceptionStatus.ProtocolError)
   {
      resp = e.Response as HttpWebResponse;
      if((int)resp.Status == 401)
      {
         strCookie = resp.Headers["Set-Cookie"];
      }
      ...
   }
}

Conclusion

In this article, we have discussed more complicated but yet not so awful stuff about WinInet. Hopefully, CF.NET will provide richer capabilities in the next SPs, but now it is still far from being as powerful as the native C/C++ environment. Nevertheless, in both cases you have all that you need to implement complex Internet conectivity features in your own applications.

About the Author

Alex Gusev started to play with mainframes at the end of the 1980s, using Pascal and REXX, but soon switched to C/C++ and Java on different platforms. When mobile PDAs seriously rose their heads in the IT market, Alex did it too. Now, he works at an international retail software company as a team leader of the Mobile R department, making programmers' lives in the mobile jungles a little bit simpler.





Page 2 of 2



Comment and Contribute

 


(Maximum characters: 1200). You have characters left.

 

 


Sitemap | Contact Us

Rocket Fuel