Solved

CInternetSession lifespan

Posted on 2000-03-16
21
1,414 Views
Last Modified: 2012-08-13
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
Comment
Question by:tomschuring
  • 10
  • 4
  • 3
  • +2
21 Comments
 
LVL 9

Expert Comment

by:ShaunWilde
ID: 2627451
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
 

Author Comment

by:tomschuring
ID: 2634071
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
 

Author Comment

by:tomschuring
ID: 2634370
Adjusted points from 100 to 400
0
 

Author Comment

by:tomschuring
ID: 2634371
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
 
LVL 9

Expert Comment

by:ShaunWilde
ID: 2635335
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
 

Author Comment

by:tomschuring
ID: 2637779
thanks, that is what I am doing now. Perhaps the original api will fix it.
0
 

Author Comment

by:tomschuring
ID: 2638181
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
 

Author Comment

by:tomschuring
ID: 2638196
Adjusted points from 400 to 800
0
 
LVL 9

Expert Comment

by:ShaunWilde
ID: 2639472
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
 
LVL 11

Expert Comment

by:mikeblas
ID: 2647953
> 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
What Security Threats Are You Missing?

Enhance your security with threat intelligence from the web. Get trending threat insights on hackers, exploits, and suspicious IP addresses delivered to your inbox with our free Cyber Daily.

 
LVL 11

Expert Comment

by:mikeblas
ID: 2647969
BTW, is this a public website?  Can you provide the query you're doing?

..B ekiM
0
 
LVL 11

Expert Comment

by:mikeblas
ID: 2647989
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
 
LVL 9

Expert Comment

by:ShaunWilde
ID: 2648281
> 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
 

Author Comment

by:tomschuring
ID: 2648812
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
 

Author Comment

by:tomschuring
ID: 2648823
btw, the problem isn't related to any particular website. It does it with all websites that rely on cookies..
0
 

Author Comment

by:tomschuring
ID: 2648850
>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
 

Author Comment

by:tomschuring
ID: 2648852
Adjusted points from 800 to 853
0
 
LVL 15

Expert Comment

by:NickRepin
ID: 2740955
Try to use different values for lpszAgent in InternetOpen("toms app",..) each time you call InternetOpen().
0
 
LVL 15

Expert Comment

by:NickRepin
ID: 2740984
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
 
LVL 15

Accepted Solution

by:
NickRepin earned 853 total points
ID: 2754431
The answer is above.
0
 
LVL 3

Expert Comment

by:darinw
ID: 4305455
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

Why You Should Analyze Threat Actor TTPs

After years of analyzing threat actor behavior, it’s become clear that at any given time there are specific tactics, techniques, and procedures (TTPs) that are particularly prevalent. By analyzing and understanding these TTPs, you can dramatically enhance your security program.

Join & Write a Comment

Article by: SunnyDark
This article's goal is to present you with an easy to use XML wrapper for C++ and also present some interesting techniques that you might use with MS C++. The reason I built this class is to ease the pain of using XML files with C++, since there is…
C++ Properties One feature missing from standard C++ that you will find in many other Object Oriented Programming languages is something called a Property (http://www.experts-exchange.com/Programming/Languages/CPP/A_3912-Object-Properties-in-C.ht…
The viewer will learn how to use the return statement in functions in C++. The video will also teach the user how to pass data to a function and have the function return data back for further processing.
The viewer will learn how to user default arguments when defining functions. This method of defining functions will be contrasted with the non-default-argument of defining functions.

758 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question

Need Help in Real-Time?

Connect with top rated Experts

17 Experts available now in Live!

Get 1:1 Help Now