Go Premium for a chance to win a PS4. Enter to Win

x
  • Status: Solved
  • Priority: Medium
  • Security: Public
  • Views: 1481
  • Last Modified:

CInternetSession lifespan

Hello,

I'm connecting to a webpage by creating a CInternetSession and CHttpFile.

The website uses cookies.

The first time I start-up my app to do a request I can see NO cookie being quoted to the server (With network monitor)

This is expected because this is the first time the session is initialized.

The webserver then sets a cookie and that can bee seen with network monitor.

After the request and response I close and delete the CHttpFile and CInternetSession.

If I however do the same thing again (without re-starting the app) the first requests that I can see going to the webserver, quotes the cookie again.

This is a bit of a mystery to me because I defenitly closed and deleted the session..

If I re-start the app the session does disappear.

I am wondering how I can force a "clean" session.

Thanks,
Tom

---------------- code ---------------
bool PostData(CString server, bool secure, CString page, CString postData, CString& responsePage, CString& strcookie)
{
      bool retValue = true;

      CInternetSession*      pSession;
      CHttpFile*                  pFile;
      INTERNET_PORT            aPort;
      DWORD                        aFlags;


      CString strHeaders =  _T("Content-Type: application/x-www-form-urlencoded");

      if( secure)
            aPort = INTERNET_DEFAULT_HTTPS_PORT ;
      else
            aPort = INTERNET_DEFAULT_HTTP_PORT;

      pSession = new CInternetSession();

      CHttpConnection* pConnection = pSession->GetHttpConnection(server, aPort);
      

      if( secure)
            aFlags = INTERNET_FLAG_SECURE;
      else
            aFlags = INTERNET_FLAG_EXISTING_CONNECT;

      try
      {

            pFile = pConnection->OpenRequest(CHttpConnection::HTTP_VERB_POST,page, NULL, 1, NULL, NULL,  aFlags );
            if( pFile != NULL )
            {
                  BOOL result = pFile->SendRequest(strHeaders,(LPVOID)(LPCTSTR)postData, postData.GetLength());

                  if( result )
                  {
                        CString testCookie;
                        if( pSession->GetCookie( pFile->GetFileURL( ) , "", testCookie ) )
                              strcookie = testCookie;

                        CString total;
                        CString aHtmlLine;
                        if( pFile->ReadString( aHtmlLine ))
                        {
                              total += aHtmlLine;
                              while(pFile->ReadString( aHtmlLine ))
                              {
                                    total += "\n";
                                    total += aHtmlLine;
                              }
                              responsePage = total;
                        }
                        else
                        {
                              retValue = false;
                        }
                  }
                  else
                  {
                        retValue = false;
                  }
            }

            pFile->Close();
            delete pFile;

            pConnection->Close();
            delete pConnection;
            
            pSession->Close();
            delete pSession;

      }
      catch (CInternetException* pEx)
      {
            pFile = NULL;
            pEx->Delete();
            retValue = false;
      }

      return retValue;
}
-------------end code ---------------
0
tomschuring
Asked:
tomschuring
  • 10
  • 4
  • 3
  • +2
1 Solution
 
ShaunWildeCommented:
It is probably being stored in the depths of wininet - have you tried SetCookie to set it to blank ("") beofre you close your session ? Or even setting it with an expired value to something in the past.
0
 
tomschuringAuthor Commented:
mmmm, yes, but I am trying to write a "generic" function for posting some data. So I usually don't know the name of the cookie that a website is going to send. The SetCookie() function assumes that I know the cookie-name.....
0
 
tomschuringAuthor Commented:
Adjusted points from 100 to 400
0
What does it mean to be "Always On"?

Is your cloud always on? With an Always On cloud you won't have to worry about downtime for maintenance or software application code updates, ensuring that your bottom line isn't affected.

 
tomschuringAuthor Commented:
Even if I do a SetCookie with an empty value, I can still see the previous cookie in the network-trace (something like: Cookie: MYCOOKIE;MYCOOKIE=oldvalue )

It doesn't look like CInternetSession can be killed at all unless I kill the whole app. Any idea's
0
 
