migration-assistant-0.6.13/0000775000000000000000000000000013035341452012471 5ustar migration-assistant-0.6.13/README0000664000000000000000000000023111732445313013350 0ustar This program will enable the user to migrate the documents and settings from the previously installed operating system to their new Debian-based system. migration-assistant-0.6.13/debian/0000775000000000000000000000000013035341452013713 5ustar migration-assistant-0.6.13/debian/migration-assistant.postinst0000664000000000000000000000002511732445313021520 0ustar #!/bin/sh -e ma-ask migration-assistant-0.6.13/debian/changelog0000664000000000000000000002355613035341452015600 0ustar migration-assistant (0.6.13) zesty; urgency=medium * debian/compat: Bump to 10. * debian/control: - Build-depend on debhelper (>= 10). - Depend on ${misc:Depends}. - Bump Standards-Version to 3.9.8. * debian/rules: - Add recommended build-arch and build-indep targets. - Use dh_prep instead of dh_clean -k. * Makefile: Pass in {C,CPP,LD}FLAGS to compiler commands for hardening. * {ma-search-users,search-items}.c: Add format argument to printf(). -- Logan Rosen Wed, 11 Jan 2017 00:31:22 -0500 migration-assistant (0.6.12) precise; urgency=low * Call os-prober with WINOSDATA set to true so that we only get a list of Windows partitions containing the OS instead of only these containing the boot record. (LP: #772470) -- Stéphane Graber Wed, 04 Apr 2012 18:38:32 -0400 migration-assistant (0.6.11) precise; urgency=low * Fix a syntax error (LP: #930676). Thanks Colin Watson. -- Evan Dandrea Wed, 21 Mar 2012 21:44:35 +0000 migration-assistant (0.6.10) natty; urgency=low * Filter out the target filesystem from consideration (LP: #754778). -- Evan Dandrea Tue, 12 Apr 2011 16:17:18 +0100 migration-assistant (0.6.9) natty; urgency=low * Reuse os-prober's newns to ensure that mounts are occuring in a new namespace (LP: #739400). -- Evan Dandrea Mon, 28 Mar 2011 12:58:14 +0100 migration-assistant (0.6.8) natty; urgency=low * Fix linking to libxml2. -- Evan Dandrea Fri, 19 Nov 2010 17:02:15 +0000 migration-assistant (0.6.7) maverick; urgency=low * No change upload for Maverick. -- Evan Dandrea Tue, 29 Jun 2010 16:15:57 +0100 migration-assistant (0.6.6) lucid-proposed; urgency=low * unmount_os can be called without arguments (LP: #536673). -- Evan Dandrea Thu, 29 Apr 2010 09:53:21 +0100 migration-assistant (0.6.5) lucid; urgency=low * Skip comments in /etc/fstab (LP 536673). * Catch empty arguments to unmount_os (LP 536673). * Continue to the next operating system if mount_os fails. * Clean up mount_os. -- Evan Dandrea Fri, 23 Apr 2010 15:26:23 +0100 migration-assistant (0.6.4build1) lucid; urgency=low * rebuild rest of main for armel armv7/thumb2 optimization; UbuntuSpec:mobile-lucid-arm-gcc-v7-thumb2 -- Alexander Sack Sun, 07 Mar 2010 00:57:04 +0100 migration-assistant (0.6.4) jaunty; urgency=low * If there are no items to import, don't bother asking the question. This supports a change to ubiquity to not always show the migration- assistant page. -- Evan Dandrea Thu, 09 Apr 2009 10:34:46 +0100 migration-assistant (0.6.3) jaunty; urgency=low * Rename Gaim to Pidgin. Thanks Mike Rooney (LP: #224797). * Do not force chpasswd to md5 crypt passwords (LP: #51551). -- Evan Dandrea Thu, 09 Apr 2009 10:26:16 +0100 migration-assistant (0.6.2) intrepid; urgency=low * Several fixes from Olivier Blin of Mandriva: - Close file descriptors when they're no longer needed. - Move a closedir() call, it can free data returned by readdir() too early. It leads to path corruption in some cases. - Fix a segfault with files with no extension. - Remove a spurious directory creation, with uninitialized name. - Fix Windows 2000 migration, by not trying to import music if not present. - Fix detection of Windows-NT-like registry path in ma-search-users, by splitting and reusing WINNT code from utils.c - Reimplement copy using read/write (like cp) to handle large files, since we can't mmap() (twice) large files in memory. - fix segfault by zeroing buffers for strcat. - Improve WINNT patch to factorize user registry location as well. - Vista profile directories support. Get profiles directory from registry for ma-search-items and ma-import as well ("Documents and Settings" is not correct in Vista), this also allows us to read the user registries. - Vista users support. Filter Public and Default users for Vista (from registry keys). Filter "Default User" key in Vista (it is a junction to Default). Do not segfault if keys are missing. * More efficient and less error-prone device substring extraction. * Set the locale to C when using expr. -- Evan Dandrea Tue, 27 May 2008 14:07:31 -0400 migration-assistant (0.6.1) hardy; urgency=low * Use + instead of : for a replacement character as it is explicitly allowed by debconf policy. * Look in .purple for Pidgin settings as well. -- Evan Dandrea Mon, 07 Apr 2008 11:16:20 -0400 migration-assistant (0.6.0) hardy; urgency=low * Copy NTFS mount fix. * Removed dead ubiquity-specific code in ma-ask. * Cleaned up ma-ask and ma-apply. * Fix potential bugs where RET could get set to an error description and then be used as the answer to other questions. * Add the user to the groups specified by user-setup-udeb. -- Evan Dandrea Thu, 24 Jan 2008 09:25:41 +0000 migration-assistant (0.5.4) gutsy; urgency=low * Added a short timeout and retry to unmounting to accomodate slow umounts (LP: #135149). -- Evan Dandrea Mon, 15 Oct 2007 11:54:33 -0400 migration-assistant (0.5.3) gutsy; urgency=low * Move initialize_registry_paths call later to avoid situations where other needed variables may not be set yet, causing m-a to fail. * Fix logging. * Fix IFS handling around call to expr. -- Evan Dandrea Tue, 09 Oct 2007 10:58:09 -0400 migration-assistant (0.5.2) gutsy; urgency=low * Fix IFS handling (LP: #145712, #135149) -- Evan Dandrea Wed, 03 Oct 2007 22:27:20 -0400 migration-assistant (0.5.1) gutsy; urgency=low [ Colin Watson ] * In the Windows case in mount_os: - Look in /proc/mounts, not /proc/partitions. - Look in /proc/mounts before /etc/mtab. - Make sure to select only the first mountpoint for a given device (in case of bind mounts). -- Evan Dandrea Fri, 21 Sep 2007 21:48:48 -0400 migration-assistant (0.5.0) gutsy; urgency=low * Handle more than one installed copy of Windows (LP: #97081). * Error if unable to mount Linux partitions. * Bump installer-menu-item to 6400. * Close directories in ma-search-users. * Don't unmount devices when we can avoid having to. * Look for registry files case-insensitively. * Quote arguments to add_user (LP: #123425). * Use stat instead of the DT_ macros to avoid issues with fuse. * Add a debug log. -- Evan Dandrea Tue, 31 Jul 2007 20:21:35 -0400 migration-assistant (0.4.5) feisty; urgency=low * Proper grep for mounted devices. (LP: #99004) -- Evan Dandrea Thu, 5 Apr 2007 02:27:15 -0400 migration-assistant (0.4.4) feisty; urgency=low * Grab the location of Documents and Settings from the registry. (LP: #95152) -- Evan Dandrea Wed, 4 Apr 2007 15:09:17 -0400 migration-assistant (0.4.3) feisty; urgency=low * Possible fix for ostype not getting set in the -ask and -apply scripts. Also added some temporary debugging information. (LP: #93197) * If the /home partition device doesn't exist under the same name in the running kernel, fail gracefully and continue to the next OS. (LP: #94878) * Added more logging and crash partial recovery. * Gracefully fail and continue on items where a non C: drive letter comes into play. (LP: #95422) * Don't import Windows default bookmarks. Import, but don't set "Bliss" as the default wallpaper. -- Evan Dandrea Tue, 27 Mar 2007 03:44:25 -0400 migration-assistant (0.4.2) feisty; urgency=low * Added XS-Vcs-Bzr field to debian/control. * Mount /home if necessary. (LP: 85222) * Display an error on unmount failure and prompt the user to continue. (LP: 89605) * Put usage statements on stderr. (LP: 89821) -- Evan Dandrea Wed, 21 Mar 2007 22:16:29 -0400 migration-assistant (0.4.1) feisty; urgency=low * Added proper support for the Windows registry's use of UTF-16 strings. * Grab locations from the registry rather than assuming that everything is a subdirectory of Documents and Settings. * Don't fail when trying to copy empty files. * Fix incorrect detection of Firefox and AIM Triton. * Handle spaces in usernames. -- Evan Dandrea Sat, 3 Mar 2007 17:57:46 -0500 migration-assistant (0.4) feisty; urgency=low * Added Outlook Express and Evolution account support. * Don't assume Windows XP means a NTFS formatted drive (LP #85330). * Unmount by device, not mountpoint (LP #85222). * Gracefully handle empty registry string values. * Fixed a bug where the non bookmarks toolbar folders were getting marked as being one. -- Evan Dandrea Fri, 16 Feb 2007 14:49:25 -0500 migration-assistant (0.3.1) feisty; urgency=low * Added a reference to common-licenses and added a long description. -- Evan Dandrea Thu, 8 Feb 2007 09:43:04 -0500 migration-assistant (0.3) feisty; urgency=low * Added tests for empty passwords, reserved usernames, bad usernames and more. * removed the administrator debconf option. * fixed quite a few bugs in ma-ask's regular expressions, mounting of filesystems and ifs handling. * Added bookmarks importing from Firefox and IE. * Removed the last bit of code referencing the administrator, allowing installs to work again. -- Evan Dandrea Tue, 6 Feb 2007 00:58:57 -0500 migration-assistant (0.2) edgy; urgency=low * Ubiquity support. -- Evan Dandrea Thu, 31 Aug 2006 16:47:25 -0400 migration-assistant (0.1) edgy; urgency=low * Initial release. -- Evan Dandrea Tue, 1 Aug 2006 00:50:33 -0400 migration-assistant-0.6.13/debian/control0000664000000000000000000000143213035341452015316 0ustar Source: migration-assistant Section: debian-installer Priority: optional Maintainer: Evan Dandrea Build-Depends: debhelper (>= 10), debconf (>= 0.5.0), libxml2-dev (>= 2.6.24) Standards-Version: 3.9.8 XS-Vcs-Bzr: http://bazaar.launchpad.net/~evand/migration-assistant/trunk Package: migration-assistant Architecture: any XB-Installer-Menu-Item: 6400 Depends: ${misc:Depends}, ${shlibs:Depends}, cdebconf-udeb, made-filesystems, os-prober, user-setup XC-Package-Type: udeb Description: Import documents and settings from existing operating systems migration-assistant is a utility that imports documents and settings from other operating systems into the current system. These can include, but are not limited to, pictures, music files, background images, and bookmarks. migration-assistant-0.6.13/debian/po/0000775000000000000000000000000011732445313014334 5ustar migration-assistant-0.6.13/debian/po/POTFILES.in0000664000000000000000000000007011732445313016106 0ustar [type: gettext/rfc822deb] migration-assistant.templates migration-assistant-0.6.13/debian/po/templates.pot0000664000000000000000000001226511732445313017064 0ustar # SOME DESCRIPTIVE TITLE. # Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER # This file is distributed under the same license as the PACKAGE package. # FIRST AUTHOR , YEAR. # #, fuzzy msgid "" msgstr "" "Project-Id-Version: PACKAGE VERSION\n" "Report-Msgid-Bugs-To: evand@ubuntu.com\n" "POT-Creation-Date: 2007-09-20 03:57-0400\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "Last-Translator: FULL NAME \n" "Language-Team: LANGUAGE \n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=CHARSET\n" "Content-Transfer-Encoding: 8bit\n" #. Type: boolean #. Description #: ../migration-assistant.templates:1001 msgid "Failed to unmount partitions" msgstr "" #. Type: boolean #. Description #: ../migration-assistant.templates:1001 msgid "" "migration-assistant needs to mount a partition, but cannot do so because the " "following mount point could not be unmounted:" msgstr "" #. Type: boolean #. Description #: ../migration-assistant.templates:1001 msgid "${MOUNTED}" msgstr "" #. Type: boolean #. Description #: ../migration-assistant.templates:1001 msgid "Please close any applications using these mount points." msgstr "" #. Type: boolean #. Description #: ../migration-assistant.templates:1001 msgid "" "Would you like migration-assistant to try to unmount these partitions again?" msgstr "" #. Type: multiselect #. Description #: ../migration-assistant.templates:2001 msgid "Select operating systems to import from:" msgstr "" #. Type: multiselect #. Description #: ../migration-assistant.templates:2001 msgid "" "Which operating systems would you like to import your documents and settings " "from?" msgstr "" #. Type: multiselect #. Description #: ../migration-assistant.templates:3001 msgid "Select users to import:" msgstr "" #. Type: multiselect #. Description #: ../migration-assistant.templates:3001 msgid "Which users would you like to import for ${os-type}?" msgstr "" #. Type: multiselect #. Description #: ../migration-assistant.templates:4001 msgid "Items to import:" msgstr "" #. Type: multiselect #. Description #: ../migration-assistant.templates:4001 msgid "" "Which items would you like to import for ${user}? Programs that serve the " "same purpose will be automatically merged into their Ubuntu equivalents. " "For example, Internet Explorer and Firefox bookmarks will both be imported " "into Firefox." msgstr "" #. Type: string #. Description #: ../migration-assistant.templates:5001 msgid "Username for your account:" msgstr "" #. Type: string #. Description #: ../migration-assistant.templates:5001 msgid "" "What user would you like to import the ${old-user} account into? If the user " "does not exist, it will be created for you." msgstr "" #. Type: password #. Description #: ../migration-assistant.templates:6001 msgid "Choose a password for the new user, ${user}:" msgstr "" #. Type: password #. Description #: ../migration-assistant.templates:6001 msgid "" "A good password will contain a mixture of letters, numbers and punctuation " "and should be changed at regular intervals." msgstr "" #. Type: password #. Description #: ../migration-assistant.templates:7001 msgid "Re-enter password to verify:" msgstr "" #. Type: password #. Description #: ../migration-assistant.templates:7001 msgid "" "Please enter the same password again for ${user} to verify that you have " "typed it correctly." msgstr "" #. Type: error #. Description #: ../migration-assistant.templates:8001 msgid "Password input error" msgstr "" #. Type: error #. Description #: ../migration-assistant.templates:8001 msgid "The two passwords you entered were not the same. Please try again." msgstr "" #. Type: error #. Description #: ../migration-assistant.templates:9001 msgid "Empty password" msgstr "" #. Type: error #. Description #: ../migration-assistant.templates:9001 msgid "" "You entered an empty password, which is not allowed. Please choose a non-" "empty password." msgstr "" #. Type: error #. Description #: ../migration-assistant.templates:10001 msgid "Invalid username" msgstr "" #. Type: error #. Description #: ../migration-assistant.templates:10001 msgid "" "The username you entered is invalid. Note that usernames must start with a " "lower-case letter, which can be followed by any combination of numbers and " "more lower-case letters." msgstr "" #. Type: error #. Description #: ../migration-assistant.templates:11001 msgid "Reserved username" msgstr "" #. Type: error #. Description #: ../migration-assistant.templates:11001 msgid "" "The username you entered (${user}) is reserved for use by the system. Please " "select a different one." msgstr "" #. Type: string #. Description #: ../migration-assistant.templates:12001 msgid "Full name for ${user}:" msgstr "" #. Type: string #. Description #: ../migration-assistant.templates:12001 msgid "" "Please enter the real name of the user, ${user}. This information will be " "used for instance as default origin for emails sent by this user as well as " "any program which displays or uses the user's real name. Their full name is " "a reasonable choice." msgstr "" #. Type: text #. Description #: ../migration-assistant.templates:13001 msgid "" "Importing documents and settings from other operating systems (this may take " "a while)." msgstr "" migration-assistant-0.6.13/debian/po/output0000664000000000000000000000001111732445313015607 0ustar 2 utf8 migration-assistant-0.6.13/debian/rules0000775000000000000000000000157213035341452015000 0ustar #!/usr/bin/make -f PACKAGE=migration-assistant build: build-arch build-indep build-arch: build-stamp build-indep: build-stamp build-stamp: dh_testdir $(MAKE) touch build-stamp clean: dh_testdir dh_testroot rm -f build-stamp [ ! -f Makefile ] || $(MAKE) clean dh_clean install: build dh_testdir dh_testroot dh_prep dh_install dh_installdirs usr/lib/finish-install.d install -m0755 debian/finish-install debian/$(PACKAGE)/usr/lib/finish-install.d/80migration-assistant $(MAKE) install DESTDIR=$(CURDIR)/debian/$(PACKAGE) binary-indep: build install binary-arch: build install dh_testdir dh_testroot dh_installdebconf dh_strip dh_compress dh_fixperms cp debian/isinstallable debian/$(PACKAGE)/DEBIAN/isinstallable dh_installdeb dh_shlibdeps dh_gencontrol dh_builddeb binary: binary-indep binary-arch .PHONY: build clean binary-indep binary-arch binary install migration-assistant-0.6.13/debian/compat0000664000000000000000000000000313035341202015103 0ustar 10 migration-assistant-0.6.13/debian/copyright0000664000000000000000000000060411732445313015651 0ustar migration-assistant is copyright 2006-2007 by Evan Dandrea . This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. A copy of the GPL can be found in /usr/share/common-licenses/GPL-2 migration-assistant-0.6.13/debian/migration-assistant.templates0000664000000000000000000000602711732445313021643 0ustar Template: migration-assistant/failed-unmount Type: boolean Default: true _Description: Failed to unmount partitions migration-assistant needs to mount a partition, but cannot do so because the following mount point could not be unmounted: . ${MOUNTED} . Please close any applications using these mount points. . Would you like migration-assistant to try to unmount these partitions again? Template: migration-assistant/partitions Type: multiselect Choices: ${choices} _Description: Select operating systems to import from: Which operating systems would you like to import your documents and settings from? Template: migration-assistant/users Type: multiselect Choices: ${user-choices} _Description: Select users to import: Which users would you like to import for ${os-type}? Template: migration-assistant/items Type: multiselect Choices: ${choices} _Description: Items to import: Which items would you like to import for ${user}? Programs that serve the same purpose will be automatically merged into their Ubuntu equivalents. For example, Internet Explorer and Firefox bookmarks will both be imported into Firefox. Template: migration-assistant/user Type: string _Description: Username for your account: What user would you like to import the ${old-user} account into? If the user does not exist, it will be created for you. Template: migration-assistant/password Type: password _Description: Choose a password for the new user, ${user}: A good password will contain a mixture of letters, numbers and punctuation and should be changed at regular intervals. Template: migration-assistant/password-again Type: password _Description: Re-enter password to verify: Please enter the same password again for ${user} to verify that you have typed it correctly. Template: migration-assistant/password-mismatch Type: error _Description: Password input error The two passwords you entered were not the same. Please try again. Template: migration-assistant/password-empty Type: error _Description: Empty password You entered an empty password, which is not allowed. Please choose a non-empty password. Template: migration-assistant/username-bad Type: error _Description: Invalid username The username you entered is invalid. Note that usernames must start with a lower-case letter, which can be followed by any combination of numbers and more lower-case letters. Template: migration-assistant/username-reserved Type: error _Description: Reserved username The username you entered (${user}) is reserved for use by the system. Please select a different one. Template: migration-assistant/fullname Type: string _Description: Full name for ${user}: Please enter the real name of the user, ${user}. This information will be used for instance as default origin for emails sent by this user as well as any program which displays or uses the user's real name. Their full name is a reasonable choice. Template: finish-install/progress/migration-assistant Type: text _Description: Importing documents and settings from other operating systems (this may take a while). migration-assistant-0.6.13/debian/install0000664000000000000000000000014611732445313015310 0ustar ma-ask usr/bin ma-apply usr/bin ma-search-users usr/bin ma-script-utils usr/share/migration-assistant migration-assistant-0.6.13/debian/finish-install0000664000000000000000000000003311732445313016561 0ustar #! /bin/sh set -e ma-apply migration-assistant-0.6.13/debian/isinstallable0000775000000000000000000000011511732445313016467 0ustar #!/bin/sh -e ret=$(os-prober) if [ -z "$ret" ]; then exit 1 fi exit 0 migration-assistant-0.6.13/evolution-import.h0000664000000000000000000000012311732445313016175 0ustar void evolution_import_outlookexpress(void); void evolution_import_evolution(void); migration-assistant-0.6.13/gaim-import.h0000664000000000000000000000013511732445313015071 0ustar void gaim_import_gaim(void); void gaim_import_yahoo(void); void gaim_import_aimtriton(void); migration-assistant-0.6.13/firefox-import.c0000664000000000000000000007022711732445313015622 0ustar /** * Copyright (C) 2007 Evan Dandrea under the GPLv2 */ /* * This file should cover importing into all Firefox versions up to and * including Firefox 2. Firefox 3.0 will introduce a new backend (finally) for * bookmarks and history using SQLite. */ #include #include #include #include #include #include #include #include #include #include "utils.h" #include "registry.h" typedef struct folder { char* title; char* description; char* ptf; } folder; typedef struct hlink { char* title; char* url; char* icon; char* feed; char* description; } hlink; typedef enum { HREF, ICON, FEED, PTF } attr_type; typedef enum { FOLDER, LINK, HR } item_type; typedef struct element { void* attributes; item_type type; struct element* next; struct element* children; } element; char* read_tag(const char* line) { char* ret; const char* ptr = line; int count = 0; while(*ptr != '<') { if(*ptr == '\0') return NULL; ptr++; } line = ++ptr; while(*ptr != '>' && *ptr != ' ') { if(*ptr == '\0') return NULL; count++; ptr++; } ret = malloc(count+1); memcpy(ret,line,count); ret[count] = '\0'; return ret; } char* getcontent(const char* string) { char* ret; const char* ptr = string; int count = 0; while(*ptr != '\0') ptr++; // Find the > while(*ptr != '>') { if(ptr == string) return NULL; ptr--; } ptr--; // Find the > if(*ptr != 'D') { while(*ptr != '>') { if(ptr == string) return NULL; ptr--; } } else ptr++; string = ++ptr; // DD ends in a newline while(*ptr != '<' && *ptr != '\n') { if(*ptr == '\0') return NULL; count++; ptr++; } ret = malloc(count+1); memcpy(ret,string,count); ret[count] = '\0'; return ret; } char* getattrib(const char* string, attr_type attr) { const char* href; const char* end; char* ret = NULL; int count = 0; const char* temp; if(attr == HREF) temp = "HREF="; else if(attr == ICON) temp = "ICON="; else if(attr == FEED) temp = "FEEDURL="; else if(attr == PTF) temp = "PERSONAL_TOOLBAR_FOLDER="; href = strstr(string, temp); if(!href) return NULL; while(*href != '\"') href++; end = ++href; while(*end != '\"') { count++; end++; } ret = malloc(count+1); memcpy(ret,href,count); ret[count] = '\0'; return ret; } int count_whitespace(const char* string) { int count = 0; while(isspace(*string)) { count++; string++; } return count; } element* current; // To avoid having to iterate the entire list on every addition. element* new_element(element** lst, item_type t, void* attributes) { element* el; el = (element *)malloc(sizeof(element)); el->next = NULL; el->children = NULL; el->type = t; el->attributes = attributes; if(current) current->next = el; if(!(*lst)) { *lst = el; } current = el; return el; } element* append_element(element* parent, item_type t, void* attributes) { element* el; el = (element *)malloc(sizeof(element)); el->next = NULL; el->children = NULL; el->type = t; el->attributes = attributes; if(parent->children) { element* ptr = parent->children; while(ptr->next != NULL) { ptr = ptr->next; } ptr->next = el; } else { parent->children = el; } return el; } char* strip_whitespace(char* line) { char* start = line; char* end = NULL; while(*start == ' ' || *start == '\t') start++; end = start; while(*end != '\r' && *end != '\t') { if(*end == '\n') break; end++; } *end = '\0'; if(start == end) return NULL; return start; } void opera_build(FILE* fp, element* parent, element** list) { char* title = NULL; char* line = NULL; char* sline = NULL; char* tmp = NULL; size_t len = 0; ssize_t read; bool reread = false; while (true) { if(!reread) { if((read = getline(&line, &len, fp)) == -1) return; } else { reread = false; } sline = strip_whitespace(line); if(!sline) continue; if(sline[0] == '-') return; if(sline[0] != '#') continue; if(strcmp(sline, "#FOLDER") == 0) { title = NULL; while ((read = getline(&line, &len, fp)) != -1) { sline = strip_whitespace(line); if(!sline) continue; if(sline[0] == '-') return; if(sline[0] == '#') { reread = true; break; } tmp = sline; while(tmp && *tmp != '=') { tmp++; } if(!tmp) continue; *tmp = '\0'; if(strcmp(sline, "NAME") == 0) { title = malloc(strlen(tmp+1) + 1); strcpy(title, tmp+1); // For now we don't import the Trash folder. if(strcmp(title,"Trash") == 0) { free(title); while ((read = getline(&line, &len, fp)) != -1) { sline = strip_whitespace(line); if(sline) if(strcmp(sline, "-") == 0) break; } break; } folder* f; f = (folder *)malloc(sizeof(folder)); f->title = title; f->description = NULL; f->ptf = NULL; element* p = NULL; if(parent) { p = append_element(parent, FOLDER, f); } else { p = new_element(list, FOLDER, f); } opera_build(fp, p, list); } } } else if(strcmp(sline, "#URL") == 0) { char* url = NULL; title = NULL; while ((read = getline(&line, &len, fp)) != -1) { sline = strip_whitespace(line); if(!sline) continue; if(*sline == '\r' || *sline == '\n') continue; if(sline[0] == '#' || sline[0] == '-') { reread = true; break; } tmp = sline; while(tmp && *tmp != '=') { tmp++; } if(!tmp) continue; *tmp = '\0'; if(strcmp(sline, "NAME") == 0) { title = malloc(strlen(tmp+1) + 1); strcpy(title, tmp+1); } else if(strcmp(sline, "URL") == 0) { url = malloc(strlen(tmp+1) + 1); strcpy(url, tmp+1); } if(title && url) { hlink* l; l = (hlink *)malloc(sizeof(hlink)); l->url = url; l->title = title; l->feed = NULL; l->description = NULL; l->icon = NULL; if(parent) { append_element(parent, LINK, l); } else { new_element(list, LINK, l); } break; } } } } } const char* blacklisted_urls[] = { "http://www.microsoft.com/isapi/redir.dll", "http://go.microsoft.com", NULL }; bool url_blacklisted(const char* url) { int i = 0; while(blacklisted_urls[i] != NULL) { if(strncmp(url, blacklisted_urls[i], strlen(blacklisted_urls[i])) == 0) return true; i++; } return false; } void internet_explorer_build(const char* path, element* parent, element** list) { struct dirent *dp; struct stat statbuf; DIR *dfd; FILE* fp; char * line = NULL; size_t len = 0; ssize_t read; char* url = NULL; if(chdir(path) == -1) { fprintf(stderr, "Error: Could not chdir into %s\n", path); return; } dfd = opendir("."); if(dfd != NULL) { while((dp = readdir(dfd)) != NULL) { if((strcmp(dp->d_name,".") == 0) || (strcmp(dp->d_name,"..") == 0)) continue; char* tmp = dp->d_name; while(*tmp != '\0') tmp++; while(tmp != dp->d_name && *tmp != '.') tmp--; if(tmp != dp->d_name) { if(strcmp(tmp,".url") == 0) { fp = fopen(dp->d_name, "r"); while((read = getline(&line, &len, fp)) != -1) { char utag[5]; strncpy(utag, line, 5); utag[4] = '\0'; if(strcmp(utag,"URL=") == 0) { url = malloc(strlen(line+4)); memcpy(url,line+4, strlen(line+4)-1); url[strlen(line+4)-2] = '\0'; } } *tmp = '\0'; if(url && !url_blacklisted(url)) { char* title = malloc(strlen(dp->d_name)+1); strcpy(title, dp->d_name); hlink* l; l = (hlink *)malloc(sizeof(hlink)); l->url = url; l->title = title; l->feed = NULL; l->description = NULL; l->icon = NULL; if(parent) { append_element(parent, LINK, l); } else { new_element(list, LINK, l); } } fclose(fp); } } else { stat(dp->d_name,&statbuf); if((statbuf.st_mode & S_IFMT) == S_IFDIR) { // is a directory char* title = malloc(strlen(dp->d_name)+1); strcpy(title, dp->d_name); folder* f; f = (folder *)malloc(sizeof(folder)); f->title = title; f->description = NULL; f->ptf = NULL; element* p; if(parent) { p = append_element(parent, FOLDER, f); } else { p = new_element(list, FOLDER, f); } internet_explorer_build(dp->d_name, p, list); } } } closedir(dfd); } chdir(".."); return; } void firefox_build(FILE* fp, element* parent, element** list) { // if parent is set then we will descend into parent and look at that level. char * line = NULL; char* tag = NULL; size_t len = 0; ssize_t read; bool repeat = false; while (true) { if(!repeat) { if((read = getline(&line, &len, fp)) == -1) break; } else { repeat = false; } tag = read_tag(line); if(!tag) continue; if(strcmp(tag, "/DL") == 0) { return; } // Horizontal Rule else if(strcmp(tag, "HR") == 0) { if(parent) { append_element(parent, HR, NULL); } else { new_element(list, HR, NULL); } } // Either a bookmark or a folder. else if(strcmp(tag, "DT") == 0) { int offset = count_whitespace(line)+4; free(tag); tag = read_tag(line + offset); if(!tag) { fprintf(stderr, "Could not find a tag after DT in line: %s\n", line + offset); return; } // Bookmark if(strcmp(tag, "A") == 0) { char* url = getattrib(line+offset+2, HREF); char* title = getcontent(line+offset+2); char* icon = getattrib(line+offset+2, ICON); char* feed = getattrib(line+offset+2, FEED); char* description = NULL; if((read = getline(&line, &len, fp)) == -1) { puts("Got an EOF after an H3 tag. Corrupt file?"); return; } tag = read_tag(line); if(strcmp(tag, "DD") == 0) { description = getcontent(line+1); } else repeat = true; hlink* l; l = (hlink *)malloc(sizeof(hlink)); l->url = url; l->title = title; l->icon = icon; l->feed = feed; l->description = description; if(parent) { append_element(parent, LINK, l); } else { new_element(list, LINK, l); } } // Folder else if(strcmp(tag, "H3") == 0) { char* title = getcontent(line+offset+3); char* description = NULL; char* ptf = getattrib(line+offset+3, PTF); if((read = getline(&line, &len, fp)) == -1) { puts("Got an EOF after an H3 tag. Corrupt file?"); return; } tag = read_tag(line); if(!tag) continue; if(strcmp(tag, "DD") == 0 || strcmp(tag, "DL") == 0) { description = getcontent(line+1); } else { puts("Tag after H3 was not DD or DL."); return; } folder* f; f = (folder *)malloc(sizeof(folder)); f->title = title; f->description = description; f->ptf = ptf; element* p; if(parent) { p = append_element(parent, FOLDER, f); } else { p = new_element(list, FOLDER, f); } firefox_build(fp, p, list); } } free(tag); } if (line) free(line); return; } void firefox_format_worker(FILE* fp, const element* ptr) { char* title = NULL; char* description = NULL; char* url = NULL; char* feed = NULL; char* icon = NULL; char* ptf = NULL; char linkstr[64] = "\0"; while(ptr) { switch(ptr->type) { case HR : fprintf(fp, "
\n"); break; case LINK : title = ((hlink *)ptr->attributes)->title; url = ((hlink *)ptr->attributes)->url; feed = ((hlink *)ptr->attributes)->feed; description = ((hlink *)ptr->attributes)->description; icon = ((hlink *)ptr->attributes)->icon; strcpy(linkstr, "
%s\n"); if(icon && feed) fprintf(fp, linkstr, url, feed, icon, title); else if(icon) fprintf(fp, linkstr, url, icon, title); else if(feed) fprintf(fp, linkstr, url, feed, title); else fprintf(fp, linkstr, url, title); linkstr[0] = '\0'; if(description) fprintf(fp, "
%s\n", description); break; case FOLDER : title = ((folder *)ptr->attributes)->title; description = ((folder *)ptr->attributes)->description; ptf = ((folder *)ptr->attributes)->ptf; if(ptf == NULL) fprintf(fp, "

