nsresult nsOperaProfileMigrator::ParseBookmarksFolder(nsILineInputStream* aStream, PRInt64 aParent, PRInt64 aToolbar, nsINavBookmarksService* aBMS) { nsresult rv; PRBool moreData = PR_FALSE; nsAutoString buffer; EntryType entryType = EntryType_BOOKMARK; nsAutoString keyword, description; nsCAutoString url, name; PRBool onToolbar = PR_FALSE; do { nsCAutoString cBuffer; rv = aStream->ReadLine(cBuffer, &moreData); if (NS_FAILED(rv)) return rv; CopyUTF8toUTF16(cBuffer, buffer); nsString data; LineType type = GetLineType(buffer, getter_Copies(data)); switch(type) { case LineType_FOLDER: entryType = EntryType_FOLDER; break; case LineType_BOOKMARK: entryType = EntryType_BOOKMARK; break; case LineType_SEPARATOR: // If we're here, we need to break out of the loop for the current folder, // essentially terminating this instance of ParseBookmarksFolder and return // to the calling function, which is either ParseBookmarksFolder for a parent // folder, or CopyBookmarks (which means we're done parsing all bookmarks). goto done; case LineType_NAME: name.Assign(NS_ConvertUTF16toUTF8(data)); break; case LineType_URL: url.Assign(NS_ConvertUTF16toUTF8(data)); break; case LineType_KEYWORD: keyword = data; break; case LineType_DESCRIPTION: description = data; break; case LineType_ONTOOLBAR: if (NS_LITERAL_STRING("YES").Equals(data)) onToolbar = PR_TRUE; break; case LineType_NL: { // XXX We don't know for sure how Opera deals with IDN hostnames in URL. // Assuming it's in UTF-8 is rather safe because it covers two cases // (UTF-8 and ASCII) out of three cases (the last is a non-UTF-8 // multibyte encoding). // XXX Todo: |description| is not saved. if (entryType == EntryType_BOOKMARK) { if (!name.IsEmpty() && !url.IsEmpty()) { nsCOMPtr<nsIURI> uri; rv = NS_NewURI(getter_AddRefs(uri), url); if (NS_FAILED(rv)) continue; PRInt64 id; rv = aBMS->InsertBookmark(onToolbar ? aToolbar : aParent, uri, nsINavBookmarksService::DEFAULT_INDEX, name, &id); if (NS_FAILED(rv)) continue; name.Truncate(); url.Truncate(); keyword.Truncate(); description.Truncate(); onToolbar = PR_FALSE; } } else if (entryType == EntryType_FOLDER) { if (!name.IsEmpty()) { PRInt64 newFolder; rv = aBMS->CreateFolder(onToolbar ? aToolbar : aParent, name, nsINavBookmarksService::DEFAULT_INDEX, &newFolder); if (NS_FAILED(rv)) continue; rv = ParseBookmarksFolder(aStream, newFolder, aToolbar, aBMS); name.Truncate(); } } break; } case LineType_OTHER: break; } } while (moreData); done: return rv; }
nsresult nsOperaProfileMigrator::CopyBookmarksBatched(PRBool aReplace) { // Find Opera Bookmarks nsCOMPtr<nsIFile> operaBookmarks; mOperaProfile->Clone(getter_AddRefs(operaBookmarks)); operaBookmarks->Append(OPERA_BOOKMARKS_FILE_NAME); nsCOMPtr<nsIInputStream> fileInputStream; NS_NewLocalFileInputStream(getter_AddRefs(fileInputStream), operaBookmarks); NS_ENSURE_TRUE(fileInputStream, NS_ERROR_OUT_OF_MEMORY); nsCOMPtr<nsILineInputStream> lineInputStream(do_QueryInterface(fileInputStream)); nsresult rv; nsCOMPtr<nsINavBookmarksService> bms = do_GetService(NS_NAVBOOKMARKSSERVICE_CONTRACTID, &rv); NS_ENSURE_SUCCESS(rv, rv); PRInt64 bookmarksMenuFolderId; rv = bms->GetBookmarksMenuFolder(&bookmarksMenuFolderId); NS_ENSURE_SUCCESS(rv, rv); PRInt64 parentFolder = bookmarksMenuFolderId; nsCOMPtr<nsIStringBundleService> bundleService = do_GetService(NS_STRINGBUNDLE_CONTRACTID, &rv); NS_ENSURE_SUCCESS(rv, rv); nsCOMPtr<nsIStringBundle> bundle; rv = bundleService->CreateBundle(MIGRATION_BUNDLE, getter_AddRefs(bundle)); NS_ENSURE_SUCCESS(rv, rv); if (!aReplace) { nsString sourceNameOpera; rv = bundle->GetStringFromName(NS_LITERAL_STRING("sourceNameOpera").get(), getter_Copies(sourceNameOpera)); NS_ENSURE_SUCCESS(rv, rv); const PRUnichar* sourceNameStrings[] = { sourceNameOpera.get() }; nsString importedOperaHotlistTitle; rv = bundle->FormatStringFromName(NS_LITERAL_STRING("importedBookmarksFolder").get(), sourceNameStrings, 1, getter_Copies(importedOperaHotlistTitle)); NS_ENSURE_SUCCESS(rv, rv); rv = bms->CreateFolder(parentFolder, NS_ConvertUTF16toUTF8(importedOperaHotlistTitle), nsINavBookmarksService::DEFAULT_INDEX, &parentFolder); NS_ENSURE_SUCCESS(rv, rv); } else { nsCOMPtr<nsIFile> profile; GetProfilePath(nsnull, profile); rv = InitializeBookmarks(profile); NS_ENSURE_SUCCESS(rv, rv); } #if defined(XP_WIN) || (defined(XP_UNIX) && !defined(XP_MACOSX)) CopySmartKeywords(bms, bundle, parentFolder); #endif PRInt64 bookmarksToolbarFolderId; rv = bms->GetToolbarFolder(&bookmarksToolbarFolderId); NS_ENSURE_SUCCESS(rv, rv); rv = ParseBookmarksFolder(lineInputStream, parentFolder, bookmarksToolbarFolderId, bms); NS_ENSURE_SUCCESS(rv, rv); return NS_OK; }
nsresult nsSafariProfileMigrator::CopyBookmarksBatched(bool aReplace) { // If "aReplace" is true, merge into the root level of bookmarks. Otherwise, create // a folder called "Imported Safari Favorites" and place all the Bookmarks there. nsresult rv; nsCOMPtr<nsINavBookmarksService> bms = do_GetService(NS_NAVBOOKMARKSSERVICE_CONTRACTID, &rv); NS_ENSURE_SUCCESS(rv, rv); PRInt64 bookmarksMenuFolderId; rv = bms->GetBookmarksMenuFolder(&bookmarksMenuFolderId); NS_ENSURE_SUCCESS(rv, rv); PRInt64 folder; if (!aReplace) { nsCOMPtr<nsIStringBundleService> bundleService = do_GetService(NS_STRINGBUNDLE_CONTRACTID, &rv); NS_ENSURE_SUCCESS(rv, rv); nsCOMPtr<nsIStringBundle> bundle; rv = bundleService->CreateBundle(MIGRATION_BUNDLE, getter_AddRefs(bundle)); NS_ENSURE_SUCCESS(rv, rv); nsString sourceNameSafari; rv = bundle->GetStringFromName(NS_LITERAL_STRING("sourceNameSafari").get(), getter_Copies(sourceNameSafari)); NS_ENSURE_SUCCESS(rv, rv); const PRUnichar* sourceNameStrings[] = { sourceNameSafari.get() }; nsString importedSafariBookmarksTitle; rv = bundle->FormatStringFromName(NS_LITERAL_STRING("importedBookmarksFolder").get(), sourceNameStrings, 1, getter_Copies(importedSafariBookmarksTitle)); NS_ENSURE_SUCCESS(rv, rv); rv = bms->CreateFolder(bookmarksMenuFolderId, NS_ConvertUTF16toUTF8(importedSafariBookmarksTitle), nsINavBookmarksService::DEFAULT_INDEX, &folder); NS_ENSURE_SUCCESS(rv, rv); } else { nsCOMPtr<nsIFile> profile; GetProfilePath(nsnull, profile); rv = InitializeBookmarks(profile); NS_ENSURE_SUCCESS(rv, rv); // In replace mode we are merging at the top level. folder = bookmarksMenuFolderId; } nsCOMPtr<nsIProperties> fileLocator(do_GetService(NS_DIRECTORY_SERVICE_CONTRACTID)); nsCOMPtr<nsILocalFile> safariBookmarksFile; fileLocator->Get(NS_MAC_USER_LIB_DIR, NS_GET_IID(nsILocalFile), getter_AddRefs(safariBookmarksFile)); safariBookmarksFile->Append(NS_LITERAL_STRING("Safari")); safariBookmarksFile->Append(SAFARI_BOOKMARKS_FILE_NAME); CFDictionaryRef safariBookmarks = static_cast<CFDictionaryRef>(CopyPListFromFile(safariBookmarksFile)); if (!safariBookmarks) return NS_OK; // The Safari Bookmarks file looks like this: // At the top level are all the Folders, Special Folders and Proxies. Proxies // are references to other data sources such as History, Rendezvous etc. // We ignore these. Special folders exist for the Bookmarks Toolbar folder // (called "BookmarksBar" and the Bookmarks Menu (called "BookmarksMenu"). // We put the contents of the "BookmarksBar" folder into our Personal Toolbar // and merge the contents of the "BookmarksMenu" folder and the other toplevel // non-special folders under our NC:BookmarksRoot. if (::CFDictionaryContainsKey(safariBookmarks, CFSTR("Children")) && ::CFDictionaryContainsKey(safariBookmarks, CFSTR("WebBookmarkFileVersion")) ) { CFNumberRef intValue = (CFNumberRef)::CFDictionaryGetValue(safariBookmarks, CFSTR("WebBookmarkFileVersion")); PRInt32 value = 0; if (::CFNumberGetValue(intValue, kCFNumberSInt32Type, &value) && value ==1) { CFArrayRef children = (CFArrayRef)::CFDictionaryGetValue(safariBookmarks, CFSTR("Children")); if (children) { rv = ParseBookmarksFolder(children, folder, bms, true); } } } ::CFRelease(safariBookmarks); return rv; }
nsresult nsSafariProfileMigrator::ParseBookmarksFolder(CFArrayRef aChildren, PRInt64 aParentFolder, nsINavBookmarksService * aBookmarksService, bool aIsAtRootLevel) { nsresult rv = NS_OK; CFIndex count = ::CFArrayGetCount(aChildren); for (PRInt32 i = 0; i < count; ++i) { CFDictionaryRef entry = (CFDictionaryRef)::CFArrayGetValueAtIndex(aChildren, i); nsAutoString type; if (!GetDictionaryStringValue(entry, CFSTR("WebBookmarkType"), type)) continue; if (!type.EqualsLiteral("WebBookmarkTypeList") && !type.EqualsLiteral("WebBookmarkTypeLeaf")) continue; if (::CFDictionaryContainsKey(entry, CFSTR("Children")) && type.EqualsLiteral("WebBookmarkTypeList")) { nsAutoString title; if (!GetDictionaryStringValue(entry, CFSTR("Title"), title)) continue; CFArrayRef children = (CFArrayRef)::CFDictionaryGetValue(entry, CFSTR("Children")); // Look for the BookmarksBar Bookmarks and add them into the appropriate // Personal Toolbar Root if (title.EqualsLiteral("BookmarksBar") && aIsAtRootLevel) { PRInt64 toolbarFolder; aBookmarksService->GetToolbarFolder(&toolbarFolder); rv |= ParseBookmarksFolder(children, toolbarFolder, aBookmarksService, false); } // Look for the BookmarksMenu Bookmarks and flatten them into the top level else if (title.EqualsLiteral("BookmarksMenu") && aIsAtRootLevel) { rv |= ParseBookmarksFolder(children, aParentFolder, aBookmarksService, true); } else { // Encountered a Folder, so create one in our Bookmarks DataSource and then // parse the contents of the Safari one into it... PRInt64 folder; rv |= aBookmarksService->CreateFolder(aParentFolder, NS_ConvertUTF16toUTF8(title), nsINavBookmarksService::DEFAULT_INDEX, &folder); rv |= ParseBookmarksFolder(children, folder, aBookmarksService, false); } } else if (type.EqualsLiteral("WebBookmarkTypeLeaf")) { // Encountered a Bookmark, so add it to the current folder... CFDictionaryRef URIDictionary = (CFDictionaryRef) ::CFDictionaryGetValue(entry, CFSTR("URIDictionary")); nsAutoString title; nsCAutoString url; if (GetDictionaryStringValue(URIDictionary, CFSTR("title"), title) && GetDictionaryCStringValue(entry, CFSTR("URLString"), url, kCFStringEncodingUTF8)) { nsCOMPtr<nsIURI> uri; rv = NS_NewURI(getter_AddRefs(uri), url); if (NS_SUCCEEDED(rv)) { PRInt64 id; rv = aBookmarksService->InsertBookmark(aParentFolder, uri, nsINavBookmarksService::DEFAULT_INDEX, NS_ConvertUTF16toUTF8(title), &id); } } } } return rv; }
nsresult nsSafariProfileMigrator::ParseBookmarksFolder(CFArrayRef aChildren, #ifdef MOZ_PLACES PRInt64 aParentFolder, nsINavBookmarksService * aBookmarksService, #else nsIRDFResource* aParentResource, nsIBookmarksService* aBookmarksService, #endif PRBool aIsAtRootLevel) { nsresult rv; CFIndex count = ::CFArrayGetCount(aChildren); for (PRInt32 i = 0; i < count; ++i) { CFDictionaryRef entry = (CFDictionaryRef)::CFArrayGetValueAtIndex(aChildren, i); nsAutoString type; if (!GetDictionaryStringValue(entry, CFSTR("WebBookmarkType"), type)) continue; if (!type.EqualsLiteral("WebBookmarkTypeList") && !type.EqualsLiteral("WebBookmarkTypeLeaf")) continue; if (::CFDictionaryContainsKey(entry, CFSTR("Children")) && type.EqualsLiteral("WebBookmarkTypeList")) { nsAutoString title; if (!GetDictionaryStringValue(entry, CFSTR("Title"), title)) continue; CFArrayRef children = (CFArrayRef)::CFDictionaryGetValue(entry, CFSTR("Children")); // Look for the BookmarksBar Bookmarks and add them into the appropriate // Personal Toolbar Root if (title.EqualsLiteral("BookmarksBar") && aIsAtRootLevel) { #ifdef MOZ_PLACES PRInt64 toolbarFolder; aBookmarksService->GetToolbarRoot(&toolbarFolder); #else nsCOMPtr<nsIRDFResource> toolbarFolder; aBookmarksService->GetBookmarksToolbarFolder(getter_AddRefs(toolbarFolder)); #endif rv |= ParseBookmarksFolder(children, toolbarFolder, aBookmarksService, PR_FALSE); } // Look for the BookmarksMenu Bookmarks and flatten them into the top level else if (title.EqualsLiteral("BookmarksMenu") && aIsAtRootLevel) { rv |= ParseBookmarksFolder(children, #ifdef MOZ_PLACES aParentFolder, #else aParentResource, #endif aBookmarksService, PR_TRUE); } else { // Encountered a Folder, so create one in our Bookmarks DataSource and then // parse the contents of the Safari one into it... #ifdef MOZ_PLACES PRInt64 folder; rv |= aBookmarksService->CreateFolder(aParentFolder, title, -1, &folder); #else nsCOMPtr<nsIRDFResource> folder; rv |= aBookmarksService->CreateFolderInContainer(title.get(), aParentResource, -1, getter_AddRefs(folder)); #endif rv |= ParseBookmarksFolder(children, folder, aBookmarksService, PR_FALSE); } } else if (type.EqualsLiteral("WebBookmarkTypeLeaf")) { // Encountered a Bookmark, so add it to the current folder... CFDictionaryRef URIDictionary = (CFDictionaryRef) ::CFDictionaryGetValue(entry, CFSTR("URIDictionary")); nsAutoString title, url; if (GetDictionaryStringValue(URIDictionary, CFSTR("title"), title) && GetDictionaryStringValue(entry, CFSTR("URLString"), url)) { #ifdef MOZ_PLACES nsCOMPtr<nsIURI> uri; rv |= NS_NewURI(getter_AddRefs(uri), url); rv |= aBookmarksService->InsertItem(aParentFolder, uri, -1); rv |= aBookmarksService->SetItemTitle(uri, title); #else nsCOMPtr<nsIRDFResource> bookmark; rv |= aBookmarksService->CreateBookmarkInContainer(title.get(), url.get(), nsnull, nsnull, nsnull, nsnull, aParentResource, -1, getter_AddRefs(bookmark)); #endif } } } return rv; }
nsresult nsSafariProfileMigrator::CopyBookmarks(PRBool aReplace) { // If "aReplace" is true, merge into the root level of bookmarks. Otherwise, create // a folder called "Imported IE Favorites" and place all the Bookmarks there. nsresult rv; #ifdef MOZ_PLACES nsCOMPtr<nsINavBookmarksService> bms(do_GetService(NS_NAVBOOKMARKSSERVICE_CONTRACTID, &rv)); NS_ENSURE_SUCCESS(rv, rv); PRInt64 root; rv = bms->GetBookmarksRoot(&root); NS_ENSURE_SUCCESS(rv, rv); PRInt64 folder; #else nsCOMPtr<nsIRDFService> rdf(do_GetService("@mozilla.org/rdf/rdf-service;1")); nsCOMPtr<nsIRDFResource> root; rdf->GetResource(NS_LITERAL_CSTRING("NC:BookmarksRoot"), getter_AddRefs(root)); nsCOMPtr<nsIBookmarksService> bms(do_GetService("@mozilla.org/browser/bookmarks-service;1")); NS_ENSURE_TRUE(bms, NS_ERROR_FAILURE); PRBool dummy; bms->ReadBookmarks(&dummy); nsCOMPtr<nsIRDFResource> folder; #endif if (!aReplace) { nsCOMPtr<nsIStringBundleService> bundleService = do_GetService(kStringBundleServiceCID, &rv); if (NS_FAILED(rv)) return rv; nsCOMPtr<nsIStringBundle> bundle; bundleService->CreateBundle(MIGRATION_BUNDLE, getter_AddRefs(bundle)); nsXPIDLString sourceNameSafari; bundle->GetStringFromName(NS_LITERAL_STRING("sourceNameSafari").get(), getter_Copies(sourceNameSafari)); const PRUnichar* sourceNameStrings[] = { sourceNameSafari.get() }; nsXPIDLString importedSafariBookmarksTitle; bundle->FormatStringFromName(NS_LITERAL_STRING("importedBookmarksFolder").get(), sourceNameStrings, 1, getter_Copies(importedSafariBookmarksTitle)); #ifdef MOZ_PLACES bms->CreateFolder(root, importedSafariBookmarksTitle, -1, &folder); #else bms->CreateFolderInContainer(importedSafariBookmarksTitle.get(), root, -1, getter_AddRefs(folder)); #endif } else { // In non-replace mode we are merging at the top level. folder = root; } nsCOMPtr<nsIProperties> fileLocator(do_GetService(NS_DIRECTORY_SERVICE_CONTRACTID)); nsCOMPtr<nsILocalFile> safariBookmarksFile; fileLocator->Get(NS_MAC_USER_LIB_DIR, NS_GET_IID(nsILocalFile), getter_AddRefs(safariBookmarksFile)); safariBookmarksFile->Append(NS_LITERAL_STRING("Safari")); safariBookmarksFile->Append(SAFARI_BOOKMARKS_FILE_NAME); CFDictionaryRef safariBookmarks = (CFDictionaryRef)CopyPListFromFile(safariBookmarksFile); if (!safariBookmarks) return NS_OK; // The Safari Bookmarks file looks like this: // At the top level are all the Folders, Special Folders and Proxies. Proxies // are references to other data sources such as History, Rendezvous etc. // We ignore these. Special folders exist for the Bookmarks Toolbar folder // (called "BookmarksBar" and the Bookmarks Menu (called "BookmarksMenu"). // We put the contents of the "BookmarksBar" folder into our Personal Toolbar // and merge the contents of the "BookmarksMenu" folder and the other toplevel // non-special folders under our NC:BookmarksRoot. if (!::CFDictionaryContainsKey(safariBookmarks, CFSTR("Children")) || !::CFDictionaryContainsKey(safariBookmarks, CFSTR("WebBookmarkFileVersion")) ) { ::CFRelease(safariBookmarks); return NS_OK; } CFNumberRef intValue = (CFNumberRef)::CFDictionaryGetValue(safariBookmarks, CFSTR("WebBookmark" \ "FileVersion")); PRInt32 value = 0; if (!::CFNumberGetValue(intValue, kCFNumberSInt32Type, &value) || value != 1) return NS_OK; CFArrayRef children = (CFArrayRef)::CFDictionaryGetValue(safariBookmarks, CFSTR("Children")); if (children) { nsresult rv = ParseBookmarksFolder(children, folder, bms, PR_TRUE); if (NS_FAILED(rv)) return rv; } ::CFRelease(safariBookmarks); return NS_OK; }