ShaunWildeCommented:
how about moving to the original wininet functions to do the same job as CInternetSession. Or moving your functions to a dll that you can load when you need them and then unload and reload when you wish to start afresh - that should get rid of any persistant information
0
 
tomschuringAuthor Commented:
thanks, that is what I am doing now. Perhaps the original api will fix it.
0
 
tomschuringAuthor Commented:
nope, the wininet api still sends the cookie on the second request even though I close everything after every call. It looks like the wininet dll stores cookies deep down. If I start a new app, the first call is clean but the second call sends the cookie received on the first call. It looks like sessions are kept open on an application base.

-------- begin code ---------

CString server("www.myserver.com.au");
bool secure = false;
CString page("/test.asp");
CString postData("name=John+Doe&userid=hithere&other=P%26Q");
CString responsePage;
CString strcookie;


      DWORD theFlags = INTERNET_FLAG_NO_CACHE_WRITE | INTERNET_FLAG_PRAGMA_NOCACHE  | INTERNET_FLAG_NO_UI ;
      HINTERNET hSession = ::InternetOpen("toms app",INTERNET_OPEN_TYPE_PRECONFIG,NULL,NULL,theFlags);

      if( hSession )
      {
            HINTERNET      connection;
            DWORD            aFlags;
            CString            strHeaders =  _T("Content-Type: application/x-www-form-urlencoded");

            if( secure)
                  aFlags = INTERNET_FLAG_RELOAD | INTERNET_FLAG_DONT_CACHE | INTERNET_FLAG_PRAGMA_NOCACHE  | INTERNET_FLAG_NO_UI | INTERNET_FLAG_NO_CACHE_WRITE | INTERNET_FLAG_SECURE ;
            else
                  aFlags = INTERNET_FLAG_RELOAD | INTERNET_FLAG_DONT_CACHE | INTERNET_FLAG_PRAGMA_NOCACHE | INTERNET_FLAG_NO_UI | INTERNET_FLAG_NO_CACHE_WRITE;

            connection = InternetConnect(hSession, server, INTERNET_INVALID_PORT_NUMBER, NULL,NULL, INTERNET_SERVICE_HTTP,NULL, NULL);
            if( connection )
            {

                  HINTERNET request = HttpOpenRequest(connection,"POST",page ,NULL,NULL,NULL,aFlags,0);
                  if( request )
                  {
                        if( HttpSendRequest(request,strHeaders,strHeaders.GetLength(),NULL,0) )
                        {

                              // Prepare the download buffer and then download the response after sending the request
                              char* buffer = new char[20];
                              DWORD dwRead = 0;
                              bool bDone = false;
                              CString total;
                              while (!bDone && ::InternetReadFile(request, (LPVOID)buffer, 20, &dwRead))
                              {
                                    if( dwRead <= 0)
                                          bDone = true;
                                    total += CString(buffer).Left(dwRead);
                              }
                              MessageBox(total);
                              m_Edit.SetWindowText(total);

                        }
                  }
                  InternetCloseHandle(request);
            }
            InternetCloseHandle(connection);
      }
      InternetCloseHandle(hSession);

-------- end code ---------
0
 
tomschuringAuthor Commented:
Adjusted points from 400 to 800
0
 
ShaunWildeCommented:
Okay - we are entering longshot zone. How about loading the wininet library using LoadLibrary and getting the functions using GetProcAddress and then after you have finished you can then call FreeLibrary.
0
 
mikeblasCommented:
> This is a bit of a mystery to me because I defenitly closed and deleted the session..

Why is that a mystery? The Internet session has nothing to do with the cookie. Once it's stored, it's stored until it expires or is deleted.

What's the exact text of the cookie you're watching in the network monitor? What's the expiration setting? What other headers are at work?

..B ekiM
0
 
mikeblasCommented:
BTW, is this a public website?  Can you provide the query you're doing?

..B ekiM
0
 
mikeblasCommented:
There's nothing MFC is doing to change this problem. Rewriting the code to use the API's directly wasn't a worthwhile idea.

You do have some code structure problems, though--you're going to leak a bunch of objects if you ever throw an exception. That's not causing this problem, though.

..B ekiM
0
 
ShaunWildeCommented:
> There's nothing MFC is doing to change this problem. Rewriting the code to use the API's directly wasn't a worthwhile idea.