%s

\n", title); else { fprintf(fp, "

" "%s

\n", title); } if(description) fprintf(fp, "
%s\n", description); fprintf(fp, "

\n"); if(ptr->children) firefox_format_worker(fp, ptr->children); fprintf(fp, "

\n"); break; default : puts("Error: Type not A, H3, or HR."); break; } ptr = ptr->next; } return; } void firefox_format(const element* ptr, const char* file) { FILE* fp; const char intro[] = "\n" "\n" "\n" "Bookmarks\n" "

Bookmarks

\n" "

\n\n"; fp = fopen(file, "w"); if(fp) { fprintf(fp, intro); firefox_format_worker(fp, ptr); fprintf(fp, "

\n"); fclose(fp); } else { fprintf(stderr, "Could not open %s for writing.\n", file); } } #if 0 void firefox_format_test(element* curr) { while(curr) { switch(curr->type) { case HR : puts("Horizontal Rule"); break; case LINK : printf("Link: %s (%s)\n", ((hlink *)curr->attributes)->title, ((hlink *)curr->attributes)->url); /* printf("Link: %s (%s)\nFeed: %s\n%s\n", ((hlink *)curr->attributes)->title, ((hlink *)curr->attributes)->url, ((hlink *)curr->attributes)->feed, ((hlink *)curr->attributes)->icon); */ break; case FOLDER : printf("Folder: %s (%s)\n", ((folder *)curr->attributes)->title, ((folder *)curr->attributes)->description); if(curr->children) { puts("Folder has children."); firefox_format_test(curr->children); puts("Done iterating children."); } break; default : puts("Unknown"); break; } curr = curr->next; } puts(""); return; } #endif void merge(element** to, element* from) { element* t = *to; element* f = from; bool found = false; while(f) { while(t) { if(t->type == f->type) { int type = t->type; switch(type) { case HR : found = true; break; case LINK : if(strcmp(((hlink *)t->attributes)->url, ((hlink *)f->attributes)->url) == 0) { found = true; } break; case FOLDER : if(strcmp(((folder *)t->attributes)->title, ((folder *)f->attributes)->title) == 0) { if(f->children && t->children) { merge(&t->children, f->children); } found = true; } break; default : puts("Link type unknown."); break; } if(found) break; } t = t->next; } if(!found) { element* ptr; element* temp = f; // Remove from its list if(from != f) { ptr = from; while(ptr->next != f) ptr = ptr->next; ptr->next = f->next; f = ptr->next; } else { // It was the first element in the list from = f->next; f = from; } // Append to the other list ptr = *to; while(ptr->next) ptr = ptr->next; ptr->next = temp; temp->next = NULL; } else { f = f->next; } found = false; t = *to; } } void setup_import(char** fullpath, element** to_bookmarks) { struct dirent *dp; struct stat statbuf; DIR *dfd; char* to_firefoxdir = NULL; char* d_name; FILE* fp; char* path = NULL; char bookmarksfile[32]; *bookmarksfile = '\0'; char random[] = "abcdefghijklmnopqrstuvwxyz0123456789"; //26 asprintf(&to_firefoxdir, "%s/home/%s/.mozilla/firefox", to_location, to_user); char* mkdir = NULL; // This might be dangerous. asprintf(&mkdir, "mkdir -p %s", to_firefoxdir); system(mkdir); free(mkdir); if(chdir(to_firefoxdir) == -1) { fprintf(stderr, "Could not change directory to %s\n", to_firefoxdir); return; } dfd = opendir("."); if(dfd == NULL) { fprintf(stderr, "Could not open directory."); return; } while((dp = readdir(dfd)) != NULL) { if((strcmp(dp->d_name,".") == 0) || (strcmp(dp->d_name,"..") == 0)) continue; stat(dp->d_name,&statbuf); if(!S_ISDIR(statbuf.st_mode)) continue; // Make sure we're looking at the default profile. d_name = malloc(strlen(dp->d_name)+1); strcpy(d_name,dp->d_name); char* d_nameptr = d_name; while(*d_nameptr != '\0') d_nameptr++; while(*d_nameptr != '.' && d_nameptr != dp->d_name) d_nameptr--; if(strcmp(d_nameptr,".default") == 0) { strcpy(bookmarksfile, dp->d_name); strcat(bookmarksfile, "/bookmarks.html"); break; } free(d_name); } closedir(dfd); if(bookmarksfile[0] != '\0') { fp = fopen(bookmarksfile, "r"); if(fp == NULL) { fprintf(stderr, "Could not open file, %s\n", bookmarksfile); return; } firefox_build(fp, NULL, to_bookmarks); fclose(fp); asprintf(fullpath, "%s/%s", to_firefoxdir, bookmarksfile); } else { int r, i; char b[17]; for(i=0; i<8; i++) { r = (int)((double)rand() / ((double)RAND_MAX + 1) * 26); b[i] = random[r]; } b[8] = '\0'; strcat(b, ".default"); asprintf(&path, "%s/profiles.ini", to_firefoxdir); fp = fopen(path, "a"); free(path); fprintf(fp, "[General]\nStartWithLastProfile=1\n\n[Profile0]\n" "Name=default\nIsRelative=1\nPath=%s\n\n", b); fclose(fp); asprintf(&path, "%s/%s", to_firefoxdir, b); asprintf(&mkdir, "mkdir -p %s", path); system(mkdir); free(mkdir); asprintf(fullpath, "%s/bookmarks.html", path); free(path); } free(to_firefoxdir); } void firefox_import_firefox(void) { struct dirent *dp, *dp2; struct stat statbuf; DIR *dfd, *dfd2; char bookmarksfile[32] = "\0"; FILE* fp; element* from_bookmarks = NULL; element* to_bookmarks = NULL; char* from_firefoxdir = NULL; char* fullpath = NULL; bool found = false; setup_import(&fullpath, &to_bookmarks); // Build a tree of the bookmarks file(s) we're importing from, then merge it // with the new bookmarks tree. if(os_type == LINUX) { asprintf(&from_firefoxdir, "%s/home/%s/.mozilla/firefox", from_location, from_user); } else if(os_type == WINDOWSXP) { char* appdata = NULL; char* path; appdata = findkey(user_key_file, "\\Software\\Microsoft\\Windows\\" "CurrentVersion\\Explorer\\Shell Folders\\Local AppData"); if(!appdata) { printf("Couldn't find %s\n", appdata); return; } path = reformat_path(appdata); free(appdata); asprintf(&from_firefoxdir, "%s/%s/Mozilla/Firefox/Profiles", from_location, path); free(path); } if(chdir(from_firefoxdir) == -1) { fprintf(stderr, "Could not change directory to %s.\n", from_firefoxdir); return; } free(from_firefoxdir); dfd = opendir("."); if(dfd != NULL) { while((dp = readdir(dfd)) != NULL) { if((strcmp(dp->d_name,".") == 0) || (strcmp(dp->d_name,"..") == 0)) continue; stat(dp->d_name,&statbuf); if(!S_ISDIR(statbuf.st_mode)) continue; dfd2 = opendir(dp->d_name); if(dfd != NULL) { while((dp2 = readdir(dfd2)) != NULL) { if(strcmp(dp2->d_name,"bookmarks.html") == 0) found = true; } } closedir(dfd2); if(found) { found = false; strcpy(bookmarksfile,dp->d_name); strcat(bookmarksfile,"/bookmarks.html"); fp = fopen(bookmarksfile,"r"); if(fp == NULL) { fprintf(stderr, "Could not open file, %s.\n", bookmarksfile); continue; } // TODO: get rid of current. current = NULL; firefox_build(fp, NULL, &from_bookmarks); fclose(fp); if(to_bookmarks) merge(&to_bookmarks, from_bookmarks); else to_bookmarks = from_bookmarks; } } closedir(dfd); } // Now we translate the tree into a bookmarks.html file. firefox_format(to_bookmarks, fullpath); free(fullpath); } void firefox_import_opera(void) { FILE* fp; char* bookmarksfile, *path; element* to_bookmarks = NULL; element* from_bookmarks = NULL; char* fullpath = NULL; char* appdata = NULL; setup_import(&fullpath, &to_bookmarks); appdata = findkey(user_key_file, "\\Software\\Microsoft\\Windows\\" "CurrentVersion\\Explorer\\Shell Folders\\Local AppData"); if(!appdata) { printf("Couldn't find %s\n", appdata); return; } path = reformat_path(appdata); free(appdata); asprintf(&bookmarksfile, "%s/%s/Opera/Opera/profile/opera6.adr", from_location, path); free(path); fp = fopen(bookmarksfile, "r"); if(fp == NULL) { fprintf(stderr, "Could not open file, %s.\n", bookmarksfile); return; } free(bookmarksfile); current = NULL; opera_build(fp, NULL, &from_bookmarks); fclose(fp); if(to_bookmarks) merge(&to_bookmarks, from_bookmarks); else to_bookmarks = from_bookmarks; firefox_format(to_bookmarks, fullpath); free(fullpath); } void firefox_import_internetexplorer(void) { char* from_iedir = NULL; element* to_bookmarks = NULL; element* from_bookmarks = NULL; char* fullpath = NULL; char* path; char* favorites = NULL; setup_import(&fullpath, &to_bookmarks); favorites = findkey(user_key_file, "\\Software\\Microsoft\\Windows\\" "CurrentVersion\\Explorer\\Shell Folders\\Favorites"); if(!favorites) { printf("Couldn't find %s\n", favorites); return; } path = reformat_path(favorites); free(favorites); asprintf(&from_iedir, "%s/%s", from_location, path); free(path); current = NULL; internet_explorer_build(from_iedir, NULL, &from_bookmarks); free(from_iedir); if(to_bookmarks) merge(&to_bookmarks, from_bookmarks); else to_bookmarks = from_bookmarks; firefox_format(to_bookmarks, fullpath); free(fullpath); } // vim:ai:et:sts=4:tw=80:sw=4: migration-assistant-0.6.13/evolution-import.c0000664000000000000000000003443711732445313016207 0ustar #include #include #include #include #include #include #include #include #include "registry.h" #include "utils.h" #if 0 int indent = 0; void print(xmlNode* node) { while(node != NULL) { int i = 0; while(i < indent) { printf(" "); i++; } if(node->children && node->children->content) printf("node: %s (%s)\n", node->name, node->children->content); else printf("node: %s\n", node->name); if(node->children) { indent++; print(node->children); indent--; } node = node->next; } } #endif bool accounts_are_equal(xmlNode* first, xmlNode* second) { // FIXME: uid will not work as we are talking about different systems, they'll // always be different. Use a combination of the server name and username // instead. xmlChar* firsturl = NULL; xmlChar* secondurl = NULL; if(!(first && second)) return false; first = first->children; while(xmlStrcmp(first->name, BAD_CAST "transport") != 0) first = first->next; first = first->children; while(xmlStrcmp(first->name, BAD_CAST "url") != 0) first = first->next; firsturl = first->children->content; second = second->children; while(xmlStrcmp(second->name, BAD_CAST "transport") != 0) second = second->next; second = second->children; while(xmlStrcmp(second->name, BAD_CAST "url") != 0) second = second->next; secondurl = second->children->content; if(!(firsturl && secondurl)) return false; if(xmlStrcmp(firsturl, secondurl) == 0) return true; else return false; } xmlNode* get_account_data(xmlNode* node){ // Expects

  • xmlChar* account = NULL; if(xmlStrcmp(node->name, BAD_CAST "li") == 0) { node = node->children; if(xmlStrcmp(node->name, BAD_CAST "stringvalue") == 0) { node = node->children; if(node && node->content) account = node->content; } } if(account) { node = xmlDocGetRootElement(xmlReadDoc(account, NULL, NULL, XML_PARSE_NOBLANKS)); } return node; } void evolution_merge(xmlNode** into, xmlNode* from) { // expects xmlNode* in = *into; xmlNode* indata = NULL; xmlNode* fromdata = NULL; bool exists = false; if(in == from) return; if(!(in && from) || !(in->children && from->children)) { fprintf(stderr, "merge called with invalid poiners: %p %p\n", in, from); return; } in = in->children; from = from->children; while(from) { fromdata = get_account_data(from); while(in) { indata = get_account_data(in); if(accounts_are_equal(indata, fromdata)) { exists = true; break; } xmlFreeDoc(indata->doc); in = in->next; } in = (*into)->children; if(!exists) { xmlAddChild(in->parent, from); } else { exists = false; } xmlFreeDoc(fromdata->doc); from = from->next; } } xmlNode* evolution_setup(const char* file) { FILE* fd = fopen(file, "r"); if(fd) { puts("File exists."); fclose(fd); xmlDoc* d = xmlReadFile(file, NULL, XML_PARSE_NOBLANKS); xmlNode* node = xmlDocGetRootElement(d); while(xmlStrcmp(node->name, BAD_CAST "gconf") != 0) node = node->next; node = node->children; while(node) { // FIXME foreach property. if(xmlStrcmp(node->properties->children->content, BAD_CAST "accounts") == 0) { break; } node = node->next; } return node; } else { char* dir = strdup(file); makegconfdirs(dirname(dir)); free(dir); return NULL; } } typedef enum { IMAP, POP3 } server_type; typedef struct account { server_type type; char* accountname; char* fullname; char* email; char* incominguser; char* incomingserver; char* incomingport; char* incomingssl; char* smtpuser; char* smtpserver; char* smtpport; char* smtpssl; char* uid; } account; void evolution_import_other(account* a) { char* file = NULL; asprintf(&file, "%s/%s/%s/%s", to_location, "home", to_user, ".gconf/apps/evolution/mail/\%gconf.xml"); char* smtpurl = NULL; char* incomingurl = NULL; if(a->incominguser != NULL) { // Need to replace ' ' with %20 // Need to replace '@' with %40 char* temp = NULL; temp = strrep(a->incominguser, " ", "\%20"); free(a->incominguser); a->incominguser = temp; temp = strrep(a->incominguser, "@", "\%40"); free(a->incominguser); a->incominguser = temp; } if(a->type == IMAP) { if(a->incominguser != NULL) { asprintf(&incomingurl, "imap://%s@%s", a->incominguser, a->incomingserver); } else { asprintf(&incomingurl, "imap://%s", a->incomingserver); } } else { if(a->incominguser != NULL) { asprintf(&incomingurl, "pop://%s@%s", a->incominguser, a->incomingserver); } else { asprintf(&incomingurl, "pop://%s", a->incomingserver); } } if(a->incomingport != NULL) { char* temp; asprintf(&temp, "%s:%s", incomingurl, a->incomingport); incomingurl = temp; } if(a->incomingssl != NULL) { char* temp; asprintf(&temp, "%s/%s", incomingurl, a->incomingssl); incomingurl = temp; } if(a->smtpuser != NULL) { // Need to replace ' ' with %20 // Need to replace '@' with %40 char* temp = NULL; temp = strrep(a->smtpuser, " ", "\%20"); free(a->smtpuser); a->smtpuser = temp; temp = strrep(a->smtpuser, "@", "\%40"); free(a->smtpuser); a->smtpuser = temp; asprintf(&smtpurl, "smtp://%s@%s", a->smtpuser, a->smtpserver); } else { asprintf(&smtpurl, "smtp://%s", a->smtpserver); } if(a->smtpport != NULL) { char* temp; asprintf(&temp, "%s:%s", smtpurl, a->smtpport); smtpurl = temp; } if(a->smtpssl != NULL) { char* temp; asprintf(&temp, "%s/%s", smtpurl, a->smtpssl); smtpurl = temp; } const char* acct = "" "%s%s" "" "%s" "%s" ""; char* accountstring = NULL; asprintf(&accountstring, acct, a->accountname, a->uid, a->fullname, a->email, incomingurl, smtpurl); xmlDoc* doc = xmlNewDoc(BAD_CAST "1.0"); xmlNode* gconf = xmlNewNode(NULL, BAD_CAST "gconf"); xmlNode* entry = xmlNewChild(gconf, NULL, BAD_CAST "entry", NULL); xmlNewProp(entry, BAD_CAST "name", BAD_CAST "accounts"); xmlNewProp(entry, BAD_CAST "type", BAD_CAST "list"); xmlNewProp(entry, BAD_CAST "ltype", BAD_CAST "string"); xmlNode* li = xmlNewChild(entry, NULL, BAD_CAST "li", NULL); xmlNewProp(li, BAD_CAST "type", BAD_CAST "string"); xmlNewChild(li, NULL, BAD_CAST "stringvalue", BAD_CAST accountstring); xmlDocSetRootElement(doc, gconf); xmlNode* to = evolution_setup(file); if(to) { evolution_merge(&to, entry); xmlSaveFormatFile(file, to->doc, 1); } else xmlSaveFormatFile(file, doc, 1); } void evolution_import_evolution(void) { char* file = NULL; asprintf(&file, "%s/%s/%s/%s", from_location, "home", from_user, ".gconf/apps/evolution/mail/\%gconf.xml"); xmlDoc* d = xmlReadFile(file, NULL, XML_PARSE_NOBLANKS); free(file); xmlNode* node = xmlDocGetRootElement(d); while(xmlStrcmp(node->name, BAD_CAST "gconf") != 0) node = node->next; node = node->children; while(node) { // FIXME foreach property. if(xmlStrcmp(node->properties->children->content, BAD_CAST "accounts") == 0) { break; } node = node->next; } asprintf(&file, "%s/%s/%s/%s", to_location, "home", to_user, ".gconf/apps/evolution/mail/\%gconf.xml"); xmlNode* to = evolution_setup(file); if(to) { evolution_merge(&to, node); xmlSaveFormatFile(file, to->doc, 1); } else xmlSaveFormatFile(file, d, 1); free(file); } void evolution_import_outlookexpress(void) { char* account_key = NULL; char* temp_key = NULL; int i = 1; static int serial; static char *hostname; account* a; while(true) { a = (account *)malloc(sizeof(account)); a->accountname = NULL; a->fullname = NULL; a->email = NULL; a->incominguser = NULL; a->incomingserver = NULL; a->incomingport = NULL; a->incomingssl = NULL; a->smtpuser = NULL; a->smtpserver = NULL; a->smtpport = NULL; a->smtpssl = NULL; a->uid = NULL; asprintf(&account_key, "\\Software\\Microsoft\\" "Internet Account Manager\\Accounts\\%.8d\\", i); asprintf(&temp_key, "%s%s", account_key, "Account Name"); a->accountname = findkey(user_key_file, temp_key); free(temp_key); if(!a->accountname) { if(a) free(a); break; } // Taken from libedataserver/e-uid.c char buffer [512]; if ((gethostname (buffer, sizeof (buffer) - 1) == 0) && (buffer [0] != 0)) hostname = buffer; else hostname = "localhost"; asprintf (&a->uid, "%lu.%lu.%d@%s", (unsigned long) time (NULL), (unsigned long) getpid (), serial++, hostname); asprintf(&temp_key, "%s%s", account_key, "SMTP Display Name"); a->fullname = findkey(user_key_file, temp_key); free(temp_key); asprintf(&temp_key, "%s%s", account_key, "SMTP Email Address"); a->email = findkey(user_key_file, temp_key); free(temp_key); asprintf(&temp_key, "%s%s", account_key, "IMAP User Name"); a->incominguser = findkey(user_key_file, temp_key); free(temp_key); if(a->incominguser) { a->type = IMAP; asprintf(&temp_key, "%s%s", account_key, "IMAP Server"); a->incomingserver = findkey(user_key_file, temp_key); free(temp_key); asprintf(&temp_key, "%s%s", account_key, "IMAP Port"); a->incomingport = findkey(user_key_file, temp_key); free(temp_key); asprintf(&temp_key, "%s%s", account_key, "IMAP Secure Connection"); a->incomingssl = findkey(user_key_file, temp_key); free(temp_key); } else { a->type = POP3; asprintf(&temp_key, "%s%s", account_key, "POP3 User Name"); a->incominguser = findkey(user_key_file, temp_key); free(temp_key); asprintf(&temp_key, "%s%s", account_key, "POP3 Server"); a->incomingserver = findkey(user_key_file, temp_key); free(temp_key); asprintf(&temp_key, "%s%s", account_key, "POP3 Port"); a->incomingport = findkey(user_key_file, temp_key); free(temp_key); asprintf(&temp_key, "%s%s", account_key, "POP3 Secure Connection"); a->incomingssl = findkey(user_key_file, temp_key); free(temp_key); } if(a->incomingssl && strcmp(a->incomingssl, "1") == 0) { free(a->incomingssl); a->incomingssl = ";use_ssl=always"; } else { free(a->incomingssl); a->incomingssl = NULL; } asprintf(&temp_key, "%s%s", account_key, "SMTP User Name"); a->smtpuser = findkey(user_key_file, temp_key); free(temp_key); asprintf(&temp_key, "%s%s", account_key, "SMTP Server"); a->smtpserver = findkey(user_key_file, temp_key); free(temp_key); asprintf(&temp_key, "%s%s", account_key, "SMTP Port"); a->smtpport = findkey(user_key_file, temp_key); free(temp_key); asprintf(&temp_key, "%s%s", account_key, "SMTP Secure Connection"); a->smtpssl = findkey(user_key_file, temp_key); free(temp_key); if(a->smtpssl && strcmp(a->smtpssl, "1") == 0) { free(a->smtpssl); a->smtpssl = ";use_ssl=always"; } else { free(a->smtpssl); a->smtpssl = NULL; } free(account_key); printf("accountname: %s\n", a->accountname); printf("fullname: %s\n", a->fullname); printf("email: %s\n", a->email); printf("incominguser: %s\n", a->incominguser); printf("incomingserver: %s\n", a->incomingserver); printf("incomingport: %s\n", a->incomingport); printf("incomingssl: %s\n", a->incomingssl); printf("smtpuser: %s\n", a->smtpuser); printf("smtpserver: %s\n", a->smtpserver); printf("smtpport: %s\n", a->smtpport); printf("smtpssl: %s\n", a->smtpssl); printf("uid: %s\n", a->uid); printf("test: %s\n", findkey(user_key_file, "\\Software\\Microsoft\\Windows\\CurrentVersion\\Explorer\\Shell Folders\\Local AppData")); puts(""); evolution_import_other(a); i++; if(a->accountname) free(a->accountname); if(a->fullname) free(a->fullname); if(a->email) free(a->email); if(a->incominguser); free(a->incominguser); if(a->incomingserver) free(a->incomingserver); if(a->incomingport); free(a->incomingport); if(a->smtpuser) free(a->smtpuser); if(a->smtpserver) free(a->smtpserver); if(a->smtpport) free(a->smtpport); free(a); } } // vim:ai:et:sts=4:tw=80:sw=4: migration-assistant-0.6.13/utils.h0000664000000000000000000000234311732445313014007 0ustar // Move into globals.h for readability. char* from_location; char* from_user; char* to_location; char* to_user; char* software_key_file; char* user_key_file; typedef enum { WINDOWSXP, LINUX } ostypes; ostypes os_type; char *strrep(const char *str, const char *old, const char *new); char* reformat_path(const char* from); void copyfile(const char* from, const char* to); void rcopy(const char* from, const char* to); void makedirs(const char*); void create_file(const char*); typedef enum { GCONF_BOOLEAN, GCONF_STRING, GCONF_LIST_STRING } gconf_type; void set_gconf_key (const char*, const char*, gconf_type, const char*); void add_wallpaper (const char*); void makegconfdirs(const char *dir); void initialize_registry_paths(); void initialize_software_registry_path(); void initialize_user_registry_path(); char* get_profiles_dir(const char *mountpoint); // struct target_t { // const char* option; // const char* name; // void (*search)(); // void (*import)(); // } // // // option name from to // struct targets_t targets[] = { // { "gaim", "Gaim IM", windowsxp_gaim, gaim_import_gaim }, // { "yahoo", "Yahoo IM", windowsxp_yahoo, gaim_import_yahoo }, // { "gaim", "Gaim IM", linux_gaim, gaim_import_gaim }, // { NULL, 0, NULL, 0 } // }; migration-assistant-0.6.13/import.c0000664000000000000000000000772011732445313014160 0ustar #include #include #include #include // For dropping to user #include #include #include // For directory manipulation #include #include // For umask #include #include "utils.h" #include "gaim-import.h" #include "firefox-import.h" #include "windows-import.h" #include "firefox-import.h" #include "evolution-import.h" void usage(char** argv) { printf("USAGE: %s --ostype=TYPE --fromuser=USER --frompath=PATH" " --touser=USER --topath=PATH --target=TARGET\n\n", argv[0]); exit(EXIT_FAILURE); } int main(int argc, char** argv) { void (*target)(); static struct option long_options[] = { { "ostype", required_argument, NULL, 'o' }, { "fromuser", required_argument, NULL, 'f' }, { "frompath", required_argument, NULL, 'l' }, { "touser", required_argument, NULL, 't' }, { "topath", required_argument, NULL, 'p' }, { "target", required_argument, NULL, 'a' }, { NULL, 0, NULL, 0 } }; while(1) { int c = getopt_long(argc, argv, "", long_options, NULL); if(c == -1) break; switch(c) { case 'o' : if(strcmp(optarg, "linux") == 0) os_type = LINUX; else if(strcmp(optarg, "windowsxp") == 0) os_type = WINDOWSXP; else usage(argv); break; case 'f' : from_user = strdup(optarg); break; case 'l' : from_location = strdup(optarg); break; case 't' : to_user = strdup(optarg); break; case 'p' : to_location = strdup(optarg); break; case 'a' : // FIXME: Clearly we need to do something about this mess. if(strcmp(optarg,"yahoo") == 0) target = gaim_import_yahoo; else if(strcmp(optarg,"aimtriton") == 0) target = gaim_import_aimtriton; else if(strcmp(optarg,"pidgin") == 0) target = gaim_import_gaim; else if(strcmp(optarg,"firefox") == 0) target = firefox_import_firefox; else if(strcmp(optarg,"mydocuments") == 0) target = windowsxp_import_mydocuments; else if(strcmp(optarg,"mypictures") == 0) target = windowsxp_import_mypictures; else if(strcmp(optarg,"mymusic") == 0) target = windowsxp_import_mymusic; else if(strcmp(optarg, "proxy") == 0) target = windowsxp_import_proxy; else if(strcmp(optarg, "userpicture") == 0) target = windowsxp_import_userpicture; else if(strcmp(optarg, "wallpaper") == 0) target = windowsxp_import_wallpaper; else if(strcmp(optarg, "mozillafirefox") == 0) target = firefox_import_firefox; else if(strcmp(optarg, "internetexplorer") == 0) target = firefox_import_internetexplorer; else if(strcmp(optarg, "opera") == 0) target = firefox_import_opera; else if(strcmp(optarg, "outlookexpress") == 0) target = evolution_import_outlookexpress; else if(strcmp(optarg, "evolution") == 0) target = evolution_import_evolution; else usage(argv); break; default: usage(argv); break; } } if((from_user && to_user) && (from_location && to_location)) { struct passwd *p; char* passwd_file; FILE* fp = NULL; // Instead of chowning everything we create, we just drop to the user // we're working with. Not entirely sure if this is a good/bad idea. asprintf(&passwd_file, "%s/etc/passwd", to_location); fp = fopen(passwd_file, "r"); if(fp) { while((p = fgetpwent(fp)) != NULL) { if(strcmp(p->pw_name, to_user) == 0) { setgid(p->pw_gid); setuid(p->pw_uid); } } endpwent(); fclose(fp); } else { fprintf(stderr, "Unable to open %s\n", passwd_file); exit(EXIT_FAILURE); } free(passwd_file); if(os_type == WINDOWSXP) initialize_registry_paths(); target(); } else usage(argv); return 0; } // vim:ai:et:sts=4:tw=80:sw=4: migration-assistant-0.6.13/ma-ask0000775000000000000000000001736511737116701013610 0ustar #!/bin/sh # TODO: Incorporate capb backup. set -e . /usr/share/debconf/confmodule . /usr/share/migration-assistant/ma-script-utils newns "$@" if [ -z "$1" ]; then mapath="/usr/bin" else mapath="$1" fi OLDIFS="$IFS" NEWLINE=' ' IFS="$NEWLINE" tmp= for line in `WINOSDATA=true os-prober`; do dist=$(LC_ALL=C expr match "$line" '.*:\(.*\):.*:.*') location=${line%%:*} # Don't present the target filesystem target="$(grep ' /target ' /proc/mounts | cut -d' ' -f1)" target="$(readlink -e "$target")" || target= home="$(grep ' /target/home ' /proc/mounts | cut -d' ' -f1)" home="$(readlink -e "$home")" || home= if [ "$target" = "$location" ] || [ "$home" = "$location" ]; then continue fi if [ -z "$tmp" ]; then tmp="$dist ($location)" else tmp="$tmp, $dist ($location)" fi done IFS="$OLDIFS" db_subst migration-assistant/partitions choices "$tmp" db_input high migration-assistant/partitions || true db_go || exit 10 db_get migration-assistant/partitions || RET= IFS="$NEWLINE" selection=`echo "$RET" | sed -e 's/, /\n/g'` for choice in $selection; do # Microsoft Windows XP Professional (/dev/hda1) IFS="$OLDIFS" location=$(LC_ALL=C expr "$choice" : '.*(\(.*\))$') # /dev/hda1 IFS="$NEWLINE" for line in `WINOSDATA=true os-prober`; do IFS="$OLDIFS" loc="${line%%:*}" if [ "$location" != "$loc" ]; then continue fi log "setting ostype from: '$line'" set_os_type "$line" || continue log "got ostype of: '$ostype', mountpoint is: '$mountpoint'" path="${loc#*/*/}" # hda1 or discs/disc0/part1 mount_os "$ostype" "$loc" || continue db_register migration-assistant/users migration-assistant/$path/users db_subst migration-assistant/$path/users user-choices \ "$($mapath/ma-search-users "$ostype" "$mountpoint" 2>>/var/log/syslog)" db_subst migration-assistant/$path/users os-type "$choice" db_input high migration-assistant/$path/users || true db_go || exit 10 db_get migration-assistant/$path/users || RET= user_selection=`echo "$RET" | sed -e 's/, /\n/g'` IFS="$NEWLINE" for usr in $user_selection; do IFS="$OLDIFS" itemsret=$($mapath/ma-search-items --path="$mountpoint" --ostype="$ostype" --user="$usr" 2>>/var/log/syslog) || \ (itemsret=; error "ma-search-items exited with an error for $usr.") # FIXME: We should figure out if there are any items for each user # before asking to import from the user. Likewise, we should # figure out if there are any users to import before asking to # import from a partition. if [ -z "$itemsret" ]; then continue fi formatted_user=`echo "$usr" | sed -e 's/ /+/g'` db_register migration-assistant/items migration-assistant/$path/$formatted_user/items db_subst migration-assistant/$path/$formatted_user/items choices "$itemsret" db_subst migration-assistant/$path/$formatted_user/items user "$usr" # migration-assistant/discs/disc0/part1/Evan/items db_input high migration-assistant/$path/$formatted_user/items || true db_go || exit 10 db_register migration-assistant/user migration-assistant/$path/$formatted_user/user # This prevents m-a from working right. change to choices #db_set migration-assistant/$path/$formatted_user/user "$(echo "$usr" | tr '[A-Z]' '[a-z]')" db_subst migration-assistant/$path/$formatted_user/user old-user "$usr" while :; do db_input high migration-assistant/$path/$formatted_user/user || true db_go || exit 10 db_get migration-assistant/$path/$formatted_user/user || RET= new_user="$RET" if ! LC_ALL=C expr "$new_user" : '[a-z][-a-z0-9]*$' >/dev/null; then db_fset migration-assistant/$path/$formatted_user/user seen false db_fset migration-assistant/username-bad seen false db_subst migration-assistant/username-bad user "$new_user" db_input critical migration-assistant/username-bad continue fi # TODO: Either copy this or depend on user-setup. if grep -v '^#' /usr/lib/user-setup/reserved-usernames | \ grep -q "^$new_user\$"; then db_fset migration-assistant/$path/$formatted_user/user seen false db_fset migration-assistant/username-reserved seen false db_subst migration-assistant/username-reserved user "$new_user" db_input critical migration-assistant/username-reserved continue fi break done # Only ask if the user doesn't match the one seeded for user-setup. db_get passwd/username || RET= if [ "$new_user" = "$RET" ]; then continue fi # Password db_register migration-assistant/password migration-assistant/new-user/$new_user/password db_subst migration-assistant/new-user/$new_user/password user "$new_user" db_register migration-assistant/password-again migration-assistant/new-user/$new_user/password-again db_subst migration-assistant/new-user/$new_user/password-again user "$new_user" while :; do db_input high migration-assistant/new-user/$new_user/password || true db_go || exit 10 db_get migration-assistant/new-user/$new_user/password || RET= pass=$RET db_input high migration-assistant/new-user/$new_user/password-again || true db_go || exit 10 db_get migration-assistant/new-user/$new_user/password-again || RET= pass2=$RET if [ -z "$pass2" ] || [ -z "$pass" ]; then db_set migration-assistant/new-user/$new_user/password "" db_set migration-assistant/new-user/$new_user/password-again "" db_fset migration-assistant/password-empty seen "false" db_input high migration-assistant/password-empty || true db_fset migration-assistant/new-user/$new_user/password seen "false" db_fset migration-assistant/new-user/$new_user/password-again seen "false" db_go || true continue fi if [ "$pass2" = "$pass" ]; then break else db_set migration-assistant/new-user/$new_user/password "" db_set migration-assistant/new-user/$new_user/password-again "" db_fset migration-assistant/password-mismatch seen "false" db_input high migration-assistant/password-mismatch || true db_fset migration-assistant/new-user/$new_user/password seen "false" db_fset migration-assistant/new-user/$new_user/password-again seen "false" db_go || true fi done # Full Name db_register migration-assistant/fullname migration-assistant/new-user/$new_user/fullname db_subst migration-assistant/new-user/$new_user/fullname user "$new_user" db_input high migration-assistant/new-user/$new_user/fullname || true db_go || exit 10 done IFS="$OLDIFS" unmount_os done done # vim:ai:et:sts=4:tw=80:sw=4: migration-assistant-0.6.13/registry.c0000664000000000000000000002762011732445313014517 0ustar /* The data structures for the Windows NT registry and some of the code within * this source file was written by Aaron D. Brooks for the BeeHive project * (http://sourceforge.net/project/?group_id=1987) and licensed under the GPL * v2. * * UTF-16 to UTF-8 conversion taken from VLC. */ #include #include #include #include #include #include "registry.h" /* MSB (big endian)/LSB (little endian) conversions - network order is always * MSB, and should be used for both network communications and files. Note that * byte orders other than little and big endians are not supported, but only * the VAX seems to have such exotic properties. */ static inline uint16_t U16_AT( void const * _p ) { uint8_t * p = (uint8_t *)_p; return ( ((uint16_t)p[0] << 8) | p[1] ); } /** * UTF16toUTF8: converts UTF-16 (host byte order) to UTF-8 * * @param src UTF-16 bytes sequence, aligned on a 16-bits boundary * @param len number of uint16_t to convert */ static char * UTF16toUTF8( const uint16_t *in, size_t len, size_t *newlen ) { char *res, *out; /* allocate memory */ out = res = (char *)malloc( 3 * len ); if( res == NULL ) return NULL; while( len > 0 ) { uint32_t uv = *in; in++; len--; if( uv < 0x80 ) { *out++ = uv; continue; } if( uv < 0x800 ) { *out++ = (( uv >> 6) | 0xc0); *out++ = (( uv & 0x3f) | 0x80); continue; } if( (uv >= 0xd800) && (uv < 0xdbff) ) { /* surrogates */ uint16_t low = U16_AT( in ); in++; len--; if( (low < 0xdc00) || (low >= 0xdfff) ) { *out++ = '?'; /* Malformed surrogate */ continue; } else uv = ((uv - 0xd800) << 10) + (low - 0xdc00) + 0x10000; } if( uv < 0x10000 ) { *out++ = (( uv >> 12) | 0xe0); *out++ = (((uv >> 6) & 0x3f) | 0x80); *out++ = (( uv & 0x3f) | 0x80); continue; } else { *out++ = (( uv >> 18) | 0xf0); *out++ = (((uv >> 12) & 0x3f) | 0x80); *out++ = (((uv >> 6) & 0x3f) | 0x80); *out++ = (( uv & 0x3f) | 0x80); continue; } } len = out - res; res = realloc( res, len ); if( newlen != NULL ) *newlen = len; return res; } /** * FromUTF16(): converts an UTF-16 string to UTF-8. * * @param src UTF-16 bytes sequence, aligned on a 16-bits boundary. * * @return the result of the conversion (must be free()'d), * or NULL in case of error. */ char *FromUTF16( const uint16_t *src ) { const uint16_t *in; size_t len; /* determine the size of the string */ for( len = 1, in = src; *in; len++ ) in++; return UTF16toUTF8( src, len, NULL ); } char* findkey(const char* location, const char* path) { FILE *hive; int numread; REGF myregf; char* hbinptr; char* ret = NULL; // FIXME char* arr; arr = strdup(path); hive = fopen(location,"r"); if(hive) { numread = fread(&myregf,sizeof(char),sizeof(REGF),hive); char* key; if((key = strrchr(arr, '\\')) != NULL){ *key++ = '\0'; } hbinptr = (char*)malloc(myregf.hivesize); if(hbinptr) { numread = fread(hbinptr,sizeof(char),myregf.hivesize,hive); NK* back = getkey(hbinptr,(NK*)&(hbinptr[myregf.firstkey]), &arr); if(back != NULL) { ret = printk(hbinptr, back, key); } free(hbinptr); // if(key) // free(key); } } else { fprintf(stderr, "Unable to open the registry file at '%s'\n%d: %s\n", location, errno, strerror(errno)); return NULL; } fclose(hive); if(ret) return ret; else return NULL; } char* expand_string(const char *string) { if(strcmp(string, "%SystemDrive%") == 0) { // FIXME: return strdup("C:"); } else { fprintf(stderr, "Unable to expand '%s'.\n", string); exit(EXIT_FAILURE); } } char* printk(char* base, NK* thisnk, char* key) { int i; int* valptr; if(thisnk->numvalues > 0) { valptr=(int*) &(base[thisnk->myvallist]); for(i=1; inumvalues+1; i++) { if(valptr[i]>0) { VK* thisvk = (VK*) &(base[valptr[i]]); char* szname; //int vksize=sizeof(VK)+thisvk->namesize; szname = (char*) malloc (thisvk->namesize+1); strncpy(szname,(char*)(thisvk+1),thisvk->namesize+1); szname[thisvk->namesize]= 0; if(strcmp(szname,key) == 0){ if(thisvk->flag && 0x0000000000000001){ // FIXME: Handle REG_EXPAND_SZ // better if (thisvk->valtype == REG_SZ || thisvk->valtype == REG_EXPAND_SZ){ char* tmp = NULL; // Emtpy string. if((base+4+(thisvk->mydata))[0] == 0) return NULL; // Convert to UTF-8. tmp = FromUTF16((uint16_t*)(base+4+(thisvk->mydata))); if(thisvk->valtype == REG_EXPAND_SZ) { char *start, *end; int startc = 0; int endc = 0; start = tmp; while(*start != '\0') { if(*start == '%') { end = start+1; endc = startc+1; while(*end != '%') { if(*end == '\0') { fprintf(stderr, "Unmatched '%%' in %s.\n", tmp); exit(EXIT_FAILURE); } end++; endc++; } //printf("endc: %d end: %s\n", endc, end); //printf("startc: %d start: %s\n", startc, start); char* toexpand = malloc((endc-startc+1)+1); memcpy(toexpand, start, (endc-startc+1)); toexpand[endc-startc+1] = '\0'; //printf("toexpand: %s\n", toexpand); char* expanded = expand_string(toexpand); free(toexpand); //printf("expanded: %s\n", expanded); int linelen = strlen(tmp) - (endc-startc+1) + strlen(expanded) + 1; //printf("linelen: %d\n", linelen); char* newtmp = calloc(linelen, 1); strncpy(newtmp, tmp, startc); strcat(newtmp, expanded); strcat(newtmp, end+1); //printf("newtmp: %s\n", newtmp); free(tmp); free(expanded); tmp = newtmp; endc = 0; startc = 0; start=tmp; } else { start++; startc++; } } } return tmp; } else if(thisvk->valtype == REG_DWORD) { char* tmp; tmp = malloc(8); sprintf(tmp, "%d",thisvk->mydata); return tmp; } } } free(szname); } } } return NULL; } NK* getkey(char* base, NK* thisnk, char** path) { NK* tmp; LF* lfrec = (LF*) &(base[thisnk->mylfrec]); HASH* hasharray = (HASH*) lfrec +1; int i; char* element; if((element = str_token(path, "\\")) != NULL) { if(thisnk->numchildren > 0) { for(i=0; inumchildren; i++) { tmp = (NK*)&(base[(hasharray+i)->nkrec]); char* szname; szname = (char*) malloc (tmp->namesize+1); strncpy(szname,(char*)(tmp+1),tmp->namesize+1); szname[tmp->namesize]= 0; if(strcmp(szname,element) == 0){ thisnk = getkey(base, tmp, path); free(szname); return thisnk; } free(szname); } return NULL; } } return thisnk; } /* Reentrant strtok, taken from a Usenet post: * http://groups.google.com/group/comp.lang.c/msg/9e92ba098baa55ac?dmode=source */ char *str_token( char **string, char *delimiters ) { char *rv, *wrk, empty[] = ""; /******************************************************************/ /* Beware the NULL pointer ! */ /******************************************************************/ if ( delimiters == NULL ) delimiters = empty; if ( string == NULL || *string == NULL || **string == '\0' ) rv = NULL; /******************************************************************/ /* If there are no delimiters the string is the token. */ /******************************************************************/ else if ( ( wrk = strpbrk( *string, delimiters ) ) == NULL ) { rv = *string; *string += strlen( rv ); } /******************************************************************/ /* Skip past any delimiters at the beginning of the string. */ /******************************************************************/ else if ( wrk == *string ) { *string += strspn( wrk, delimiters ); rv = str_token( string, delimiters ); } /******************************************************************/ /* Got a token! Null terminate it and prep for the next call. */ /******************************************************************/ else { *wrk++ = '\0'; rv = *string; *string = wrk + strspn( wrk, delimiters ); } return rv; } // vim:ai:et:sts=4:tw=80:sw=4: migration-assistant-0.6.13/Makefile0000664000000000000000000000375213035341452014140 0ustar ARGS=-g -Wall -D_GNU_SOURCE LIBXML_LIBS := $(shell xml2-config --libs) LIBXML_CFLAGS := $(shell xml2-config --cflags) BIN=$(DESTDIR)/usr/bin CPPFLAGS:=$(shell dpkg-buildflags --get CPPFLAGS) CFLAGS:=$(shell dpkg-buildflags --get CFLAGS) LDFLAGS:=$(shell dpkg-buildflags --get LDFLAGS) all: ma-import ma-search-items ma-search-users registry.o : registry.c registry.h $(CC) $(CFLAGS) $(CPPFLAGS) $(ARGS) -c registry.c # TODO: Split XML utils out of regular utils. ma-search-users : registry.o utils.o ma-search-users.c $(CC) $(CFLAGS) $(CPPFLAGS) $(ARGS) -c ma-search-users.c $(CC) $(LDFLAGS) $(ARGS) -o ma-search-users ma-search-users.o registry.o utils.o $(LIBXML_LIBS) ma-search-items : registry.o utils.o search-items.c $(CC) $(CFLAGS) $(CPPFLAGS) $(ARGS) -c search-items.c $(CC) $(LDFLAGS) $(ARGS) -o ma-search-items search-items.o registry.o utils.o $(LIBXML_LIBS) ma-import : gaim-import.o windows-import.o evolution-import.o firefox-import.o import.o utils.o $(CC) $(CFLAGS) $(CPPFLAGS) $(ARGS) -c import.c $(CC) $(LDFLAGS) $(ARGS) -o ma-import gaim-import.o windows-import.o firefox-import.o evolution-import.o registry.o import.o utils.o $(LIBXML_LIBS) evolution-import.o : registry.o utils.o evolution-import.c $(CC) $(CFLAGS) $(CPPFLAGS) $(ARGS) $(LIBXML_CFLAGS) -c evolution-import.c gaim-import.o : registry.o utils.o gaim-import.c $(CC) $(CFLAGS) $(CPPFLAGS) $(ARGS) $(LIBXML_CFLAGS) -c gaim-import.c utils.o: utils.c utils.h $(CC) $(CFLAGS) $(CPPFLAGS) $(ARGS) $(LIBXML_CFLAGS) -c utils.c firefox-import.o: firefox-import.c registry.o $(CC) $(CFLAGS) $(CPPFLAGS) $(ARGS) -c firefox-import.c windows-import.o: windows-import.c utils.o registry.o $(CC) $(CFLAGS) $(CPPFLAGS) $(ARGS) -c windows-import.c strip: ma-import ma-search-items strip --remove-section=.comment --remove-section=.note ma-import ma-search-items clean : -rm -f *.o ma-import ma-search-items ma-search-users install: install -d $(BIN) cp ma-import $(BIN) cp ma-search-items $(BIN) .PHONY: clean install strip all migration-assistant-0.6.13/search-items.c0000664000000000000000000002545413035341452015233 0ustar #include #include #include #include #include #include #include #include "registry.h" #include "utils.h" /* Windows Applications */ /* Instant Messaging */ const char* windowsxp_yahoo (void) { // Doesn't account for more than one account. // Doesn't matter here, but just don't do this at the import stage. char* registry_key; registry_key = findkey(user_key_file, "\\Software\\Yahoo\\pager\\Yahoo! User ID"); if(registry_key) { free(registry_key); return "Yahoo"; } else { return NULL; } } const char* windowsxp_gaim (void) { FILE* fp; char* accounts_file; char* accounts_file_new; char* appdata = NULL; char* path = NULL; appdata = findkey(user_key_file, "\\Software\\Microsoft\\Windows\\" "CurrentVersion\\Explorer\\Shell Folders\\Local AppData"); if(!appdata) { return NULL; } path = reformat_path(appdata); if(!path) return NULL; free(appdata); asprintf(&accounts_file, "%s/%s/%s", from_location, path, "/.gaim/accounts.xml"); asprintf(&accounts_file_new, "%s/%s/%s", from_location, path, "/.purple/accounts.xml"); free(path); fp = fopen(accounts_file, "r"); free(accounts_file); if(fp != NULL) { fclose(fp); return "Pidgin"; } fp = fopen(accounts_file_new, "r"); free(accounts_file_new); if(fp != NULL) { fclose(fp); return "Pidgin"; } return NULL; } const char* windowsxp_msn (void) { return NULL; } const char* windowsxp_aim_triton (void) { /* Any directory in * Documents and Settings\User\Local Settings\Application Data\AOL\UserProfiles * aside from "All Users" is an account. */ DIR* dir; struct dirent *entry; struct stat st; char* dirname; char* appdata = NULL; char* path = NULL; char* profile = NULL; appdata = findkey(user_key_file, "\\Software\\Microsoft\\Windows\\" "CurrentVersion\\Explorer\\Shell Folders\\Local AppData"); if(!appdata) { return NULL; } path = reformat_path(appdata); if(!path) return NULL; free(appdata); asprintf(&dirname, "%s/%s/%s", from_location, path, "AOL/UserProfiles"); free(path); dir = opendir(dirname); if(!dir) return NULL; while((entry = readdir(dir)) != NULL) { asprintf(&profile, "%s/%s", dirname, entry->d_name); if( -1 == stat(profile, &st)) { fprintf(stderr, "Unable to stat %s.\n", profile); free(profile); } else if(S_ISDIR(st.st_mode)) { free(profile); if(strcmp(entry->d_name,".") == 0 || strcmp(entry->d_name,"..") == 0) continue; if(strcmp(entry->d_name,"All Users") != 0) return "AIM Triton"; } } free(dirname); return NULL; } /* Web Browsers */ const char* windowsxp_opera (void) { char* filename; char* appdata = NULL; char* path = NULL; appdata = findkey(user_key_file, "\\Software\\Microsoft\\Windows\\" "CurrentVersion\\Explorer\\Shell Folders\\Local AppData"); if(!appdata) { return NULL; } path = reformat_path(appdata); if(!path) return NULL; free(appdata); asprintf(&filename, "%s/%s/%s", from_location, path, "Opera/Opera/profile/opera6.adr"); free(path); FILE* fp; if((fp = fopen(filename, "r")) != NULL) { fclose(fp); free(filename); return "Opera"; } else { free(filename); return NULL; } } const char* windowsxp_firefox (void) { DIR* dir; struct dirent *entry; struct stat st; char* dirname; char* appdata = NULL; char* path = NULL; char* profile = NULL; appdata = findkey(user_key_file, "\\Software\\Microsoft\\Windows\\" "CurrentVersion\\Explorer\\Shell Folders\\Local AppData"); if(!appdata) { return NULL; } path = reformat_path(appdata); if(!path) return NULL; free(appdata); asprintf(&dirname, "%s/%s/%s", from_location, path, "Mozilla/Firefox/Profiles"); free(path); dir = opendir(dirname); if(!dir) return NULL; while((entry = readdir(dir)) != NULL) { asprintf(&profile, "%s/%s", dirname, entry->d_name); if( -1 == stat(profile, &st)) { fprintf(stderr, "Unable to stat %s.\n", profile); free(profile); } else if(S_ISDIR(st.st_mode)) { free(profile); if(strcmp(entry->d_name,".") == 0 || strcmp(entry->d_name,"..") == 0) continue; free(dirname); return "Mozilla Firefox"; } } free(dirname); return NULL; } const char* windowsxp_iexplorer (void) { DIR* dir; struct dirent *entry; char* path, *iedir; char* favorites = NULL; favorites = findkey(user_key_file, "\\Software\\Microsoft\\Windows\\" "CurrentVersion\\Explorer\\Shell Folders\\Favorites"); if(!favorites) return NULL; path = reformat_path(favorites); if(!path) return NULL; free(favorites); asprintf(&iedir, "%s/%s", from_location, path); free(path); dir = opendir(iedir); if(!dir) return NULL; free(iedir); while((entry = readdir(dir)) != NULL) { if(strcmp(entry->d_name,".") == 0 || strcmp(entry->d_name,"..") == 0) continue; if(strcmp(entry->d_name, "Desktop.ini") == 0) continue; return "Internet Explorer"; } return NULL; } /* Windows Settings */ const char* windowsxp_wallpaper (void) { return "Wallpaper"; } const char* windowsxp_userpicture (void) { char* appdata = NULL; char* path = NULL; char* from = NULL; FILE* fp; appdata = findkey(software_key_file, "\\Microsoft\\Windows\\CurrentVersion\\" "Explorer\\Shell Folders\\Common AppData"); if(!appdata) return NULL; path = reformat_path(appdata); if(!path) return NULL; free(appdata); asprintf(&from, "%s/%s/Microsoft/User Account Pictures/%s.bmp", from_location, path, from_user); free(path); if((fp = fopen(from, "r")) == NULL) return NULL; else return "User Picture"; } const char* windowsxp_mydocuments (void) { // Only return success if there's more than the default in there. return "My Documents"; } const char* windowsxp_mymusic (void) { // Only return success if there's more than the default in there. return "My Music"; } const char* windowsxp_mypictures (void) { // Only return success if there's more than the default in there. return "My Pictures"; } const char* windowsxp_proxy (void) { // Need to add REG_DWORD support to the registry utils. char* registry_key; registry_key = findkey(user_key_file, "\\Software\\Microsoft\\Windows\\CurrentVersion\\" "Internet Settings\\ProxyEnable"); if(registry_key && (strcmp(registry_key, "0x00000001") == 0)) return "Proxy"; else return NULL; } const char* windowsxp_outlookexpress (void) { char* registry_key = NULL; registry_key = findkey(user_key_file, "\\Software\\Microsoft\\Internet Account Manager\\Accounts\\00000001" "\\Account Name"); if(registry_key) return "Outlook Express"; else return NULL; } /* Linux Applications */ const char* linux_gaim (void) { char* accounts_file; char* accounts_file_new; FILE* fp; asprintf(&accounts_file, "%s/%s/%s/%s", from_location, "home", from_user, ".gaim/accounts.xml"); asprintf(&accounts_file_new, "%s/%s/%s/%s", from_location, "home", from_user, ".purple/accounts.xml"); fp = fopen(accounts_file, "r"); if(fp != NULL) { fclose(fp); return "Pidgin"; } fp = fopen(accounts_file_new, "r"); if(fp != NULL) { fclose(fp); return "Pidgin"; } return NULL; } const char* linux_firefox (void) { DIR* dir; struct dirent *entry; struct stat st; char* dirname; char* profile = NULL; asprintf(&dirname, "%s/%s/%s/%s", from_location, "home", from_user, ".mozilla/firefox"); dir = opendir(dirname); if(!dir) return NULL; while((entry = readdir(dir)) != NULL) { asprintf(&profile, "%s/%s", dirname, entry->d_name); if( -1 == stat(profile, &st)) { fprintf(stderr, "Unable to stat %s.\n", profile); free(profile); } else if(S_ISDIR(st.st_mode)) { free(profile); if(strcmp(entry->d_name,".") == 0 || strcmp(entry->d_name,"..") == 0) continue; free(dirname); return "Mozilla Firefox"; } } free(dirname); return NULL; } const char* linux_evolution (void) { FILE* fp = NULL; char* file = NULL; asprintf(&file, "%s/%s/%s/%s", from_location, "home", from_user, ".gconf/apps/evolution/mail/\%gconf.xml"); if((fp = fopen(file, "r")) != NULL) { fclose(fp); free(file); return "Evolution"; } else { free(file); return NULL; } } void usage(void) { puts("USAGE: --path=\"PATH\" --user=\"USER\" --ostype=\"OSTYPE\""); exit(EXIT_FAILURE); } int main(int argc, char** argv) { if(argc < 4) usage(); enum { WINDOWSXP, LINUX }; int ostype; int test = 0; int passed = 0; const char* ret; const char* (**tests)(); const char* (*windowsxp_tests[])() = { windowsxp_yahoo, windowsxp_gaim, windowsxp_msn, windowsxp_aim_triton, windowsxp_opera, windowsxp_firefox, windowsxp_iexplorer, windowsxp_wallpaper, windowsxp_userpicture, windowsxp_mydocuments, windowsxp_mymusic, windowsxp_mypictures, windowsxp_proxy, windowsxp_outlookexpress, NULL, }; const char* (*linux_tests[])() = { linux_gaim, linux_firefox, linux_evolution, NULL, }; static struct option long_options[] = { { "path", required_argument, NULL, 'p' }, { "ostype", required_argument, NULL, 'o' }, { "user", required_argument, NULL, 'u' }, { NULL, 0, NULL, 0 } }; int c; while(1) { c = getopt_long_only(argc, argv, "", long_options, NULL); if(c == -1) break; switch(c) { case 'o' : if(strcmp(optarg, "linux") == 0) ostype = LINUX; else if(strcmp(optarg, "windowsxp") == 0) ostype = WINDOWSXP; else usage(); break; case 'p' : from_location = strdup(optarg); break; case 'u' : from_user = strdup(optarg); break; default: usage(); } } if(ostype == LINUX) tests = linux_tests; else if(ostype == WINDOWSXP) { tests = windowsxp_tests; initialize_registry_paths(); } while(tests[test]) { ret = tests[test](); if(ret) { if(passed) printf(", "); printf("%s", ret); passed = 1; } test++; } if(passed) putchar('\n'); return 0; } // vim:ai:et:sts=4:tw=80:sw=4: migration-assistant-0.6.13/gaim-import.c0000664000000000000000000001644611732445313015100 0ustar #include #include #include #include #include #include #include #include "gaim-import.h" #include "registry.h" #include "utils.h" xmlDoc* gaim_new_accounts_file(void) { static xmlDoc* doc = NULL; xmlNode* node = NULL; char* accounts_file; int opts = XML_PARSE_NOBLANKS | XML_PARSE_NOERROR | XML_PARSE_RECOVER; if(!doc) { asprintf(&accounts_file, "%s/%s/%s/%s", to_location, "home", to_user, ".purple/accounts.xml"); create_file(accounts_file); doc = xmlReadFile(accounts_file, NULL, opts); free(accounts_file); node = xmlDocGetRootElement(doc); if(!node) { node = xmlNewNode(NULL, (xmlChar*) "accounts"); xmlNewProp(node, (xmlChar*) "version", (xmlChar*) "1.0"); xmlDocSetRootElement(doc, node); } } return doc; } void gaim_save_accounts_file(void) { xmlDoc* doc = gaim_new_accounts_file(); char* accounts_file; asprintf(&accounts_file, "%s/%s/%s/%s", to_location, "home", to_user, ".purple/accounts.xml"); xmlSaveFormatFile(accounts_file, doc, 1); } int gaim_account_exists(xmlNode* node) { xmlNode* ptr = NULL; xmlDoc* doc = NULL; xmlChar* username = NULL; xmlChar* protocol = NULL; node = node->children; while(node != NULL) { if(xmlStrcmp(node->name, (xmlChar*) "name") == 0) username = node->children->content; else if(xmlStrcmp(node->name, (xmlChar*) "protocol") == 0) protocol = node->children->content; node = node->next; } doc = gaim_new_accounts_file(); node = xmlDocGetRootElement(doc); node = node->children; int found = 0; // For each account. while(node) { if(node->type == XML_ELEMENT_NODE && (xmlStrcmp(node->name, (xmlChar*) "account") == 0)) { ptr = node->children; // For each account property. while(ptr != NULL) { if(xmlStrcmp(ptr->name, (xmlChar*) "name") == 0) { if(xmlStrcmp(ptr->children->content, (xmlChar*) username) == 0) { found++; } } if(xmlStrcmp(ptr->name, (xmlChar*) "protocol") == 0) { if(xmlStrcmp(ptr->children->content, (xmlChar*) protocol) == 0) { found++; } } ptr = ptr->next; } if(found == 2) return 1; found = 0; } node = node->next; } return 0; } void gaim_add_account(xmlNode* node) { xmlDoc* doc = gaim_new_accounts_file(); xmlNode* top = xmlDocGetRootElement(doc); xmlAddChild(top, node); } void gaim_import_gaim(void) { xmlDoc* doc = NULL; xmlNode* node, *node_copy = NULL; char* accounts_file; char* path; char* appdata = NULL; FILE* fp; if(os_type == LINUX) { asprintf(&accounts_file, "%s/%s/%s/%s", from_location, "home", from_user, ".gaim/accounts.xml"); fp = fopen(accounts_file, "r"); if(fp == NULL) { free(accounts_file); asprintf(&accounts_file, "%s/%s/%s/%s", from_location, "home", from_user, ".purple/accounts.xml"); } else fclose(fp); } else if(os_type == WINDOWSXP) { appdata = findkey(user_key_file, "\\Software\\Microsoft\\Windows\\" "CurrentVersion\\Explorer\\Shell Folders\\Local AppData"); if(!appdata) { printf("Couldn't find %s\n", appdata); return; } path = reformat_path(appdata); free(appdata); asprintf(&accounts_file, "%s/%s/%s", from_location, path, "/.gaim/accounts.xml"); fp = fopen(accounts_file, "r"); if(fp == NULL) { free(accounts_file); asprintf(&accounts_file, "%s/%s/%s", from_location, path, "/.purple/accounts.xml"); } else fclose(fp); free(path); } if(!accounts_file) return; doc = xmlReadFile(accounts_file, NULL, XML_PARSE_NOBLANKS); free(accounts_file); if(!doc) return; node = xmlDocGetRootElement(doc); node = node->children; while(node) { if(node->type == XML_ELEMENT_NODE && (xmlStrcmp(node->name, (xmlChar*) "account") == 0)) { if(!gaim_account_exists(node)) { node_copy = xmlCopyNode(node, 1); gaim_add_account(node_copy); } } node = node->next; } gaim_save_accounts_file(); } void gaim_import_other(const char* proto, const char* username, const char* password) { xmlNode *account, *name, *protocol; account = xmlNewNode(NULL, (xmlChar*) "account"); // protocol must come before name in the accounts file otherwise Gaim will // have a bad time. protocol = xmlNewChild(account, NULL, (xmlChar*) "protocol", (xmlChar*) proto); name = xmlNewChild(account, NULL, (xmlChar*) "name", (xmlChar*) username); if(!gaim_account_exists(account)) gaim_add_account(account); } void gaim_import_yahoo(void) { char* username; username = findkey(user_key_file, "\\Software\\Yahoo\\pager\\Yahoo! User ID"); if(username) { gaim_import_other("prpl-yahoo", username, NULL); free(username); gaim_save_accounts_file(); } else { puts("could not get yahoo ID from registry."); exit(EXIT_FAILURE); } } // FIXME: This is a terrible test. If the user has an AIM account with the // same username as the one they use for Windows, the test will fail. void gaim_import_aimtriton(void) { DIR *dir, *dir2; struct dirent *entry, *entry2; struct stat buf; struct stat st; char* dirname, *uprofile, *cls, *path; char* appdata = NULL; char* profile = NULL; appdata = findkey(user_key_file, "\\Software\\Microsoft\\Windows\\" "CurrentVersion\\Explorer\\Shell Folders\\Local AppData"); if(!appdata) { printf("Couldn't find %s\n", appdata); return; } path = reformat_path(appdata); free(appdata); asprintf(&dirname, "%s/%s/%s", from_location, path, "AOL/UserProfiles"); free(path); dir = opendir(dirname); if(!dir) { printf("Could not open AIM profile root directory: %s\n", dirname); free(dirname); return; } while((entry = readdir(dir)) != NULL) { asprintf(&profile, "%s/%s", dirname, entry->d_name); if( -1 == stat(profile, &st)) { fprintf(stderr, "Unable to stat %s.\n", profile); free(profile); } else if(!(S_ISDIR(st.st_mode))) { free(profile); continue; } else if(strcmp(entry->d_name,"All Users") == 0 || (strcmp(entry->d_name,".") == 0 || strcmp(entry->d_name,"..") == 0)) { free(profile); continue; } free(profile); asprintf(&uprofile, "%s/%s", dirname, entry->d_name); dir2 = opendir(uprofile); if(!dir2) { printf("Could not open user's AIM profile directory: %s\n", uprofile); free(uprofile); return; } while((entry2 = readdir(dir2)) != NULL) { if((strcmp(entry2->d_name,from_user) != 0) && ((strcmp(entry2->d_name,".") != 0) && (strcmp(entry2->d_name,"..") != 0))) { asprintf(&cls, "%s/%s/cls", uprofile, entry2->d_name); if(stat(cls, &buf) == 0) gaim_import_other("prpl-oscar", entry2->d_name, NULL); free(cls); } } closedir(dir2); free(uprofile); } free(dirname); closedir(dir); gaim_save_accounts_file(); } migration-assistant-0.6.13/firefox-import.h0000664000000000000000000000016011732445313015614 0ustar void firefox_import_firefox(void); void firefox_import_internetexplorer(void); void firefox_import_opera(void); migration-assistant-0.6.13/ma-apply0000775000000000000000000000460211737116665014156 0ustar #!/bin/sh set -e . /usr/share/debconf/confmodule . /usr/share/migration-assistant/ma-script-utils OLDIFS="$IFS" NEWLINE=' ' newns "$@" if [ -z "$1" ]; then mapath="/usr/bin" else mapath="$1" fi db_get migration-assistant/partitions || exit 10 IFS="$NEWLINE" selection=`echo "$RET" | sed -e 's/, /\n/g'` for choice in $selection; do # Microsoft Windows XP Professional (/dev/hda1) IFS="$OLDIFS" location=$(LC_ALL=C expr "$choice" : '.*(\(.*\))') # /dev/hda1 IFS="$NEWLINE" for line in `WINOSDATA=true os-prober`; do IFS="$OLDIFS" loc="${line%%:*}" if [ "$location" != "$loc" ]; then continue fi set_os_type "$line" || continue path=${loc#*/*/} mount_os "$ostype" "$loc" || continue db_get migration-assistant/$path/users || continue IFS="$NEWLINE" user_selection=`echo "$RET" | sed -e 's/, /\n/g'` for usr in $user_selection; do IFS="$OLDIFS" formatted_user=`echo "$usr" | sed -e 's/ /+/g' | sed -e 's/,+/, /g'` db_get migration-assistant/$path/$formatted_user/user || continue new_user=$RET if [ $(grep -c ^$new_user: $ROOT/etc/passwd) -eq 0 ]; then log "creating user $new_user" db_get migration-assistant/new-user/$new_user/password || continue pass=$RET db_get migration-assistant/new-user/$new_user/fullname || continue fn=$RET add_user "$new_user" "$fn" "$pass" fi db_get migration-assistant/$path/$formatted_user/items || continue log "importing: $RET" IFS="$NEWLINE" item_selection=`echo "$RET" | sed -e 's/, /\n/g'` for itm in $item_selection; do IFS="$OLDIFS" itm=$(echo $itm | sed -e 's/ //g' | tr [A-Z] [a-z]) log-output -t migration-assistant $mapath/ma-import \ --target="$itm" \ --ostype="$ostype" \ --fromuser="$usr" \ --frompath="$mountpoint" \ --touser="$new_user" \ --topath="$ROOT" \ || error "importing $itm failed." IFS="$NEWLINE" done IFS="$NEWLINE" done IFS="$OLDIFS" unmount_os IFS="$NEWLINE" done done migration-assistant-0.6.13/utils.c0000664000000000000000000003215711732445313014010 0ustar #include #include #include #include #include #include #include // For gconf utils #include #include #include // for copyfile and rcopy #include #include #include "utils.h" #include "registry.h" /* This function discovers the correct case-sensitive file or directory path * from a case-insensitive file or directory path. * * It assumes that only one case-insensitive file or directory matches the * case-sensitive path. * * FIXME: It will accept somefile.ext/ * FIXME: chdir is not thread-safe, however this currently does not get called * in areas that might be optimized into concurrent processes or threads. */ char* get_insensitive_path(const char* path) { DIR *d; char* head = NULL; char* start; char* end; int done = 0; int found; char* ret = ""; struct dirent *de; int cwd; if(!path || *path == '\0') { fprintf(stderr, \ "Error: get_insensitive_path was passed a NULL string.\n"); return NULL; } head = strdup(path); if(head == NULL) { fprintf(stderr, "Fatal: Out of memory.\n"); exit(EXIT_FAILURE); } end = head; if ((cwd = open(".", O_RDONLY)) == -1) { fprintf(stderr, "Fatal: Could not get a file descriptor for the" \ " current working directory.\n"); exit(EXIT_FAILURE); } if(*end == '/') { ret = "/"; chdir("/"); end++; } while(!done) { start = end; if(*start == '\0') break; while(*end != '/' && *end != '\0') end++; if(*end == '\0') done = 1; else *end = '\0'; end++; d = opendir("."); found = 0; while((de = readdir(d)) != NULL) { if(strcasecmp(de->d_name, start) == 0) { found = 1; break; } } if(!found) { closedir(d); fprintf(stderr, "Error: Could not find the path %s\n", path); return NULL; } else { if(done) asprintf(&ret, "%s%s", ret, de->d_name); else asprintf(&ret, "%s%s/", ret, de->d_name); chdir(ret); } closedir(d); } if(head) free(head); if (fchdir(cwd) == -1) { fprintf(stderr, "Fatal: Could not change back to the original " \ "directory.\n"); exit(EXIT_FAILURE); } //printf("ret: %s\n", ret); return ret; } void initialize_registry_paths() { initialize_software_registry_path(); initialize_user_registry_path(); } void initialize_software_registry_path() { char* tmp; software_key_file = NULL; asprintf(&tmp, "%s/WINDOWS/system32/config/software", from_location); software_key_file = get_insensitive_path(tmp); if(tmp) free(tmp); if(software_key_file == NULL) { asprintf(&tmp, "%s/WINNT/system32/config/software", from_location); software_key_file = get_insensitive_path(tmp); if(software_key_file == NULL) { fprintf(stderr, "Fatal: Could not find the SOFTWARE registry " \ "hive at %s.\n", tmp); exit(EXIT_FAILURE); } if(tmp) free(tmp); } } char* get_profiles_dir(const char *mountpoint) { char *profilesdir = findkey(software_key_file, "\\Microsoft\\Windows NT\\CurrentVersion" "\\ProfileList\\ProfilesDirectory"); if(!profilesdir) { fprintf(stderr, "ma-search-users: Error. Could not find " "ProfilesDirectory.\n"); exit(EXIT_FAILURE); } char* pdir = reformat_path(profilesdir); free(profilesdir); asprintf(&profilesdir, "%s/%s", mountpoint, pdir); free(pdir); fprintf(stderr, "profilesdir: %s\n", profilesdir); return profilesdir; } void initialize_user_registry_path() { char* tmp; user_key_file = NULL; char* profilesdir = get_profiles_dir(from_location); asprintf(&tmp, "%s/%s/%s", profilesdir, from_user, "NTUSER.DAT"); user_key_file = get_insensitive_path(tmp); if(user_key_file == NULL) { fprintf(stderr, "Fatal: Could not find the USER registry hive at " \ "%s\n.", tmp); exit(EXIT_FAILURE); } if(tmp) free(tmp); } // Taken from comp.lang.c: // http://groups.google.com/group/comp.lang.c/msg/8d7be5a7387de73f?dmode=source char *strrep(const char *str, const char *old, const char *new) { char *ret, *r; const char *p, *q; size_t len_str = strlen(str); size_t len_old = strlen(old); size_t len_new = strlen(new); size_t count; for(count = 0, p = str; (p = strstr(p, old)); p += len_old) count++; ret = malloc(count * (len_new - len_old) + len_str + 1); if(!ret) return NULL; for(r = ret, p = str; (q = strstr(p, old)); p = q + len_old) { count = q - p; memcpy(r, p, count); r += count; strcpy(r, new); r += len_new; } strcpy(r, p); return ret; } char* reformat_path(const char* from) { /* takes a string of the form: * C:\Windows\Something * and returns the following string that must be free()'d: * Windows/Something */ if(strstr(from, "C:\\") == NULL) { fprintf(stderr, "Pointed to a location other than C:"); return NULL; } /* +1 for \0, -3 for C: */ char* ret = malloc(strlen(from)-2); strcpy(ret, from+3); char* tmp = ret; while(*tmp != '\0') { if(*tmp == '\\') *tmp = '/'; tmp++; } return ret; } // Modified from Advanced Programming in the Unix Environment. void copyfile(const char* from, const char* to) { int fdin, fdout; struct stat statbuf; const int mode = S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH; create_file(to); if ((fdin = open(from, O_RDONLY)) < 0) { printf("can't open %s for reading\n", from); exit(EXIT_FAILURE); } // if file exists, check to see if the files are the same (byte by byte, // returning on the first inconsistant byte) and if not append a .1 at the // end (followed by .2, .3, etc). if ((fdout = open(to, O_RDWR | O_CREAT | O_TRUNC, mode)) < 0) { printf("can't creat %s for writing\n", to); exit(EXIT_FAILURE); } if (fstat(fdin, &statbuf) < 0) { /* need size of input file */ puts("fstat error"); exit(EXIT_FAILURE); } if(statbuf.st_size == 0) { close(fdin); close(fdout); return; } /* does the file copy */ /* simplified version of coreutils/src/copy.c */ blksize_t blocksize = statbuf.st_blksize; char *buf = alloca(blocksize); for (;;) { ssize_t n_read = read(fdin, buf, blocksize); if (n_read < 0) { printf("can't read in %s\n", from); exit(EXIT_FAILURE); } if (n_read == 0) break; if (write(fdout, buf, n_read) != n_read) { printf("can't write in %s\n", to); exit(EXIT_FAILURE); } } close(fdin); close(fdout); } void rcopy(const char* from, const char* to) { struct dirent *de; struct stat st; DIR *d; char* fpn, *tpn; char* extension = NULL; d = opendir(from); if(!d) { printf("could not open dir, %s\n", from); exit(EXIT_FAILURE); } mkdir(to, 0755); while((de = readdir(d)) != NULL) { if(strcmp(de->d_name, ".") == 0 || strcmp(de->d_name, "..") == 0) continue; asprintf(&fpn, "%s/%s", from, de->d_name); asprintf(&tpn, "%s/%s", to, de->d_name); if( -1 == stat(fpn, &st)) { fprintf(stderr, "Unable to stat %s.\n", fpn); } else if(S_ISREG(st.st_mode)) { extension = de->d_name; while(*extension != '\0') extension++; while(extension != de->d_name && *extension != '.') extension--; if(extension == de->d_name) extension = ""; else extension++; // TODO: Make a array of ignored extensions instead. if(!((strcmp(extension, "ini") == 0) || (strcmp(extension, "lnk") == 0))) { copyfile(fpn, tpn); } } else if(S_ISDIR(st.st_mode)) { mkdir(tpn, 0755); // I think we can axe this. See above. rcopy(fpn, tpn); } free(fpn); free(tpn); } closedir(d); } /* taken from partconf/partconf.c */ void makedirs(const char *dir) { DIR *d; char *dirtmp, *basedir; if ((d = opendir(dir)) != NULL) { closedir(d); return; } if (mkdir(dir, 0755) < 0) { dirtmp = strdup(dir); basedir = dirname(dirtmp); makedirs(basedir); free(dirtmp); mkdir(dir, 0755); } } void create_file(const char* file) { FILE* fp; char* tmp; char* filename; int fd; if((fp = fopen(file, "r")) != NULL) { fclose(fp); return; } tmp = strdup(file); filename = dirname(tmp); makedirs(filename); free(tmp); fd = creat(file, S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH); close(fd); } void add_wallpaper (const char* path) { xmlDoc* doc = NULL; xmlNode* root, *wallpaper, *ptr = NULL; char* file, *name, *orig_name; const int opts = XML_PARSE_NOBLANKS | XML_PARSE_NOERROR | XML_PARSE_RECOVER; orig_name = strdup(path); name = basename(orig_name); asprintf(&file, "%s/home/%s/.gnome2/backgrounds.xml", to_location, to_user); create_file(file); doc = xmlReadFile(file, NULL, opts); root = xmlDocGetRootElement(doc); if(!root) { // FIXME: set DTD. root = xmlNewNode(NULL, (xmlChar*) "wallpapers"); xmlDocSetRootElement(doc, root); } else { wallpaper = root->children; while(wallpaper != NULL) { ptr = wallpaper->children; while(ptr != NULL) { if((xmlStrcmp(ptr->name, (xmlChar*) "filename") == 0) && (xmlStrcmp(ptr->children->content, (xmlChar*) path) == 0)) { return; // Already set. } ptr = ptr->next; } wallpaper = wallpaper->next; } } wallpaper = xmlNewChild(root, NULL, (xmlChar*) "wallpaper", NULL); xmlNewProp(wallpaper, (xmlChar*) "deleted", (xmlChar*) "false"); xmlNewTextChild(wallpaper, NULL, (xmlChar*) "name", (xmlChar*) name); xmlNewTextChild(wallpaper, NULL, (xmlChar*) "filename", (xmlChar*) path); xmlNewTextChild(wallpaper, NULL, (xmlChar*) "options", (xmlChar*) "scaled"); free(orig_name); xmlSaveFormatFile(file, doc, 1); free(file); } // yikes, get rid of this. void makegconfdirs(const char *dir) { DIR *d; char *dirtmp, *basedir, *gconf; if ((d = opendir(dir)) != NULL) { closedir(d); return; } if (mkdir(dir, 0755) < 0) { dirtmp = strdup(dir); basedir = dirname(dirtmp); makegconfdirs(basedir); free(dirtmp); mkdir(dir, 0755); } dirtmp = strdup(dir); basedir = basename(dirtmp); if(strcmp(basedir,".gconf") != 0) { asprintf(&gconf, "%s/%%gconf.xml", dir); creat(gconf, S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH); free(gconf); } free(dirtmp); } void set_gconf_key (const char* path, const char* name, gconf_type type, const char* value) { char* file, *gconf; xmlDoc* doc = NULL; xmlNode* root, *entry = NULL; const int opts = XML_PARSE_NOBLANKS | XML_PARSE_NOERROR | XML_PARSE_RECOVER; asprintf(&gconf, "%s/home/%s/.gconf/%s", to_location, to_user, path); asprintf(&file, "%s/%%gconf.xml", gconf); makegconfdirs(gconf); free(gconf); create_file(file); doc = xmlReadFile(file, NULL, opts); root = xmlDocGetRootElement(doc); if(!root) { root = xmlNewNode(NULL, (xmlChar*) "gconf"); xmlDocSetRootElement(doc, root); entry = xmlNewChild(root, NULL, (xmlChar*) "entry", NULL); xmlNewProp(entry, (xmlChar*) "name", (xmlChar*) name); } else { entry = root->children; while(entry != NULL) { if(xmlStrcmp(xmlGetProp(entry, (xmlChar*) "name"),(xmlChar*) name) == 0) break; entry = entry->next; } if(!entry) { entry = xmlNewChild(root, NULL, (xmlChar*) "entry", NULL); xmlNewProp(entry, (xmlChar*) "name", (xmlChar*) name); } } if(type == GCONF_STRING) { xmlSetProp(entry, (xmlChar*) "type", (xmlChar*) "string"); if(entry->children == NULL) xmlNewTextChild(entry, NULL, (xmlChar*) "stringvalue", (xmlChar*) value); else xmlNodeSetContent(entry->children, (xmlChar*) value); } else if (type == GCONF_BOOLEAN) { xmlSetProp(entry, (xmlChar*) "type", (xmlChar*) "bool"); xmlSetProp(entry, (xmlChar*) "value", (xmlChar*) value); } else if (type == GCONF_LIST_STRING) { xmlNode* li, *sv = NULL; xmlSetProp(entry, (xmlChar*) "type", (xmlChar*) "list"); xmlSetProp(entry, (xmlChar*) "ltype", (xmlChar*) "string"); if(entry->children == NULL) li = xmlNewChild(entry, NULL, (xmlChar*) "li", NULL); else li = entry->children; xmlSetProp(li, (xmlChar*) "type", (xmlChar*) "string"); sv = li->children; while(sv != NULL) { // Already exists. if(xmlStrcmp(sv->children->content, (xmlChar*) value) == 0) return; sv = sv->next; } xmlNewTextChild(li, NULL, (xmlChar*) "stringvalue", (xmlChar*) value); } xmlSaveFormatFile(file, doc, 1); } migration-assistant-0.6.13/ma-script-utils0000775000000000000000000001451211732445313015462 0ustar #!/bin/sh . /usr/share/debconf/confmodule newns () { [ "$OS_PROBER_NEWNS" ] || exec /usr/lib/os-prober/newns "$0" "$@" } error () { logger -t migration-assistant "error: $@" } log () { logger -t migration-assistant "info: $@" } ostype="" set_os_type () { # Rather than test for every distro possible in the shortname, we test # the bootloader type for 'linux.' This *should* be fine as we're only # working with user's home directories. if [ ${1##*:} = "linux" ]; then ostype="linux" return 0 fi case `LC_ALL=C expr match "$1" '.*:.*:\(.*\):.*'` in "Windows" ) ostype="windowsxp" return 0 ;; Windows[0-9] ) ostype="windowsxp" return 0 ;; "Windows9xMe" ) ostype="windows9x" return 0 ;; "MacOSX" ) ostype="macosx" return 0 ;; *) echo "Unknown ostype from $1" 1>&2 return 1 ;; esac } mountpoint="/mnt/migrationassistant" unmount_os() { # If we didn't mount the device ourselves, don't unmount it. [ "$mountpoint" = "/mnt/migrationassistant" ] || return 0 unmount_previously_run= device="$1" if [ -f /etc/mtab ]; then MTAB=/etc/mtab else MTAB=/proc/mounts fi while :; do failed= ISMOUNTED= if [ "$device" ]; then ISMOUNTED=$(grep "^$device " $MTAB) || ISMOUNTED= else ISMOUNTED=$(grep " $mountpoint " $MTAB) || ISMOUNTED= fi if [ -z "$ISMOUNTED" ]; then break fi HOME=$(grep " $mountpoint/home " $MTAB) || HOME= if [ "$HOME" ]; then umount "$mountpoint/home" || failed="$mountpoint/home" fi if [ -z "$failed" ]; then if [ -z "$device" ]; then umount $mountpoint || failed="$mountpoint" else umount $device || failed="$device" fi fi if [ -z "$failed" ]; then break fi # lets try waiting briefly once before we completely give up on # unmounting the partition and dump the problem on the user. if [ -z "$unmount_previously_run" ]; then unmount_previously_run=1 sleep 15 continue fi db_reset migration-assistant/failed-unmount db_subst migration-assistant/failed-unmount MOUNTED "$failed" db_input critical migration-assistant/failed-unmount || true db_go || exit 10 db_get migration-assistant/failed-unmount [ "$RET" = true ] || exit 10 done } mount_os () { ostype="$1" device="$2" if [ "$1" = "linux" ]; then mkdir -p $mountpoint unmount_os $device if ! mount $device $mountpoint; then error "Failed to mount $device" exit 1 fi if [ -f "$mountpoint/etc/fstab" ]; then while read uuid mp rest; do echo "$uuid" | grep -q '^#' && continue if [ "$mp" != "/home" ]; then continue fi devname= if [ -n "${uuid#*=}" ]; then if [ "${uuid%=*}" = "UUID" ]; then devname="/dev/disk/by-uuid/${uuid#*=}" elif [ "${uuid%=*}" = "LABEL" ]; then devname="/dev/disk/by-label/${uuid#*=}" fi fi if [ -n "$devname" ]; then uuid=$(readlink -e "$devname") || uuid= if [ -z "$uuid"]; then error "$devname does not exist." return 1 fi else error "couldn't understand $uuid." return 1 fi if [ ! -e "$uuid" ]; then # This happens when the IDE driver in the old OS # doesn't match the driver in the installer. The old # /home might be mounted on /dev/hda3 which could now # be /dev/sda3 or something entirely different. Since # there's no way to determine what the device is # without the old kernel loaded, we fail gracefully so # that we can continue to the next OS. error "$uuid does not exist." return 1 fi if ! mount $uuid "$mountpoint/home"; then unmount_os "$uuid" if ! mount $uuid "$mountpoint/home"; then error "failed to mount $uuid" return 1 fi fi break done < "$mountpoint/etc/fstab" fi elif [ "$1" = "windowsxp" ]; then # Since we don't have to worry about separate partitions making up the # whole system in Windows (yet), we can allow already mounted # partitions. This may fix some corner cases. At any rate, it's # required for Wubi to function properly. mnt=$(grep "$device" /proc/mounts | head -n1 | cut -d " " -f 2) [ -z "$mnt" ] && [ -f /etc/mtab ] && mnt=$(grep "$device" /etc/mtab | head -n1 | cut -d " " -f 2) [ -n "$mnt" ] && mountpoint=$mnt && return 0 mkdir -p $mountpoint unmount_os $device if ! mount -t ntfs $device $mountpoint -o umask=0022,nls=utf8 3>&-; then log "Mounting $device to $mountpoint with NTFS failed." if ! mount -t vfat $device $mountpoint -o umask=0022,utf8; then log "Mounting $device to $mountpoint with VFAT failed." return 1 fi fi fi } ROOT=/target add_user() { local username local fullname local password username="$1" fullname="$2" password="$3" chroot=chroot # Taken from user-setup/user-setup-apply # Add the user if [ -x $ROOT/usr/sbin/adduser ]; then $chroot $ROOT adduser --disabled-password --gecos \ "$fullname" "$username" >/dev/null || true else $chroot $ROOT useradd -c "$fullname" -m "$username" >/dev/null || true fi # Set the password $chroot $ROOT chpasswd </dev/null 2>&1 || true done fi } # vim:ai:et:sts=4:tw=80:sw=4: migration-assistant-0.6.13/ma-search-users.c0000664000000000000000000001071113035341452015634 0ustar #include #include #include #include #include #include "registry.h" #include "utils.h" void search_linux(const char* mountpoint) { DIR* dir; struct dirent *entry; struct stat st; char* fullpath = NULL; char* cwd; char* profile = NULL; int mult = 0; asprintf(&fullpath, "%s/home", mountpoint); dir = opendir(fullpath); if(!dir) { fprintf(stderr, "ma-search-users: Error. Unable to open %s\n", fullpath); exit(EXIT_FAILURE); } while((entry = readdir(dir)) != NULL) { asprintf(&profile, "%s/%s", fullpath, entry->d_name); if( -1 == stat(profile, &st)) { fprintf(stderr, "Unable to stat %s.\n", profile); free(profile); } else if(S_ISDIR(st.st_mode)) { free(profile); cwd = entry->d_name; if(strcmp(cwd,".") == 0 || strcmp(cwd,"..") == 0) continue; if(strcmp(cwd,"lost+found") == 0) continue; if(mult != 0) printf(", %s", cwd); else { printf("%s", cwd); mult = 1; } } } free(fullpath); closedir(dir); puts(""); } void search_windowsxp(const char* mountpoint) { DIR* dir; struct dirent *entry; struct stat st; char* cwd; char* profilesdir = NULL; char* allusers = NULL; char* defaultuser = NULL; char* defaultuser_junction = NULL; char* publicuser = NULL; char* profile = NULL; int mult = 0; from_location = mountpoint; initialize_software_registry_path(); profilesdir = get_profiles_dir(mountpoint); allusers = findkey(software_key_file, "\\Microsoft\\Windows NT\\CurrentVersion" "\\ProfileList\\AllUsersProfile"); if (!allusers) allusers = "All Users"; defaultuser = findkey(software_key_file, "\\Microsoft\\Windows NT\\CurrentVersion" "\\ProfileList\\DefaultUserProfile"); if (!defaultuser) { defaultuser = findkey(software_key_file, "\\Microsoft\\Windows NT\\CurrentVersion" "\\ProfileList\\Default"); if (defaultuser) { // Windows Vista char *path = reformat_path(defaultuser); free(defaultuser); defaultuser = strdup(basename(path)); free(path); defaultuser_junction = "Default User"; } } publicuser = findkey(software_key_file, "\\Microsoft\\Windows NT\\CurrentVersion" "\\ProfileList\\Public"); if (publicuser) { // Windows Vista char *path = reformat_path(publicuser); free(publicuser); publicuser = strdup(basename(path)); free(path); } dir = opendir(profilesdir); if(!dir) { fprintf(stderr, "ma-search-users: Error. Unable to open %s\n", profilesdir); exit(EXIT_FAILURE); } while((entry = readdir(dir)) != NULL) { asprintf(&profile, "%s/%s", profilesdir, entry->d_name); if( -1 == stat(profile, &st)) { fprintf(stderr, "Unable to stat %s.\n", profile); free(profile); } else if(S_ISDIR(st.st_mode)) { free(profile); cwd = entry->d_name; if(strcmp(cwd,".") == 0 || strcmp(cwd,"..") == 0) continue; if(strcmp(cwd,allusers) == 0 || (defaultuser && strcmp(cwd,defaultuser) == 0) || (defaultuser_junction && strcmp(cwd,defaultuser_junction) == 0) || (publicuser && strcmp(cwd,publicuser) == 0)) continue; if(strcmp(cwd,"NetworkService") == 0 || strcmp(cwd,"LocalService") == 0) continue; if(mult != 0) printf(", %s", cwd); else { printf("%s", cwd); mult = 1; } } } free(profilesdir); closedir(dir); puts(""); } int main(int argc, char** argv) { char *ostype, *mountpoint; if(argc < 3) { fprintf(stderr, "%s OSTYPE MOUNTPOINT\n", argv[0]); return EXIT_FAILURE; } ostype = argv[1]; mountpoint = argv[2]; if(strcmp(ostype,"linux") == 0) search_linux(mountpoint); else if(strcmp(ostype,"windowsxp") == 0) search_windowsxp(mountpoint); else { fprintf(stderr, "ma-search-users: Error. OS type '%s' is not" "understood.\n", ostype); return EXIT_FAILURE; } return 0; } // vim:ai:et:sts=4:tw=80:sw=4: migration-assistant-0.6.13/windows-import.h0000664000000000000000000000035711732445313015654 0ustar void windowsxp_import_userpicture (void); void windowsxp_import_proxy (void); void windowsxp_import_mymusic (void); void windowsxp_import_mypictures (void); void windowsxp_import_mydocuments (void); void windowsxp_import_wallpaper (void); migration-assistant-0.6.13/registry.h0000664000000000000000000001066411732445313014524 0ustar // registry.h -- 1999-05-19 ADB // This code is for educational and research purposes only. typedef unsigned short uint16_t; typedef unsigned int uint32_t; typedef unsigned char uint8_t; enum VALTYPE { // MicroSoft UNICODE = ASCII byte followed by UNICODE byte REG_NONE=0x0000, REG_SZ=0x0001, // UNICODE character string REG_EXPAND_SZ=0x0002, // Unicode string with "%var%" expanded REG_BINARY=0x0003, // Raw-binary value REG_DWORD=0x0004, // Joe Normal DWord: 2 Words, 4 Bytes, 8 Nibbles, 32 Bits REG_DWORD_LITTLE_ENDIAN=0x0004, // Joe Normal DWord: 2 Words, 4 Bytes, 8 Nibbles, 32 Bits REG_DWORD_BIG_ENDIAN=0x0005, REG_LINK=0x0006, REG_MULTI_SZ=0x0007, // Multiple UNICODE strings followed by NULL (0x0000) REG_RESOURCE_LIST=0x0008, REG_FULL_RESOURCE_DESCRIPTOR=0x0009, REG_RESOURCE_REQUIREMENTS_LIST=0x000a }; typedef struct { int recsize; //0x00 DWord: Length of sk record char rectype[2]; //0x04 Word: ID="v=sk", 0x6B73 short skuk001; //0x06 Word: sk Unknown 1 -- "Unused" int prevsk; //0x08 DWord: Global offset of previous sk record int nextsk; //0x0C DWord: Global offset of next sk record int usecount; //0x10 DWord: Count of usage int sksize; //0x14 DWord: Length of sk payload in bytes // a sk record is followed by sksize of bytes of security and auditing payload } SK; //Security Key typedef struct { int recsize; //0x00 DWord: Length of vk record char rectype[2]; //0x04 Word: ID="vk", 0x6B76 short namesize; //0x06 Word: Length of name int datasize; //0x08 DWord: Length of data int mydata; //0x0C DWord: Global offset to data int valtype; //0x10 DWord: Type of value short flag; //0x14 Word: Flag bits (bit[0]=0 then vk is "default") short vkuk001; //0x16 Word: vk Unknown 1 -- "Unused (data-trash)" // a vk record is followed by namesize of chars of the vk's name } VK; //Value Key typedef struct { int nkrec; //0x00 DWord: Global offset of nk record char pseudohash[4]; //0x04 DWord: First four characters of nk record name } HASH; typedef struct { int recsize; //0x00 DWord: Length of lf record char rectype[2]; //0x04 Word: ID="lf", 0x666C short numkeys; //0x06 Word: Number of keys // a lf record is followed immediately by numkeys of HASH records } LF; //List? Fields? typedef struct { int recsize; //0x00 Dword: Length of nk record char rectype[2]; //0x04 Word: ID="nk", 0x6B6E short nktype; //0x04 Word: Type: 0x20 (0x2C for root key) int datetime1; //0x04 QWord: NT Date Format int datetime2; //0x04 QWord: NT Date Format int parentnk; //0x0C DWord: Global offset to parent int nkuk001; //0x10 DWord: nk Unknown 1 int numchildren; //0x14 DWord: Number of sub keys int nkuk002; //0x18 DWord: nk Unknown 2 int mylfrec; //0x1C DWord: Global offset to lf record int nkuk003; //0x20 DWord: nk Unknown 3 int numvalues; //0x24 DWord: Number of values = 0x00000000 if none int myvallist; //0x28 DWord: Global offset to value list = 0xFFFFFFFF if none int skrec; //0x2C DWord: Global offset to sk record int myclassname; //0x30 DWord: Global offset to class name char nkuk004[16]; //0x34 xByte: nk Unknown 4 int nkuk005; //0x44 DWord: nk Unknown 5 -- "Unused (data-trash)" short namesize; //0x48 Word: Length of name short classnamesize; //0x4A Word: Length class name // a nk record is followed by namesize of chars of the nk's name } NK; //Named? Key typedef struct { char sig[4]; //0x00 Word: ID="regf" int regfuk001; //0x04 DWord: regf Unknown 1 = regfuk002 int regfuk002; //0x08 DWord: regf Unknown 2 = regfuk001 int ntdate1; //0x0C QWord: NT Date Format Chunk 1 int ntdate2; //0x0C QWord: NT Date Format Chunk 2 int regfuk003; //0x14 DWord: regf Unknown 3 = 1 int regfuk004; //0x18 DWord: regf Unknown 4 = 3 int regfuk005; //0x1C DWord: regf Unknown 5 = 0 int regfuk006; //0x20 DWord: regf Unknown 6 = 1 int firstkey; //0x24 DWord: Global offset of root nk record int hivesize; //0x28 DWord: Sum of all 4096 byte hbins int regfuk007; //0x2C DWord: regf Unknown 7 = 1 int regfuk008[115]; //0x30 DWord: regf Unknown 8 = last accessed? int cksum; //0x1FC DWord: Checksum char balast[3584]; //Pure Junk = 0x00... } REGF; //Registry File char* findkey(const char* location, const char* path); NK* getkey(char* base, NK* thisnk, char** path); char *str_token( char **string, char *delimiters ); char* printk(char* base, NK* thisnk, char* key); migration-assistant-0.6.13/windows-import.c0000664000000000000000000001404411732445313015645 0ustar #include #include #include #include #include #include #include "windows-import.h" #include "utils.h" #include "registry.h" const char* mydocumentskey = "\\Software\\Microsoft\\Windows\\CurrentVersion" "\\Explorer\\Shell Folders\\Personal"; const char* mymusickey = "\\Software\\Microsoft\\Windows\\CurrentVersion" "\\Explorer\\Shell Folders\\My Music"; const char* mypictureskey = "\\Software\\Microsoft\\Windows\\CurrentVersion" "\\Explorer\\Shell Folders\\My Pictures"; // FIXME: gnome-about-me also adds this to EDS. void windowsxp_import_userpicture (void) { char *from, *to; char* appdata = NULL; char* path = NULL; appdata = findkey(software_key_file, "\\Microsoft\\Windows\\CurrentVersion\\" "Explorer\\Shell Folders\\Common AppData"); if(!appdata) { puts("Couldn't find Common AppData"); return; } path = reformat_path(appdata); free(appdata); asprintf(&from, "%s/%s/Microsoft/User Account Pictures/%s.bmp", from_location, path, from_user); free(path); asprintf(&to, "%s/home/%s/.face", to_location, to_user); copyfile(from, to); free(from); free(to); } // It appears that we need to set this in both gconf and Firefox's prefs.js. void windowsxp_import_proxy (void) { return; } void windowsxp_import_mymusic (void) { char* to, *from; char* mymusic = NULL; char* path = NULL; mymusic = findkey(user_key_file, mymusickey); if(!mymusic) { printf("Couldn't find %s\n", mymusickey); return; } path = reformat_path(mymusic); free(mymusic); asprintf(&to, "%s/home/%s/Music", to_location, to_user); asprintf(&from, "%s/%s", from_location, path); free(path); rcopy(from, to); free(from); free(to); asprintf(&to, "file:///home/%s/Music", to_user); set_gconf_key("/apps/rhythmbox", "library_locations", GCONF_LIST_STRING, to); set_gconf_key("/apps/rhythmbox", "first_time_flag", GCONF_BOOLEAN, "true"); set_gconf_key("/apps/rhythmbox", "monitor_library", GCONF_BOOLEAN, "true"); } void windowsxp_import_mypictures (void) { char *to, *from; char* mypictures = NULL; char* path = NULL; mypictures = findkey(user_key_file, mypictureskey); if(!mypictures) { printf("Couldn't find %s\n", mypictureskey); return; } path = reformat_path(mypictures); free(mypictures); asprintf(&to, "%s/home/%s/Pictures", to_location, to_user); asprintf(&from, "%s/%s", from_location, path); free(path); rcopy(from, to); free(to); free(from); } void windowsxp_import_mydocuments (void) { char *to, *from, *f, *t; DIR *d; struct dirent *rep; char* mydocuments = NULL; char* path = NULL; char* extension = NULL; struct stat st; mydocuments = findkey(user_key_file, mydocumentskey); if(!mydocuments) { printf("Couldn't find %s\n", mydocumentskey); return; } path = reformat_path(mydocuments); free(mydocuments); char* mypictures = NULL; char* mymusic = NULL; mypictures = findkey(user_key_file, mypictureskey); if(!mypictures) { printf("Couldn't find %s\n", mypictureskey); return; } mymusic = findkey(user_key_file, mymusickey); if(!mymusic) { printf("Couldn't find %s\n", mymusickey); mymusic = strdup(""); } const char* pic = mypictures; const char* mus = mymusic; while(*pic != '\0') pic++; while(*pic != '\\') pic--; pic++; while(*mus != '\0') mus++; while(*mus != '\\') mus--; mus++; asprintf(&to, "%s/home/%s/Documents", to_location, to_user); asprintf(&from, "%s/%s", from_location, path); free(path); FILE* fp; if((fp = fopen(from, "r")) == NULL) { printf("%s does not exist.\n", from); return; } fclose(fp); makedirs(to); d = opendir(from); while((rep = readdir(d)) != NULL) { if(strcmp(rep->d_name,".") == 0 || strcmp(rep->d_name,"..") == 0) continue; else if(strcmp(rep->d_name, pic) == 0 || strcmp(rep->d_name,mus) == 0) { continue; } else { asprintf(&f, "%s/%s", from, rep->d_name); //mkdir(to, 0755); asprintf(&t, "%s/%s", to, rep->d_name); if( -1 == stat(f, &st)) { fprintf(stderr, "Unable to stat %s.\n", f); } else if(S_ISREG(st.st_mode)) { extension = rep->d_name; while(*extension != '\0') extension++; while(extension != rep->d_name && *extension != '.') extension--; if(extension == rep->d_name) extension = ""; else extension++; // TODO: Make a array of ignored extensions instead. if(!((strcmp(extension, "ini") == 0) || (strcmp(extension, "lnk") == 0))) { copyfile(f,t); } } else if(S_ISDIR(st.st_mode)) { rcopy(f,t); } free(t); free(f); } } closedir(d); free(to); free(from); free(mypictures); free(mymusic); } void windowsxp_import_wallpaper (void) { char *to, *from, *image, *path; char* wallpaperloc = NULL; wallpaperloc = findkey(user_key_file, "\\Control Panel\\Desktop\\ConvertedWallpaper"); if(!wallpaperloc) { wallpaperloc = findkey(user_key_file, "\\Control Panel\\Desktop\\Wallpaper"); } if(!wallpaperloc) { printf("Couldn't find %s\n", wallpaperloc); return; } path = reformat_path(wallpaperloc); image = basename(path); asprintf(&from, "%s/%s", from_location, path); asprintf(&to, "%s/home/%s/%s", to_location, to_user, image); copyfile(from, to); free(from); free(to); if(strcmp(wallpaperloc, "C:\\WINDOWS\\web\\wallpaper\\Bliss.bmp") != 0) { asprintf(&to, "/home/%s/%s", to_user, image); set_gconf_key("/desktop/gnome/background", "picture_filename", GCONF_STRING, to); add_wallpaper(to); free(to); } free(wallpaperloc); free(path); } // vim:ai:et:sts=4:tw=80:sw=4: