770 lines
24 KiB
C++
770 lines
24 KiB
C++
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
|
/* ***** BEGIN LICENSE BLOCK *****
|
|
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
|
*
|
|
* The contents of this file are subject to the Mozilla Public License Version
|
|
* 1.1 (the "License"); you may not use this file except in compliance with
|
|
* the License. You may obtain a copy of the License at
|
|
* http://www.mozilla.org/MPL/
|
|
*
|
|
* Software distributed under the License is distributed on an "AS IS" basis,
|
|
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
|
* for the specific language governing rights and limitations under the
|
|
* License.
|
|
*
|
|
* The Original Code is mozilla.org code.
|
|
*
|
|
* The Initial Developer of the Original Code is
|
|
* Netscape Communications Corporation.
|
|
* Portions created by the Initial Developer are Copyright (C) 2002
|
|
* the Initial Developer. All Rights Reserved.
|
|
*
|
|
* Contributor(s):
|
|
*
|
|
* Alternatively, the contents of this file may be used under the terms of
|
|
* either the GNU General Public License Version 2 or later (the "GPL"), or
|
|
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
|
* in which case the provisions of the GPL or the LGPL are applicable instead
|
|
* of those above. If you wish to allow use of your version of this file only
|
|
* under the terms of either the GPL or the LGPL, and not to allow others to
|
|
* use your version of this file under the terms of the MPL, indicate your
|
|
* decision by deleting the provisions above and replace them with the notice
|
|
* and other provisions required by the GPL or the LGPL. If you do not delete
|
|
* the provisions above, a recipient may use your version of this file under
|
|
* the terms of any one of the MPL, the GPL or the LGPL.
|
|
*
|
|
* ***** END LICENSE BLOCK ***** */
|
|
|
|
#include <stdio.h>
|
|
#include <string.h>
|
|
#include <windows.h>
|
|
#include "nsAppDirectoryServiceDefs.h"
|
|
#include "nsCOMPtr.h"
|
|
#include "nsNetCID.h"
|
|
#include "nsDebug.h"
|
|
#include "nsDependentString.h"
|
|
#include "nsDirectoryServiceDefs.h"
|
|
#include "nsString.h"
|
|
#include "nsTridentPreferencesWin.h"
|
|
#include "plstr.h"
|
|
#include "prio.h"
|
|
#include "prmem.h"
|
|
#include "prlong.h"
|
|
#include "nsICookieManager2.h"
|
|
#include "nsIFile.h"
|
|
#include "nsILocalFile.h"
|
|
#include "nsIPrefService.h"
|
|
#include "nsIPrefBranch.h"
|
|
#include "nsServiceManagerUtils.h"
|
|
#include "nsISimpleEnumerator.h"
|
|
#include "nsITridentProfileMigrator.h"
|
|
|
|
const int sInitialCookieBufferSize = 1024; // but it can grow
|
|
const int sUsernameLengthLimit = 80;
|
|
const int sHostnameLengthLimit = 255;
|
|
|
|
//***********************************************************************
|
|
//*** windows registry to mozilla prefs data type translation functions
|
|
//***********************************************************************
|
|
|
|
typedef void (*regEntryHandler)(unsigned char *, DWORD, DWORD,
|
|
nsIPrefBranch *, char *);
|
|
|
|
// yes/no string to T/F boolean
|
|
void
|
|
TranslateYNtoTF(unsigned char *aRegValue, DWORD aRegValueLength,
|
|
DWORD aRegValueType,
|
|
nsIPrefBranch *prefs, char *aPrefKeyName) {
|
|
|
|
PRInt32 prefIntValue = 0;
|
|
|
|
// input type is a string, lowercase "yes" or "no"
|
|
if (aRegValueType != REG_SZ)
|
|
NS_WARNING("unexpected yes/no data type");
|
|
|
|
if (aRegValueType == REG_SZ && aRegValue[0] != 0) {
|
|
// strcmp is safe; it's bounded by its second parameter
|
|
prefIntValue = strcmp(reinterpret_cast<char *>(aRegValue), "yes") == 0;
|
|
prefs->SetBoolPref(aPrefKeyName, prefIntValue);
|
|
}
|
|
}
|
|
|
|
// yes/no string to F/T boolean
|
|
void
|
|
TranslateYNtoFT(unsigned char *aRegValue, DWORD aRegValueLength,
|
|
DWORD aRegValueType,
|
|
nsIPrefBranch *prefs, char *aPrefKeyName) {
|
|
|
|
PRInt32 prefIntValue = 0;
|
|
|
|
// input type is a string, lowercase "yes" or "no"
|
|
if (aRegValueType != REG_SZ)
|
|
NS_WARNING("unexpected yes/no data type");
|
|
|
|
if (aRegValueType == REG_SZ && aRegValue[0] != 0) {
|
|
// strcmp is safe; it's bounded by its second parameter
|
|
prefIntValue = strcmp(reinterpret_cast<char *>(aRegValue), "yes") != 0;
|
|
prefs->SetBoolPref(aPrefKeyName, prefIntValue);
|
|
}
|
|
}
|
|
|
|
// decimal RGB (1,2,3) to hex RGB (#010203)
|
|
void
|
|
TranslateDRGBtoHRGB(unsigned char *aRegValue, DWORD aRegValueLength,
|
|
DWORD aRegValueType,
|
|
nsIPrefBranch *prefs, char *aPrefKeyName) {
|
|
|
|
// clear previous settings with defaults
|
|
char prefStringValue[10];
|
|
|
|
// input type is a string
|
|
if (aRegValueType != REG_SZ)
|
|
NS_WARNING("unexpected RGB data type");
|
|
|
|
if (aRegValueType == REG_SZ && aRegValue[0] != 0) {
|
|
int red, green, blue;
|
|
::sscanf(reinterpret_cast<char *>(aRegValue), "%d,%d,%d",
|
|
&red, &green, &blue);
|
|
::sprintf(prefStringValue, "#%02X%02X%02X", red, green, blue);
|
|
prefs->SetCharPref(aPrefKeyName, prefStringValue);
|
|
}
|
|
}
|
|
|
|
// translate a windows registry DWORD int to a mozilla prefs PRInt32
|
|
void
|
|
TranslateDWORDtoPRInt32(unsigned char *aRegValue, DWORD aRegValueLength,
|
|
DWORD aRegValueType,
|
|
nsIPrefBranch *prefs, char *aPrefKeyName) {
|
|
|
|
// clear previous settings with defaults
|
|
PRInt32 prefIntValue = 0;
|
|
|
|
if (aRegValueType != REG_DWORD)
|
|
NS_WARNING("unexpected signed int data type");
|
|
|
|
if (aRegValueType == REG_DWORD) {
|
|
prefIntValue = *(reinterpret_cast<DWORD *>(aRegValue));
|
|
prefs->SetIntPref(aPrefKeyName, prefIntValue);
|
|
}
|
|
}
|
|
|
|
// string copy
|
|
void
|
|
TranslateString(unsigned char *aRegValue, DWORD aRegValueLength,
|
|
DWORD aRegValueType,
|
|
nsIPrefBranch *prefs, char *aPrefKeyName) {
|
|
|
|
if (aRegValueType != REG_SZ)
|
|
NS_WARNING("unexpected string data type");
|
|
|
|
if (aRegValueType == REG_SZ)
|
|
prefs->SetCharPref(aPrefKeyName,
|
|
reinterpret_cast<char *>(aRegValue));
|
|
}
|
|
|
|
// translate homepage
|
|
// (modified string copy)
|
|
void
|
|
TranslateHomepage(unsigned char *aRegValue, DWORD aRegValueLength,
|
|
DWORD aRegValueType,
|
|
nsIPrefBranch *prefs, char *aPrefKeyName) {
|
|
|
|
if (aRegValueType != REG_SZ)
|
|
NS_WARNING("unexpected string data type");
|
|
|
|
if (aRegValueType == REG_SZ) {
|
|
// strcmp is safe; it's bounded by its second parameter
|
|
if (strcmp(reinterpret_cast<char *>(aRegValue), "about:blank") == 0)
|
|
prefs->SetIntPref("browser.startup.page", 0);
|
|
else {
|
|
prefs->SetIntPref("browser.startup.page", 1);
|
|
prefs->SetCharPref(aPrefKeyName,
|
|
reinterpret_cast<char *>(aRegValue));
|
|
}
|
|
}
|
|
}
|
|
|
|
// translate accepted language character set formats
|
|
// (modified string copy)
|
|
void
|
|
TranslateLanglist(unsigned char *aRegValue, DWORD aRegValueLength,
|
|
DWORD aRegValueType,
|
|
nsIPrefBranch *prefs, char *aPrefKeyName) {
|
|
|
|
char prefStringValue[MAX_PATH]; // a convenient size, one hopes
|
|
|
|
if (aRegValueType != REG_SZ)
|
|
NS_WARNING("unexpected string data type");
|
|
|
|
if (aRegValueType != REG_SZ)
|
|
return;
|
|
|
|
// copy source format like "en-us,ar-kw;q=0.7,ar-om;q=0.3" into
|
|
// destination format like "en-us, ar-kw, ar-om"
|
|
|
|
char *source = reinterpret_cast<char *>(aRegValue),
|
|
*dest = prefStringValue,
|
|
*sourceEnd = source + aRegValueLength,
|
|
*destEnd = dest + (MAX_PATH-2); // room for " \0"
|
|
PRBool skip = PR_FALSE,
|
|
comma = PR_FALSE;
|
|
|
|
while (source < sourceEnd && *source && dest < destEnd) {
|
|
if (*source == ',')
|
|
skip = PR_FALSE;
|
|
else if (*source == ';')
|
|
skip = PR_TRUE;
|
|
if (!skip) {
|
|
if (comma && *source != ' ')
|
|
*dest++ = ' ';
|
|
*dest = *source;
|
|
}
|
|
comma = *source == ',';
|
|
++source;
|
|
}
|
|
*dest = 0;
|
|
|
|
prefs->SetCharPref(aPrefKeyName, prefStringValue);
|
|
}
|
|
|
|
static int CALLBACK
|
|
fontEnumProc(const LOGFONT *aLogFont, const TEXTMETRIC *aMetric,
|
|
DWORD aFontType, LPARAM aClosure) {
|
|
*((int *) aClosure) = aLogFont->lfPitchAndFamily & FF_ROMAN;
|
|
return 0;
|
|
}
|
|
void
|
|
TranslatePropFont(unsigned char *aRegValue, DWORD aRegValueLength,
|
|
DWORD aRegValueType,
|
|
nsIPrefBranch *prefs, char *aPrefKeyName) {
|
|
|
|
HDC dc = ::GetDC(0);
|
|
LOGFONT lf;
|
|
int isSerif = 1;
|
|
|
|
// serif or sans-serif font?
|
|
lf.lfCharSet = DEFAULT_CHARSET;
|
|
lf.lfPitchAndFamily = 0;
|
|
PL_strncpyz(lf.lfFaceName, reinterpret_cast<char *>(aRegValue),
|
|
LF_FACESIZE);
|
|
::EnumFontFamiliesEx(dc, &lf, fontEnumProc, (LPARAM) &isSerif, 0);
|
|
::ReleaseDC(0, dc);
|
|
|
|
if (isSerif) {
|
|
prefs->SetCharPref("font.name.serif.x-western",
|
|
reinterpret_cast<char *>(aRegValue));
|
|
prefs->SetCharPref("font.default.x-western", "serif");
|
|
} else {
|
|
prefs->SetCharPref("font.name.sans-serif.x-western",
|
|
reinterpret_cast<char *>(aRegValue));
|
|
prefs->SetCharPref("font.default.x-western", "sans-serif");
|
|
}
|
|
}
|
|
|
|
//***********************************************************************
|
|
//*** master table of registry-to-gecko-pref translations
|
|
//***********************************************************************
|
|
|
|
struct regEntry {
|
|
char *regKeyName, // registry key (HKCU\Software ...)
|
|
*regValueName; // registry key leaf
|
|
char *prefKeyName; // pref name ("javascript.enabled" ...)
|
|
regEntryHandler entryHandler; // processing func
|
|
};
|
|
struct regEntry gRegEntries[] = {
|
|
{ "Software\\Microsoft\\Windows\\CurrentVersion\\Explorer\\AutoComplete",
|
|
"AutoSuggest",
|
|
"browser.urlbar.autocomplete.enabled",
|
|
TranslateYNtoTF },
|
|
{ "Software\\Microsoft\\Internet Explorer\\International",
|
|
"AcceptLanguage",
|
|
"intl.accept_languages",
|
|
TranslateLanglist },
|
|
{ "Software\\Microsoft\\Internet Explorer\\International\\Scripts\\3",
|
|
"IEFixedFontName",
|
|
"font.name.monospace.x-western",
|
|
TranslateString },
|
|
{ 0, // an optimization: 0 means use the previous key
|
|
"IEPropFontName",
|
|
"", // special-cased in the translation function
|
|
TranslatePropFont },
|
|
{ "Software\\Microsoft\\Internet Explorer\\Main",
|
|
"Use_DlgBox_Colors",
|
|
"browser.display.use_system_colors",
|
|
TranslateYNtoTF },
|
|
{ 0,
|
|
"Use FormSuggest",
|
|
"wallet.captureForms",
|
|
TranslateYNtoTF },
|
|
{ 0,
|
|
"FormSuggest Passwords",
|
|
"signon.rememberSignons",
|
|
TranslateYNtoTF },
|
|
{ 0,
|
|
"Start Page",
|
|
"browser.startup.homepage",
|
|
TranslateHomepage },
|
|
{ "Software\\Microsoft\\Internet Explorer\\Settings",
|
|
"Always Use My Colors",
|
|
"browser.display.use_document_colors",
|
|
TranslateYNtoFT },
|
|
{ 0,
|
|
"Text Color",
|
|
"browser.display.foreground_color",
|
|
TranslateDRGBtoHRGB },
|
|
{ 0,
|
|
"Background Color",
|
|
"browser.display.background_color",
|
|
TranslateDRGBtoHRGB },
|
|
{ 0,
|
|
"Anchor Color",
|
|
"browser.anchor_color",
|
|
TranslateDRGBtoHRGB },
|
|
{ 0,
|
|
"Anchor Color Visited",
|
|
"browser.visited_color",
|
|
TranslateDRGBtoHRGB },
|
|
{ 0,
|
|
"Always Use My Font Face",
|
|
"browser.display.use_document_fonts",
|
|
TranslateYNtoFT },
|
|
{ "Software\\Microsoft\\Windows\\CurrentVersion\\Internet Settings\\Url History",
|
|
"DaysToKeep",
|
|
"browser.history_expire_days",
|
|
TranslateDWORDtoPRInt32 }
|
|
};
|
|
|
|
#if 0
|
|
user_pref("font.size.fixed.x-western", 14);
|
|
user_pref("font.size.variable.x-western", 15);
|
|
#endif
|
|
|
|
//*****************************************************************************
|
|
//*** factory
|
|
//*****************************************************************************
|
|
|
|
nsTridentPreferences *
|
|
MakeTridentPreferences() {
|
|
return new nsTridentPreferencesWin();
|
|
}
|
|
|
|
//*****************************************************************************
|
|
//*** nsTridentPreferences
|
|
//*****************************************************************************
|
|
|
|
nsTridentPreferences::nsTridentPreferences() {
|
|
}
|
|
|
|
nsTridentPreferences::~nsTridentPreferences() {
|
|
}
|
|
|
|
//*****************************************************************************
|
|
//*** nsTridentPreferencesWin
|
|
//*****************************************************************************
|
|
|
|
nsTridentPreferencesWin::nsTridentPreferencesWin() {
|
|
}
|
|
|
|
nsTridentPreferencesWin::~nsTridentPreferencesWin() {
|
|
}
|
|
|
|
// migration entry point
|
|
nsresult
|
|
nsTridentPreferencesWin::MigrateTridentPreferences(PRUint32 aItems) {
|
|
|
|
nsresult rv = NS_OK;
|
|
|
|
if (aItems & nsITridentProfileMigrator::PREFERENCES)
|
|
rv = CopyPreferences();
|
|
if (NS_SUCCEEDED(rv) && (aItems & nsITridentProfileMigrator::COOKIES))
|
|
rv = CopyCookies();
|
|
|
|
return rv;
|
|
}
|
|
|
|
nsresult
|
|
nsTridentPreferencesWin::CopyPreferences() {
|
|
|
|
HKEY regKey;
|
|
PRBool regKeyOpen = PR_FALSE;
|
|
struct regEntry *entry,
|
|
*endEntry = gRegEntries +
|
|
sizeof(gRegEntries)/sizeof(struct regEntry);
|
|
DWORD regType;
|
|
DWORD regLength;
|
|
unsigned char regValue[MAX_PATH]; // a convenient size
|
|
|
|
nsCOMPtr<nsIPrefBranch> prefs;
|
|
|
|
{ // scope pserve why not
|
|
nsCOMPtr<nsIPrefService> pserve(do_GetService(NS_PREFSERVICE_CONTRACTID));
|
|
if (pserve)
|
|
pserve->GetBranch("", getter_AddRefs(prefs));
|
|
}
|
|
if (!prefs)
|
|
return NS_ERROR_FAILURE;
|
|
|
|
// step through gRegEntries table
|
|
|
|
for (entry = gRegEntries; entry < endEntry; ++entry) {
|
|
|
|
// a new keyname? close any previous one and open the new one
|
|
if (entry->regKeyName) {
|
|
if (regKeyOpen) {
|
|
::RegCloseKey(regKey);
|
|
regKeyOpen = PR_FALSE;
|
|
}
|
|
regKeyOpen = ::RegOpenKeyEx(HKEY_CURRENT_USER, entry->regKeyName, 0,
|
|
KEY_READ, ®Key) == ERROR_SUCCESS;
|
|
}
|
|
|
|
if (regKeyOpen) {
|
|
// read registry data
|
|
regLength = MAX_PATH;
|
|
if (::RegQueryValueEx(regKey, entry->regValueName, 0,
|
|
®Type, regValue, ®Length) == ERROR_SUCCESS)
|
|
|
|
entry->entryHandler(regValue, regLength, regType,
|
|
prefs, entry->prefKeyName);
|
|
}
|
|
}
|
|
|
|
if (regKeyOpen)
|
|
::RegCloseKey(regKey);
|
|
|
|
return CopyStyleSheet();
|
|
}
|
|
|
|
/* Fetch and translate the current user's cookies.
|
|
Return true if successful. */
|
|
nsresult
|
|
nsTridentPreferencesWin::CopyCookies() {
|
|
|
|
// IE cookies are stored in files named <username>@domain[n].txt
|
|
// (in <username>'s Cookies folder. isn't the naming redundant?)
|
|
|
|
PRBool rv = NS_OK;
|
|
|
|
nsCOMPtr<nsIFile> cookiesDir;
|
|
nsCOMPtr<nsISimpleEnumerator> cookieFiles;
|
|
|
|
nsCOMPtr<nsICookieManager2> cookieManager(do_GetService(NS_COOKIEMANAGER_CONTRACTID));
|
|
if (!cookieManager)
|
|
return NS_ERROR_FAILURE;
|
|
|
|
// find the cookies directory
|
|
NS_GetSpecialDirectory(NS_WIN_COOKIES_DIR, getter_AddRefs(cookiesDir));
|
|
if (cookiesDir)
|
|
cookiesDir->GetDirectoryEntries(getter_AddRefs(cookieFiles));
|
|
if (!cookieFiles)
|
|
return NS_ERROR_FAILURE;
|
|
|
|
// fetch the current user's name from the environment
|
|
char username[sUsernameLengthLimit+2];
|
|
::GetEnvironmentVariable("USERNAME", username, sizeof(username));
|
|
username[sizeof(username)-2] = '\0';
|
|
PL_strcat(username, "@");
|
|
int usernameLength = PL_strlen(username);
|
|
|
|
// allocate a buffer into which to read each cookie file
|
|
char *fileContents = (char *) PR_Malloc(sInitialCookieBufferSize);
|
|
if (!fileContents)
|
|
return NS_ERROR_OUT_OF_MEMORY;
|
|
PRUint32 fileContentsSize = sInitialCookieBufferSize;
|
|
|
|
do { // for each file in the cookies directory
|
|
// get the next file
|
|
PRBool moreFiles = PR_FALSE;
|
|
if (NS_FAILED(cookieFiles->HasMoreElements(&moreFiles)) || !moreFiles)
|
|
break;
|
|
|
|
nsCOMPtr<nsISupports> supFile;
|
|
cookieFiles->GetNext(getter_AddRefs(supFile));
|
|
nsCOMPtr<nsIFile> cookieFile(do_QueryInterface(supFile));
|
|
if (!cookieFile) {
|
|
rv = NS_ERROR_FAILURE;
|
|
break; // unexpected! punt!
|
|
}
|
|
|
|
// is it a cookie file for the current user?
|
|
nsCAutoString fileName;
|
|
cookieFile->GetNativeLeafName(fileName);
|
|
const nsACString &fileOwner = Substring(fileName, 0, usernameLength);
|
|
if (!fileOwner.Equals(username, nsCaseInsensitiveCStringComparator()))
|
|
continue;
|
|
|
|
// ensure the contents buffer is large enough to hold the entire file
|
|
// plus one byte (see DelimitField())
|
|
PRInt64 llFileSize;
|
|
if (NS_FAILED(cookieFile->GetFileSize(&llFileSize)))
|
|
continue;
|
|
|
|
PRUint32 fileSize, readSize;
|
|
LL_L2UI(fileSize, llFileSize);
|
|
if (fileSize >= fileContentsSize) {
|
|
PR_Free(fileContents);
|
|
fileContents = (char *) PR_Malloc(fileSize+1);
|
|
if (!fileContents) {
|
|
rv = NS_ERROR_FAILURE;
|
|
break; // fatal error
|
|
}
|
|
fileContentsSize = fileSize;
|
|
}
|
|
|
|
// read the entire cookie file
|
|
PRFileDesc *fd;
|
|
nsCOMPtr<nsILocalFile> localCookieFile(do_QueryInterface(cookieFile));
|
|
if (localCookieFile &&
|
|
NS_SUCCEEDED(localCookieFile->OpenNSPRFileDesc(PR_RDONLY, 0444, &fd))) {
|
|
|
|
readSize = PR_Read(fd, fileContents, fileSize);
|
|
PR_Close(fd);
|
|
|
|
if (fileSize == readSize) { // translate this file's cookies
|
|
nsresult onerv;
|
|
onerv = CopyCookiesFromBuffer(fileContents, readSize, cookieManager);
|
|
if (NS_FAILED(onerv))
|
|
rv = onerv;
|
|
}
|
|
}
|
|
} while(1);
|
|
|
|
if (fileContents)
|
|
PR_Free(fileContents);
|
|
return rv;
|
|
}
|
|
|
|
/* Fetch cookies from a single IE cookie file.
|
|
Return true if successful. */
|
|
nsresult
|
|
nsTridentPreferencesWin::CopyCookiesFromBuffer(
|
|
char *aBuffer,
|
|
PRUint32 aBufferLength,
|
|
nsICookieManager2 *aCookieManager) {
|
|
|
|
nsresult rv = NS_OK;
|
|
|
|
const char *bufferEnd = aBuffer + aBufferLength;
|
|
// cookie fields:
|
|
char *name,
|
|
*value,
|
|
*host,
|
|
*path,
|
|
*flags,
|
|
*expirationDate1, *expirationDate2,
|
|
*creationDate1, *creationDate2,
|
|
*terminator;
|
|
int flagsValue;
|
|
time_t expirationDate,
|
|
creationDate;
|
|
char hostCopy[sHostnameLengthLimit+1],
|
|
*hostCopyConstructor,
|
|
*hostCopyEnd = hostCopy + sHostnameLengthLimit;
|
|
|
|
do { // for each cookie in the buffer
|
|
DelimitField(&aBuffer, bufferEnd, &name);
|
|
DelimitField(&aBuffer, bufferEnd, &value);
|
|
DelimitField(&aBuffer, bufferEnd, &host);
|
|
DelimitField(&aBuffer, bufferEnd, &flags);
|
|
DelimitField(&aBuffer, bufferEnd, &expirationDate1);
|
|
DelimitField(&aBuffer, bufferEnd, &expirationDate2);
|
|
DelimitField(&aBuffer, bufferEnd, &creationDate1);
|
|
DelimitField(&aBuffer, bufferEnd, &creationDate2);
|
|
DelimitField(&aBuffer, bufferEnd, &terminator);
|
|
|
|
// it's a cookie if we got one of each
|
|
if (terminator >= bufferEnd)
|
|
break;
|
|
|
|
// IE stores deleted cookies with a zero-length value
|
|
if (*value == '\0')
|
|
continue;
|
|
|
|
// convert flags to an int, date numbers to useable dates
|
|
::sscanf(flags, "%d", &flagsValue);
|
|
expirationDate = FileTimeToTimeT(expirationDate1, expirationDate2);
|
|
creationDate = FileTimeToTimeT(creationDate1, creationDate2);
|
|
|
|
// munge host, and separate host from path
|
|
|
|
hostCopyConstructor = hostCopy;
|
|
|
|
// first, with a non-null domain, assume it's what Mozilla considers
|
|
// a domain cookie. see bug 222343.
|
|
if (*host && *host != '.' && *host != '/')
|
|
*hostCopyConstructor++ = '.';
|
|
|
|
// copy the host part and leave path pointing to the path part
|
|
for (path = host; *path && *path != '/'; ++path)
|
|
;
|
|
int hostLength = path - host;
|
|
if (hostLength > hostCopyEnd - hostCopyConstructor)
|
|
hostLength = hostCopyEnd - hostCopyConstructor;
|
|
PL_strncpy(hostCopyConstructor, host, hostLength);
|
|
hostCopyConstructor += hostLength;
|
|
|
|
*hostCopyConstructor = '\0';
|
|
|
|
nsDependentCString stringName(name),
|
|
stringPath(path);
|
|
|
|
// delete any possible extant matching host cookie
|
|
if (hostCopy[0] == '.')
|
|
aCookieManager->Remove(nsDependentCString(hostCopy+1),
|
|
stringName, stringPath, PR_FALSE);
|
|
|
|
nsresult onerv;
|
|
// Add() makes a new domain cookie
|
|
onerv = aCookieManager->Add(nsDependentCString(hostCopy),
|
|
stringPath,
|
|
stringName,
|
|
nsDependentCString(value),
|
|
flagsValue & 0x1, // isSecure
|
|
PR_FALSE, // isHttpOnly
|
|
PR_FALSE, // isSession
|
|
PRInt64(expirationDate));
|
|
if (NS_FAILED(onerv)) {
|
|
rv = onerv;
|
|
break;
|
|
}
|
|
|
|
} while(aBuffer < bufferEnd);
|
|
|
|
return rv;
|
|
}
|
|
|
|
/* Delimit the next field in the IE cookie buffer.
|
|
when called:
|
|
aBuffer: at the beginning of the next field or preceding whitespace
|
|
aBufferEnd: one past the last valid character in the buffer
|
|
on return:
|
|
aField: at the beginning of the next field, which is null delimited
|
|
aBuffer: after the null at the end of the field
|
|
|
|
the character at which aBufferEnd points must be part of the buffer
|
|
so we can set it to \0.
|
|
*/
|
|
void
|
|
nsTridentPreferencesWin::DelimitField(char **aBuffer,
|
|
const char *aBufferEnd,
|
|
char **aField) {
|
|
|
|
char *scan = *aBuffer;
|
|
*aField = scan;
|
|
while (scan < aBufferEnd && (*scan != '\r' && *scan != '\n'))
|
|
++scan;
|
|
if (scan+1 < aBufferEnd && (*(scan+1) == '\r' || *(scan+1) == '\n') &&
|
|
*scan != *(scan+1)) {
|
|
*scan = '\0';
|
|
scan += 2;
|
|
} else {
|
|
if (scan <= aBufferEnd) // (1 byte past bufferEnd is guaranteed allocated)
|
|
*scan = '\0';
|
|
++scan;
|
|
}
|
|
*aBuffer = scan;
|
|
}
|
|
|
|
// conversion routine. returns 0 (epoch date) if the input is out of range
|
|
time_t
|
|
nsTridentPreferencesWin::FileTimeToTimeT(const char *aLowDateIntString,
|
|
const char *aHighDateIntString) {
|
|
|
|
FILETIME fileTime;
|
|
SYSTEMTIME systemTime;
|
|
tm tTime;
|
|
time_t rv;
|
|
|
|
::sscanf(aLowDateIntString, "%ld", &fileTime.dwLowDateTime);
|
|
::sscanf(aHighDateIntString, "%ld", &fileTime.dwHighDateTime);
|
|
::FileTimeToSystemTime(&fileTime, &systemTime);
|
|
tTime.tm_year = systemTime.wYear - 1900;
|
|
tTime.tm_mon = systemTime.wMonth-1;
|
|
tTime.tm_mday = systemTime.wDay;
|
|
tTime.tm_hour = systemTime.wHour;
|
|
tTime.tm_min = systemTime.wMinute;
|
|
tTime.tm_sec = systemTime.wSecond;
|
|
tTime.tm_isdst = -1;
|
|
rv = ::mktime(&tTime);
|
|
return rv < 0 ? 0 : rv;
|
|
}
|
|
|
|
/* Find the accessibility stylesheet if it exists and replace Mozilla's
|
|
with it. Return true if we found and copied a stylesheet. */
|
|
nsresult
|
|
nsTridentPreferencesWin::CopyStyleSheet() {
|
|
|
|
nsresult rv = NS_OK; // return failure only if filecopy fails
|
|
HKEY regKey;
|
|
DWORD regType,
|
|
regLength,
|
|
regDWordValue;
|
|
char tridentFilename[MAX_PATH];
|
|
|
|
// is there a trident user stylesheet?
|
|
if (::RegOpenKeyEx(HKEY_CURRENT_USER,
|
|
"Software\\Microsoft\\Internet Explorer\\Styles", 0,
|
|
KEY_READ, ®Key) != ERROR_SUCCESS)
|
|
return NS_OK;
|
|
|
|
regLength = sizeof(DWORD);
|
|
if (::RegQueryValueEx(regKey, "Use My Stylesheet", 0, ®Type,
|
|
reinterpret_cast<unsigned char *>(®DWordValue),
|
|
®Length) == ERROR_SUCCESS &&
|
|
regType == REG_DWORD && regDWordValue == 1) {
|
|
|
|
regLength = MAX_PATH;
|
|
if (::RegQueryValueEx(regKey, "User Stylesheet", 0, ®Type,
|
|
reinterpret_cast<unsigned char *>(tridentFilename),
|
|
®Length)
|
|
== ERROR_SUCCESS) {
|
|
|
|
// tridentFilename is a native path to the specified stylesheet file
|
|
// point an nsIFile at it
|
|
nsCOMPtr<nsILocalFile> tridentFile(do_CreateInstance(NS_LOCAL_FILE_CONTRACTID));
|
|
if (tridentFile) {
|
|
PRBool exists;
|
|
|
|
tridentFile->InitWithNativePath(nsDependentCString(tridentFilename));
|
|
tridentFile->Exists(&exists);
|
|
if (exists) {
|
|
// now establish our file (userContent.css in the profile/chrome dir)
|
|
nsCOMPtr<nsIFile> chromeDir;
|
|
NS_GetSpecialDirectory(NS_APP_USER_CHROME_DIR,
|
|
getter_AddRefs(chromeDir));
|
|
if (chromeDir)
|
|
rv = tridentFile->CopyToNative(chromeDir,
|
|
nsDependentCString("userContent.css"));
|
|
}
|
|
}
|
|
}
|
|
}
|
|
::RegCloseKey(regKey);
|
|
return rv;
|
|
}
|
|
|
|
void
|
|
nsTridentPreferencesWin::GetUserStyleSheetFile(nsIFile **aUserFile) {
|
|
|
|
nsCOMPtr<nsIFile> userChrome;
|
|
|
|
*aUserFile = 0;
|
|
|
|
// establish the chrome directory
|
|
NS_GetSpecialDirectory(NS_APP_USER_CHROME_DIR, getter_AddRefs(userChrome));
|
|
|
|
if (userChrome) {
|
|
PRBool exists;
|
|
userChrome->Exists(&exists);
|
|
if (!exists &&
|
|
NS_FAILED(userChrome->Create(nsIFile::DIRECTORY_TYPE, 0755)))
|
|
return;
|
|
|
|
// establish the user content stylesheet file
|
|
userChrome->AppendNative(NS_LITERAL_CSTRING("userContent.css"));
|
|
*aUserFile = userChrome;
|
|
NS_ADDREF(*aUserFile);
|
|
}
|
|
}
|
|
|