True but the information has to be stored somewhere and if it is in the wininet.dll then being able to drop the library will get rid of any persistanrt information - something I've never attempted to do do with the MFC DLL (as I can already see the foolhardiness of it) - if this info is being stored elsewhere then it won't help at all, however it was only a suggestion.

Also his original post indicated that the cookie was connected to his process and didn't cross between sequential runs of his app but was deleted when his app stopped. Which to me indicated that it was connected to that running instance of the app and therefore maybe connected to the wininet.dll. Since that is the DLL through which all his calls were being made.
0
 
tomschuringAuthor Commented:
It seems weird to me that no one has ever tried it before to have multiple sessions(in the meaning of asp-session, not connection-session) from one application. Although for example IE can only have one cookie at the same time. If I start up another IExplore it can have a different cookie but when I do a new window, the cookie seems to be shared..

The "storing of the cookie' is hidden so deep within wininet that I don't seem to be able to "clear" it without knowing the name of the cookie (just by overwriting the cooky in the second request with a blank the webserver thinks it is a new sessiom)

I have now put my code inside a transaction server object and set the time-out time of the package to 0 seconds. This seems to work, but it goes wrong when multiple requests are being send simultaniously.

I'm almost to the stage that I would like to ask the users of the function not to rely on cookies...
0
 
tomschuringAuthor Commented:
btw, the problem isn't related to any particular website. It does it with all websites that rely on cookies..
0
 
tomschuringAuthor Commented:
>Why is that a mystery? The Internet session has nothing to do with the cookie. Once it's stored, it's stored until it expires or is deleted.

So how would I implement one app that can handle multple requests to a website with their own cookie ?

0
 
tomschuringAuthor Commented:
Adjusted points from 800 to 853
0
 
NickRepinCommented:
Try to use different values for lpszAgent in InternetOpen("toms app",..) each time you call InternetOpen().
0
 
NickRepinCommented:
There is a easy way to delete all cookies.

1) obtain all cookies for the url:

char* url="http://www.microsoft.com";
DWORD sz=0;
InternetGetCookie(url,0,0,&sz);
if(!sz) return;
char* buf=new char[sz];
InternetGetCookie(url,0,buf,&sz);

Now buf contains the cookies in the form:

Name1=Data1; Name2=Data2; Data3

Note that the data may contain = sign:

Name1=Data1a=Data1b; Name2=Data2; Data3

Data3 is a cookie without name.


GetCookie() implemented as

BOOL CInternetSession::GetCookie(LPCSTR pstrUrl, LPCTSTR pstrCookieName, LPTSTR pstrCookieData, DWORD dwBufLen)
{
   ASSERT(AfxIsValidString(pstrUrl));
   ASSERT(AfxIsValidString(pstrCookieName));
   ASSERT(pstrCookieData != NULL);
   return InternetGetCookie(pstrUrl, pstrCookieName, pstrCookieData, &dwBufLen);
}

So it seems it can produce error in the debug version of MFC if pstrCookieName=0.

But according SDK, <<lpszCookieName
Address of the name of the cookie to get for the specified URL. ***This has not been implemented in this release***.>>

So you can use InternetGetCookie directly with lpszCookieName=0.


2) Parse returned buffer and then call InternetSetCookie for each cookie.
For the cookie without name, call InternetSetCookie(url,0,"");

This will delete all cookes.

If this helps you, please move your question to the Windows Programming topic area. I usually answer there, so your points will be more useful for me. Especially that this is a not C++, but Windows question. You can make it via Community Support area
http://www1.experts-exchange.com/Customer_Service/Experts_Exchange/

0
 
NickRepinCommented:
The answer is above.
0
 
darinwCommented:
Hello everyone,

It is not possible to move questions around. If you think the question is more appropriate for another topic area, then please delete it and repost it in the appropriate topic area before doing all the work on it.

darinw
Community Support
0

Featured Post

Independent Software Vendors: We Want Your Opinion

We value your feedback.

Take our survey and automatically be enter to win anyone of the following:
Yeti Cooler, Amazon eGift Card, and Movie eGift Card!

  • 10
  • 4
  • 3
  • +2
Tackle projects and never again get stuck behind a technical roadblock.
Join Now