Introduction
I was browsing through some folders the other day when I stumbled into the Cookies folder. I was shocked, to say the least, to see several thousand files in there, some of which were nearly three years old. Thinking that something must be wrong with IE's cookie-related settings, I checked IE's properties and everything looked as it should. I clicked on the Delete Cookies button and was presented with a "Delete all cookies in the Temporary Internet Files folder?" message. I responded in the affirmative and then went to check the Cookies folder. It was untouched! All other temporary files had been deleted, however. At this point, I was not sure if the Cookies folder was a special case, or if I was just missing something obvious (it happens). I tried this same thing on a few other machines and got mixed results. On some of them, the Cookies folder was emptied. On others, the folder remained untouched.
Back when I was doing Web development, I seem to remember an Expires
attribute of the Cookies
collection that was used to set the date on which the cookie would expire. I left that company before we ever got around to verifying whether cookies did all they needed to or not. Maybe, I'm incorrect in thinking that they would automatically get cleaned up when the date indicated by the Expires
attribute had passed. Instead, maybe it is simply an indicator to the Web page that the cookie is too old to be used and that another should be created. I welcome any input on this mystery.
That said, I thought I would put together an article on what it would take to automatically clean out the Cookies folder of any old/unused files. The following sections are a brief discussion of that endeavor. Feel free to change the code to fit your needs (e.g., more options, more flexibility, more error checking).
Please note that I did not create this article/utility with the intent of replacing something that IE does internally. It was merely an attempt at addressing what appears to be an inconsistency in how IE manages its Cookies folder. If IE cleans up your Cookies folder with no troubles, this article is not intended for you. If, however, you find that IE does not clean up your Cookies folder, you might just find this article helpful. Enjoy!
Locating the Cookies folder
So, where is the Cookie jar folder anyhow? The easiest way to find out is with the SHGetFolderPath()
function.
CString strCookiesPath;
LPTSTR lpszPath = strCookiesPath.GetBuffer(MAX_PATH);
HRESULT hResult = SHGetFolderPath(NULL, CSIDL_COOKIES,
NULL, SHGFP_TYPE_CURRENT, lpszPath);
if (FAILED(hResult))
hResult = SHGetFolderPath(NULL, CSIDL_COOKIES,
NULL, SHGFP_TYPE_DEFAULT, lpszPath);
strCookiesPath.ReleaseBuffer();
At this point, strCookiesPath
should contain something like "C:\Documents and Settings\<user>\Cookies". To begin searching this folder, all we need to do is tack on a backslash and a pair of wildcard characters, and we're off! Prior to MFC, I would have employed code like the following to do this:
char szPath[256] = "C:\Documents and Settings\<user>\Cookies";
if (szPath[strlen(szPath)] != '\\')
strcat(szPath, "\\");
This worked as intended, but when I started using MFC back in 1993, I switched to CString
objects instead. This resulted in:
strCookiesPath = "C:\Documents and Settings\<user>\Cookies";
if (strCookiesPath.Right(1) != "\\")
strCookiesPath += "\\";
This was a little bit cleaner but then the problem of localization came up. Hard-coding the backslash character could invite trouble. It has to do with the Right()
method. In DBCS languages (e.g., Japanese), this is a common bug because if the last character in the string is double-byte, and the trail byte is 0x5C (the value of backslash), the code will mistakenly think a backslash is already there (thanks Michael Dunn). To address that, I used PathAddBackslash()
like:
PathAddBackslash(strCookiesPath.GetBuffer(MAX_PATH));
strCookiesPath.ReleaseBuffer();
Process the Cookies folder
Our string now contains a trailing backslash. Now we are ready to search (or process) the Cookies folder. To do this, I simply used a CFileFind
object. Since the whole premise of this article was to find cookies that had not been accessed in a certain number of days, we simply need to compare the cookie's last-accessed date with some other user-configured date (i.e., cutoff date). If the cookie is old enough, it is added to a list of cookies to be removed, or displayed, later. I am using Michael Dunn's CShellFileOp
class for this. This is a nice wrapper around the SHFileOperation()
function.
CShellFileOp shfo;
CTime dateFile,
dateCutoff;
CFileFind fileFind;
BOOL bFound = fileFind.FindFile(strCookiesPath + _T("*.*"));
while (TRUE == bFound)
{
bFound = fileFind.FindNextFile();
if (! fileFind.IsDirectory())
{
fileFind.GetLastWriteTime(dateFile);
if (CTime(dateFile.GetTime()) < dateCutoff)
shfo.AddSourceFile(fileFind.GetFilePath());
}
}
We now have a list of cookies that can either be deleted, or output to the screen (maybe you want to see the cookies that would be deleted). To show the cookies, just iterate through the list. CShellFileOp
provides a method, GetSourceFileList()
, to access this list.
const CStringList &listSourceFiles = shfo.GetSourceFileList();
POSITION pos;
CString strFilename;
pos = listSourceFiles.GetHeadPosition();
while (NULL != pos)
{
strFilename = listSourceFiles.GetNext(pos);
cout << (LPCTSTR) strFilename << endl;
}
If however, we actually wanted to delete the cookies, we would just use the CShellFileOp::Go()
method for this. For more on how to use this class, including how to move cookies to the Recycle Bin instead of deleting them, consult Michael's page.
Calculating the cutoff date
The cutoff date can be calculated by simply constructing a CTimeSpan
object and subtracting it from the current date. For example, if you wanted to delete cookies that had not been accessed within the last 15 days, you would specify a cutoff date of:
dateCutoff = CTime::GetCurrentTime() - CTimeSpan(15, 0, 0, 0);
Now, if the cookie's last-accessed date is older than the cutoff date, it will get deleted.
Notes
Using the utility, aptly named cookiemonster, in its current state, five command-line switches are supported. The handling of these is done via Paul DiLascia's CCommandLineInfoEx
class. Here is a synopsis of each:
|
/days ## |
Number of days since cookie was last accessed. |
|
/list |
Show cookies that would be deleted. Cookies are not affected if this is used. |
|
/verbose |
Show details of what the program is doing. |
|
/recycle |
Move cookies to the Recycle Bin. Ignored if /list is used. |
|
/? |
Show the help screen. |
Issuing cookiemonster /days 2 /verbose /recycle at a command prompt, which could just as easily be a scheduled task, yielded the following result on my machine:
Deleting cookies last accessed before 10/19/04.
Cookies will be moved to the Recycle Bin.
Deleting cookies from C:\Documents and Settings\davidc\Cookies.
File: davidc@arstechnica[2].txt.
...Date: 10/21/04
File: davidc@arvest[2].txt
...Date: 10/19/04
...Added
File: davidc@ask[2].txt
...Date: 10/20/04
File: davidc@bbc.co[1].txt
...Date: 10/19/04
...Added
File: davidc@cardeals[2].txt
...Date: 10/20/04
File: davidc@celebritytrivia[1].txt
...Date: 10/20/04
File: davidc@channelintelligence[2].txt
...Date: 10/21/04
<balance of output deleted for brevity>
Note that two files were added to the list, while five were not because their last-accessed date was newer than the cutoff date.
References