|
|
#include <wininetp.h>
#define SZ_COOKIE_EXPORT_HEADER "# Internet Explorer cookie file, exported for Netscape browsers."
#define IE_LOCAL_PREFIX "~~local~~"
#define IE_COOKIE_PREFIX "Cookie:"
void FileTimeToDosTime( FILETIME ft, DWORD* pTime_t);
struct CACHE_ENTRY_INFO_BUFFER : public INTERNET_CACHE_ENTRY_INFO { BYTE _ab[MAX_CACHE_ENTRY_INFO_SIZE]; };
//****************************************************
//
// FileOutputStream - utility
//
class FileOutputStream { public: FileOutputStream() : m_hFile(INVALID_HANDLE_VALUE), m_fError(FALSE), m_dwLastError(0) { }
~FileOutputStream() { if( m_hFile != INVALID_HANDLE_VALUE) CloseHandle( m_hFile); }
BOOL Load( LPCTSTR szFilename, BOOL fAppend) { m_hFile = CreateFile( szFilename, GENERIC_WRITE | GENERIC_READ, 0, NULL, fAppend ? OPEN_ALWAYS : CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
if( m_hFile == INVALID_HANDLE_VALUE) { m_fError = TRUE; m_dwLastError = GetLastError(); return FALSE; }
if( fAppend && SetFilePointer( m_hFile, 0, NULL, FILE_END) == 0xFFFFFFFF) { m_fError = TRUE; m_dwLastError = GetLastError(); return FALSE; }
return TRUE; }
BOOL DumpStr( LPCSTR szString, DWORD cbSize) { DWORD dwTemp;
if( m_fError == TRUE) return FALSE; if( WriteFile( m_hFile, szString, cbSize, &dwTemp, NULL) == TRUE) { return TRUE; } else { m_fError = TRUE; m_dwLastError = GetLastError(); return FALSE; } }
BOOL WriteBool( BOOL fBool) { if( fBool == TRUE) return DumpStr( "TRUE", sizeof("TRUE") - 1); else return DumpStr( "FALSE", sizeof("FALSE") - 1); }
BOOL WriteTab() { return DumpStr( "\t", sizeof('\t')); }
BOOL WriteNSNewline() { return DumpStr( "\r\n\r\n", sizeof("\r\n\r\n") - 1); }
BOOL IsError() { return m_fError; }
private: HANDLE m_hFile; BOOL m_fError; DWORD m_dwLastError; };
//****************************************************
//
// ExportCookieFile
//
// per-line format of Netscape cookie file
//DOMAIN \t is_given_domain(TRUE|FALSE) \t PATH \t secure(TRUE|FALSE) \t time_t(EXPIRES) \t NAME \t VALUE
BOOLAPI ExportCookieFileW( IN LPCWSTR szFilename, IN BOOL fAppend) { MEMORYPACKET mpFilename; ALLOC_MB(szFilename,0,mpFilename); if (!mpFilename.psStr) { return FALSE; } UNICODE_TO_ANSI(szFilename,mpFilename);
return ExportCookieFileA( mpFilename.psStr, fAppend); };
BOOLAPI ExportCookieFileA( IN LPCSTR szFilename, IN BOOL fAppend) { BOOL retVal = FALSE;
CHAR* cursor; DWORD dwTemp;
FileOutputStream outFile;
CACHE_ENTRY_INFO_BUFFER *pcei = new CACHE_ENTRY_INFO_BUFFER;
if (pcei == NULL) goto doneExportCookieFile;
DWORD cbCeiSize = sizeof(*pcei); HANDLE hEnumeration = FindFirstUrlCacheEntry( IE_COOKIE_PREFIX, pcei, &cbCeiSize); if( hEnumeration == NULL) goto doneExportCookieFile;
if( outFile.Load( szFilename, fAppend) != TRUE) goto doneExportCookieFile;
if( !fAppend) { outFile.DumpStr( SZ_COOKIE_EXPORT_HEADER, sizeof(SZ_COOKIE_EXPORT_HEADER) - 1); outFile.WriteNSNewline(); } if( outFile.IsError() == TRUE) goto doneExportCookieFile;
// enumerate over the cookie cache entries.
//Each cache entry will have a file which contains multiple cookies,
//so inside this loop we will be enumerating over individual cookies.
do { CHAR* pFileBuf = NULL; DWORD cbFileBufSize; CHAR* pDomain;
//Generate the DOMAIN for all the cookies in this entry
// example Urls in pEntry:
// "Cookie:[email protected]/"
// "Cookie:t-franks@~~local~~/c:\local\path\"
// The correspondingDomain entry in NS cookie.txt:
// "amazon.com"
// "" -> local paths are empty strings to NS
cursor = pcei->lpszSourceUrlName;
while( *cursor != '@' && *cursor != '\0') cursor++; if( *cursor != '@') goto doneWithEntryOnExportCookie;
pDomain = ++cursor;
if( StrCmpN( pDomain, IE_LOCAL_PREFIX, sizeof(IE_LOCAL_PREFIX) - 1) != 0) { // if we have a non-local domain, clip off the path.
while( *cursor != '/' && *cursor != '\0') cursor++;
if( *cursor != '/') goto doneWithEntryOnExportCookie;
*cursor = '\0'; } else { // Else local cookies have a blank domain in the Netscape cookie files.
pDomain[0] = '\0'; }
// load the attached file and enumerate through the contained cookies.
if( (pcei->lpszLocalFileName == NULL) || (ReadFileToBuffer( pcei->lpszLocalFileName, (BYTE**)&pFileBuf, &cbFileBufSize) != TRUE)) { goto doneWithEntryOnExportCookie; } CHAR* pFileCursor; pFileCursor = pFileBuf; while( pFileCursor < pFileBuf + cbFileBufSize) { CHAR *pszName, *pszValue, *pszHash, *pszFlags, *pszExpireTimeLow, *pszExpireTimeHigh, *pszLastTimeHigh, *pszLastTimeLow, *pszDelimiter; FILETIME ftExpire; DWORD dwFlags; // Get the first token (cookie name).
pszName = StrTokEx(&pFileCursor, "\n"); if (!pszName) // Cookie name.
{ // Normal termination of the parse.
goto doneWithEntryOnExportCookie; }
// Parse the rest of the cookie
if( *pFileCursor == '\n') { pszValue = pFileCursor; *pszValue = '\0'; pFileCursor++; } else pszValue = StrTokEx(&pFileCursor, "\n"); // Cookie value.
pszHash = StrTokEx(&pFileCursor, "\n"); // Combo of domain and path.
pszFlags = StrTokEx(&pFileCursor, "\n"); // Cookie flags.
pszExpireTimeLow = StrTokEx(&pFileCursor, "\n"); // Expire time.
pszExpireTimeHigh = StrTokEx(&pFileCursor, "\n"); pszLastTimeLow = StrTokEx(&pFileCursor, "\n"); // Last Modified time.
pszLastTimeHigh = StrTokEx(&pFileCursor, "\n"); pszDelimiter = StrTokEx(&pFileCursor, "\n"); // Delimiter should be "*"
// Abnormal termination of parse.
if (!pszDelimiter || pszDelimiter[0] != '*') { INET_ASSERT(FALSE); goto doneWithEntryOnExportCookie; }
// Get the expire time.
ftExpire.dwLowDateTime = atoi(pszExpireTimeLow); ftExpire.dwHighDateTime = atoi(pszExpireTimeHigh);
// Get the flags
dwFlags = atoi(pszFlags);
// If this is a session cookie, its non-persistent
//and shouldn't be saved to file.
// (session cookies shouldn't be in the index file, anyhow)
INET_ASSERT( (dwFlags & COOKIE_SESSION) == 0 ? TRUE : FALSE); if( (dwFlags & COOKIE_SESSION) != 0) continue; // process parsed contents.
CHAR* pszNSPath; DWORD timetExpire;
// Example IE cookie file:
// pszHash = "amazon.com/main/"
// pszHash = "~~local~~/c:\local\path\"
// corresponding Netscape path format:
// pszNSPath = "/main/"
// pszNSPath = "/c|/local/path/"
cursor = pszHash;
// move to the first '/'
while( *cursor != '/' && *cursor != '\0') cursor++; if( *cursor != '/') continue;
pszNSPath = cursor; // If this is a path on the Hard Disk, turn the '\\'s to '/'s
//and ':'s to '|'s. (to conform with funky NS format)
if( StrCmpN( pszHash, IE_LOCAL_PREFIX, sizeof(IE_LOCAL_PREFIX) - 1) == 0) { while( *cursor != '\0') { if( *cursor == '\\') *cursor = '/';
if( *cursor == ':') *cursor = '|';
cursor++; } }
// convert to Netscape time format
FileTimeToDosTime( ftExpire, &timetExpire);
outFile.DumpStr( pDomain, lstrlen( pDomain)); outFile.WriteTab(); outFile.WriteBool( TRUE); outFile.WriteTab(); outFile.DumpStr( pszNSPath, lstrlen( pszNSPath)); outFile.WriteTab(); outFile.WriteBool( (dwFlags & COOKIE_SECURE) != 0 ? TRUE : FALSE); outFile.WriteTab();
CHAR expireBuffer[16]; wsprintf( expireBuffer, "%lu", timetExpire); outFile.DumpStr( expireBuffer, lstrlen( expireBuffer)); outFile.WriteTab();
outFile.DumpStr( pszName, lstrlen( pszName)); outFile.WriteTab(); outFile.DumpStr( pszValue, lstrlen( pszValue)); outFile.WriteNSNewline(); } doneWithEntryOnExportCookie: if( pFileBuf != NULL) delete [] pFileBuf;
if( outFile.IsError() == TRUE) goto doneExportCookieFile; } while( FindNextUrlCacheEntry( hEnumeration, pcei, &(cbCeiSize = sizeof(*pcei))));
retVal = TRUE; doneExportCookieFile:
if (pcei) delete pcei;
if( hEnumeration != NULL) FindCloseUrlCache( hEnumeration);
return retVal; }
// reverse of part of transformation in InternetTimeFromTime_t
// A filetime is the numbers of 100 ns since Jan 1, 1601, while
//a dostime is the number of seconds since Jan 1, 1970.
void FileTimeToDosTime( FILETIME ft, DWORD* pTime_t) { //dwl1970Offset is the number of ns from 1601 to 1970
const DWORDLONG dwl1970Offset = 0x019dae9064bafa80;
DWORDLONG lVal; lVal = ft.dwLowDateTime; lVal |= Int64ShllMod32( Int64ShllMod32( ft.dwHighDateTime, 16), 16 );
*pTime_t = (DWORD)((lVal - dwl1970Offset) / 10000000);
return; }
|