nsIEProfileMigrator.cpp
Go to the documentation of this file.
1 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2 /* ***** BEGIN LICENSE BLOCK *****
3  * Version: MPL 1.1/GPL 2.0/LGPL 2.1
4  *
5  * The contents of this file are subject to the Mozilla Public License Version
6  * 1.1 (the "License"); you may not use this file except in compliance with
7  * the License. You may obtain a copy of the License at
8  * http://www.mozilla.org/MPL/
9  *
10  * Software distributed under the License is distributed on an "AS IS" basis,
11  * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
12  * for the specific language governing rights and limitations under the
13  * License.
14  *
15  * The Original Code is mozilla.org code.
16  *
17  * The Initial Developer of the Original Code is
18  * Netscape Communications Corporation.
19  * Portions created by the Initial Developer are Copyright (C) 2002
20  * the Initial Developer. All Rights Reserved.
21  *
22  * Contributor(s):
23  * Daniel Matejka
24  * (Original Author)
25  * Ben Goodger <ben@bengoodger.com>
26  * (History, Favorites, Passwords, Form Data, some settings)
27  *
28  * Alternatively, the contents of this file may be used under the terms of
29  * either the GNU General Public License Version 2 or later (the "GPL"), or
30  * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
31  * in which case the provisions of the GPL or the LGPL are applicable instead
32  * of those above. If you wish to allow use of your version of this file only
33  * under the terms of either the GPL or the LGPL, and not to allow others to
34  * use your version of this file under the terms of the MPL, indicate your
35  * decision by deleting the provisions above and replace them with the notice
36  * and other provisions required by the GPL or the LGPL. If you do not delete
37  * the provisions above, a recipient may use your version of this file under
38  * the terms of any one of the MPL, the GPL or the LGPL.
39  *
40  * ***** END LICENSE BLOCK ***** */
41 
42 #include <stdio.h>
43 #include <string.h>
44 #include <windows.h>
45 #include "nsAppDirectoryServiceDefs.h"
47 #include "nsCOMPtr.h"
48 #include "nsCRTGlue.h"
49 #include "nsNetCID.h"
50 #include "nsDocShellCID.h"
51 #include "nsDebug.h"
52 #include "nsDirectoryServiceDefs.h"
53 #include "nsDirectoryServiceUtils.h"
54 #include "nsStringAPI.h"
55 #include "plstr.h"
56 #include "prio.h"
57 #include "prmem.h"
58 #include "prlong.h"
59 #include "nsICookieManager2.h"
60 #include "nsIEProfileMigrator.h"
61 #include "nsIFile.h"
62 #include "nsILocalFile.h"
63 #include "nsIPrefService.h"
64 #include "nsIPrefBranch.h"
65 #include "nsISimpleEnumerator.h"
66 #include "nsISupportsArray.h"
67 #include "nsIProfileMigrator.h"
68 #include "nsIBrowserProfileMigrator.h"
69 #include "nsIObserverService.h"
70 #include "nsILocalFileWin.h"
71 #include "nsAutoPtr.h"
72 
73 #include <objbase.h>
74 #include <shlguid.h>
75 #include <urlhist.h>
76 #include <comdef.h>
77 #include <shlobj.h>
78 #include <intshcut.h>
79 
80 #include "nsIBrowserHistory.h"
81 #include "nsIGlobalHistory.h"
82 #include "nsIRDFRemoteDataSource.h"
83 #include "nsIURI.h"
84 #include "nsILoginManagerIEMigrationHelper.h"
85 #include "nsILoginInfo.h"
86 #include "nsIFormHistory.h"
87 #include "nsIRDFService.h"
88 #include "nsIRDFContainer.h"
89 #include "nsIURL.h"
90 #include "nsINavBookmarksService.h"
91 #include "nsBrowserCompsCID.h"
92 #include "nsIStringBundle.h"
93 #include "nsNetUtil.h"
94 #include "nsToolkitCompsCID.h"
95 #include "nsUnicharUtils.h"
96 #include "nsIWindowsRegKey.h"
97 #include "nsISupportsPrimitives.h"
98 
99 #define TRIDENTPROFILE_BUNDLE "chrome://browser/locale/migration/migration.properties"
100 
101 #define REGISTRY_IE_MAIN_KEY \
102  NS_LITERAL_STRING("Software\\Microsoft\\Internet Explorer\\Main")
103 #define REGISTRY_IE_TYPEDURL_KEY \
104  NS_LITERAL_STRING("Software\\Microsoft\\Internet Explorer\\TypedURLs")
105 #define REGISTRY_IE_TOOLBAR_KEY \
106  NS_LITERAL_STRING("Software\\Microsoft\\Internet Explorer\\Toolbar")
107 #define REGISTRY_IE_SEARCHURL_KEY \
108  NS_LITERAL_STRING("Software\\Microsoft\\Internet Explorer\\SearchUrl")
109 
110 const int sInitialCookieBufferSize = 1024; // but it can grow
111 const int sUsernameLengthLimit = 80;
112 const int sHostnameLengthLimit = 255;
113 
114 //***********************************************************************
115 //*** Replacements for comsupp.lib calls used by pstorec.dll
116 //***********************************************************************
117 void __stdcall _com_issue_error(HRESULT hr)
118 {
119  // XXX - Do nothing for now
120 }
121 
122 //***********************************************************************
123 //*** windows registry to mozilla prefs data type translation functions
124 //***********************************************************************
125 
126 typedef void (*regEntryHandler)(nsIWindowsRegKey *, const nsString&,
127  nsIPrefBranch *, char *);
128 
129 // yes/no string to T/F boolean
130 void
131 TranslateYNtoTF(nsIWindowsRegKey *aRegKey, const nsString& aRegValueName,
132  nsIPrefBranch *aPrefs, char *aPrefKeyName) {
133 
134  // input type is a string, lowercase "yes" or "no"
135  nsAutoString regValue;
136  if (NS_SUCCEEDED(aRegKey->ReadStringValue(aRegValueName, regValue)))
137  aPrefs->SetBoolPref(aPrefKeyName, regValue.EqualsLiteral("yes"));
138 }
139 
140 // yes/no string to F/T boolean
141 void
142 TranslateYNtoFT(nsIWindowsRegKey *aRegKey, const nsString& aRegValueName,
143  nsIPrefBranch *aPrefs, char *aPrefKeyName) {
144 
145  // input type is a string, lowercase "yes" or "no"
146  nsAutoString regValue;
147  if (NS_SUCCEEDED(aRegKey->ReadStringValue(aRegValueName, regValue)))
148  aPrefs->SetBoolPref(aPrefKeyName, !regValue.EqualsLiteral("yes"));
149 }
150 
151 void
152 TranslateYNtoImageBehavior(nsIWindowsRegKey *aRegKey,
153  const nsString& aRegValueName,
154  nsIPrefBranch *aPrefs, char *aPrefKeyName) {
155  // input type is a string, lowercase "yes" or "no"
156  nsAutoString regValue;
157  if (NS_SUCCEEDED(aRegKey->ReadStringValue(aRegValueName, regValue)) &&
158  !regValue.IsEmpty()) {
159  if (regValue.EqualsLiteral("yes"))
160  aPrefs->SetIntPref(aPrefKeyName, 1);
161  else
162  aPrefs->SetIntPref(aPrefKeyName, 2);
163  }
164 }
165 
166 void
167 TranslateDWORDtoHTTPVersion(nsIWindowsRegKey *aRegKey,
168  const nsString& aRegValueName,
169  nsIPrefBranch *aPrefs, char *aPrefKeyName) {
170  PRUint32 val;
171  if (NS_SUCCEEDED(aRegKey->ReadIntValue(aRegValueName, &val))) {
172  if (val & 0x1)
173  aPrefs->SetCharPref(aPrefKeyName, "1.1");
174  else
175  aPrefs->SetCharPref(aPrefKeyName, "1.0");
176  }
177 }
178 
179 // decimal RGB (1,2,3) to hex RGB (#010203)
180 void
181 TranslateDRGBtoHRGB(nsIWindowsRegKey *aRegKey, const nsString& aRegValueName,
182  nsIPrefBranch *aPrefs, char *aPrefKeyName) {
183 
184  // clear previous settings with defaults
185  char prefStringValue[10];
186 
187  nsAutoString regValue;
188  if (NS_SUCCEEDED(aRegKey->ReadStringValue(aRegValueName, regValue)) &&
189  !regValue.IsEmpty()) {
190  int red, green, blue;
191  ::swscanf(regValue.get(), L"%d,%d,%d", &red, &green, &blue);
192  ::sprintf(prefStringValue, "#%02X%02X%02X", red, green, blue);
193  aPrefs->SetCharPref(aPrefKeyName, prefStringValue);
194  }
195 }
196 
197 // translate a windows registry DWORD int to a mozilla prefs PRInt32
198 void
199 TranslateDWORDtoPRInt32(nsIWindowsRegKey *aRegKey,
200  const nsString& aRegValueName,
201  nsIPrefBranch *aPrefs, char *aPrefKeyName) {
202 
203  // clear previous settings with defaults
204  PRInt32 prefIntValue = 0;
205 
206  if (NS_SUCCEEDED(aRegKey->ReadIntValue(aRegValueName,
207  reinterpret_cast<PRUint32 *>(&prefIntValue))))
208  aPrefs->SetIntPref(aPrefKeyName, prefIntValue);
209 }
210 
211 // string copy
212 void
213 TranslateString(nsIWindowsRegKey *aRegKey, const nsString& aRegValueName,
214  nsIPrefBranch *aPrefs, char *aPrefKeyName) {
215  nsAutoString regValue;
216  if (NS_SUCCEEDED(aRegKey->ReadStringValue(aRegValueName, regValue)) &&
217  !regValue.IsEmpty()) {
218  aPrefs->SetCharPref(aPrefKeyName, NS_ConvertUTF16toUTF8(regValue).get());
219  }
220 }
221 
222 // translate accepted language character set formats
223 // (modified string copy)
224 void
225 TranslateLanglist(nsIWindowsRegKey *aRegKey, const nsString& aRegValueName,
226  nsIPrefBranch *aPrefs, char *aPrefKeyName) {
227 
228  nsAutoString lang;
229  if (NS_FAILED(aRegKey->ReadStringValue(aRegValueName, lang)))
230  return;
231 
232  // copy source format like "en-us,ar-kw;q=0.7,ar-om;q=0.3" into
233  // destination format like "en-us, ar-kw, ar-om"
234 
235  char prefStringValue[MAX_PATH]; // a convenient size, one hopes
236  NS_LossyConvertUTF16toASCII langCstr(lang);
237  const char *source = langCstr.get(),
238  *sourceEnd = source + langCstr.Length();
239  char *dest = prefStringValue,
240  *destEnd = dest + (MAX_PATH-2); // room for " \0"
241  PRBool skip = PR_FALSE,
242  comma = PR_FALSE;
243 
244  while (source < sourceEnd && *source && dest < destEnd) {
245  if (*source == ',')
246  skip = PR_FALSE;
247  else if (*source == ';')
248  skip = PR_TRUE;
249  if (!skip) {
250  if (comma && *source != ' ')
251  *dest++ = ' ';
252  *dest++ = *source;
253  }
254  comma = *source == ',';
255  ++source;
256  }
257  *dest = 0;
258 
259  aPrefs->SetCharPref(aPrefKeyName, prefStringValue);
260 }
261 
262 static int CALLBACK
263 fontEnumProc(const LOGFONTW *aLogFont, const TEXTMETRICW *aMetric,
264  DWORD aFontType, LPARAM aClosure) {
265  *((int *) aClosure) = aLogFont->lfPitchAndFamily & FF_ROMAN;
266  return 0;
267 }
268 void
269 TranslatePropFont(nsIWindowsRegKey *aRegKey, const nsString& aRegValueName,
270  nsIPrefBranch *aPrefs, char *aPrefKeyName) {
271 
272  HDC dc = ::GetDC(0);
273  LOGFONTW lf;
274  int isSerif = 1;
275 
276  // serif or sans-serif font?
277  lf.lfCharSet = DEFAULT_CHARSET;
278  lf.lfPitchAndFamily = 0;
279  nsAutoString font;
280  if (NS_FAILED(aRegKey->ReadStringValue(aRegValueName, font)))
281  return;
282 
283  ::wcsncpy(lf.lfFaceName, font.get(), LF_FACESIZE);
284  lf.lfFaceName[LF_FACESIZE - 1] = L'\0';
285  ::EnumFontFamiliesExW(dc, &lf, fontEnumProc, (LPARAM) &isSerif, 0);
286  ::ReleaseDC(0, dc);
287 
288  // XXX : For now, only x-western font is translated.
289  // All or Locale-dependent subset of fonts need to be translated.
290  nsDependentCString generic(isSerif ? "serif" : "sans-serif");
291  nsCAutoString prefName("font.name.");
292  prefName.Append(generic);
293  prefName.Append(".x-western");
294  aPrefs->SetCharPref(prefName.get(), NS_ConvertUTF16toUTF8(font).get());
295  aPrefs->SetCharPref("font.default.x-western", generic.get());
296 }
297 
298 //***********************************************************************
299 //*** master table of registry-to-gecko-pref translations
300 //***********************************************************************
301 
302 struct regEntry {
303  char *regKeyName, // registry key (HKCU\Software ...)
304  *regValueName; // registry key leaf
305  char *prefKeyName; // pref name ("javascript.enabled" ...)
306  regEntryHandler entryHandler; // processing func
307 };
308 
310  { "Software\\Microsoft\\Windows\\CurrentVersion\\Explorer\\AutoComplete",
311  "AutoSuggest",
312  "browser.urlbar.autocomplete.enabled",
313  TranslateYNtoTF },
314  { "Software\\Microsoft\\Internet Explorer\\International",
315  "AcceptLanguage",
316  "intl.accept_languages",
318  // XXX : For now, only x-western font is translated.
319  // All or Locale-dependent subset of fonts need to be translated.
320  { "Software\\Microsoft\\Internet Explorer\\International\\Scripts\\3",
321  "IEFixedFontName",
322  "font.name.monospace.x-western",
323  TranslateString },
324  { 0, // an optimization: 0 means use the previous key
325  "IEPropFontName",
326  "", // special-cased in the translation function
328  { "Software\\Microsoft\\Internet Explorer\\Main",
329  "Use_DlgBox_Colors",
330  "browser.display.use_system_colors",
331  TranslateYNtoTF },
332  { 0,
333  "Use FormSuggest",
334  "browser.formfill.enable",
335  TranslateYNtoTF },
336  { 0,
337  "FormSuggest Passwords",
338  "signon.rememberSignons",
339  TranslateYNtoTF },
340 #if 0
341  // Firefox supplies its own home page.
342  { 0,
343  "Start Page",
344  REG_SZ,
345  "browser.startup.homepage",
346  TranslateString },
347 #endif
348  { 0,
349  "Anchor Underline",
350  "browser.underline_anchors",
351  TranslateYNtoTF },
352  { 0,
353  "Display Inline Images",
354  "permissions.default.image",
356  { 0,
357  "Enable AutoImageResize",
358  "browser.enable_automatic_image_resizing",
359  TranslateYNtoTF },
360  { 0,
361  "Move System Caret",
362  "accessibility.browsewithcaret",
363  TranslateYNtoTF },
364  { 0,
365  "NotifyDownloadComplete",
366  "browser.download.manager.showAlertOnComplete",
367  TranslateYNtoTF },
368  { 0,
369  "SmoothScroll", // XXX DWORD
370  "general.smoothScroll",
371  TranslateYNtoTF },
372  { "Software\\Microsoft\\Windows\\CurrentVersion\\Internet Settings",
373  "EnableHttp1_1",
374  "network.http.version",
376  { 0,
377  "ProxyHttp1.1",
378  "network.http.proxy.version",
380 // SecureProtocols
381  { "Software\\Microsoft\\Windows\\CurrentVersion\\Internet Settings\\Url History",
382  "DaysToKeep",
383  "browser.history_expire_days",
385  { "Software\\Microsoft\\Internet Explorer\\Settings",
386  "Always Use My Colors", // XXX DWORD
387  "browser.display.use_document_colors",
388  TranslateYNtoFT },
389  { 0,
390  "Text Color",
391  "browser.display.foreground_color",
393  { 0,
394  "Background Color",
395  "browser.display.background_color",
397  { 0,
398  "Anchor Color",
399  "browser.anchor_color",
401  { 0,
402  "Anchor Color Visited",
403  "browser.visited_color",
405  { 0,
406  "Always Use My Font Face", // XXX DWORD
407  "browser.display.use_document_fonts",
408  TranslateYNtoFT },
409  { "Software\\Microsoft\\Windows\\CurrentVersion\\Internet Settings\\Url History",
410  "DaysToKeep",
411  "browser.history_expire_days",
413 };
414 
415 #if 0
416 user_pref("font.size.fixed.x-western", 14);
417 user_pref("font.size.variable.x-western", 15);
418 #endif
419 
421 // nsIBrowserProfileMigrator
422 NS_IMETHODIMP
423 nsIEProfileMigrator::Migrate(PRUint16 aItems, nsIProfileStartup* aStartup, const PRUnichar* aProfile)
424 {
425  nsresult rv = NS_OK;
426 
427  PRBool aReplace = PR_FALSE;
428 
429  if (aStartup) {
430  aReplace = PR_TRUE;
431  rv = aStartup->DoStartup();
432  NS_ENSURE_SUCCESS(rv, rv);
433  }
434 
436 
443 
445 
446  return rv;
447 }
448 
449 NS_IMETHODIMP
450 nsIEProfileMigrator::GetMigrateData(const PRUnichar* aProfile,
451  PRBool aReplace,
452  PRUint16* aResult)
453 {
454  if (TestForIE7()) {
455  // IE7 and up store form data and passwords in an unrecoverable
456  // way, preventing us from importing this data.
461  }
462  else {
469  }
470 
471  return NS_OK;
472 }
473 
474 NS_IMETHODIMP
475 nsIEProfileMigrator::GetSourceExists(PRBool* aResult)
476 {
477  // IE always exists.
478  *aResult = PR_TRUE;
479 
480  return NS_OK;
481 }
482 
483 NS_IMETHODIMP
484 nsIEProfileMigrator::GetSourceHasMultipleProfiles(PRBool* aResult)
485 {
486  *aResult = PR_FALSE;
487  return NS_OK;
488 }
489 
490 NS_IMETHODIMP
491 nsIEProfileMigrator::GetSourceProfiles(nsISupportsArray** aResult)
492 {
493  *aResult = nsnull;
494  return NS_OK;
495 }
496 
497 NS_IMETHODIMP
498 nsIEProfileMigrator::GetSourceHomePageURL(nsACString& aResult)
499 {
500  nsCOMPtr<nsIWindowsRegKey> regKey =
501  do_CreateInstance("@mozilla.org/windows-registry-key;1");
502  if (!regKey ||
503  NS_FAILED(regKey->Open(nsIWindowsRegKey::ROOT_KEY_CURRENT_USER,
506  return NS_OK;
507  // Read in the main home page
508  NS_NAMED_LITERAL_STRING(homeURLValName, "Start Page");
509  nsAutoString homeURLVal;
510 
511  if (NS_SUCCEEDED(regKey->ReadStringValue(homeURLValName, homeURLVal))) {
512  // Do we need this round-about way to get |homePageURL|?
513  // Perhaps, we do to have the form of URL under our control
514  // (cf. network.standard-url.escape-utf8)
515  // Note that Windows stores URLs in IRI in the registry
516  nsCAutoString homePageURL;
517  nsCOMPtr<nsIURI> homePageURI;
518 
519  if (NS_SUCCEEDED(NS_NewURI(getter_AddRefs(homePageURI), homeURLVal))) {
520  if (NS_SUCCEEDED(homePageURI->GetSpec(homePageURL)) && !homePageURL.IsEmpty()) {
521  aResult.Assign(homePageURL);
522  }
523  }
524  }
525 
526  // With IE7, The "Start Page" key still exists. Secondary home pages
527  // are located in a string stored in "Secondary Start Pages" which
528  // contains multiple Unicode URI seperated by nulls. (REG_MULTI_SZ)
529  NS_NAMED_LITERAL_STRING(ssRegKeyName, "Secondary Start Pages");
530  nsAutoString secondaryList;
531 
532  if (NS_SUCCEEDED(regKey->ReadStringValue(ssRegKeyName, secondaryList)) &&
533  !secondaryList.IsEmpty()) {
534  nsTArray<nsCString> parsedList;
535  if (!ParseString(NS_ConvertUTF16toUTF8(secondaryList), '\0', parsedList))
536  return NS_OK;
537 
538  // Split the result up into individual uri
539  for (PRUint32 index = 0; index < parsedList.Length(); ++index) {
540  nsCOMPtr<nsIURI> uri;
541  nsCAutoString homePage;
542  // Append "|uri" to result. This is how we currently handle
543  // storing multiple home pages.
544  if (NS_SUCCEEDED(NS_NewURI(getter_AddRefs(uri), parsedList[index]))) {
545  if (NS_SUCCEEDED(uri->GetSpec(homePage)) && !homePage.IsEmpty()) {
546  aResult.AppendLiteral("|");
547  aResult.Append(homePage);
548  }
549  }
550  }
551  }
552 
553  return NS_OK;
554 }
555 
556 
558 // nsIEProfileMigrator
560 
562 {
563  mObserverService = do_GetService("@mozilla.org/observer-service;1");
564 }
565 
567 {
568 }
569 
570 // Test used in detecting Internet Explorer 7 prior to presenting
571 // import options.
572 PRBool
574 {
575  nsCOMPtr<nsIWindowsRegKey> regKey =
576  do_CreateInstance("@mozilla.org/windows-registry-key;1");
577  if (!regKey)
578  return PR_FALSE;
579 
580  NS_NAMED_LITERAL_STRING(key,
581  "Applications\\iexplore.exe\\shell\\open\\command");
582  if (NS_FAILED(regKey->Open(nsIWindowsRegKey::ROOT_KEY_CLASSES_ROOT,
583  key, nsIWindowsRegKey::ACCESS_QUERY_VALUE)))
584  return PR_FALSE;
585 
586  nsAutoString iePath;
587  if (NS_FAILED(regKey->ReadStringValue(EmptyString(), iePath)))
588  return PR_FALSE;
589 
590  // Replace embedded environment variables.
591  PRUint32 bufLength =
592  ::ExpandEnvironmentStringsW(iePath.get(),
593  L"", 0);
594  if (bufLength == 0) // Error
595  return PR_FALSE;
596 
597  nsAutoArrayPtr<PRUnichar> destination(new PRUnichar[bufLength]);
598  if (!destination)
599  return PR_FALSE;
600 
601  if (!::ExpandEnvironmentStringsW(iePath.get(),
602  destination,
603  bufLength))
604  return PR_FALSE;
605 
606  iePath = destination;
607 
608  if (StringBeginsWith(iePath, NS_LITERAL_STRING("\""))) {
609  iePath.Cut(0,1);
610  PRUint32 index = iePath.FindChar('\"', 0);
611  if (index > 0)
612  iePath.Cut(index,iePath.Length());
613  }
614 
615  nsCOMPtr<nsILocalFile> lf;
616  NS_NewLocalFile(iePath, PR_TRUE, getter_AddRefs(lf));
617 
618  nsCOMPtr<nsILocalFileWin> lfw = do_QueryInterface(lf);
619  if (!lfw)
620  return PR_FALSE;
621 
622  nsAutoString ieVersion;
623  if (NS_FAILED(lfw->GetVersionInfoField("FileVersion", ieVersion)))
624  return PR_FALSE;
625 
626  if (ieVersion.Length() > 2) {
627  PRUint32 index = ieVersion.FindChar('.', 0);
628  if (index < 0)
629  return PR_FALSE;
630  ieVersion.Cut(index, ieVersion.Length());
631  PRInt32 ver = wcstol(ieVersion.get(), nsnull, 0);
632  if (ver >= 7) // Found 7 or greater major version
633  return PR_TRUE;
634  }
635 
636  return PR_FALSE;
637 }
638 
639 NS_IMETHODIMP
640 nsIEProfileMigrator::RunBatched(nsISupports* aUserData)
641 {
642  PRUint8 batchAction;
643  nsCOMPtr<nsISupportsPRUint8> strWrapper(do_QueryInterface(aUserData));
644  NS_ASSERTION(strWrapper, "Unable to create nsISupportsPRUint8 wrapper!");
645  nsresult rv = strWrapper->GetData(&batchAction);
646  NS_ENSURE_SUCCESS(rv, rv);
647 
648  switch (batchAction) {
650  rv = CopyHistoryBatched(PR_FALSE);
651  break;
653  rv = CopyHistoryBatched(PR_TRUE);
654  break;
656  rv = CopyFavoritesBatched(PR_FALSE);
657  break;
659  rv = CopyFavoritesBatched(PR_TRUE);
660  break;
661  }
662  NS_ENSURE_SUCCESS(rv, rv);
663 
664  return NS_OK;
665 }
666 
667 nsresult
669 {
670  nsresult rv;
671  nsCOMPtr<nsINavHistoryService> history =
672  do_GetService(NS_NAVHISTORYSERVICE_CONTRACTID, &rv);
673  NS_ENSURE_SUCCESS(rv, rv);
674 
675  PRUint8 batchAction = aReplace ? BATCH_ACTION_HISTORY_REPLACE
677  nsCOMPtr<nsISupportsPRUint8> supports =
678  do_CreateInstance(NS_SUPPORTS_PRUINT8_CONTRACTID);
679  NS_ENSURE_TRUE(supports, NS_ERROR_OUT_OF_MEMORY);
680  rv = supports->SetData(batchAction);
681  NS_ENSURE_SUCCESS(rv, rv);
682 
683  rv = history->RunInBatchMode(this, supports);
684  NS_ENSURE_SUCCESS(rv, rv);
685 
686  return NS_OK;
687 }
688 
689 nsresult
691 {
692  nsCOMPtr<nsIBrowserHistory> hist(do_GetService(NS_GLOBALHISTORY2_CONTRACTID));
693  nsCOMPtr<nsIIOService> ios(do_GetService(NS_IOSERVICE_CONTRACTID));
694 
695  // First, Migrate standard IE History entries...
696  ::CoInitialize(NULL);
697 
698  IUrlHistoryStg2* ieHistory;
699  HRESULT hr = ::CoCreateInstance(CLSID_CUrlHistory,
700  NULL,
701  CLSCTX_INPROC_SERVER,
702  IID_IUrlHistoryStg2,
703  reinterpret_cast<void**>(&ieHistory));
704  if (SUCCEEDED(hr)) {
705  IEnumSTATURL* enumURLs;
706  hr = ieHistory->EnumUrls(&enumURLs);
707  if (SUCCEEDED(hr)) {
708  STATURL statURL;
709  ULONG fetched;
710  _bstr_t url;
711  nsCAutoString scheme;
712  SYSTEMTIME st;
713  PRBool validScheme = PR_FALSE;
714  PRUnichar* tempTitle = nsnull;
715 
716  for (int count = 0; (hr = enumURLs->Next(1, &statURL, &fetched)) == S_OK; ++count) {
717  if (statURL.pwcsUrl) {
718  // 1 - Page Title
719  tempTitle = statURL.pwcsTitle ? (PRUnichar*)((wchar_t*)(statURL.pwcsTitle)) : nsnull;
720 
721  // 2 - Last Visit Date
722  ::FileTimeToSystemTime(&(statURL.ftLastVisited), &st);
723  PRExplodedTime prt;
724  prt.tm_year = st.wYear;
725  prt.tm_month = st.wMonth - 1; // SYSTEMTIME's day-of-month parameter is 1-based, PRExplodedTime's is 0-based.
726  prt.tm_mday = st.wDay;
727  prt.tm_hour = st.wHour;
728  prt.tm_min = st.wMinute;
729  prt.tm_sec = st.wSecond;
730  prt.tm_usec = st.wMilliseconds * 1000;
731  prt.tm_wday = 0;
732  prt.tm_yday = 0;
733  prt.tm_params.tp_gmt_offset = 0;
734  prt.tm_params.tp_dst_offset = 0;
735  PRTime lastVisited = PR_ImplodeTime(&prt);
736 
737  // 3 - URL
738  url = statURL.pwcsUrl;
739 
740  NS_ConvertUTF16toUTF8 urlStr(url);
741 
742  if (NS_FAILED(ios->ExtractScheme(urlStr, scheme))) {
743  ::CoTaskMemFree(statURL.pwcsUrl);
744  if (statURL.pwcsTitle)
745  ::CoTaskMemFree(statURL.pwcsTitle);
746  continue;
747  }
748  ToLowerCase(scheme);
749 
750  // XXXben -
751  // MSIE stores some types of URLs in its history that we can't handle, like HTMLHelp
752  // and others. At present Necko isn't clever enough to delegate handling of these types
753  // to the system, so we should just avoid importing them.
754  const char* schemes[] = { "http", "https", "ftp", "file" };
755  for (int i = 0; i < 4; ++i) {
756  if (validScheme = scheme.Equals(schemes[i]))
757  break;
758  }
759 
760  // 4 - Now add the page
761  if (validScheme) {
762  nsCOMPtr<nsIURI> uri;
763  ios->NewURI(urlStr, nsnull, nsnull, getter_AddRefs(uri));
764  if (uri) {
765  if (tempTitle)
766  hist->AddPageWithDetails(uri, tempTitle, lastVisited);
767  else
768  hist->AddPageWithDetails(uri, url, lastVisited);
769  }
770  }
771  ::CoTaskMemFree(statURL.pwcsUrl);
772  }
773  if (statURL.pwcsTitle)
774  ::CoTaskMemFree(statURL.pwcsTitle);
775  }
776  nsCOMPtr<nsIRDFRemoteDataSource> ds(do_QueryInterface(hist));
777  if (ds)
778  ds->Flush();
779 
780  enumURLs->Release();
781  }
782 
783  ieHistory->Release();
784  }
785  ::CoUninitialize();
786 
787  // Now, find out what URLs were typed in by the user
788  nsCOMPtr<nsIWindowsRegKey> regKey =
789  do_CreateInstance("@mozilla.org/windows-registry-key;1");
790  if (regKey &&
791  NS_SUCCEEDED(regKey->Open(nsIWindowsRegKey::ROOT_KEY_CURRENT_USER,
794  int offset = 0;
795 
796  while (1) {
797  nsAutoString valueName;
798  if (NS_FAILED(regKey->GetValueName(offset, valueName)))
799  break;
800 
801  nsAutoString url;
802  if (Substring(valueName, 0, 3).EqualsLiteral("url") &&
803  NS_SUCCEEDED(regKey->ReadStringValue(valueName, url))) {
804  nsCOMPtr<nsIURI> uri;
805  ios->NewURI(NS_ConvertUTF16toUTF8(url), nsnull, nsnull,
806  getter_AddRefs(uri));
807  if (uri)
808  hist->MarkPageAsTyped(uri);
809  }
810  ++offset;
811  }
812  }
813 
814  return NS_OK;
815 }
816 
818 // IE PASSWORDS AND FORM DATA - A PROTECTED STORAGE SYSTEM PRIMER
819 //
820 // Internet Explorer 4.0 and up store sensitive form data (saved through form
821 // autocomplete) and saved passwords in a special area of the Registry called
822 // the Protected Storage System. The data IE stores in the Protected Storage
823 // System is located under:
824 //
825 // HKEY_CURRENT_USER\Software\Microsoft\Protected Storage System Provider\
826 // <USER_ID>\Data<IE_PSS_GUID><IE_PSS_GUID>\
827 //
828 // <USER_ID> is a long string that uniquely identifies the current user
829 // <IE_PSS_GUID> is a GUID that identifies a subsection of the Protected Storage
830 // System specific to MSIE. This GUID is defined below ("IEPStoreAutocompGUID").
831 //
832 // Data is stored in the Protected Strage System ("PStore") in the following
833 // format:
834 //
835 // <IE_PStore_Key> \
836 // fieldName1:StringData \ ItemData = <REG_BINARY>
837 // fieldName2:StringData \ ItemData = <REG_BINARY>
838 // http://foo.com/login.php:StringData \ ItemData = <REG_BINARY>
839 // ... etc ...
840 //
841 // Each key represents either the identifier of a web page text field that
842 // data was saved from (e.g. <input name="fieldName1">), or a URL that a login
843 // (username + password) was saved at (e.g. "http://foo.com/login.php")
844 //
845 // Data is stored for each of these cases in the following format:
846 //
847 // for both types of data, the Value ItemData is REG_BINARY data format encrypted with
848 // a 3DES cipher.
849 //
850 // for FormData: the decrypted data is in the form:
851 // value1\0value2\0value3\0value4 ...
852 // for Signons: the decrypted data is in the form:
853 // username\0password
854 //
855 // We cannot read the PStore directly by using Registry functions because the
856 // keys have limited read access such that only System process can read from them.
857 // In order to read from the PStore we need to use Microsoft's undocumented PStore
858 // API(*).
859 //
860 // (* Sparse documentation became available as of the January 2004 MSDN Library
861 // release)
862 //
863 // The PStore API lets us read decrypted data from the PStore. Encryption does not
864 // appear to be strong.
865 //
866 // Details on how each type of data is read from the PStore and migrated appropriately
867 // is discussed in more detail below.
868 //
869 // For more information about the PStore, read:
870 //
871 // http://msdn.microsoft.com/library/default.asp?url=/library/en-us/devnotes/winprog/pstore.asp
872 //
873 
874 
875 typedef HRESULT (WINAPI *PStoreCreateInstancePtr)(IPStore**, DWORD, DWORD, DWORD);
876 
877 // IE PStore Type GUIDs
878 // {e161255a-37c3-11d2-bcaa-00c04fd929db} Autocomplete Password & Form Data
879 // Subtype has same GUID
880 // {5e7e8100-9138-11d1-945a-00c04fc308ff} HTTP/FTP Auth Login Data
881 // Subtype has a zero GUID
882 static GUID IEPStoreAutocompGUID = { 0xe161255a, 0x37c3, 0x11d2, { 0xbc, 0xaa, 0x00, 0xc0, 0x4f, 0xd9, 0x29, 0xdb } };
883 static GUID IEPStoreSiteAuthGUID = { 0x5e7e8100, 0x9138, 0x11d1, { 0x94, 0x5a, 0x00, 0xc0, 0x4f, 0xc3, 0x08, 0xff } };
884 
886 // IMPORTING AUTOCOMPLETE PASSWORDS
887 //
888 // This is tricky, and requires 2 passes through the subkeys in IE's PStore
889 // section.
890 //
891 // First, we walk IE's PStore section, looking for subkeys that are prefixed
892 // with a URI. As mentioned above, we assume all such subkeys are stored
893 // passwords.
894 //
895 // http://foo.com/login.php:StringData username\0password
896 //
897 // We can't add this item to the Password Manager just yet though.
898 //
899 // The password manager requires the uniquifier of the username field (that is,
900 // the value of the "name" or "id" attribute) from the webpage so that it can
901 // prefill the value automatically. IE doesn't store this information with
902 // the password entry, but it DOES store this information independently as a
903 // separate Form Data entry.
904 //
905 // In other words, if you go to foo.com above and log in with "username" and
906 // "password" as your details in a form where the username field is uniquified
907 // as "un" (<input type="text" name="un">), when you login and elect to have IE
908 // save the password for the site, the following TWO entries are created in IE's
909 // PStore section:
910 //
911 // http://foo.com/login.php:StringData username\0password
912 // un:StringData username
913 //
914 // Thus to discover the field name for each login we need to first gather up
915 // all the signons (collecting usernames in the process), then walk the list
916 // again, looking ONLY at non-URI prefixed subkeys, and searching for each
917 // username as a value in each such subkey's value list. If we have a match,
918 // we assume that the subkey (with its uniquifier prefix) is a login field.
919 //
920 // With this information, we call Password Manager's "AddLogin" method
921 // providing this detail. We don't need to provide the password field name,
922 // we have no means of retrieving this info from IE, and the Password Manager
923 // knows to hunt for a password field near the login field if none is specified.
924 //
925 // IMPLICATIONS:
926 // 1) redundant signon entries for non-login forms might be created, but these
927 // should be benign.
928 // 2) if the IE user ever clears his Form AutoComplete cache but doesn't clear
929 // his passwords, we will be hosed, as we have no means of locating the
930 // username field. Maybe someday the Password Manager will become
931 // artificially intelligent and be able to guess where the login fields are,
932 // but I'm not holding my breath.
933 //
934 
935 nsresult
937 {
938  HRESULT hr;
939  nsresult rv;
940  nsTArray<SignonData> signonsFound;
941 
942  HMODULE pstoreDLL = ::LoadLibraryW(L"pstorec.dll");
943  if (!pstoreDLL) {
944  // XXXben TODO
945  // Need to figure out what to do here on Windows 98 etc... it may be that the key is universal read
946  // and we can just blunder into the registry and use CryptUnprotect to get the data out.
947  return NS_ERROR_FAILURE;
948  }
949 
950  PStoreCreateInstancePtr PStoreCreateInstance = (PStoreCreateInstancePtr)::GetProcAddress(pstoreDLL, "PStoreCreateInstance");
951  IPStorePtr PStore;
952  hr = PStoreCreateInstance(&PStore, 0, 0, 0);
953 
954  rv = GetSignonsListFromPStore(PStore, &signonsFound);
955  if (NS_SUCCEEDED(rv))
956  ResolveAndMigrateSignons(PStore, &signonsFound);
957 
958  MigrateSiteAuthSignons(PStore);
959  return NS_OK;
960 }
961 
963 // IMPORTING SITE AUTHENTICATION PASSWORDS
964 //
965 // This is simple and straightforward. We iterate through the part of the
966 // PStore that matches the type GUID defined in IEPStoreSiteAuthGUID and
967 // a zero subtype GUID. For each item, we check the data for a ':' that
968 // separates the username and password parts. If there is no ':', we give up.
969 // After that, we check to see if the name of the item starts with "DPAPI:".
970 // We bail out if that's the case, because we can't handle those yet.
971 // However, if everything is all and well, we convert the itemName to a realm
972 // string that the password manager can work with and save this login
973 // via AddLogin.
974 
975 nsresult
977 {
978  HRESULT hr;
979 
980  NS_ENSURE_ARG_POINTER(aPStore);
981 
982  nsCOMPtr<nsILoginManagerIEMigrationHelper> pwmgr(
983  do_GetService("@mozilla.org/login-manager/storage/legacy;1"));
984  if (!pwmgr)
985  return NS_OK;
986 
987  GUID mtGuid = {0};
988  IEnumPStoreItemsPtr enumItems = NULL;
989  hr = aPStore->EnumItems(0, &IEPStoreSiteAuthGUID, &mtGuid, 0, &enumItems);
990  if (SUCCEEDED(hr) && enumItems != NULL) {
991  LPWSTR itemName = NULL;
992  while ((enumItems->Next(1, &itemName, 0) == S_OK) && itemName) {
993  unsigned long count = 0;
994  unsigned char* data = NULL;
995 
996  hr = aPStore->ReadItem(0, &IEPStoreSiteAuthGUID, &mtGuid, itemName,
997  &count, &data, NULL, 0);
998  if (SUCCEEDED(hr) && data) {
999  unsigned long i;
1000  unsigned char* password = NULL;
1001  for (i = 0; i < count; i++)
1002  if (data[i] == ':') {
1003  data[i] = '\0';
1004  if (i + 1 < count)
1005  password = &data[i + 1];
1006  break;
1007  }
1008 
1009  nsAutoString host(itemName), realm;
1010  if (Substring(host, 0, 6).EqualsLiteral("DPAPI:")) // often FTP logins
1011  password = NULL; // We can't handle these yet
1012 
1013  if (password) {
1014  int idx;
1015  idx = host.FindChar('/');
1016  if (idx) {
1017  realm.Assign(Substring(host, idx + 1));
1018  host.Assign(Substring(host, 0, idx));
1019  }
1020  // XXX: username and password are always ASCII in IPStore?
1021  // If not, are they in UTF-8 or the default codepage? (ref. bug 41489)
1022  nsresult rv;
1023 
1024  nsCOMPtr<nsILoginInfo> aLogin (do_CreateInstance(
1025  NS_LOGININFO_CONTRACTID, &rv));
1026  NS_ENSURE_SUCCESS(rv, rv);
1027 
1028  // nsStringAPI doesn't let us create void strings, so we won't
1029  // use Init() here.
1030  aLogin->SetHostname(host);
1031  aLogin->SetHttpRealm(realm);
1032  aLogin->SetUsername(NS_ConvertUTF8toUTF16((char *)data));
1033  aLogin->SetPassword(NS_ConvertUTF8toUTF16((char *)password));
1034  aLogin->SetUsernameField(EmptyString());
1035  aLogin->SetPasswordField(EmptyString());
1036 
1037  pwmgr->MigrateAndAddLogin(aLogin);
1038  }
1039  ::CoTaskMemFree(data);
1040  }
1041  }
1042  }
1043  return NS_OK;
1044 }
1045 
1046 nsresult
1047 nsIEProfileMigrator::GetSignonsListFromPStore(IPStore* aPStore, nsTArray<SignonData>* aSignonsFound)
1048 {
1049  HRESULT hr;
1050 
1051  NS_ENSURE_ARG_POINTER(aPStore);
1052 
1053  IEnumPStoreItemsPtr enumItems = NULL;
1054  hr = aPStore->EnumItems(0, &IEPStoreAutocompGUID, &IEPStoreAutocompGUID, 0, &enumItems);
1055  if (SUCCEEDED(hr) && enumItems != NULL) {
1056  LPWSTR itemName = NULL;
1057  while ((enumItems->Next(1, &itemName, 0) == S_OK) && itemName) {
1058  unsigned long count = 0;
1059  unsigned char* data = NULL;
1060 
1061  // We are responsible for freeing |data| using |CoTaskMemFree|!!
1062  // But we don't do it here...
1063  hr = aPStore->ReadItem(0, &IEPStoreAutocompGUID, &IEPStoreAutocompGUID, itemName, &count, &data, NULL, 0);
1064  if (SUCCEEDED(hr) && data) {
1065  nsAutoString itemNameString(itemName);
1066  if (StringTail(itemNameString, 11).
1067  LowerCaseEqualsLiteral(":stringdata")) {
1068  // :StringData contains the saved data
1069  const nsAString& key = Substring(itemNameString, 0, itemNameString.Length() - 11);
1070  char* realm = nsnull;
1071  if (KeyIsURI(key, &realm)) {
1072  // This looks like a URL and could be a password. If it has username and password data, then we'll treat
1073  // it as one and add it to the password manager
1074  unsigned char* username = NULL;
1075  unsigned char* pass = NULL;
1076  GetUserNameAndPass(data, count, &username, &pass);
1077 
1078  if (username && pass) {
1079  // username and pass are pointers into the data buffer allocated by IPStore's ReadItem
1080  // method, and we own that buffer. We don't free it here, since we're going to be using
1081  // it after the password harvesting stage to locate the username field. Only after the second
1082  // phase is complete do we free the buffer.
1083  SignonData* d = aSignonsFound->AppendElement();
1084  if (!d)
1085  return NS_ERROR_OUT_OF_MEMORY;
1086  d->user = (PRUnichar*)username;
1087  d->pass = (PRUnichar*)pass;
1088  d->realm = realm; // freed in ResolveAndMigrateSignons
1089  }
1090  }
1091  }
1092  }
1093  }
1094  }
1095  return NS_OK;
1096 }
1097 
1098 PRBool
1099 nsIEProfileMigrator::KeyIsURI(const nsAString& aKey, char** aRealm)
1100 {
1101  *aRealm = nsnull;
1102 
1103  nsCOMPtr<nsIURI> uri;
1104 
1105  if (NS_FAILED(NS_NewURI(getter_AddRefs(uri), aKey)))
1106  return PR_FALSE;
1107 
1108  PRBool validScheme = PR_FALSE;
1109  const char* schemes[] = { "http", "https" };
1110  for (int i = 0; i < 2; ++i) {
1111  uri->SchemeIs(schemes[i], &validScheme);
1112  if (validScheme) {
1113  nsCAutoString realm;
1114  uri->GetScheme(realm);
1115  realm.AppendLiteral("://");
1116 
1117  nsCAutoString host;
1118  uri->GetHost(host);
1119  realm.Append(host);
1120 
1121  *aRealm = ToNewCString(realm);
1122  return validScheme;
1123  }
1124  }
1125  return PR_FALSE;
1126 }
1127 
1128 nsresult
1129 nsIEProfileMigrator::ResolveAndMigrateSignons(IPStore* aPStore, nsTArray<SignonData>* aSignonsFound)
1130 {
1131  HRESULT hr;
1132 
1133  IEnumPStoreItemsPtr enumItems = NULL;
1134  hr = aPStore->EnumItems(0, &IEPStoreAutocompGUID, &IEPStoreAutocompGUID, 0, &enumItems);
1135  if (SUCCEEDED(hr) && enumItems != NULL) {
1136  LPWSTR itemName = NULL;
1137  while ((enumItems->Next(1, &itemName, 0) == S_OK) && itemName) {
1138  unsigned long count = 0;
1139  unsigned char* data = NULL;
1140 
1141  hr = aPStore->ReadItem(0, &IEPStoreAutocompGUID, &IEPStoreAutocompGUID, itemName, &count, &data, NULL, 0);
1142  if (SUCCEEDED(hr) && data) {
1143  nsAutoString itemNameString(itemName);
1144  if (StringTail(itemNameString, 11).
1145  LowerCaseEqualsLiteral(":stringdata")) {
1146  // :StringData contains the saved data
1147  const nsAString& key = Substring(itemNameString, 0, itemNameString.Length() - 11);
1148 
1149  // Assume all keys that are valid URIs are signons, not saved form data, and that
1150  // all keys that aren't valid URIs are form field names (containing form data).
1151  nsCString realm;
1152  if (!KeyIsURI(key, getter_Copies(realm))) {
1153  // Search the data for a username that matches one of the found signons.
1154  EnumerateUsernames(key, (PRUnichar*)data, (count/sizeof(PRUnichar)), aSignonsFound);
1155  }
1156  }
1157 
1158  ::CoTaskMemFree(data);
1159  }
1160  }
1161  // Now that we've done resolving signons, we need to walk the signons list, freeing the data buffers
1162  // for each SignonData entry, since these buffers were allocated by the system back in |GetSignonListFromPStore|
1163  // but never freed.
1164  PRUint32 signonCount = aSignonsFound->Length();
1165  for (PRUint32 i = 0; i < signonCount; ++i) {
1166  SignonData &sd = aSignonsFound->ElementAt(i);
1167  ::CoTaskMemFree(sd.user); // |sd->user| is a pointer to the start of a buffer that also contains sd->pass
1168  NS_Free(sd.realm);
1169  }
1170  aSignonsFound->Clear();
1171  }
1172  return NS_OK;
1173 }
1174 
1175 void
1176 nsIEProfileMigrator::EnumerateUsernames(const nsAString& aKey, PRUnichar* aData, unsigned long aCount, nsTArray<SignonData>* aSignonsFound)
1177 {
1178  nsCOMPtr<nsILoginManagerIEMigrationHelper> pwmgr(
1179  do_GetService("@mozilla.org/login-manager/storage/legacy;1"));
1180  if (!pwmgr)
1181  return;
1182 
1183  PRUnichar* cursor = aData;
1184  PRUint32 offset = 0;
1185  PRUint32 signonCount = aSignonsFound->Length();
1186 
1187  while (offset < aCount) {
1188  nsAutoString curr; curr = cursor;
1189 
1190  // Compare the value at the current cursor position with the collected list of signons
1191  for (PRUint32 i = 0; i < signonCount; ++i) {
1192  SignonData &sd = aSignonsFound->ElementAt(i);
1193  if (curr.Equals(sd.user)) {
1194  // Bingo! Found a username in the saved data for this item. Now, add a Signon.
1195  nsDependentString usernameStr(sd.user), passStr(sd.pass);
1196  nsAutoString realm(NS_ConvertUTF8toUTF16(sd.realm));
1197 
1198  nsresult rv;
1199 
1200  nsCOMPtr<nsILoginInfo> aLogin (do_CreateInstance(NS_LOGININFO_CONTRACTID, &rv));
1201  NS_ENSURE_SUCCESS(rv, /* */);
1202 
1203  // nsStringAPI doesn't let us create void strings, so we won't
1204  // use Init() here.
1205  // IE doesn't have the form submit URL, so set to empty-string,
1206  // which the login manager uses as a wildcard value.
1207  // IE doesn't store the password field name either, so just set it
1208  // to an empty string.
1209  aLogin->SetHostname(realm);
1210  aLogin->SetFormSubmitURL(EmptyString());
1211  aLogin->SetUsername(usernameStr);
1212  aLogin->SetPassword(passStr);
1213  aLogin->SetUsernameField(aKey);
1214  aLogin->SetPasswordField(EmptyString());
1215 
1216  pwmgr->MigrateAndAddLogin(aLogin);
1217  }
1218  }
1219 
1220  // Advance the cursor
1221  PRInt32 advance = curr.Length() + 1;
1222  cursor += advance; // Advance to next string (length of curr string + 1 PRUnichar for null separator)
1223  offset += advance;
1224  }
1225 }
1226 
1227 void
1228 nsIEProfileMigrator::GetUserNameAndPass(unsigned char* data, unsigned long len, unsigned char** username, unsigned char** pass)
1229 {
1230  *username = data;
1231  *pass = NULL;
1232 
1233  unsigned char* temp = data;
1234 
1235  for (unsigned int i = 0; i < len; i += 2, temp += 2*sizeof(unsigned char)) {
1236  if (*temp == '\0') {
1237  *pass = temp + 2*sizeof(unsigned char);
1238  break;
1239  }
1240  }
1241 }
1242 
1244 // IMPORTING FORM DATA
1245 //
1246 // This is a much simpler task as all we need is the field name and that's part
1247 // of the key used to identify each data set in the PStore. The algorithm here
1248 // is as follows:
1249 //
1250 // fieldName1:StringData value1\0value2\0value3\0
1251 // fieldName2:StringData value1\0value2\0value3\0
1252 // fieldName3:StringData value1\0value2\0value3\0
1253 //
1254 // Walk each non-URI prefixed key in IE's PStore section, split the value provided
1255 // into chunks (\0 delimited) and use nsIFormHistory2's |addEntry| method to add
1256 // an entry for the fieldName prefix and each value.
1257 //
1258 // "Quite Easily Done". ;-)
1259 //
1260 nsresult
1262 {
1263  HRESULT hr;
1264 
1265  HMODULE pstoreDLL = ::LoadLibraryW(L"pstorec.dll");
1266  if (!pstoreDLL) {
1267  // XXXben TODO
1268  // Need to figure out what to do here on Windows 98 etc... it may be that the key is universal read
1269  // and we can just blunder into the registry and use CryptUnprotect to get the data out.
1270  return NS_ERROR_FAILURE;
1271  }
1272 
1273  PStoreCreateInstancePtr PStoreCreateInstance = (PStoreCreateInstancePtr)::GetProcAddress(pstoreDLL, "PStoreCreateInstance");
1274  IPStorePtr PStore = NULL;
1275  hr = PStoreCreateInstance(&PStore, 0, 0, 0);
1276  if (FAILED(hr) || PStore == NULL)
1277  return NS_OK;
1278 
1279  IEnumPStoreItemsPtr enumItems = NULL;
1280  hr = PStore->EnumItems(0, &IEPStoreAutocompGUID, &IEPStoreAutocompGUID, 0, &enumItems);
1281  if (SUCCEEDED(hr) && enumItems != NULL) {
1282  LPWSTR itemName = NULL;
1283  while ((enumItems->Next(1, &itemName, 0) == S_OK) && itemName) {
1284  unsigned long count = 0;
1285  unsigned char* data = NULL;
1286 
1287  // We are responsible for freeing |data| using |CoTaskMemFree|!!
1288  hr = PStore->ReadItem(0, &IEPStoreAutocompGUID, &IEPStoreAutocompGUID, itemName, &count, &data, NULL, 0);
1289  if (SUCCEEDED(hr) && data) {
1290  nsAutoString itemNameString(itemName);
1291  if (StringTail(itemNameString, 11).
1292  LowerCaseEqualsLiteral(":stringdata")) {
1293  // :StringData contains the saved data
1294  const nsAString& key = Substring(itemNameString, 0, itemNameString.Length() - 11);
1295  nsCString realm;
1296  if (!KeyIsURI(key, getter_Copies(realm))) {
1297  nsresult rv = AddDataToFormHistory(key, (PRUnichar*)data, (count/sizeof(PRUnichar)));
1298  if (NS_FAILED(rv)) return rv;
1299  }
1300  }
1301  }
1302  }
1303  }
1304  return NS_OK;
1305 }
1306 
1307 nsresult
1308 nsIEProfileMigrator::AddDataToFormHistory(const nsAString& aKey, PRUnichar* aData, unsigned long aCount)
1309 {
1310  nsCOMPtr<nsIFormHistory2> formHistory(do_GetService("@mozilla.org/satchel/form-history;1"));
1311  if (!formHistory)
1312  return NS_ERROR_OUT_OF_MEMORY;
1313 
1314  PRUnichar* cursor = aData;
1315  PRUint32 offset = 0;
1316 
1317  while (offset < aCount) {
1318  nsAutoString curr; curr = cursor;
1319 
1320  formHistory->AddEntry(aKey, curr);
1321 
1322  // Advance the cursor
1323  PRInt32 advance = curr.Length() + 1;
1324  cursor += advance; // Advance to next string (length of curr string + 1 PRUnichar for null separator)
1325  offset += advance;
1326  }
1327 
1328  return NS_OK;
1329 }
1330 
1332 //
1333 // favorites
1334 // search keywords
1335 //
1336 nsresult
1338 {
1339  nsresult rv;
1340  nsCOMPtr<nsINavBookmarksService> bookmarks =
1341  do_GetService(NS_NAVBOOKMARKSSERVICE_CONTRACTID, &rv);
1342  NS_ENSURE_SUCCESS(rv, rv);
1343 
1344  PRBool batchAction = aReplace ? BATCH_ACTION_BOOKMARKS_REPLACE
1346  nsCOMPtr<nsISupportsPRUint8> supports =
1347  do_CreateInstance(NS_SUPPORTS_PRUINT8_CONTRACTID);
1348  NS_ENSURE_TRUE(supports, NS_ERROR_OUT_OF_MEMORY);
1349  rv = supports->SetData(batchAction);
1350  NS_ENSURE_SUCCESS(rv, rv);
1351 
1352  rv = bookmarks->RunInBatchMode(this, supports);
1353  NS_ENSURE_SUCCESS(rv, rv);
1354 
1355  return NS_OK;
1356 }
1357 
1358 nsresult
1360 {
1361  // If "aReplace" is true, merge into the root level of bookmarks. Otherwise,
1362  // create a folder called "Imported IE Favorites" and place all the Bookmarks
1363  // there.
1364  nsresult rv;
1365 
1366  nsCOMPtr<nsINavBookmarksService> bms =
1367  do_GetService(NS_NAVBOOKMARKSSERVICE_CONTRACTID, &rv);
1368  NS_ENSURE_SUCCESS(rv, rv);
1369 
1370  PRInt64 bookmarksMenuFolderId;
1371  rv = bms->GetBookmarksMenuFolder(&bookmarksMenuFolderId);
1372  NS_ENSURE_SUCCESS(rv, rv);
1373 
1374  nsAutoString personalToolbarFolderName;
1375  PRInt64 folder;
1376  if (!aReplace) {
1377  nsCOMPtr<nsIStringBundleService> bundleService =
1378  do_GetService(NS_STRINGBUNDLE_CONTRACTID, &rv);
1379  NS_ENSURE_SUCCESS(rv, rv);
1380  nsCOMPtr<nsIStringBundle> bundle;
1381  rv = bundleService->CreateBundle(TRIDENTPROFILE_BUNDLE,
1382  getter_AddRefs(bundle));
1383  NS_ENSURE_SUCCESS(rv, rv);
1384 
1385  nsString sourceNameIE;
1386  rv = bundle->GetStringFromName(NS_LITERAL_STRING("sourceNameIE").get(),
1387  getter_Copies(sourceNameIE));
1388  NS_ENSURE_SUCCESS(rv, rv);
1389 
1390  const PRUnichar* sourceNameStrings[] = { sourceNameIE.get() };
1391  nsString importedIEFavsTitle;
1392  rv = bundle->FormatStringFromName(NS_LITERAL_STRING("importedBookmarksFolder").get(),
1393  sourceNameStrings, 1,
1394  getter_Copies(importedIEFavsTitle));
1395  NS_ENSURE_SUCCESS(rv, rv);
1396 
1397  rv = bms->CreateFolder(bookmarksMenuFolderId,
1398  NS_ConvertUTF16toUTF8(importedIEFavsTitle),
1399  nsINavBookmarksService::DEFAULT_INDEX,
1400  &folder);
1401  NS_ENSURE_SUCCESS(rv, rv);
1402  }
1403  else {
1404  // Initialize the default bookmarks
1405  nsCOMPtr<nsIFile> profile;
1406  GetProfilePath(nsnull, profile);
1407  rv = InitializeBookmarks(profile);
1408  NS_ENSURE_SUCCESS(rv, rv);
1409 
1410  // Locate the Links toolbar folder, we want to replace the Personal Toolbar
1411  // content with Favorites in this folder.
1412  nsCOMPtr<nsIWindowsRegKey> regKey =
1413  do_CreateInstance("@mozilla.org/windows-registry-key;1");
1414  if (regKey &&
1415  NS_SUCCEEDED(regKey->Open(nsIWindowsRegKey::ROOT_KEY_CURRENT_USER,
1418  nsAutoString linksFolderName;
1419  if (NS_SUCCEEDED(regKey->ReadStringValue(
1420  NS_LITERAL_STRING("LinksFolderName"),
1421  linksFolderName)))
1422  personalToolbarFolderName = linksFolderName;
1423  }
1424  folder = bookmarksMenuFolderId;
1425  }
1426 
1427  nsCOMPtr<nsIProperties> fileLocator =
1428  do_GetService("@mozilla.org/file/directory_service;1", &rv);
1429  NS_ENSURE_SUCCESS(rv, rv);
1430  nsCOMPtr<nsIFile> favoritesDirectory;
1431  (void)fileLocator->Get("Favs", NS_GET_IID(nsIFile),
1432  getter_AddRefs(favoritesDirectory));
1433 
1434  // If |favoritesDirectory| is null, it means that we're on a Windows
1435  // platform that does not have a Favorites folder, e.g. Windows 95
1436  // (early SRs, before IE integrated with the shell).
1437  // Only try to read Favorites folder if it exists on the machine.
1438  if (favoritesDirectory) {
1439  rv = ParseFavoritesFolder(favoritesDirectory, folder, bms,
1440  personalToolbarFolderName, PR_TRUE);
1441  NS_ENSURE_SUCCESS(rv, rv);
1442  }
1443 
1444  return CopySmartKeywords(bms, bookmarksMenuFolderId);
1445 }
1446 
1447 nsresult
1448 nsIEProfileMigrator::CopySmartKeywords(nsINavBookmarksService* aBMS,
1449  PRInt64 aParentFolder)
1450 {
1451  nsresult rv;
1452 
1453  nsCOMPtr<nsIWindowsRegKey> regKey =
1454  do_CreateInstance("@mozilla.org/windows-registry-key;1");
1455  if (regKey &&
1456  NS_SUCCEEDED(regKey->Open(nsIWindowsRegKey::ROOT_KEY_CURRENT_USER,
1459 
1460  nsCOMPtr<nsIStringBundleService> bundleService =
1461  do_GetService(NS_STRINGBUNDLE_CONTRACTID, &rv);
1462  NS_ENSURE_SUCCESS(rv, rv);
1463  nsCOMPtr<nsIStringBundle> bundle;
1464  rv = bundleService->CreateBundle(TRIDENTPROFILE_BUNDLE,
1465  getter_AddRefs(bundle));
1466  NS_ENSURE_SUCCESS(rv, rv);
1467 
1468  PRInt64 keywordsFolder = 0;
1469  int offset = 0;
1470  while (1) {
1471  nsAutoString keyName;
1472  if (NS_FAILED(regKey->GetChildName(offset, keyName)))
1473  break;
1474 
1475  if (!keywordsFolder) {
1476  nsString sourceNameIE;
1477  rv = bundle->GetStringFromName(NS_LITERAL_STRING("sourceNameIE").get(),
1478  getter_Copies(sourceNameIE));
1479  NS_ENSURE_SUCCESS(rv, rv);
1480 
1481  const PRUnichar* sourceNameStrings[] = { sourceNameIE.get() };
1482  nsString importedIESearchUrlsTitle;
1483  rv = bundle->FormatStringFromName(NS_LITERAL_STRING("importedSearchURLsFolder").get(),
1484  sourceNameStrings, 1,
1485  getter_Copies(importedIESearchUrlsTitle));
1486  NS_ENSURE_SUCCESS(rv, rv);
1487  rv = aBMS->CreateFolder(aParentFolder,
1488  NS_ConvertUTF16toUTF8(importedIESearchUrlsTitle),
1489  nsINavBookmarksService::DEFAULT_INDEX,
1490  &keywordsFolder);
1491  NS_ENSURE_SUCCESS(rv, rv);
1492  }
1493 
1494  nsCOMPtr<nsIWindowsRegKey> childKey;
1495  if (NS_SUCCEEDED(regKey->OpenChild(keyName,
1497  getter_AddRefs(childKey)))) {
1498  nsAutoString url;
1499  if (NS_SUCCEEDED(childKey->ReadStringValue(EmptyString(), url))) {
1500  nsCOMPtr<nsIURI> uri;
1501  if (NS_FAILED(NS_NewURI(getter_AddRefs(uri), url))) {
1502  NS_WARNING("Invalid url while importing smart keywords of MS IE");
1503  ++offset;
1504  childKey->Close();
1505  continue;
1506  }
1507  PRInt64 id;
1508  rv = aBMS->InsertBookmark(keywordsFolder, uri,
1509  nsINavBookmarksService::DEFAULT_INDEX,
1510  NS_ConvertUTF16toUTF8(keyName),
1511  &id);
1512  NS_ENSURE_SUCCESS(rv, rv);
1513  }
1514  childKey->Close();
1515  }
1516 
1517  ++offset;
1518  }
1519  }
1520 
1521  return NS_OK;
1522 }
1523 
1524 void
1525 nsIEProfileMigrator::ResolveShortcut(const nsString &aFileName, char** aOutURL)
1526 {
1527  HRESULT result;
1528 
1529  IUniformResourceLocatorW* urlLink = nsnull;
1530  result = ::CoCreateInstance(CLSID_InternetShortcut, NULL, CLSCTX_INPROC_SERVER,
1531  IID_IUniformResourceLocatorW, (void**)&urlLink);
1532  if (SUCCEEDED(result) && urlLink) {
1533  IPersistFile* urlFile = nsnull;
1534  result = urlLink->QueryInterface(IID_IPersistFile, (void**)&urlFile);
1535  if (SUCCEEDED(result) && urlFile) {
1536  result = urlFile->Load(aFileName.get(), STGM_READ);
1537  if (SUCCEEDED(result) ) {
1538  LPWSTR lpTemp = nsnull;
1539  result = urlLink->GetURL(&lpTemp);
1540  if (SUCCEEDED(result) && lpTemp) {
1541  *aOutURL = (char*)ToNewUTF8String(nsDependentString(lpTemp));
1542  // free the string that GetURL alloc'd
1543  ::CoTaskMemFree(lpTemp);
1544  }
1545  }
1546  urlFile->Release();
1547  }
1548  urlLink->Release();
1549  }
1550 }
1551 
1552 nsresult
1554  PRInt64 aParentFolder,
1555  nsINavBookmarksService* aBMS,
1556  const nsAString& aPersonalToolbarFolderName,
1557  PRBool aIsAtRootLevel)
1558 {
1559  nsresult rv;
1560 
1561  nsCOMPtr<nsISimpleEnumerator> entries;
1562  rv = aDirectory->GetDirectoryEntries(getter_AddRefs(entries));
1563  NS_ENSURE_SUCCESS(rv, rv);
1564 
1565  do {
1566  PRBool hasMore = PR_FALSE;
1567  rv = entries->HasMoreElements(&hasMore);
1568  if (NS_FAILED(rv) || !hasMore) break;
1569 
1570  nsCOMPtr<nsISupports> supp;
1571  rv = entries->GetNext(getter_AddRefs(supp));
1572  if (NS_FAILED(rv)) break;
1573 
1574  nsCOMPtr<nsIFile> currFile(do_QueryInterface(supp));
1575 
1576  nsCOMPtr<nsIURI> uri;
1577  rv = NS_NewFileURI(getter_AddRefs(uri), currFile);
1578  if (NS_FAILED(rv)) break;
1579 
1580  nsAutoString bookmarkName;
1581  currFile->GetLeafName(bookmarkName);
1582 
1583  PRBool isSymlink = PR_FALSE;
1584  PRBool isDir = PR_FALSE;
1585 
1586  currFile->IsSymlink(&isSymlink);
1587  currFile->IsDirectory(&isDir);
1588 
1589  if (isSymlink) {
1590  // It's a .lnk file. Get the path and check to see if it's
1591  // a dir. If so, create a bookmark for the dir. If not, then
1592  // simply do nothing and continue.
1593 
1594  // Get the path that the .lnk file is pointing to.
1595  nsAutoString path;
1596  rv = currFile->GetTarget(path);
1597  if (NS_FAILED(rv)) continue;
1598 
1599  nsCOMPtr<nsILocalFile> localFile;
1600  rv = NS_NewLocalFile(path, PR_TRUE, getter_AddRefs(localFile));
1601  if (NS_FAILED(rv)) continue;
1602 
1603  // Check for dir here. If path is not a dir, just continue with
1604  // next import.
1605  rv = localFile->IsDirectory(&isDir);
1606  NS_ENSURE_SUCCESS(rv, rv);
1607  if (!isDir) continue;
1608 
1609  // Look for and strip out the .lnk extension.
1610  NS_NAMED_LITERAL_STRING(lnkExt, ".lnk");
1611  PRInt32 lnkExtStart = bookmarkName.Length() - lnkExt.Length();
1612  if (StringEndsWith(bookmarkName, lnkExt,
1613  CaseInsensitiveCompare))
1614  bookmarkName.SetLength(lnkExtStart);
1615 
1616  nsCOMPtr<nsIURI> bookmarkURI;
1617  rv = NS_NewFileURI(getter_AddRefs(bookmarkURI), localFile);
1618  if (NS_FAILED(rv)) continue;
1619  PRInt64 id;
1620  rv = aBMS->InsertBookmark(aParentFolder, bookmarkURI,
1621  nsINavBookmarksService::DEFAULT_INDEX,
1622  NS_ConvertUTF16toUTF8(bookmarkName),
1623  &id);
1624  if (NS_FAILED(rv)) continue;
1625  }
1626  else if (isDir) {
1627  PRInt64 folderId;
1628  if (bookmarkName.Equals(aPersonalToolbarFolderName)) {
1629  rv = aBMS->GetToolbarFolder(&folderId);
1630  if (NS_FAILED(rv)) break;
1631  }
1632  else {
1633  rv = aBMS->CreateFolder(aParentFolder,
1634  NS_ConvertUTF16toUTF8(bookmarkName),
1635  nsINavBookmarksService::DEFAULT_INDEX,
1636  &folderId);
1637  if (NS_FAILED(rv)) continue;
1638  }
1639 
1640  rv = ParseFavoritesFolder(currFile, folderId,
1641  aBMS, aPersonalToolbarFolderName,
1642  PR_FALSE);
1643  if (NS_FAILED(rv)) continue;
1644  }
1645  else {
1646  nsCOMPtr<nsIURL> url(do_QueryInterface(uri));
1647  nsCAutoString extension;
1648 
1649  url->GetFileExtension(extension);
1650  if (!extension.Equals("url", CaseInsensitiveCompare))
1651  continue;
1652 
1653  nsAutoString name(Substring(bookmarkName, 0,
1654  bookmarkName.Length() - extension.Length() - 1));
1655 
1656  nsAutoString path;
1657  currFile->GetPath(path);
1658 
1659  nsCString resolvedURL;
1660  ResolveShortcut(path, getter_Copies(resolvedURL));
1661 
1662  nsCOMPtr<nsIURI> resolvedURI;
1663  rv = NS_NewURI(getter_AddRefs(resolvedURI), resolvedURL);
1664  if (NS_FAILED(rv)) continue;
1665  PRInt64 id;
1666  rv = aBMS->InsertBookmark(aParentFolder, resolvedURI,
1667  nsINavBookmarksService::DEFAULT_INDEX,
1668  NS_ConvertUTF16toUTF8(name), &id);
1669  if (NS_FAILED(rv)) continue;
1670  }
1671  }
1672  while (1);
1673 
1674  return rv;
1675 }
1676 
1677 nsresult
1679 {
1680  PRBool regKeyOpen = PR_FALSE;
1681  const regEntry *entry,
1682  *endEntry = gRegEntries + NS_ARRAY_LENGTH(gRegEntries);
1683 
1684 
1685  nsCOMPtr<nsIPrefBranch> prefs;
1686 
1687  { // scope pserve why not
1688  nsCOMPtr<nsIPrefService> pserve(do_GetService(NS_PREFSERVICE_CONTRACTID));
1689  if (pserve)
1690  pserve->GetBranch("", getter_AddRefs(prefs));
1691  }
1692  if (!prefs)
1693  return NS_ERROR_FAILURE;
1694 
1695  nsCOMPtr<nsIWindowsRegKey> regKey =
1696  do_CreateInstance("@mozilla.org/windows-registry-key;1");
1697  if (!regKey)
1698  return NS_ERROR_UNEXPECTED;
1699 
1700  // step through gRegEntries table
1701  for (entry = gRegEntries; entry < endEntry; ++entry) {
1702 
1703  // a new keyname? close any previous one and open the new one
1704  if (entry->regKeyName) {
1705  if (regKeyOpen) {
1706  regKey->Close();
1707  regKeyOpen = PR_FALSE;
1708  }
1709  regKeyOpen = NS_SUCCEEDED(regKey->
1710  Open(nsIWindowsRegKey::ROOT_KEY_CURRENT_USER,
1711  NS_ConvertASCIItoUTF16(
1712  nsDependentCString(entry->regKeyName)),
1714  }
1715 
1716  if (regKeyOpen)
1717  // read registry data
1718  entry->entryHandler(regKey,
1719  NS_ConvertASCIItoUTF16(
1720  nsDependentCString(entry->regValueName)),
1721  prefs, entry->prefKeyName);
1722  }
1723 
1724  nsresult rv = CopySecurityPrefs(prefs);
1725  if (NS_FAILED(rv)) return rv;
1726 
1727  rv = CopyProxyPreferences(prefs);
1728  if (NS_FAILED(rv)) return rv;
1729 
1730  return CopyStyleSheet(aReplace);
1731 }
1732 
1733 /* Fetch and translate the current user's cookies.
1734  Return true if successful. */
1735 nsresult
1737 {
1738  // IE cookies are stored in files named <username>@domain[n].txt
1739  // (in <username>'s Cookies folder. isn't the naming redundant?)
1740  nsresult rv = NS_OK;
1741 
1742  nsCOMPtr<nsIFile> cookiesDir;
1743  nsCOMPtr<nsISimpleEnumerator> cookieFiles;
1744 
1745  nsCOMPtr<nsICookieManager2> cookieManager(do_GetService(NS_COOKIEMANAGER_CONTRACTID));
1746  if (!cookieManager)
1747  return NS_ERROR_FAILURE;
1748 
1749  // find the cookies directory
1750  NS_GetSpecialDirectory(NS_WIN_COOKIES_DIR, getter_AddRefs(cookiesDir));
1751  if (!cookiesDir)
1752  return NS_ERROR_FAILURE;
1753 
1754  // Check for Vista's UAC, if so, tack on a "Low" sub dir
1755  nsCOMPtr<nsIWindowsRegKey> regKey =
1756  do_CreateInstance("@mozilla.org/windows-registry-key;1");
1757  if (regKey) {
1758  NS_NAMED_LITERAL_STRING(regPath,"Software\\Microsoft\\Windows\\CurrentVersion\\Policies\\System");
1759  if (NS_SUCCEEDED(regKey->Open(nsIWindowsRegKey::ROOT_KEY_LOCAL_MACHINE,
1760  regPath,
1761  nsIWindowsRegKey::ACCESS_QUERY_VALUE))) {
1762  PRUint32 value;
1763  if (NS_SUCCEEDED(regKey->ReadIntValue(NS_LITERAL_STRING("EnableLUA"),
1764  &value)) &&
1765  value == 1) {
1766  nsAutoString dir;
1767  // For cases where we are running under protected mode, check
1768  // cookiesDir for the Low sub directory. (Simpler than using
1769  // process token calls to check our Vista integrity level.)
1770  cookiesDir->GetLeafName(dir);
1771  if (!dir.EqualsLiteral("Low"))
1772  cookiesDir->Append(NS_LITERAL_STRING("Low"));
1773  }
1774  }
1775  }
1776 
1777  cookiesDir->GetDirectoryEntries(getter_AddRefs(cookieFiles));
1778  if (!cookieFiles)
1779  return NS_ERROR_FAILURE;
1780 
1781  // fetch the current user's name from the environment
1782  PRUnichar username[sUsernameLengthLimit+2];
1783  ::GetEnvironmentVariableW(L"USERNAME", username,
1784  sizeof(username)/sizeof(PRUnichar));
1785  username[sUsernameLengthLimit] = L'\0';
1786  wcscat(username, L"@");
1787  int usernameLength = wcslen(username);
1788 
1789  // allocate a buffer into which to read each cookie file
1790  char *fileContents = (char *) PR_Malloc(sInitialCookieBufferSize);
1791  if (!fileContents)
1792  return NS_ERROR_OUT_OF_MEMORY;
1793  PRUint32 fileContentsSize = sInitialCookieBufferSize;
1794 
1795  do { // for each file in the cookies directory
1796  // get the next file
1797  PRBool moreFiles = PR_FALSE;
1798  if (NS_FAILED(cookieFiles->HasMoreElements(&moreFiles)) || !moreFiles)
1799  break;
1800 
1801  nsCOMPtr<nsISupports> supFile;
1802  cookieFiles->GetNext(getter_AddRefs(supFile));
1803  nsCOMPtr<nsIFile> cookieFile(do_QueryInterface(supFile));
1804  if (!cookieFile) {
1805  rv = NS_ERROR_FAILURE;
1806  break; // unexpected! punt!
1807  }
1808 
1809  // is it a cookie file for the current user?
1810  nsAutoString fileName;
1811  cookieFile->GetLeafName(fileName);
1812  const nsAString &fileOwner = Substring(fileName, 0, usernameLength);
1813  if (!fileOwner.Equals(username, CaseInsensitiveCompare))
1814  continue;
1815 
1816  // ensure the contents buffer is large enough to hold the entire file
1817  // plus one byte (see DelimitField())
1818  PRInt64 llFileSize;
1819  if (NS_FAILED(cookieFile->GetFileSize(&llFileSize)))
1820  continue;
1821 
1822  PRUint32 fileSize, readSize;
1823  LL_L2UI(fileSize, llFileSize);
1824  if (fileSize >= fileContentsSize) {
1825  PR_Free(fileContents);
1826  fileContents = (char *) PR_Malloc(fileSize+1);
1827  if (!fileContents) {
1828  rv = NS_ERROR_FAILURE;
1829  break; // fatal error
1830  }
1831  fileContentsSize = fileSize;
1832  }
1833 
1834  // read the entire cookie file
1835  PRFileDesc *fd;
1836  nsCOMPtr<nsILocalFile> localCookieFile(do_QueryInterface(cookieFile));
1837  if (localCookieFile &&
1838  NS_SUCCEEDED(localCookieFile->OpenNSPRFileDesc(PR_RDONLY, 0444, &fd))) {
1839 
1840  readSize = PR_Read(fd, fileContents, fileSize);
1841  PR_Close(fd);
1842 
1843  if (fileSize == readSize) { // translate this file's cookies
1844  nsresult onerv;
1845  onerv = CopyCookiesFromBuffer(fileContents, readSize, cookieManager);
1846  if (NS_FAILED(onerv))
1847  rv = onerv;
1848  }
1849  }
1850  } while(1);
1851 
1852  if (fileContents)
1853  PR_Free(fileContents);
1854  return rv;
1855 }
1856 
1857 /* Fetch cookies from a single IE cookie file.
1858  Return true if successful. */
1859 nsresult
1861  PRUint32 aBufferLength,
1862  nsICookieManager2 *aCookieManager)
1863 {
1864  nsresult rv = NS_OK;
1865 
1866  const char *bufferEnd = aBuffer + aBufferLength;
1867  // cookie fields:
1868  char *name,
1869  *value,
1870  *host,
1871  *path,
1872  *flags,
1873  *expirationDate1, *expirationDate2,
1874  *creationDate1, *creationDate2,
1875  *terminator;
1876  int flagsValue;
1877  time_t expirationDate,
1878  creationDate;
1879  char hostCopy[sHostnameLengthLimit+1],
1880  *hostCopyConstructor,
1881  *hostCopyEnd = hostCopy + sHostnameLengthLimit;
1882 
1883  do { // for each cookie in the buffer
1884  DelimitField(&aBuffer, bufferEnd, &name);
1885  DelimitField(&aBuffer, bufferEnd, &value);
1886  DelimitField(&aBuffer, bufferEnd, &host);
1887  DelimitField(&aBuffer, bufferEnd, &flags);
1888  DelimitField(&aBuffer, bufferEnd, &expirationDate1);
1889  DelimitField(&aBuffer, bufferEnd, &expirationDate2);
1890  DelimitField(&aBuffer, bufferEnd, &creationDate1);
1891  DelimitField(&aBuffer, bufferEnd, &creationDate2);
1892  DelimitField(&aBuffer, bufferEnd, &terminator);
1893 
1894  // it's a cookie if we got one of each
1895  if (terminator >= bufferEnd)
1896  break;
1897 
1898  // IE stores deleted cookies with a zero-length value
1899  if (*value == '\0')
1900  continue;
1901 
1902  // convert flags to an int, date numbers to useable dates
1903  ::sscanf(flags, "%d", &flagsValue);
1904  expirationDate = FileTimeToTimeT(expirationDate1, expirationDate2);
1905  creationDate = FileTimeToTimeT(creationDate1, creationDate2);
1906 
1907  // munge host, and separate host from path
1908 
1909  hostCopyConstructor = hostCopy;
1910 
1911  // first, with a non-null domain, assume it's what Mozilla considers
1912  // a domain cookie. see bug 222343.
1913  if (*host && *host != '.' && *host != '/')
1914  *hostCopyConstructor++ = '.';
1915 
1916  // copy the host part and leave path pointing to the path part
1917  for (path = host; *path && *path != '/'; ++path)
1918  ;
1919  int hostLength = path - host;
1920  if (hostLength > hostCopyEnd - hostCopyConstructor)
1921  hostLength = hostCopyEnd - hostCopyConstructor;
1922  PL_strncpy(hostCopyConstructor, host, hostLength);
1923  hostCopyConstructor += hostLength;
1924 
1925  *hostCopyConstructor = '\0';
1926 
1927  nsDependentCString stringName(name),
1928  stringPath(path);
1929 
1930  // delete any possible extant matching host cookie
1931  if (hostCopy[0] == '.')
1932  aCookieManager->Remove(nsDependentCString(hostCopy+1),
1933  stringName, stringPath, PR_FALSE);
1934 
1935  nsresult onerv;
1936  // Add() makes a new domain cookie
1937  onerv = aCookieManager->Add(nsDependentCString(hostCopy),
1938  stringPath,
1939  stringName,
1940  nsDependentCString(value),
1941  flagsValue & 0x1, // isSecure
1942  PR_FALSE, // isHttpOnly
1943  PR_FALSE, // isSession
1944  PRInt64(expirationDate));
1945  if (NS_FAILED(onerv)) {
1946  rv = onerv;
1947  break;
1948  }
1949 
1950  } while(aBuffer < bufferEnd);
1951 
1952  return rv;
1953 }
1954 
1955 /* Delimit the next field in the IE cookie buffer.
1956  when called:
1957  aBuffer: at the beginning of the next field or preceding whitespace
1958  aBufferEnd: one past the last valid character in the buffer
1959  on return:
1960  aField: at the beginning of the next field, which is null delimited
1961  aBuffer: after the null at the end of the field
1962 
1963  the character at which aBufferEnd points must be part of the buffer
1964  so we can set it to \0.
1965 */
1966 void
1968  const char *aBufferEnd,
1969  char **aField)
1970 {
1971  char *scan = *aBuffer;
1972  *aField = scan;
1973  while (scan < aBufferEnd && (*scan != '\r' && *scan != '\n'))
1974  ++scan;
1975  if (scan+1 < aBufferEnd && (*(scan+1) == '\r' || *(scan+1) == '\n') &&
1976  *scan != *(scan+1)) {
1977  *scan = '\0';
1978  scan += 2;
1979  } else {
1980  if (scan <= aBufferEnd) // (1 byte past bufferEnd is guaranteed allocated)
1981  *scan = '\0';
1982  ++scan;
1983  }
1984  *aBuffer = scan;
1985 }
1986 
1987 // conversion routine. returns 0 (epoch date) if the input is out of range
1988 time_t
1989 nsIEProfileMigrator::FileTimeToTimeT(const char *aLowDateIntString,
1990  const char *aHighDateIntString)
1991 {
1992  FILETIME fileTime;
1993  SYSTEMTIME systemTime;
1994  tm tTime;
1995  time_t rv;
1996 
1997  ::sscanf(aLowDateIntString, "%ld", &fileTime.dwLowDateTime);
1998  ::sscanf(aHighDateIntString, "%ld", &fileTime.dwHighDateTime);
1999  ::FileTimeToSystemTime(&fileTime, &systemTime);
2000  tTime.tm_year = systemTime.wYear - 1900;
2001  tTime.tm_mon = systemTime.wMonth-1;
2002  tTime.tm_mday = systemTime.wDay;
2003  tTime.tm_hour = systemTime.wHour;
2004  tTime.tm_min = systemTime.wMinute;
2005  tTime.tm_sec = systemTime.wSecond;
2006  tTime.tm_isdst = -1;
2007  rv = ::mktime(&tTime);
2008  return rv < 0 ? 0 : rv;
2009 }
2010 
2011 /* Find the accessibility stylesheet if it exists and replace Mozilla's
2012  with it. Return true if we found and copied a stylesheet. */
2013 nsresult
2015 {
2016  nsresult rv = NS_OK; // return failure only if filecopy fails
2017 
2018  // is there a trident user stylesheet?
2019  nsCOMPtr<nsIWindowsRegKey> regKey =
2020  do_CreateInstance("@mozilla.org/windows-registry-key;1");
2021  if (!regKey)
2022  return NS_ERROR_UNEXPECTED;
2023 
2024  NS_NAMED_LITERAL_STRING(styleKey,
2025  "Software\\Microsoft\\Internet Explorer\\Styles");
2026  if (NS_FAILED(regKey->Open(nsIWindowsRegKey::ROOT_KEY_CURRENT_USER,
2027  styleKey, nsIWindowsRegKey::ACCESS_READ)))
2028  return NS_OK;
2029 
2030  NS_NAMED_LITERAL_STRING(myStyleValName, "Use My StyleSheet");
2031  PRUint32 type, useMyStyle;
2032  if (NS_SUCCEEDED(regKey->GetValueType(myStyleValName, &type)) &&
2033  type == nsIWindowsRegKey::TYPE_INT &&
2034  NS_SUCCEEDED(regKey->ReadIntValue(myStyleValName, &useMyStyle)) &&
2035  useMyStyle == 1) {
2036 
2037  nsAutoString tridentFilename;
2038  if (NS_SUCCEEDED(regKey->ReadStringValue(
2039  NS_LITERAL_STRING("User Stylesheet"), tridentFilename))) {
2040 
2041  // tridentFilename is a native path to the specified stylesheet file
2042  // point an nsIFile at it
2043  nsCOMPtr<nsILocalFile> tridentFile(do_CreateInstance(NS_LOCAL_FILE_CONTRACTID));
2044  if (tridentFile) {
2045  PRBool exists;
2046 
2047  tridentFile->InitWithPath(tridentFilename);
2048  tridentFile->Exists(&exists);
2049  if (exists) {
2050  // now establish our file (userContent.css in the profile/chrome dir)
2051  nsCOMPtr<nsIFile> chromeDir;
2052  NS_GetSpecialDirectory(NS_APP_USER_CHROME_DIR,
2053  getter_AddRefs(chromeDir));
2054  if (chromeDir)
2055  rv = tridentFile->CopyTo(chromeDir,
2056  NS_LITERAL_STRING("userContent.css"));
2057  }
2058  }
2059  }
2060  }
2061  return rv;
2062 }
2063 
2064 void
2066 {
2067  nsCOMPtr<nsIFile> userChrome;
2068 
2069  *aUserFile = 0;
2070 
2071  // establish the chrome directory
2072  NS_GetSpecialDirectory(NS_APP_USER_CHROME_DIR, getter_AddRefs(userChrome));
2073 
2074  if (userChrome) {
2075  PRBool exists;
2076  userChrome->Exists(&exists);
2077  if (!exists &&
2078  NS_FAILED(userChrome->Create(nsIFile::DIRECTORY_TYPE, 0755)))
2079  return;
2080 
2081  // establish the user content stylesheet file
2082  userChrome->Append(NS_LITERAL_STRING("userContent.css"));
2083  *aUserFile = userChrome;
2084  NS_ADDREF(*aUserFile);
2085  }
2086 }
2087 
2088 nsresult
2090 {
2091  nsCOMPtr<nsIWindowsRegKey> regKey =
2092  do_CreateInstance("@mozilla.org/windows-registry-key;1");
2093  NS_NAMED_LITERAL_STRING(key,
2094  "Software\\Microsoft\\Windows\\CurrentVersion\\Internet Settings");
2095  if (regKey &&
2096  NS_SUCCEEDED(regKey->Open(nsIWindowsRegKey::ROOT_KEY_CURRENT_USER,
2098 
2099  PRUint32 value;
2100  if (NS_SUCCEEDED(regKey->ReadIntValue(NS_LITERAL_STRING("SecureProtocols"),
2101  &value))) {
2102  aPrefs->SetBoolPref("security.enable_ssl2", (value >> 3) & PR_TRUE);
2103  aPrefs->SetBoolPref("security.enable_ssl3", (value >> 5) & PR_TRUE);
2104  aPrefs->SetBoolPref("security.enable_tls", (value >> 7) & PR_TRUE);
2105  }
2106  }
2107 
2108  return NS_OK;
2109 }
2110 
2111 struct ProxyData {
2112  char* prefix;
2113  PRInt32 prefixLength;
2115  char* hostPref;
2116  char* portPref;
2117 };
2118 
2119 nsresult
2121 {
2122  nsCOMPtr<nsIWindowsRegKey> regKey =
2123  do_CreateInstance("@mozilla.org/windows-registry-key;1");
2124  NS_NAMED_LITERAL_STRING(key,
2125  "Software\\Microsoft\\Windows\\CurrentVersion\\Internet Settings");
2126  if (regKey &&
2127  NS_SUCCEEDED(regKey->Open(nsIWindowsRegKey::ROOT_KEY_CURRENT_USER,
2129  nsAutoString buf;
2130 
2131  PRUint32 proxyType = 0;
2132  // If there's an autoconfig URL specified in the registry at all,
2133  // it is being used.
2134  if (NS_SUCCEEDED(regKey->
2135  ReadStringValue(NS_LITERAL_STRING("AutoConfigURL"), buf))) {
2136  // make this future-proof (MS IE will support IDN eventually and
2137  // 'URL' will contain more than ASCII characters)
2138  SetUnicharPref("network.proxy.autoconfig_url", buf, aPrefs);
2139  proxyType = 2;
2140  }
2141 
2142  // ProxyEnable
2143  PRUint32 enabled;
2144  if (NS_SUCCEEDED(regKey->
2145  ReadIntValue(NS_LITERAL_STRING("ProxyEnable"), &enabled))) {
2146  if (enabled & 0x1)
2147  proxyType = 1;
2148  }
2149 
2150  aPrefs->SetIntPref("network.proxy.type", proxyType);
2151 
2152  if (NS_SUCCEEDED(regKey->
2153  ReadStringValue(NS_LITERAL_STRING("ProxyOverride"), buf)))
2154  ParseOverrideServers(buf, aPrefs);
2155 
2156  if (NS_SUCCEEDED(regKey->
2157  ReadStringValue(NS_LITERAL_STRING("ProxyServer"), buf))) {
2158 
2159  ProxyData data[] = {
2160  { "ftp=", 4, PR_FALSE, "network.proxy.ftp",
2161  "network.proxy.ftp_port" },
2162  { "gopher=", 7, PR_FALSE, "network.proxy.gopher",
2163  "network.proxy.gopher_port" },
2164  { "http=", 5, PR_FALSE, "network.proxy.http",
2165  "network.proxy.http_port" },
2166  { "https=", 6, PR_FALSE, "network.proxy.ssl",
2167  "network.proxy.ssl_port" },
2168  { "socks=", 6, PR_FALSE, "network.proxy.socks",
2169  "network.proxy.socks_port" },
2170  };
2171 
2172  PRInt32 startIndex = 0, count = 0;
2173  PRBool foundSpecificProxy = PR_FALSE;
2174  for (PRUint32 i = 0; i < 5; ++i) {
2175  PRInt32 offset = buf.Find(NS_ConvertASCIItoUTF16(data[i].prefix));
2176  if (offset >= 0) {
2177  foundSpecificProxy = PR_TRUE;
2178 
2179  data[i].proxyConfigured = PR_TRUE;
2180 
2181  startIndex = offset + data[i].prefixLength;
2182 
2183  PRInt32 terminal = buf.FindChar(';', offset);
2184  count = terminal > startIndex ? terminal - startIndex :
2185  buf.Length() - startIndex;
2186 
2187  // hostPort now contains host:port
2188  SetProxyPref(Substring(buf, startIndex, count), data[i].hostPref,
2189  data[i].portPref, aPrefs);
2190  }
2191  }
2192 
2193  if (!foundSpecificProxy) {
2194  // No proxy config for any specific type was found, assume
2195  // the ProxyServer value is of the form host:port and that
2196  // it applies to all protocols.
2197  for (PRUint32 i = 0; i < 5; ++i)
2198  SetProxyPref(buf, data[i].hostPref, data[i].portPref, aPrefs);
2199  aPrefs->SetBoolPref("network.proxy.share_proxy_settings", PR_TRUE);
2200  }
2201  }
2202 
2203  }
2204 
2205  return NS_OK;
2206 }
2207 
const int sHostnameLengthLimit
nsresult InitializeBookmarks(nsIFile *aTargetProfile)
classDescription entry
Definition: FeedWriter.js:1427
void TranslateString(nsIWindowsRegKey *aRegKey, const nsString &aRegValueName, nsIPrefBranch *aPrefs, char *aPrefKeyName)
void TranslateDWORDtoHTTPVersion(nsIWindowsRegKey *aRegKey, const nsString &aRegValueName, nsIPrefBranch *aPrefs, char *aPrefKeyName)
void TranslateYNtoFT(nsIWindowsRegKey *aRegKey, const nsString &aRegValueName, nsIPrefBranch *aPrefs, char *aPrefKeyName)
return NS_OK
nsresult CopyStyleSheet(PRBool aReplace)
const int sInitialCookieBufferSize
char * regKeyName
nsresult CopyFavorites(PRBool aReplace)
const PR_RDONLY
menuItem id
Definition: FeedWriter.js:971
void ParseOverrideServers(const nsAString &aServers, nsIPrefBranch *aBranch)
static GUID IEPStoreAutocompGUID
HRESULT(WINAPI * PStoreCreateInstancePtr)(IPStore **, DWORD, DWORD, DWORD)
void TranslatePropFont(nsIWindowsRegKey *aRegKey, const nsString &aRegValueName, nsIPrefBranch *aPrefs, char *aPrefKeyName)
nsresult CopyProxyPreferences(nsIPrefBranch *aPrefs)
static GUID IEPStoreSiteAuthGUID
#define BATCH_ACTION_BOOKMARKS
var history
const NS_PREFSERVICE_CONTRACTID
void TranslateDWORDtoPRInt32(nsIWindowsRegKey *aRegKey, const nsString &aRegValueName, nsIPrefBranch *aPrefs, char *aPrefKeyName)
void TranslateDRGBtoHRGB(nsIWindowsRegKey *aRegKey, const nsString &aRegValueName, nsIPrefBranch *aPrefs, char *aPrefKeyName)
void(* regEntryHandler)(nsIWindowsRegKey *, const nsString &, nsIPrefBranch *, char *)
nsresult AddDataToFormHistory(const nsAString &aKey, PRUnichar *data, unsigned long len)
sbDeviceFirmwareAutoCheckForUpdate prototype flags
nsresult ParseFavoritesFolder(nsIFile *aDirectory, PRInt64 aParentFolder, nsINavBookmarksService *aBookmarksService, const nsAString &aPersonalToolbarFolderName, PRBool aIsAtRootLevel)
nsresult CopyHistoryBatched(PRBool aReplace)
nsresult CopyFormData(PRBool aReplace)
const nsIPrefBranch
PRUnichar * user
static int CALLBACK fontEnumProc(const LOGFONTW *aLogFont, const TEXTMETRICW *aMetric, DWORD aFontType, LPARAM aClosure)
void GetUserStyleSheetFile(nsIFile **aUserFile)
#define BATCH_ACTION_HISTORY_REPLACE
function skip(aMessage)
#define REGISTRY_IE_TYPEDURL_KEY
#define NOTIFY_OBSERVERS(message, item)
void DelimitField(char **aBuffer, const char *aBufferEnd, char **aField)
const regEntry gRegEntries[]
function d(s)
PRUint32 & offset
var resolvedURI
Definition: FeedWriter.js:1136
var bundle
var count
Definition: test_bug7406.js:32
nsresult CopyCookiesFromBuffer(char *aBuffer, PRUint32 aBufferLength, nsICookieManager2 *aCookieManager)
time_t FileTimeToTimeT(const char *aLowDateIntString, const char *aHighDateIntString)
#define MIGRATION_STARTED
char * regValueName
#define COPY_DATA(func, replace, itemIndex)
#define TRIDENTPROFILE_BUNDLE
#define REGISTRY_IE_SEARCHURL_KEY
#define MIGRATION_ENDED
this _dialogInput val(dateText)
void TranslateYNtoTF(nsIWindowsRegKey *aRegKey, const nsString &aRegValueName, nsIPrefBranch *aPrefs, char *aPrefKeyName)
void * aClosure
Definition: sbArray.cpp:52
nsresult MigrateSiteAuthSignons(IPStore *aPStore)
PRBool KeyIsURI(const nsAString &aKey, char **aRealm)
function fileContents(file)
Definition: head_utils.js:94
void TranslateYNtoImageBehavior(nsIWindowsRegKey *aRegKey, const nsString &aRegValueName, nsIPrefBranch *aPrefs, char *aPrefKeyName)
void __stdcall _com_issue_error(HRESULT hr)
void TranslateLanglist(nsIWindowsRegKey *aRegKey, const nsString &aRegValueName, nsIPrefBranch *aPrefs, char *aPrefKeyName)
nsresult CopyPreferences(PRBool aReplace)
void ResolveShortcut(const nsString &aFileName, char **aOutURL)
char * prefKeyName
regEntryHandler entryHandler
void GetUserNameAndPass(unsigned char *data, unsigned long len, unsigned char **username, unsigned char **pass)
function url(spec)
var uri
Definition: FeedWriter.js:1135
StringArrayEnumerator prototype hasMore
nsresult GetSignonsListFromPStore(IPStore *aPStore, nsTArray< SignonData > *aSignonsFound)
var prefs
Definition: FeedWriter.js:1169
countRef value
Definition: FeedWriter.js:1423
nsresult CopySmartKeywords(nsINavBookmarksService *aBMS, PRInt64 aParentFolder)
void SetUnicharPref(const char *aPref, const nsAString &aValue, nsIPrefBranch *aPrefs)
nsresult CopyFavoritesBatched(PRBool aReplace)
#define REGISTRY_IE_MAIN_KEY
void GetProfilePath(nsIProfileStartup *aStartup, nsCOMPtr< nsIFile > &aProfileDir)
#define BATCH_ACTION_HISTORY
void SetProxyPref(const nsAString &aHostPort, const char *aPref, const char *aPortPref, nsIPrefBranch *aPrefs)
var ios
Definition: head_feeds.js:5
nsresult CopyHistory(PRBool aReplace)
restoreHistoryPrecursor aCount
void EnumerateUsernames(const nsAString &aKey, PRUnichar *aData, unsigned long aCount, nsTArray< SignonData > *aSignonsFound)
PRUnichar * pass
#define BATCH_ACTION_BOOKMARKS_REPLACE
nsresult CopyPasswords(PRBool aReplace)
nsresult ResolveAndMigrateSignons(IPStore *aPStore, nsTArray< SignonData > *aSignonsFound)
observe data
Definition: FeedWriter.js:1329
const ACCESS_READ
Definition: pageInfo.js:194
_getSelectedPageStyle s i
nsresult CopySecurityPrefs(nsIPrefBranch *aPrefs)
NS_IMPL_ISUPPORTS2(nsIEProfileMigrator, nsIBrowserProfileMigrator, nsINavHistoryBatchCallback)
nsresult CopyCookies(PRBool aReplace)
const int sUsernameLengthLimit
_updateTextAndScrollDataForFrame aData
#define REGISTRY_IE_TOOLBAR_KEY
NS_DECL_NSIBROWSERPROFILEMIGRATOR NS_DECL_NSINAVHISTORYBATCHCALLBACK NS_DECL_ISUPPORTS nsIEProfileMigrator()