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
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/
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
15 * The Original Code is The Browser Profile Migrator.
17 * The Initial Developer of the Original Code is Ben Goodger.
18 * Portions created by the Initial Developer are Copyright (C) 2004
19 * the Initial Developer. All Rights Reserved.
22 * Ben Goodger <ben@bengoodger.com>
24 * Alternatively, the contents of this file may be used under the terms of
25 * either the GNU General Public License Version 2 or later (the "GPL"), or
26 * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
27 * in which case the provisions of the GPL or the LGPL are applicable instead
28 * of those above. If you wish to allow use of your version of this file only
29 * under the terms of either the GPL or the LGPL, and not to allow others to
30 * use your version of this file under the terms of the MPL, indicate your
31 * decision by deleting the provisions above and replace them with the notice
32 * and other provisions required by the GPL or the LGPL. If you do not delete
33 * the provisions above, a recipient may use your version of this file under
34 * the terms of any one of the MPL, the GPL or the LGPL.
36 * ***** END LICENSE BLOCK ***** */
38 #include "nsAppDirectoryServiceDefs.h"
39 #include "nsBrowserProfileMigratorUtils.h"
40 #include "nsDirectoryServiceDefs.h"
41 #include "nsDirectoryServiceUtils.h"
42 #include "nsDocShellCID.h"
43 #include "nsINavBookmarksService.h"
44 #include "nsBrowserCompsCID.h"
45 #include "nsIBrowserProfileMigrator.h"
46 #include "nsIBrowserHistory.h"
47 #include "nsICookieManager2.h"
48 #include "nsIGlobalHistory.h"
49 #include "nsIInputStream.h"
50 #include "nsILineInputStream.h"
51 #include "nsILocalFile.h"
52 #include "nsINIParser.h"
53 #include "nsIObserverService.h"
54 #include "nsIPermissionManager.h"
55 #include "nsIPrefLocalizedString.h"
56 #include "nsIPrefService.h"
57 #include "nsIProfileMigrator.h"
58 #include "nsIProperties.h"
59 #include "nsIRDFContainer.h"
60 #include "nsIRDFService.h"
61 #include "nsIServiceManager.h"
62 #include "nsIStringBundle.h"
63 #include "nsISupportsPrimitives.h"
64 #include "nsNetUtil.h"
65 #include "nsOperaProfileMigrator.h"
66 #include "nsToolkitCompsCID.h"
71 #define MIGRATION_BUNDLE "chrome://browser/locale/migration/migration.properties"
74 #define OPERA_PREFERENCES_FOLDER_NAME NS_LITERAL_STRING("Opera")
75 #define OPERA_PREFERENCES_FILE_NAME NS_LITERAL_STRING("opera6.ini")
76 #define OPERA_HISTORY_FILE_NAME NS_LITERAL_STRING("global.dat")
77 #define OPERA_BOOKMARKS_FILE_NAME NS_LITERAL_STRING("opera6.adr")
78 #elif defined(XP_MACOSX)
79 #define OPERA_PREFERENCES_FOLDER_NAME NS_LITERAL_STRING("Opera 6 Preferences")
80 #define OPERA_PREFERENCES_FILE_NAME NS_LITERAL_STRING("Opera 6 Preferences")
81 #define OPERA_HISTORY_FILE_NAME NS_LITERAL_STRING("Opera Global History")
82 #define OPERA_BOOKMARKS_FILE_NAME NS_LITERAL_STRING("Bookmarks")
83 #elif defined (XP_UNIX)
84 #define OPERA_PREFERENCES_FOLDER_NAME NS_LITERAL_STRING(".opera")
85 #define OPERA_PREFERENCES_FILE_NAME NS_LITERAL_STRING("opera6.ini")
86 #define OPERA_HISTORY_FILE_NAME NS_LITERAL_STRING("global.dat")
87 #define OPERA_BOOKMARKS_FILE_NAME NS_LITERAL_STRING("opera6.adr")
88 #elif defined (XP_BEOS)
89 #define OPERA_PREFERENCES_FOLDER_NAME NS_LITERAL_STRING("Opera")
90 #define OPERA_PREFERENCES_FILE_NAME NS_LITERAL_STRING("opera.ini")
91 #define OPERA_HISTORY_FILE_NAME NS_LITERAL_STRING("global.dat")
92 #define OPERA_BOOKMARKS_FILE_NAME NS_LITERAL_STRING("opera.adr")
94 #error Need to define location of Opera Profile data.
97 #define OPERA_COOKIES_FILE_NAME NS_LITERAL_STRING("cookies4.dat")
99 #define OPERA_COOKIES_FILE_NAME NS_LITERAL_STRING("cookies.dat")
102 ///////////////////////////////////////////////////////////////////////////////
103 // nsBrowserProfileMigrator
105 NS_IMPL_ISUPPORTS1(nsOperaProfileMigrator
, nsIBrowserProfileMigrator
)
107 nsOperaProfileMigrator::nsOperaProfileMigrator()
109 mObserverService
= do_GetService("@mozilla.org/observer-service;1");
112 nsOperaProfileMigrator::~nsOperaProfileMigrator()
117 nsOperaProfileMigrator::Migrate(PRUint16 aItems
, nsIProfileStartup
* aStartup
, const PRUnichar
* aProfile
)
120 PRBool aReplace
= aStartup
? PR_TRUE
: PR_FALSE
;
123 rv
= aStartup
->DoStartup();
124 NS_ENSURE_SUCCESS(rv
, rv
);
128 GetOperaProfile(aProfile
, getter_AddRefs(mOperaProfile
));
130 NOTIFY_OBSERVERS(MIGRATION_STARTED
, nsnull
);
132 COPY_DATA(CopyPreferences
, aReplace
, nsIBrowserProfileMigrator::SETTINGS
);
133 COPY_DATA(CopyCookies
, aReplace
, nsIBrowserProfileMigrator::COOKIES
);
134 COPY_DATA(CopyHistory
, aReplace
, nsIBrowserProfileMigrator::HISTORY
);
135 COPY_DATA(CopyBookmarks
, aReplace
, nsIBrowserProfileMigrator::BOOKMARKS
);
137 NOTIFY_OBSERVERS(MIGRATION_ENDED
, nsnull
);
143 nsOperaProfileMigrator::GetMigrateData(const PRUnichar
* aProfile
,
148 if (!mOperaProfile
) {
149 GetOperaProfile(aProfile
, getter_AddRefs(mOperaProfile
));
151 return NS_ERROR_FILE_NOT_FOUND
;
154 MigrationData data
[] = { { ToNewUnicode(OPERA_PREFERENCES_FILE_NAME
),
155 nsIBrowserProfileMigrator::SETTINGS
,
157 { ToNewUnicode(OPERA_COOKIES_FILE_NAME
),
158 nsIBrowserProfileMigrator::COOKIES
,
160 { ToNewUnicode(OPERA_HISTORY_FILE_NAME
),
161 nsIBrowserProfileMigrator::HISTORY
,
163 { ToNewUnicode(OPERA_BOOKMARKS_FILE_NAME
),
164 nsIBrowserProfileMigrator::BOOKMARKS
,
167 // Frees file name strings allocated above.
168 GetMigrateDataFromArray(data
, sizeof(data
)/sizeof(MigrationData
),
169 aReplace
, mOperaProfile
, aResult
);
175 nsOperaProfileMigrator::GetSourceExists(PRBool
* aResult
)
177 nsCOMPtr
<nsISupportsArray
> profiles
;
178 GetSourceProfiles(getter_AddRefs(profiles
));
182 profiles
->Count(&count
);
183 *aResult
= count
> 0;
192 nsOperaProfileMigrator::GetSourceHasMultipleProfiles(PRBool
* aResult
)
194 nsCOMPtr
<nsISupportsArray
> profiles
;
195 GetSourceProfiles(getter_AddRefs(profiles
));
200 profiles
->Count(&count
);
201 *aResult
= count
> 1;
211 nsOperaProfileMigrator::GetSourceProfiles(nsISupportsArray
** aResult
)
216 mProfiles
= do_CreateInstance(NS_SUPPORTSARRAY_CONTRACTID
, &rv
);
217 if (NS_FAILED(rv
)) return rv
;
219 nsCOMPtr
<nsIProperties
> fileLocator(do_GetService("@mozilla.org/file/directory_service;1"));
220 nsCOMPtr
<nsILocalFile
> file
;
222 fileLocator
->Get(NS_WIN_APPDATA_DIR
, NS_GET_IID(nsILocalFile
), getter_AddRefs(file
));
224 // Opera profile lives under %APP_DATA%\Opera\<operaver>\profile
225 file
->Append(OPERA_PREFERENCES_FOLDER_NAME
);
227 nsCOMPtr
<nsISimpleEnumerator
> e
;
228 rv
= file
->GetDirectoryEntries(getter_AddRefs(e
));
233 e
->HasMoreElements(&hasMore
);
235 nsCOMPtr
<nsILocalFile
> curr
;
236 e
->GetNext(getter_AddRefs(curr
));
238 PRBool isDirectory
= PR_FALSE
;
239 curr
->IsDirectory(&isDirectory
);
241 nsCOMPtr
<nsISupportsString
> string(do_CreateInstance("@mozilla.org/supports-string;1"));
242 nsAutoString leafName
;
243 curr
->GetLeafName(leafName
);
244 string
->SetData(leafName
);
245 mProfiles
->AppendElement(string
);
248 e
->HasMoreElements(&hasMore
);
250 #elif defined (XP_MACOSX)
251 fileLocator
->Get(NS_MAC_USER_LIB_DIR
, NS_GET_IID(nsILocalFile
), getter_AddRefs(file
));
253 file
->Append(NS_LITERAL_STRING("Preferences"));
254 file
->Append(OPERA_PREFERENCES_FOLDER_NAME
);
257 file
->Exists(&exists
);
260 nsCOMPtr
<nsISupportsString
> string(do_CreateInstance("@mozilla.org/supports-string;1"));
261 string
->SetData(OPERA_PREFERENCES_FOLDER_NAME
);
262 mProfiles
->AppendElement(string
);
264 #elif defined (XP_UNIX)
265 fileLocator
->Get(NS_UNIX_HOME_DIR
, NS_GET_IID(nsILocalFile
), getter_AddRefs(file
));
267 file
->Append(OPERA_PREFERENCES_FOLDER_NAME
);
270 file
->Exists(&exists
);
273 nsCOMPtr
<nsISupportsString
> string(do_CreateInstance("@mozilla.org/supports-string;1"));
274 string
->SetData(OPERA_PREFERENCES_FOLDER_NAME
);
275 mProfiles
->AppendElement(string
);
280 *aResult
= mProfiles
;
281 NS_IF_ADDREF(*aResult
);
286 nsOperaProfileMigrator::GetSourceHomePageURL(nsACString
& aResult
)
291 nsCOMPtr
<nsIFile
> operaPrefs
;
292 mOperaProfile
->Clone(getter_AddRefs(operaPrefs
));
293 operaPrefs
->Append(OPERA_PREFERENCES_FILE_NAME
);
295 nsCOMPtr
<nsILocalFile
> lf(do_QueryInterface(operaPrefs
));
296 NS_ENSURE_TRUE(lf
, NS_ERROR_UNEXPECTED
);
299 rv
= parser
.Init(lf
);
300 NS_ENSURE_SUCCESS(rv
, rv
);
302 rv
= parser
.GetString("User Prefs",
306 if (NS_SUCCEEDED(rv
))
313 #define _OPM(type) nsOperaProfileMigrator::type
316 nsOperaProfileMigrator::PrefTransform gTransforms
[] = {
317 { "User Prefs", "Download Directory", _OPM(STRING
), "browser.download.dir", _OPM(SetFile
), PR_FALSE
, -1 },
318 { nsnull
, "Enable Cookies", _OPM(INT
), "network.cookie.cookieBehavior", _OPM(SetCookieBehavior
), PR_FALSE
, -1 },
319 { nsnull
, "Accept Cookies Session Only", _OPM(BOOL
), "network.cookie.lifetimePolicy", _OPM(SetCookieLifetime
), PR_FALSE
, -1 },
320 { nsnull
, "Allow script to resize window", _OPM(BOOL
), "dom.disable_window_move_resize", _OPM(SetBool
), PR_FALSE
, -1 },
321 { nsnull
, "Allow script to move window", _OPM(BOOL
), "dom.disable_window_move_resize", _OPM(SetBool
), PR_FALSE
, -1 },
322 { nsnull
, "Allow script to raise window", _OPM(BOOL
), "dom.disable_window_flip", _OPM(SetBool
), PR_FALSE
, -1 },
323 { nsnull
, "Allow script to change status", _OPM(BOOL
), "dom.disable_window_status_change", _OPM(SetBool
), PR_FALSE
, -1 },
324 { nsnull
, "Ignore Unrequested Popups", _OPM(BOOL
), "dom.disable_open_during_load", _OPM(SetBool
), PR_FALSE
, -1 },
325 { nsnull
, "Load Figures", _OPM(BOOL
), "permissions.default.image", _OPM(SetImageBehavior
), PR_FALSE
, -1 },
327 { "Visited link", nsnull
, _OPM(COLOR
), "browser.visited_color", _OPM(SetString
), PR_FALSE
, -1 },
328 { "Link", nsnull
, _OPM(COLOR
), "browser.anchor_color", _OPM(SetString
), PR_FALSE
, -1 },
329 { nsnull
, "Underline", _OPM(BOOL
), "browser.underline_anchors", _OPM(SetBool
), PR_FALSE
, -1 },
330 { nsnull
, "Expiry", _OPM(INT
), "browser.history_expire_days", _OPM(SetInt
), PR_FALSE
, -1 },
332 { "Security Prefs", "Enable SSL v2", _OPM(BOOL
), "security.enable_ssl2", _OPM(SetBool
), PR_FALSE
, -1 },
333 { nsnull
, "Enable SSL v3", _OPM(BOOL
), "security.enable_ssl3", _OPM(SetBool
), PR_FALSE
, -1 },
334 { nsnull
, "Enable TLS v1.0", _OPM(BOOL
), "security.enable_tls", _OPM(SetBool
), PR_FALSE
, -1 },
336 { "Extensions", "Scripting", _OPM(BOOL
), "javascript.enabled", _OPM(SetBool
), PR_FALSE
, -1 }
340 nsOperaProfileMigrator::SetFile(void* aTransform
, nsIPrefBranch
* aBranch
)
342 PrefTransform
* xform
= (PrefTransform
*)aTransform
;
343 nsCOMPtr
<nsILocalFile
> lf(do_CreateInstance("@mozilla.org/file/local;1"));
344 lf
->InitWithPath(NS_ConvertUTF8toUTF16(xform
->stringValue
));
345 return aBranch
->SetComplexValue(xform
->targetPrefName
, NS_GET_IID(nsILocalFile
), lf
);
349 nsOperaProfileMigrator::SetCookieBehavior(void* aTransform
, nsIPrefBranch
* aBranch
)
351 PrefTransform
* xform
= (PrefTransform
*)aTransform
;
352 PRInt32 val
= (xform
->intValue
== 3) ? 0 : (xform
->intValue
== 0) ? 2 : 1;
353 return aBranch
->SetIntPref(xform
->targetPrefName
, val
);
357 nsOperaProfileMigrator::SetCookieLifetime(void* aTransform
, nsIPrefBranch
* aBranch
)
359 PrefTransform
* xform
= (PrefTransform
*)aTransform
;
360 return aBranch
->SetIntPref(xform
->targetPrefName
, xform
->boolValue
? 2 : 0);
364 nsOperaProfileMigrator::SetImageBehavior(void* aTransform
, nsIPrefBranch
* aBranch
)
366 PrefTransform
* xform
= (PrefTransform
*)aTransform
;
367 return aBranch
->SetIntPref(xform
->targetPrefName
, xform
->boolValue
? 1 : 2);
371 nsOperaProfileMigrator::SetBool(void* aTransform
, nsIPrefBranch
* aBranch
)
373 PrefTransform
* xform
= (PrefTransform
*)aTransform
;
374 return aBranch
->SetBoolPref(xform
->targetPrefName
, xform
->boolValue
);
378 nsOperaProfileMigrator::SetWString(void* aTransform
, nsIPrefBranch
* aBranch
)
380 PrefTransform
* xform
= (PrefTransform
*)aTransform
;
381 nsCOMPtr
<nsIPrefLocalizedString
> pls(do_CreateInstance("@mozilla.org/pref-localizedstring;1"));
382 NS_ConvertUTF8toUTF16
data(xform
->stringValue
);
383 pls
->SetData(data
.get());
384 return aBranch
->SetComplexValue(xform
->targetPrefName
, NS_GET_IID(nsIPrefLocalizedString
), pls
);
388 nsOperaProfileMigrator::SetInt(void* aTransform
, nsIPrefBranch
* aBranch
)
390 PrefTransform
* xform
= (PrefTransform
*)aTransform
;
391 return aBranch
->SetIntPref(xform
->targetPrefName
, xform
->intValue
);
395 nsOperaProfileMigrator::SetString(void* aTransform
, nsIPrefBranch
* aBranch
)
397 PrefTransform
* xform
= (PrefTransform
*)aTransform
;
398 return aBranch
->SetCharPref(xform
->targetPrefName
, xform
->stringValue
);
402 nsOperaProfileMigrator::CopyPreferences(PRBool aReplace
)
406 nsCOMPtr
<nsIFile
> operaPrefs
;
407 mOperaProfile
->Clone(getter_AddRefs(operaPrefs
));
408 operaPrefs
->Append(OPERA_PREFERENCES_FILE_NAME
);
410 nsCOMPtr
<nsILocalFile
> lf(do_QueryInterface(operaPrefs
));
411 NS_ENSURE_TRUE(lf
, NS_ERROR_UNEXPECTED
);
414 rv
= parser
.Init(lf
);
415 NS_ENSURE_SUCCESS(rv
, rv
);
417 nsCOMPtr
<nsIPrefBranch
> branch(do_GetService(NS_PREFSERVICE_CONTRACTID
));
419 // Traverse the standard transforms
420 PrefTransform
* transform
;
421 PrefTransform
* end
= gTransforms
+ sizeof(gTransforms
)/sizeof(PrefTransform
);
423 char* lastSectionName
= nsnull
;
424 for (transform
= gTransforms
; transform
< end
; ++transform
) {
425 if (transform
->sectionName
)
426 lastSectionName
= transform
->sectionName
;
428 if (transform
->type
== _OPM(COLOR
)) {
429 char* colorString
= nsnull
;
430 nsresult rv
= ParseColor(parser
, lastSectionName
, &colorString
);
431 if (NS_SUCCEEDED(rv
)) {
432 transform
->stringValue
= colorString
;
434 transform
->prefHasValue
= PR_TRUE
;
435 transform
->prefSetterFunc(transform
, branch
);
442 rv
= parser
.GetString(lastSectionName
,
445 if (NS_SUCCEEDED(rv
)) {
447 switch (transform
->type
) {
449 transform
->stringValue
= ToNewCString(val
);
452 transform
->intValue
= val
.ToInteger(&strerr
);
456 transform
->boolValue
= val
.ToInteger(&strerr
) != 0;
462 transform
->prefHasValue
= PR_TRUE
;
463 transform
->prefSetterFunc(transform
, branch
);
464 if (transform
->type
== _OPM(STRING
) && transform
->stringValue
) {
465 NS_Free(transform
->stringValue
);
466 transform
->stringValue
= nsnull
;
472 // Copy Proxy Settings
473 CopyProxySettings(parser
, branch
);
475 // Copy User Content Sheet
477 CopyUserContentSheet(parser
);
483 nsOperaProfileMigrator::CopyProxySettings(nsINIParser
&aParser
,
484 nsIPrefBranch
* aBranch
)
488 PRInt32 networkProxyType
= 0;
490 const char* protocols
[4] = { "HTTP", "HTTPS", "FTP", "GOPHER" };
491 const char* protocols_l
[4] = { "http", "https", "ftp", "gopher" };
492 char toggleBuf
[15], serverBuf
[20], serverPrefBuf
[20],
493 serverPortPrefBuf
[25];
495 for (PRUint32 i
= 0; i
< 4; ++i
) {
496 sprintf(toggleBuf
, "Use %s", protocols
[i
]);
497 GetInteger(aParser
, "Proxy", toggleBuf
, &enabled
);
499 // Enable the "manual configuration" setting if we have at least
500 // one protocol using a Proxy.
501 networkProxyType
= 1;
504 sprintf(serverBuf
, "%s Server", protocols
[i
]);
505 nsCAutoString proxyServer
;
506 rv
= aParser
.GetString("Proxy", serverBuf
, proxyServer
);
510 sprintf(serverPrefBuf
, "network.proxy.%s", protocols_l
[i
]);
511 sprintf(serverPortPrefBuf
, "network.proxy.%s_port", protocols_l
[i
]);
512 // strings in Opera pref. file are in UTF-8
513 SetProxyPref(NS_ConvertUTF8toUTF16(proxyServer
),
514 serverPrefBuf
, serverPortPrefBuf
, aBranch
);
517 GetInteger(aParser
, "Proxy", "Use Automatic Proxy Configuration", &enabled
);
519 networkProxyType
= 2;
521 nsCAutoString configURL
;
522 rv
= aParser
.GetString("Proxy", "Automatic Proxy Configuration URL",
524 if (NS_SUCCEEDED(rv
))
525 aBranch
->SetCharPref("network.proxy.autoconfig_url", configURL
.get());
527 GetInteger(aParser
, "Proxy", "No Proxy Servers Check", &enabled
);
529 nsCAutoString servers
;
530 rv
= aParser
.GetString("Proxy", "No Proxy Servers", servers
);
531 if (NS_SUCCEEDED(rv
))
532 // strings in Opera pref. file are in UTF-8
533 ParseOverrideServers(NS_ConvertUTF8toUTF16(servers
), aBranch
);
536 aBranch
->SetIntPref("network.proxy.type", networkProxyType
);
542 nsOperaProfileMigrator::GetInteger(nsINIParser
&aParser
,
543 const char* aSectionName
,
544 const char* aKeyName
,
549 nsresult rv
= aParser
.GetString(aSectionName
, aKeyName
, val
);
553 *aResult
= val
.ToInteger(&rv
);
560 nsOperaProfileMigrator::ParseColor(nsINIParser
&aParser
,
561 const char* aSectionName
, char** aResult
)
566 rv
= GetInteger(aParser
, aSectionName
, "Red", &r
);
567 rv
|= GetInteger(aParser
, aSectionName
, "Green", &g
);
568 rv
|= GetInteger(aParser
, aSectionName
, "Blue", &b
);
570 return NS_OK
; // This Preference has no value. Bail now before we get in trouble.
572 *aResult
= (char*)malloc(sizeof(char) * 8);
574 return NS_ERROR_OUT_OF_MEMORY
;
576 sprintf(*aResult
, "#%02X%02X%02X", r
, g
, b
);
582 nsOperaProfileMigrator::CopyUserContentSheet(nsINIParser
&aParser
)
586 nsCAutoString userContentCSS
;
587 rv
= aParser
.GetString("User Prefs", "Local CSS File", userContentCSS
);
588 if (NS_FAILED(rv
) || userContentCSS
.Length() == 0)
592 nsCOMPtr
<nsILocalFile
> userContentCSSFile
;
593 rv
= NS_NewNativeLocalFile(userContentCSS
, PR_TRUE
,
594 getter_AddRefs(userContentCSSFile
));
599 rv
= userContentCSSFile
->Exists(&exists
);
600 if (NS_FAILED(rv
) || !exists
)
603 nsCOMPtr
<nsIFile
> profileChromeDir
;
604 NS_GetSpecialDirectory(NS_APP_USER_CHROME_DIR
,
605 getter_AddRefs(profileChromeDir
));
606 if (!profileChromeDir
)
609 userContentCSSFile
->CopyToNative(profileChromeDir
,
610 NS_LITERAL_CSTRING("userContent.css"));
616 nsOperaProfileMigrator::CopyCookies(PRBool aReplace
)
620 nsCOMPtr
<nsIFile
> temp
;
621 mOperaProfile
->Clone(getter_AddRefs(temp
));
622 nsCOMPtr
<nsILocalFile
> historyFile(do_QueryInterface(temp
));
624 historyFile
->Append(OPERA_COOKIES_FILE_NAME
);
626 nsCOMPtr
<nsIInputStream
> fileStream
;
627 NS_NewLocalFileInputStream(getter_AddRefs(fileStream
), historyFile
);
629 return NS_ERROR_OUT_OF_MEMORY
;
631 nsOperaCookieMigrator
* ocm
= new nsOperaCookieMigrator(fileStream
);
633 return NS_ERROR_OUT_OF_MEMORY
;
645 nsOperaCookieMigrator::nsOperaCookieMigrator(nsIInputStream
* aSourceStream
) :
646 mAppVersion(0), mFileVersion(0), mTagTypeLength(0), mPayloadTypeLength(0),
647 mCookieOpen(PR_FALSE
), mCurrHandlingInfo(0)
649 mStream
= do_CreateInstance("@mozilla.org/binaryinputstream;1");
651 mStream
->SetInputStream(aSourceStream
);
653 mCurrCookie
.isSecure
= PR_FALSE
;
654 mCurrCookie
.expiryTime
= 0;
657 nsOperaCookieMigrator::~nsOperaCookieMigrator()
660 mStream
->SetInputStream(nsnull
);
665 nsOperaCookieMigrator::Migrate()
668 return NS_ERROR_FAILURE
;
676 nsCOMPtr
<nsICookieManager2
> manager(do_GetService(NS_COOKIEMANAGER_CONTRACTID
));
677 nsCOMPtr
<nsIPermissionManager
> permissionManager(do_GetService("@mozilla.org/permissionmanager;1"));
680 PRUint16 length
, segmentLength
;
684 if (NS_FAILED(mStream
->Read8(&tag
)))
685 return NS_OK
; // EOF.
688 case BEGIN_DOMAIN_SEGMENT
:
689 mStream
->Read16(&length
);
691 case DOMAIN_COMPONENT
:
693 mStream
->Read16(&length
);
695 mStream
->ReadBytes(length
, &buf
);
696 buf
= (char*)nsMemory::Realloc(buf
, length
+1);
698 mDomainStack
.AppendElement((void*)buf
);
701 case END_DOMAIN_SEGMENT
:
703 if (mCurrHandlingInfo
)
704 AddCookieOverride(permissionManager
);
706 // Pop the domain stack
707 PRUint32 count
= mDomainStack
.Count();
709 char* segment
= (char*)mDomainStack
.ElementAt(count
- 1);
711 nsMemory::Free(segment
);
712 mDomainStack
.RemoveElementAt(count
- 1);
717 case BEGIN_PATH_SEGMENT
:
718 mStream
->Read16(&length
);
722 mStream
->Read16(&length
);
724 mStream
->ReadBytes(length
, &buf
);
725 buf
= (char*)nsMemory::Realloc(buf
, length
+1);
727 mPathStack
.AppendElement((void*)buf
);
730 case END_PATH_SEGMENT
:
732 // Add the last remaining cookie for this path.
736 // We receive one "End Path Segment" even if the path stack is empty
737 // i.e. telling us that we are done processing cookies for "/"
739 // Pop the path stack
740 PRUint32 count
= mPathStack
.Count();
742 char* segment
= (char*)mPathStack
.ElementAt(count
- 1);
744 nsMemory::Free(segment
);
745 mPathStack
.RemoveElementAt(count
- 1);
751 mStream
->Read16(&length
);
752 mStream
->Read8(&mCurrHandlingInfo
);
754 case PATH_HANDLING_INFO
:
755 case THIRD_PARTY_HANDLING_INFO
:
757 mStream
->Read16(&length
);
759 mStream
->Read8(&temp
);
763 case BEGIN_COOKIE_SEGMENT
:
765 // Be sure to save the last cookie before overwriting the buffers
766 // with data from subsequent cookies.
770 mStream
->Read16(&segmentLength
);
771 mCookieOpen
= PR_TRUE
;
776 mStream
->Read16(&length
);
777 mStream
->ReadBytes(length
, &buf
);
778 buf
= (char*)nsMemory::Realloc(buf
, length
+1);
780 mCurrCookie
.id
.Assign(buf
);
789 mStream
->Read16(&length
);
790 mStream
->ReadBytes(length
, &buf
);
791 buf
= (char*)nsMemory::Realloc(buf
, length
+1);
793 mCurrCookie
.data
.Assign(buf
);
801 mStream
->Read16(&length
);
802 mStream
->Read32(reinterpret_cast<PRUint32
*>(&(mCurrCookie
.expiryTime
)));
805 mCurrCookie
.isSecure
= PR_TRUE
;
808 // We don't support any of these fields but we must read them in
809 // to advance the stream cursor.
810 case COOKIE_LASTUSED
:
812 mStream
->Read16(&length
);
814 mStream
->Read32(reinterpret_cast<PRUint32
*>(&temp
));
818 case COOKIE_COMMENT_URL
:
819 case COOKIE_V1_DOMAIN
:
821 case COOKIE_V1_PORT_LIMITATIONS
:
823 mStream
->Read16(&length
);
824 mStream
->ReadBytes(length
, &buf
);
833 mStream
->Read16(&length
);
835 mStream
->Read8(&temp
);
838 case COOKIE_OTHERFLAG_1
:
839 case COOKIE_OTHERFLAG_2
:
840 case COOKIE_OTHERFLAG_3
:
841 case COOKIE_OTHERFLAG_4
:
842 case COOKIE_OTHERFLAG_5
:
843 case COOKIE_OTHERFLAG_6
:
849 // Make sure the path and domain stacks are clear.
850 char* segment
= nsnull
;
852 PRUint32 count
= mPathStack
.Count();
853 for (i
= 0; i
< count
; ++i
) {
854 segment
= (char*)mPathStack
.ElementAt(i
);
856 nsMemory::Free(segment
);
860 count
= mDomainStack
.Count();
861 for (i
= 0; i
< count
; ++i
) {
862 segment
= (char*)mDomainStack
.ElementAt(i
);
864 nsMemory::Free(segment
);
873 nsOperaCookieMigrator::AddCookieOverride(nsIPermissionManager
* aManager
)
878 SynthesizeDomain(getter_Copies(domain
));
879 nsCOMPtr
<nsIURI
> uri(do_CreateInstance("@mozilla.org/network/standard-url;1"));
881 return NS_ERROR_OUT_OF_MEMORY
;
882 uri
->SetHost(domain
);
884 rv
= aManager
->Add(uri
, "cookie",
885 (mCurrHandlingInfo
== 1 || mCurrHandlingInfo
== 3) ? nsIPermissionManager::ALLOW_ACTION
:
886 nsIPermissionManager::DENY_ACTION
);
888 mCurrHandlingInfo
= 0;
895 nsOperaCookieMigrator::AddCookie(nsICookieManager2
* aManager
)
897 // This is where we use the information gathered in all the other
898 // states to add a cookie to the Firebird/Firefox Cookie Manager.
900 SynthesizeDomain(getter_Copies(domain
));
903 SynthesizePath(getter_Copies(path
));
905 mCookieOpen
= PR_FALSE
;
907 nsresult rv
= aManager
->Add(domain
,
911 mCurrCookie
.isSecure
,
912 PR_FALSE
, // isHttpOnly
913 PR_FALSE
, // isSession
914 PRInt64(mCurrCookie
.expiryTime
));
916 mCurrCookie
.isSecure
= 0;
917 mCurrCookie
.expiryTime
= 0;
923 nsOperaCookieMigrator::SynthesizePath(char** aResult
)
925 PRUint32 count
= mPathStack
.Count();
926 nsCAutoString
synthesizedPath("/");
927 for (PRUint32 i
= 0; i
< count
; ++i
) {
928 synthesizedPath
.Append((char*)mPathStack
.ElementAt(i
));
930 synthesizedPath
.Append("/");
932 if (synthesizedPath
.IsEmpty())
933 synthesizedPath
.Assign("/");
935 *aResult
= ToNewCString(synthesizedPath
);
939 nsOperaCookieMigrator::SynthesizeDomain(char** aResult
)
941 PRUint32 count
= mDomainStack
.Count();
945 nsCAutoString synthesizedDomain
;
946 for (PRInt32 i
= (PRInt32
)count
- 1; i
>= 0; --i
) {
947 synthesizedDomain
.Append((char*)mDomainStack
.ElementAt((PRUint32
)i
));
949 synthesizedDomain
.Append(".");
952 *aResult
= ToNewCString(synthesizedDomain
);
956 nsOperaCookieMigrator::ReadHeader()
958 mStream
->Read32(&mAppVersion
);
959 mStream
->Read32(&mFileVersion
);
961 if (mAppVersion
& 0x1000 && mFileVersion
& 0x2000) {
962 mStream
->Read16(&mTagTypeLength
);
963 mStream
->Read16(&mPayloadTypeLength
);
967 return NS_ERROR_FAILURE
;
971 nsOperaProfileMigrator::CopyHistory(PRBool aReplace
)
974 nsCOMPtr
<nsINavHistoryService
> history
= do_GetService(NS_NAVHISTORYSERVICE_CONTRACTID
, &rv
);
975 NS_ENSURE_SUCCESS(rv
, rv
);
977 return history
->RunInBatchMode(this, nsnull
);
981 nsOperaProfileMigrator::RunBatched(nsISupports
* aUserData
)
983 nsCOMPtr
<nsIBrowserHistory
> hist(do_GetService(NS_GLOBALHISTORY2_CONTRACTID
));
985 nsCOMPtr
<nsIFile
> temp
;
986 mOperaProfile
->Clone(getter_AddRefs(temp
));
987 nsCOMPtr
<nsILocalFile
> historyFile(do_QueryInterface(temp
));
988 historyFile
->Append(OPERA_HISTORY_FILE_NAME
);
990 nsCOMPtr
<nsIInputStream
> fileStream
;
991 NS_NewLocalFileInputStream(getter_AddRefs(fileStream
), historyFile
);
992 if (!fileStream
) return NS_ERROR_OUT_OF_MEMORY
;
994 nsCOMPtr
<nsILineInputStream
> lineStream
= do_QueryInterface(fileStream
);
996 nsCAutoString buffer
, url
;
998 PRTime lastVisitDate
;
999 PRBool moreData
= PR_FALSE
;
1001 enum { TITLE
, URL
, LASTVISIT
} state
= TITLE
;
1003 // Format is "title\nurl\nlastvisitdate"
1005 nsresult rv
= lineStream
->ReadLine(buffer
, &moreData
);
1011 CopyUTF8toUTF16(buffer
, title
);
1019 // Opera time format is a second offset, PRTime is a microsecond offset
1021 lastVisitDate
= buffer
.ToInteger(&err
);
1023 PRInt64 temp
, million
;
1024 LL_I2L(temp
, lastVisitDate
);
1025 LL_I2L(million
, PR_USEC_PER_SEC
);
1026 LL_MUL(lastVisitDate
, temp
, million
);
1028 nsCOMPtr
<nsIURI
> uri
;
1029 NS_NewURI(getter_AddRefs(uri
), url
);
1031 hist
->AddPageWithDetails(uri
, title
.get(), lastVisitDate
);
1043 nsOperaProfileMigrator::CopyBookmarks(PRBool aReplace
)
1045 // Find Opera Bookmarks
1046 nsCOMPtr
<nsIFile
> operaBookmarks
;
1047 mOperaProfile
->Clone(getter_AddRefs(operaBookmarks
));
1048 operaBookmarks
->Append(OPERA_BOOKMARKS_FILE_NAME
);
1050 nsCOMPtr
<nsIInputStream
> fileInputStream
;
1051 NS_NewLocalFileInputStream(getter_AddRefs(fileInputStream
), operaBookmarks
);
1052 if (!fileInputStream
) return NS_ERROR_OUT_OF_MEMORY
;
1054 nsCOMPtr
<nsILineInputStream
> lineInputStream(do_QueryInterface(fileInputStream
));
1057 nsCOMPtr
<nsINavBookmarksService
> bms(do_GetService(NS_NAVBOOKMARKSSERVICE_CONTRACTID
, &rv
));
1058 NS_ENSURE_SUCCESS(rv
, rv
);
1060 rv
= bms
->GetBookmarksMenuFolder(&root
);
1061 NS_ENSURE_SUCCESS(rv
, rv
);
1062 PRInt64 parentFolder
= root
;
1064 nsCOMPtr
<nsIStringBundleService
> bundleService(do_GetService(NS_STRINGBUNDLE_CONTRACTID
));
1065 nsCOMPtr
<nsIStringBundle
> bundle
;
1066 bundleService
->CreateBundle(MIGRATION_BUNDLE
, getter_AddRefs(bundle
));
1068 nsString sourceNameOpera
;
1069 bundle
->GetStringFromName(NS_LITERAL_STRING("sourceNameOpera").get(),
1070 getter_Copies(sourceNameOpera
));
1072 const PRUnichar
* sourceNameStrings
[] = { sourceNameOpera
.get() };
1073 nsString importedOperaHotlistTitle
;
1074 bundle
->FormatStringFromName(NS_LITERAL_STRING("importedBookmarksFolder").get(),
1075 sourceNameStrings
, 1,
1076 getter_Copies(importedOperaHotlistTitle
));
1078 bms
->CreateFolder(parentFolder
, NS_ConvertUTF16toUTF8(importedOperaHotlistTitle
),
1079 nsINavBookmarksService::DEFAULT_INDEX
, &parentFolder
);
1082 nsCOMPtr
<nsIFile
> profile
;
1083 GetProfilePath(nsnull
, profile
);
1084 rv
= InitializeBookmarks(profile
);
1085 NS_ENSURE_SUCCESS(rv
, rv
);
1088 #if defined(XP_WIN) || (defined(XP_UNIX) && !defined(XP_MACOSX))
1089 printf("*** about to copy smart keywords\n");
1090 CopySmartKeywords(bms
, bundle
, parentFolder
);
1091 printf("*** done copying smart keywords\n");
1095 rv
= bms
->GetToolbarFolder(&toolbar
);
1096 NS_ENSURE_SUCCESS(rv
, rv
);
1098 rv
= ParseBookmarksFolder(lineInputStream
, parentFolder
, toolbar
, bms
);
1099 NS_ENSURE_SUCCESS(rv
, rv
);
1101 // after importing the favorites,
1102 // we need to set this pref so that on startup
1103 // we don't blow away what we just imported
1104 nsCOMPtr
<nsIPrefBranch
> pref(do_GetService(NS_PREFSERVICE_CONTRACTID
));
1105 NS_ENSURE_TRUE(pref
, NS_ERROR_FAILURE
);
1106 rv
= pref
->SetBoolPref("browser.places.importBookmarksHTML", PR_FALSE
);
1107 NS_ENSURE_SUCCESS(rv
, rv
);
1111 #if defined(XP_WIN) || (defined(XP_UNIX) && !defined(XP_MACOSX))
1113 nsOperaProfileMigrator::CopySmartKeywords(nsINavBookmarksService
* aBMS
,
1114 nsIStringBundle
* aBundle
,
1115 PRInt64 aParentFolder
)
1119 nsCOMPtr
<nsIFile
> smartKeywords
;
1120 mOperaProfile
->Clone(getter_AddRefs(smartKeywords
));
1121 smartKeywords
->Append(NS_LITERAL_STRING("search.ini"));
1123 nsCOMPtr
<nsILocalFile
> lf(do_QueryInterface(smartKeywords
));
1128 rv
= parser
.Init(lf
);
1132 nsString sourceNameOpera
;
1133 aBundle
->GetStringFromName(NS_LITERAL_STRING("sourceNameOpera").get(),
1134 getter_Copies(sourceNameOpera
));
1136 const PRUnichar
* sourceNameStrings
[] = { sourceNameOpera
.get() };
1137 nsString importedSearchUrlsTitle
;
1138 aBundle
->FormatStringFromName(NS_LITERAL_STRING("importedSearchURLsFolder").get(),
1139 sourceNameStrings
, 1,
1140 getter_Copies(importedSearchUrlsTitle
));
1142 PRInt64 keywordsFolder
;
1143 rv
= aBMS
->CreateFolder(aParentFolder
, NS_ConvertUTF16toUTF8(importedSearchUrlsTitle
),
1144 nsINavBookmarksService::DEFAULT_INDEX
, &keywordsFolder
);
1145 NS_ENSURE_SUCCESS(rv
, rv
);
1147 PRInt32 sectionIndex
= 1;
1148 nsCAutoString name
, url
, keyword
;
1150 nsCAutoString
section("Search Engine ");
1151 section
.AppendInt(sectionIndex
++);
1153 rv
= parser
.GetString(section
.get(), "Name", name
);
1157 rv
= parser
.GetString(section
.get(), "URL", url
);
1161 rv
= parser
.GetString(section
.get(), "Key", keyword
);
1166 rv
= GetInteger(parser
, section
.get(), "Is post", &post
);
1167 if (NS_SUCCEEDED(rv
) && post
)
1170 if (url
.IsEmpty() || keyword
.IsEmpty() || name
.IsEmpty())
1173 PRUint32 length
= name
.Length();
1176 index
= name
.FindChar('&', index
);
1177 if (index
>= length
- 2)
1180 // Assume "&&" is an escaped ampersand in the search query title.
1181 if (name
.CharAt(index
+ 1) == '&') {
1189 while (index
< length
);
1191 nsCOMPtr
<nsIURI
> uri
;
1192 NS_NewURI(getter_AddRefs(uri
), url
.get());
1194 return NS_ERROR_OUT_OF_MEMORY
;
1196 nsCAutoString hostCStr
;
1197 uri
->GetHost(hostCStr
);
1198 NS_ConvertASCIItoUTF16
host(hostCStr
);
1200 const PRUnichar
* descStrings
[] = { NS_ConvertUTF8toUTF16(keyword
).get(), host
.get() };
1201 nsString keywordDesc
;
1202 aBundle
->FormatStringFromName(NS_LITERAL_STRING("importedSearchUrlDesc").get(),
1203 descStrings
, 2, getter_Copies(keywordDesc
));
1206 rv
= aBMS
->InsertBookmark(keywordsFolder
, uri
,
1207 nsINavBookmarksService::DEFAULT_INDEX
,
1209 NS_ENSURE_SUCCESS(rv
, rv
);
1210 // TODO -- set bookmark keyword to keyword and description to keywordDesc.
1218 typedef enum { LineType_FOLDER
,
1224 LineType_DESCRIPTION
,
1227 LineType_OTHER
} LineType
;
1229 static LineType
GetLineType(nsAString
& aBuffer
, PRUnichar
** aData
)
1231 if (Substring(aBuffer
, 0, 7).Equals(NS_LITERAL_STRING("#FOLDER")))
1232 return LineType_FOLDER
;
1233 if (Substring(aBuffer
, 0, 4).Equals(NS_LITERAL_STRING("#URL")))
1234 return LineType_BOOKMARK
;
1235 if (Substring(aBuffer
, 0, 1).Equals(NS_LITERAL_STRING("-")))
1236 return LineType_SEPARATOR
;
1237 if (Substring(aBuffer
, 1, 5).Equals(NS_LITERAL_STRING("NAME="))) {
1238 const nsAString
& data
= Substring(aBuffer
, 6, aBuffer
.Length() - 6);
1239 *aData
= ToNewUnicode(data
);
1240 return LineType_NAME
;
1242 if (Substring(aBuffer
, 1, 4).Equals(NS_LITERAL_STRING("URL="))) {
1243 const nsAString
& data
= Substring(aBuffer
, 5, aBuffer
.Length() - 5);
1244 *aData
= ToNewUnicode(data
);
1245 return LineType_URL
;
1247 if (Substring(aBuffer
, 1, 12).Equals(NS_LITERAL_STRING("DESCRIPTION="))) {
1248 const nsAString
& data
= Substring(aBuffer
, 13, aBuffer
.Length() - 13);
1249 *aData
= ToNewUnicode(data
);
1250 return LineType_DESCRIPTION
;
1252 if (Substring(aBuffer
, 1, 11).Equals(NS_LITERAL_STRING("SHORT NAME="))) {
1253 const nsAString
& data
= Substring(aBuffer
, 12, aBuffer
.Length() - 12);
1254 *aData
= ToNewUnicode(data
);
1255 return LineType_KEYWORD
;
1257 if (Substring(aBuffer
, 1, 15).Equals(NS_LITERAL_STRING("ON PERSONALBAR="))) {
1258 const nsAString
& data
= Substring(aBuffer
, 16, aBuffer
.Length() - 16);
1259 *aData
= ToNewUnicode(data
);
1260 return LineType_ONTOOLBAR
;
1262 if (aBuffer
.IsEmpty())
1263 return LineType_NL
; // Newlines separate bookmarks
1264 return LineType_OTHER
;
1267 typedef enum { EntryType_BOOKMARK
, EntryType_FOLDER
} EntryType
;
1270 nsOperaProfileMigrator::ParseBookmarksFolder(nsILineInputStream
* aStream
,
1273 nsINavBookmarksService
* aBMS
)
1276 PRBool moreData
= PR_FALSE
;
1277 nsAutoString buffer
;
1278 EntryType entryType
= EntryType_BOOKMARK
;
1279 nsAutoString keyword
, description
;
1280 nsCAutoString url
, name
;
1281 PRBool onToolbar
= PR_FALSE
;
1283 nsCAutoString cBuffer
;
1284 rv
= aStream
->ReadLine(cBuffer
, &moreData
);
1285 if (NS_FAILED(rv
)) return rv
;
1287 CopyUTF8toUTF16(cBuffer
, buffer
);
1289 LineType type
= GetLineType(buffer
, getter_Copies(data
));
1291 case LineType_FOLDER
:
1292 entryType
= EntryType_FOLDER
;
1294 case LineType_BOOKMARK
:
1295 entryType
= EntryType_BOOKMARK
;
1297 case LineType_SEPARATOR
:
1298 // If we're here, we need to break out of the loop for the current folder,
1299 // essentially terminating this instance of ParseBookmarksFolder and return
1300 // to the calling function, which is either ParseBookmarksFolder for a parent
1301 // folder, or CopyBookmarks (which means we're done parsing all bookmarks).
1304 name
.Assign(NS_ConvertUTF16toUTF8(data
));
1307 url
.Assign(NS_ConvertUTF16toUTF8(data
));
1309 case LineType_KEYWORD
:
1312 case LineType_DESCRIPTION
:
1315 case LineType_ONTOOLBAR
:
1316 if (NS_LITERAL_STRING("YES").Equals(data
))
1317 onToolbar
= PR_TRUE
;
1320 // XXX We don't know for sure how Opera deals with IDN hostnames in URL.
1321 // Assuming it's in UTF-8 is rather safe because it covers two cases
1322 // (UTF-8 and ASCII) out of three cases (the last is a non-UTF-8
1323 // multibyte encoding).
1324 // XXX Todo: |description| is not saved.
1325 if (entryType
== EntryType_BOOKMARK
) {
1326 if (!name
.IsEmpty() && !url
.IsEmpty()) {
1327 nsCOMPtr
<nsIURI
> uri
;
1328 rv
= NS_NewURI(getter_AddRefs(uri
), url
);
1332 rv
= aBMS
->InsertBookmark(onToolbar
? aToolbar
: aParent
,
1333 uri
, nsINavBookmarksService::DEFAULT_INDEX
,
1340 description
.Truncate();
1341 onToolbar
= PR_FALSE
;
1344 else if (entryType
== EntryType_FOLDER
) {
1345 if (!name
.IsEmpty()) {
1347 rv
= aBMS
->CreateFolder(onToolbar
? aToolbar
: aParent
,
1348 name
, nsINavBookmarksService::DEFAULT_INDEX
, &newFolder
);
1351 rv
= ParseBookmarksFolder(aStream
, newFolder
, aToolbar
, aBMS
);
1357 case LineType_OTHER
:
1368 nsOperaProfileMigrator::GetOperaProfile(const PRUnichar
* aProfile
, nsILocalFile
** aFile
)
1370 nsCOMPtr
<nsIProperties
> fileLocator(do_GetService("@mozilla.org/file/directory_service;1"));
1371 nsCOMPtr
<nsILocalFile
> file
;
1373 fileLocator
->Get(NS_WIN_APPDATA_DIR
, NS_GET_IID(nsILocalFile
), getter_AddRefs(file
));
1375 // Opera profile lives under %APP_DATA%\Opera\<operaver>\profile
1376 file
->Append(OPERA_PREFERENCES_FOLDER_NAME
);
1377 file
->Append(nsDependentString(aProfile
));
1378 file
->Append(NS_LITERAL_STRING("profile"));
1379 #elif defined (XP_MACOSX)
1380 fileLocator
->Get(NS_MAC_USER_LIB_DIR
, NS_GET_IID(nsILocalFile
), getter_AddRefs(file
));
1382 file
->Append(NS_LITERAL_STRING("Preferences"));
1383 file
->Append(OPERA_PREFERENCES_FOLDER_NAME
);
1384 #elif defined (XP_UNIX)
1385 fileLocator
->Get(NS_UNIX_HOME_DIR
, NS_GET_IID(nsILocalFile
), getter_AddRefs(file
));
1387 file
->Append(OPERA_PREFERENCES_FOLDER_NAME
);