diff --git a/src/main/java/org/olat/admin/user/UserAdminController.java b/src/main/java/org/olat/admin/user/UserAdminController.java
index 4c5b5d370735b4e8664f98ea42240811d8d5a98e..7632ed3ad572fee098c65d47e5c1694a4cbbab8b 100644
--- a/src/main/java/org/olat/admin/user/UserAdminController.java
+++ b/src/main/java/org/olat/admin/user/UserAdminController.java
@@ -201,7 +201,7 @@ public class UserAdminController extends BasicController implements Activateable
 				//reload profile data on top
 				myIdentity = (Identity) DBFactory.getInstance().loadObject(myIdentity);
 				exposeUserDataToVC(ureq, myIdentity);
-				userProfileCtr.resetForm(ureq, getWindowControl());
+				userProfileCtr.resetForm(ureq);
 			}
 		}
 	}
diff --git a/src/main/java/org/olat/basesecurity/BaseSecurityManager.java b/src/main/java/org/olat/basesecurity/BaseSecurityManager.java
index fd8dadc02f788ee33fa1f65f723df61015206b07..5f4127402be32a0802c1a5630ee196ec6e71a443 100644
--- a/src/main/java/org/olat/basesecurity/BaseSecurityManager.java
+++ b/src/main/java/org/olat/basesecurity/BaseSecurityManager.java
@@ -70,7 +70,6 @@ import org.olat.portfolio.manager.InvitationDAO;
 import org.olat.resource.OLATResource;
 import org.olat.resource.OLATResourceManager;
 import org.olat.user.ChangePasswordController;
-import org.olat.user.PersonalSettingsController;
 import org.olat.user.UserManager;
 
 /**
@@ -205,7 +204,6 @@ public class BaseSecurityManager extends BasicManager implements BaseSecurity {
 		createAndPersistPolicyIfNotExists(olatuserGroup, Constants.PERMISSION_HASROLE, Constants.ORESOURCE_USERS);
 
 		createAndPersistPolicyIfNotExists(olatuserGroup, Constants.PERMISSION_ACCESS, OresHelper.lookupType(ChangePasswordController.class));
-		createAndPersistPolicyIfNotExists(olatuserGroup, Constants.PERMISSION_ACCESS, OresHelper.lookupType(PersonalSettingsController.class));
 	}
 
 	/**
diff --git a/src/main/java/org/olat/user/HomePageDisplayController.java b/src/main/java/org/olat/user/HomePageDisplayController.java
index 92a2b337ef242af0162b9bc264bac02870facade..867dffe5636c7ceb74287aca168f2de94bdc737e 100644
--- a/src/main/java/org/olat/user/HomePageDisplayController.java
+++ b/src/main/java/org/olat/user/HomePageDisplayController.java
@@ -49,6 +49,7 @@ import org.olat.instantMessaging.InstantMessagingService;
 import org.olat.instantMessaging.OpenInstantMessageEvent;
 import org.olat.instantMessaging.model.Buddy;
 import org.olat.user.propertyhandlers.UserPropertyHandler;
+import org.springframework.beans.factory.annotation.Autowired;
 
 /**
  * Initial Date:  Jul 25, 2005
@@ -62,6 +63,10 @@ public class HomePageDisplayController extends BasicController {
 	
 	private Link imLink;
 	
+	@Autowired
+	private UserManager userManager;
+	@Autowired
+	private InstantMessagingModule imModule;
 
 	/**
 	 * @param ureq
@@ -71,11 +76,8 @@ public class HomePageDisplayController extends BasicController {
 	public HomePageDisplayController(UserRequest ureq, WindowControl wControl, Identity homeIdentity, HomePageConfig hpc) {
 		super(ureq, wControl);
 
-		UserManager userManager = CoreSpringFactory.getImpl(UserManager.class);
-		InstantMessagingModule imModule = CoreSpringFactory.getImpl(InstantMessagingModule.class);
-
 		// use property handler translator for translating of user fields
-		setTranslator(UserManager.getInstance().getPropertyHandlerTranslator(getTranslator()));
+		setTranslator(userManager.getPropertyHandlerTranslator(getTranslator()));
 		VelocityContainer mainVC = createVelocityContainer("homepagedisplay");
 		
 		String fullname = StringHelper.escapeHtml(userManager.getUserDisplayName(homeIdentity));
diff --git a/src/main/java/org/olat/user/HomePageSettingsController.java b/src/main/java/org/olat/user/HomePageSettingsController.java
new file mode 100644
index 0000000000000000000000000000000000000000..9e8fb35dd773081865e69a7e957999a533db8415
--- /dev/null
+++ b/src/main/java/org/olat/user/HomePageSettingsController.java
@@ -0,0 +1,210 @@
+/**
+ * <a href="http://www.openolat.org">
+ * OpenOLAT - Online Learning and Training</a><br>
+ * <p>
+ * Licensed under the Apache License, Version 2.0 (the "License"); <br>
+ * you may not use this file except in compliance with the License.<br>
+ * You may obtain a copy of the License at the
+ * <a href="http://www.apache.org/licenses/LICENSE-2.0">Apache homepage</a>
+ * <p>
+ * Unless required by applicable law or agreed to in writing,<br>
+ * software distributed under the License is distributed on an "AS IS" BASIS, <br>
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. <br>
+ * See the License for the specific language governing permissions and <br>
+ * limitations under the License.
+ * <p>
+ * Initial code contributed and copyrighted by<br>
+ * frentix GmbH, http://www.frentix.com
+ * <p>
+ */
+package org.olat.user;
+
+import java.util.List;
+
+import org.olat.core.gui.UserRequest;
+import org.olat.core.gui.components.Component;
+import org.olat.core.gui.components.form.flexible.FormItem;
+import org.olat.core.gui.components.form.flexible.FormItemContainer;
+import org.olat.core.gui.components.form.flexible.elements.MultipleSelectionElement;
+import org.olat.core.gui.components.form.flexible.impl.FormBasicController;
+import org.olat.core.gui.components.form.flexible.impl.FormEvent;
+import org.olat.core.gui.components.form.flexible.impl.FormItemImpl;
+import org.olat.core.gui.components.form.flexible.impl.FormLayoutContainer;
+import org.olat.core.gui.control.Controller;
+import org.olat.core.gui.control.WindowControl;
+import org.olat.core.id.Identity;
+import org.olat.user.propertyhandlers.UserPropertyHandler;
+import org.springframework.beans.factory.annotation.Autowired;
+
+/**
+ * 
+ * Initial date: 01.07.2014<br>
+ * @author srosse, stephane.rosse@frentix.com, http://www.frentix.com
+ *
+ */
+public class HomePageSettingsController extends FormBasicController {
+	
+	private static final String usageIdentifier = ProfileFormController.class.getCanonicalName();
+	private static final String[] checkKeys = new String[]{ "on" }; 
+	private static final String[] checkValues = new String[]{ "" }; 
+	
+	private Identity identityToModify;
+	private final boolean isAdministrativeUser;
+	private final List<UserPropertyHandler> userPropertyHandlers;
+
+	private HomePageFormItem previewEl;
+	private FormLayoutContainer previewContainer;
+	
+	@Autowired
+	private UserManager userManager;
+	@Autowired
+	private HomePageConfigManager hpcm;
+	
+	public HomePageSettingsController(UserRequest ureq, WindowControl wControl,
+			Identity identityToModify, boolean isAdministrativeUser) {
+		super(ureq, wControl, LAYOUT_BAREBONE);
+		this.identityToModify = identityToModify;
+		this.isAdministrativeUser = isAdministrativeUser;
+		setTranslator(userManager.getPropertyHandlerTranslator(getTranslator()));
+		userPropertyHandlers = userManager.getUserPropertyHandlersFor(usageIdentifier, isAdministrativeUser);
+		
+		initForm(ureq);
+	}
+	
+	public void updateIdentityToModify(UserRequest ureq, Identity identityToModify) {
+		this.identityToModify = identityToModify;
+		updatePreview(ureq);
+	}
+
+	@Override
+	protected void initForm(FormItemContainer formLayout, Controller listener, UserRequest ureq) {
+		String currentGroup = null;
+		FormLayoutContainer groupContainer = null;
+		List<UserPropertyHandler> homepagePropertyHanders = userManager.getUserPropertyHandlersFor(HomePageConfig.class.getCanonicalName(), isAdministrativeUser);
+
+		HomePageConfig conf = hpcm.loadConfigFor(identityToModify.getName());
+		for (UserPropertyHandler userPropertyHandler : userPropertyHandlers) {
+			if (userPropertyHandler == null) {
+				continue;
+			}
+			
+			// add spacer if necessary (i.e. when group name changes)
+			String group = userPropertyHandler.getGroup();
+			if (!group.equals(currentGroup)) {
+				groupContainer = FormLayoutContainer.createDefaultFormLayout("group." + group, getTranslator());
+				groupContainer.setFormTitle(translate("form.group." + group));
+				formLayout.add(groupContainer);
+				if(currentGroup == null) {
+					groupContainer.setFormContextHelp("org.olat.user","home-vcard.html","help.hover.vcard");
+				}
+				currentGroup = group;
+			}
+			
+			if (homepagePropertyHanders.contains(userPropertyHandler)) {
+				// add checkbox to container if configured for homepage usage identifier
+				String checkboxName = userPropertyHandler.getName();
+				MultipleSelectionElement publishCheckbox = uifactory.addCheckboxesHorizontal(checkboxName,
+						userPropertyHandler.i18nFormElementLabelKey(),
+						groupContainer, checkKeys , checkValues);
+				
+				boolean isEnabled = conf.isEnabled(userPropertyHandler.getName());
+				publishCheckbox.select(checkKeys[0], isEnabled);
+				publishCheckbox.setUserObject(userPropertyHandler.getName());
+							
+				// Mandatory homepage properties can not be changed by user
+				if (userManager.isMandatoryUserProperty(HomePageConfig.class.getCanonicalName(), userPropertyHandler)) {
+					publishCheckbox.select(checkKeys[0], true);
+					publishCheckbox.setEnabled(false);
+				} else {
+					publishCheckbox.addActionListener(FormEvent.ONCHANGE);
+				}
+			}
+		}
+		
+		String previewPage = velocity_root + "/homepage_preview.html";
+		previewContainer = FormLayoutContainer.createCustomFormLayout("preview", getTranslator(), previewPage);
+		previewContainer.setFormTitle(translate("tab.preview"));
+		previewContainer.setRootForm(mainForm);
+		formLayout.add(previewContainer);
+		updatePreview(ureq);
+	}
+
+	protected void updatePreview(UserRequest ureq) {
+		HomePageConfig conf = hpcm.loadConfigFor(identityToModify.getName());
+		updatePreview(ureq, conf);
+	}
+	
+	protected void updatePreview(UserRequest ureq, HomePageConfig conf) {
+		if(previewEl != null) {
+			previewContainer.remove(previewEl);
+			removeAsListenerAndDispose(previewEl.getController());
+		}
+		
+		HomePageDisplayController displayCtrl = new HomePageDisplayController(ureq, getWindowControl(), identityToModify, conf);
+		listenTo(displayCtrl);
+		previewEl = new HomePageFormItem(displayCtrl);
+		previewContainer.add(previewEl);
+	}
+	
+	@Override
+	protected void doDispose() {
+		//
+	}
+
+	@Override
+	protected void formOK(UserRequest ureq) {
+		//
+	}
+
+	@Override
+	protected void formInnerEvent(UserRequest ureq, FormItem source, FormEvent event) {
+		if(source instanceof MultipleSelectionElement) {
+			MultipleSelectionElement publishCheckbox = (MultipleSelectionElement)source;
+			if (publishCheckbox.isEnabled()) {
+				boolean enabled = publishCheckbox.isAtLeastSelected(1);
+				String propName = (String)publishCheckbox.getUserObject();
+				
+				//load and update config
+				HomePageConfig conf = hpcm.loadConfigFor(identityToModify.getName());
+				conf.setEnabled(propName, enabled);
+				hpcm.saveConfigTo(identityToModify.getName(), conf);
+				updatePreview(ureq, conf);
+			}
+		}
+		super.formInnerEvent(ureq, source, event);
+	}
+	
+	public class HomePageFormItem extends FormItemImpl {
+		
+		private final HomePageDisplayController previewCtrl;
+		
+		public HomePageFormItem(HomePageDisplayController previewCtrl) {
+			super("homepage");
+			this.previewCtrl = previewCtrl;
+		}
+		
+		public HomePageDisplayController getController() {
+			return previewCtrl;
+		}
+
+		@Override
+		protected Component getFormItemComponent() {
+			return previewCtrl.getInitialComponent();
+		}
+
+		@Override
+		protected void rootFormAvailable() {
+			//
+		}
+
+		@Override
+		public void evalFormRequest(UserRequest ureq) {
+			//
+		}
+
+		@Override
+		public void reset() {
+			//
+		}
+	}
+}
\ No newline at end of file
diff --git a/src/main/java/org/olat/user/PersonalSettingsController.java b/src/main/java/org/olat/user/PersonalSettingsController.java
deleted file mode 100644
index 9d518966cbf1b71ad20145aab788b54be037c050..0000000000000000000000000000000000000000
--- a/src/main/java/org/olat/user/PersonalSettingsController.java
+++ /dev/null
@@ -1,173 +0,0 @@
-/**
-* OLAT - Online Learning and Training<br>
-* http://www.olat.org
-* <p>
-* Licensed under the Apache License, Version 2.0 (the "License"); <br>
-* you may not use this file except in compliance with the License.<br>
-* You may obtain a copy of the License at
-* <p>
-* http://www.apache.org/licenses/LICENSE-2.0
-* <p>
-* Unless required by applicable law or agreed to in writing,<br>
-* software distributed under the License is distributed on an "AS IS" BASIS, <br>
-* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. <br>
-* See the License for the specific language governing permissions and <br>
-* limitations under the License.
-* <p>
-* Copyright (c) since 2004 at Multimedia- & E-Learning Services (MELS),<br>
-* University of Zurich, Switzerland.
-* <hr>
-* <a href="http://www.openolat.org">
-* OpenOLAT - Online Learning and Training</a><br>
-* This file has been modified by the OpenOLAT community. Changes are licensed
-* under the Apache 2.0 license as the original file.
-*/
-
-package org.olat.user;
-
-import java.util.List;
-
-import org.olat.basesecurity.Authentication;
-import org.olat.basesecurity.BaseSecurity;
-import org.olat.basesecurity.BaseSecurityManager;
-import org.olat.basesecurity.Constants;
-import org.olat.core.CoreSpringFactory;
-import org.olat.core.commons.persistence.DBFactory;
-import org.olat.core.commons.services.webdav.WebDAVModule;
-import org.olat.core.gui.UserRequest;
-import org.olat.core.gui.components.Component;
-import org.olat.core.gui.components.tabbedpane.TabbedPane;
-import org.olat.core.gui.components.tabbedpane.TabbedPaneChangedEvent;
-import org.olat.core.gui.control.Controller;
-import org.olat.core.gui.control.Event;
-import org.olat.core.gui.control.WindowControl;
-import org.olat.core.gui.control.controller.BasicController;
-import org.olat.core.gui.control.generic.dtabs.Activateable2;
-import org.olat.core.id.Identity;
-import org.olat.core.id.context.ContextEntry;
-import org.olat.core.id.context.StateEntry;
-import org.olat.core.logging.OLATSecurityException;
-import org.olat.core.util.resource.OresHelper;
-import org.olat.instantMessaging.InstantMessagingModule;
-import org.olat.instantMessaging.ui.IMPreferenceController;
-import org.olat.ldap.LDAPLoginModule;
-import org.olat.ldap.ui.LDAPAuthenticationController;
-import org.olat.registration.DisclaimerController;
-import org.olat.registration.RegistrationModule;
-
-/**
- * Initial Date:  Jul 29, 2003
- *
- * @author Sabina Jeger
- * 
- */
-public class PersonalSettingsController extends BasicController implements Activateable2 {
-	
-	private TabbedPane userConfig;
-	
-	private Controller ucsc;
-	private Controller pwdc;
-	private Controller hpec; 
-	private Controller cimsc;
-	private Controller pwdav;
-	
-
-	/**
-	 * @param ureq
-	 * @param wControl
-	 */
-	public PersonalSettingsController(UserRequest ureq, WindowControl wControl) {
-		super(ureq, wControl);
-		
-			BaseSecurity mgr = BaseSecurityManager.getInstance();
-			if (!mgr.isIdentityPermittedOnResourceable(
-					ureq.getIdentity(), 
-					Constants.PERMISSION_ACCESS, 
-					OresHelper.lookupType(this.getClass())))
-				throw new OLATSecurityException("Insufficient permissions to access PersonalSettingsController");
-
-			userConfig = new TabbedPane("userConfig", ureq.getLocale());
-			//fxdiff BAKS-7 Resume function
-			userConfig.addListener(this);
-
-			hpec = new ProfileAndHomePageEditController(ureq, getWindowControl(), (Identity)DBFactory.getInstance().loadObject(ureq.getIdentity()), false);
-			listenTo(hpec);
-			userConfig.addTab(translate("tab.profile"), hpec.getInitialComponent());
-			
-			ucsc = new ChangePrefsController(ureq, getWindowControl(), (Identity)DBFactory.getInstance().loadObject(ureq.getIdentity()));
-			listenTo(ucsc);	
-			userConfig.addTab(translate("tab.prefs"), ucsc.getInitialComponent());
-			
-			if(canChangePassword()) {
-				pwdc = new ChangePasswordController(ureq, getWindowControl());
-				listenTo(pwdc);
-				userConfig.addTab(translate("tab.pwd"), pwdc.getInitialComponent());
-			}
-
-			if(CoreSpringFactory.getImpl(WebDAVModule.class).isEnabled()) {
-				pwdav = new WebDAVPasswordController(ureq, getWindowControl());
-				userConfig.addTab(translate("tab.pwdav"), pwdav.getInitialComponent());
-				listenTo(pwdav);
-			}
-			
-			if(CoreSpringFactory.getImpl(InstantMessagingModule.class).isEnabled()){
-				cimsc = new IMPreferenceController(ureq, getWindowControl(), (Identity)DBFactory.getInstance().loadObject(ureq.getIdentity()));
-				listenTo(cimsc);
-				userConfig.addTab(translate("tab.im"), cimsc.getInitialComponent());
-			}
-
-			// Show read only display of disclaimer so user sees what he accepted if disclaimer enabled
-			if (CoreSpringFactory.getImpl(RegistrationModule.class).isDisclaimerEnabled()) {
-				Controller disclaimerCtr = new DisclaimerController(ureq, getWindowControl(), true);
-				listenTo(disclaimerCtr);
-				userConfig.addTab(translate("tab.disclaimer"), disclaimerCtr.getInitialComponent());
-			}
-			
-			putInitialPanel(userConfig);
-			
-			logDebug("PersonalSettingsController constructed, set velocity page to index.html", PersonalSettingsController.class.getSimpleName());	
-	}
-	
-	private boolean canChangePassword() {
-		//check if LDAP is enabled + cannot propagate password on LDAP Server
-		if(LDAPLoginModule.isLDAPEnabled() && !LDAPLoginModule.isPropagatePasswordChangedOnLdapServer()) {
-			//check if the user has a LDAP Authentication 
-			Authentication auth = BaseSecurityManager.getInstance().findAuthentication(getIdentity(), LDAPAuthenticationController.PROVIDER_LDAP);
-			return auth == null;//if not in LDAP -> can change his password
-		}
-		return true;
-	}
-
-	/**
-	 * @see org.olat.core.gui.control.DefaultController#event(org.olat.core.gui.UserRequest, org.olat.core.gui.components.Component, org.olat.core.gui.control.Event)
-	 */
-	@Override
-	//fxdiff BAKS-7 Resume function
-	public void event(UserRequest ureq, Component source, Event event) {
-		if (source == userConfig && event instanceof TabbedPaneChangedEvent) {
-			userConfig.addToHistory(ureq, getWindowControl());
-		}
-	}
-	
-	/**
-	 * @see org.olat.core.gui.control.DefaultController#event(org.olat.core.gui.UserRequest, org.olat.core.gui.control.Controller, org.olat.core.gui.control.Event)
-	 */
-	@Override
-	public void event(UserRequest ureq, Controller source, Event event) {
-		// nothing to be done
-	}
-		
-	/** 
-	 * @see org.olat.core.gui.control.DefaultController#doDispose(boolean)
-	 */
-	@Override
-	protected void doDispose() {
-		//
-	}
-
-	@Override
-	//fxdiff BAKS-7 Resume function
-	public void activate(UserRequest ureq, List<ContextEntry> entries, StateEntry state) {
-		userConfig.activate(ureq, entries, state);
-	}
-}
\ No newline at end of file
diff --git a/src/main/java/org/olat/user/PortraitUploadController.java b/src/main/java/org/olat/user/PortraitUploadController.java
deleted file mode 100644
index 5b3ef2b9272ea27bcd011336b41d1f0adc4d5aa3..0000000000000000000000000000000000000000
--- a/src/main/java/org/olat/user/PortraitUploadController.java
+++ /dev/null
@@ -1,171 +0,0 @@
-/**
-* OLAT - Online Learning and Training<br>
-* http://www.olat.org
-* <p>
-* Licensed under the Apache License, Version 2.0 (the "License"); <br>
-* you may not use this file except in compliance with the License.<br>
-* You may obtain a copy of the License at
-* <p>
-* http://www.apache.org/licenses/LICENSE-2.0
-* <p>
-* Unless required by applicable law or agreed to in writing,<br>
-* software distributed under the License is distributed on an "AS IS" BASIS, <br>
-* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. <br>
-* See the License for the specific language governing permissions and <br>
-* limitations under the License.
-* <p>
-* Copyright (c) since 2004 at Multimedia- & E-Learning Services (MELS),<br>
-* University of Zurich, Switzerland.
-* <hr>
-* <a href="http://www.openolat.org">
-* OpenOLAT - Online Learning and Training</a><br>
-* This file has been modified by the OpenOLAT community. Changes are licensed
-* under the Apache 2.0 license as the original file.
-*/
-package org.olat.user;
-
-import java.io.File;
-import java.util.HashSet;
-import java.util.Set;
-
-import org.olat.core.commons.modules.bc.FileUploadController;
-import org.olat.core.commons.modules.bc.FolderEvent;
-import org.olat.core.gui.UserRequest;
-import org.olat.core.gui.components.Component;
-import org.olat.core.gui.components.link.Link;
-import org.olat.core.gui.components.link.LinkFactory;
-import org.olat.core.gui.components.velocity.VelocityContainer;
-import org.olat.core.gui.control.Controller;
-import org.olat.core.gui.control.Event;
-import org.olat.core.gui.control.WindowControl;
-import org.olat.core.gui.control.controller.BasicController;
-import org.olat.core.gui.media.MediaResource;
-import org.olat.core.id.Identity;
-import org.olat.core.util.FileUtils;
-import org.olat.core.util.vfs.LocalFolderImpl;
-import org.olat.core.util.vfs.VFSContainer;
-
-/**
- * Description:
- * <p>
- * This controller shows the users uploaded portrait and offers a way to upload
- * a new portrait.
- * <p>
- * Events fired by this controller:
- * <ul>
- * <li>Event.DONE</li>
- * <li>PORTRAIT_DELETED_EVENT</li>
- * </ul>
- * 
- * @author Alexander Schneider
- */
-public class PortraitUploadController extends BasicController {
-	public static final Event PORTRAIT_DELETED_EVENT = new Event("portraitdeleted");
-
-	private VelocityContainer folderContainer;
-	private Link deleteButton;
-	private DisplayPortraitController dpc;
-	private FileUploadController uploadCtr;
-	
-	private Identity portraitIdent;
-	private File uploadDir;
-	private File newFile = null;
-	private int limitKB; // max UL limit
-	
-	private final DisplayPortraitManager dps;
-		
-	/**
-	 * Display upload form to upload a file to the given currentPath.
-	 * @param uploadDir  
-	 * @param wControl 
-	 * @param translator
-	 * @param limitKB
-	 */
-	public PortraitUploadController(UserRequest ureq, WindowControl wControl, Identity portraitIdent, long limitKB) {
-		super(ureq, wControl);
-		dps = DisplayPortraitManager.getInstance();
-		this.portraitIdent = portraitIdent;
-		this.uploadDir = dps.getPortraitDir(portraitIdent.getName());
-		this.limitKB = (int) limitKB;
-		
-		folderContainer = createVelocityContainer("portraitupload");
-		deleteButton = LinkFactory.createButtonSmall("command.delete", this.folderContainer, this);
-		
-		MediaResource mr = dps.getSmallPortraitResource(portraitIdent.getName());
-		if (mr != null) folderContainer.contextPut("hasPortrait", Boolean.TRUE);
-		else folderContainer.contextPut("hasPortrait", Boolean.FALSE);
-		
-		displayPortrait(ureq, portraitIdent, true);
-		
-		// Init upload controller
-		Set<String> mimeTypes = new HashSet<String>();
-		mimeTypes.add("image/gif");
-		mimeTypes.add("image/jpg");
-		mimeTypes.add("image/jpeg");
-		mimeTypes.add("image/png");
-		VFSContainer uploadContainer = new LocalFolderImpl(uploadDir);
-		uploadCtr = new FileUploadController(getWindowControl(), uploadContainer, ureq, this.limitKB, this.limitKB, mimeTypes,
-				false, false, false, true, false);
-		uploadCtr.hideTitleAndFieldset();
-		listenTo(uploadCtr);
-		folderContainer.put("uploadCtr", uploadCtr.getInitialComponent());
-		putInitialPanel(folderContainer);
-	}
-
-	/**
-	 * @see org.olat.core.gui.control.DefaultController#event(org.olat.core.gui.UserRequest, org.olat.core.gui.components.Component, org.olat.core.gui.control.Event)
-	 */
-	public void event(UserRequest ureq, Component source, Event event) {
-		if (source == deleteButton){
-    	FileUtils.deleteDirsAndFiles(uploadDir, false, false);
-    	folderContainer.contextPut("hasPortrait", Boolean.FALSE);
-    	uploadCtr.reset();
-    	fireEvent(ureq, PORTRAIT_DELETED_EVENT);
-		}
-		displayPortrait(ureq, portraitIdent, true);		
-	}
-	
-	/**
-	 * @see org.olat.core.gui.control.DefaultController#event(org.olat.core.gui.UserRequest, org.olat.core.gui.control.Controller, org.olat.core.gui.control.Event)
-	 */
-	public void event(UserRequest ureq, Controller source, Event event) {
-		if (source == uploadCtr) {
-			// catch upload event
-			if (event instanceof FolderEvent && event.getCommand().equals(FolderEvent.UPLOAD_EVENT)) {
-				FolderEvent folderEvent = (FolderEvent) event;
-				// Get file from temp folder location
-				String uploadFileName = folderEvent.getFilename();
-				newFile = new File(uploadDir, uploadFileName);
-				if (!newFile.exists()) {
-					showError("Failed");
-				} else {
-					dps.setPortrait(newFile, portraitIdent.getName());
-					// Cleanup original file
-					newFile.delete();
-					// And finish workflow
-					fireEvent(ureq, Event.DONE_EVENT);
-					folderContainer.contextPut("hasPortrait", Boolean.TRUE);					
-				}
-			}
-			// redraw image
-			displayPortrait(ureq, portraitIdent, true);
-		}
-	}
-	
-	
-	private void displayPortrait(UserRequest ureq, Identity portraitIdent, boolean useLarge){	
-			if (dpc != null) removeAsListenerAndDispose(dpc);
-			dpc = new DisplayPortraitController(ureq, getWindowControl(), portraitIdent, useLarge, false);
-			listenTo(dpc);
-			folderContainer.put("portrait", dpc.getInitialComponent());
-	}
-	
-	/**
-	 * 
-	 * @see org.olat.core.gui.control.DefaultController#doDispose(boolean)
-	 */
-	protected void doDispose() {
-		// controllers autodisposed by basic cotntroller
-	}
-
-}
diff --git a/src/main/java/org/olat/user/ProfileAndHomePageEditController.java b/src/main/java/org/olat/user/ProfileAndHomePageEditController.java
index aad11b2acc863f14c5eb26c7392d690020687823..aed02babd547d88057242bb70553a2b9146743f0 100644
--- a/src/main/java/org/olat/user/ProfileAndHomePageEditController.java
+++ b/src/main/java/org/olat/user/ProfileAndHomePageEditController.java
@@ -25,50 +25,25 @@
 
 package org.olat.user;
 
-import java.text.DateFormat;
-import java.util.Calendar;
-import java.util.Date;
-import java.util.HashMap;
 import java.util.List;
-import java.util.Map;
 
-import org.olat.basesecurity.BaseSecurityManager;
-import org.olat.basesecurity.BaseSecurityModule;
-import org.olat.core.CoreSpringFactory;
-import org.olat.core.commons.persistence.DBFactory;
 import org.olat.core.gui.UserRequest;
 import org.olat.core.gui.components.Component;
 import org.olat.core.gui.components.link.Link;
 import org.olat.core.gui.components.link.LinkFactory;
+import org.olat.core.gui.components.segmentedview.SegmentViewComponent;
+import org.olat.core.gui.components.segmentedview.SegmentViewEvent;
+import org.olat.core.gui.components.segmentedview.SegmentViewFactory;
 import org.olat.core.gui.components.velocity.VelocityContainer;
 import org.olat.core.gui.control.Controller;
 import org.olat.core.gui.control.Event;
 import org.olat.core.gui.control.WindowControl;
 import org.olat.core.gui.control.controller.BasicController;
-import org.olat.core.gui.control.generic.closablewrapper.CloseableModalController;
-import org.olat.core.gui.control.generic.modal.DialogBoxController;
-import org.olat.core.gui.control.generic.modal.DialogBoxUIFactory;
-import org.olat.core.gui.translator.Translator;
-import org.olat.core.helpers.Settings;
+import org.olat.core.gui.control.generic.dtabs.Activateable2;
 import org.olat.core.id.Identity;
-import org.olat.core.id.User;
-import org.olat.core.util.Util;
-import org.olat.core.util.WebappHelper;
-import org.olat.core.util.coordinate.CoordinatorManager;
-import org.olat.core.util.coordinate.SyncerExecutor;
-import org.olat.core.util.event.MultiUserEvent;
-import org.olat.core.util.mail.MailBundle;
-import org.olat.core.util.mail.MailManager;
-import org.olat.core.util.mail.MailerResult;
-import org.olat.core.util.resource.OresHelper;
+import org.olat.core.id.context.ContextEntry;
+import org.olat.core.id.context.StateEntry;
 import org.olat.login.SupportsAfterLoginInterceptor;
-import org.olat.registration.RegistrationManager;
-import org.olat.registration.TemporaryKey;
-import org.olat.registration.TemporaryKeyImpl;
-
-import com.thoughtworks.xstream.XStream;
-
-import de.bps.olat.user.ChangeEMailController;
 
 /**
  * Initial Date: Jul 14, 2005
@@ -77,36 +52,19 @@ import de.bps.olat.user.ChangeEMailController;
  * 
  *         Comment:
  */
-public class ProfileAndHomePageEditController extends BasicController implements SupportsAfterLoginInterceptor {
-
-	private static final String VELOCITY_ROOT = Util.getPackageVelocityRoot(ProfileAndHomePageEditController.class);
-	private static final long UPLOAD_LIMIT_KB = 500;
-
-	private VelocityContainer myContent;
-	private Link previewButton;
+public class ProfileAndHomePageEditController extends BasicController implements Activateable2, SupportsAfterLoginInterceptor {
 
-	private Translator translator;
+	private final VelocityContainer myContent;
+	private final Link profilLink, homePageLink;
+	private final SegmentViewComponent segmentView;
+	private ProfileFormController profileFormController;
+	private HomePageSettingsController homePageController;
 
-	protected ProfileFormController profileFormController;
-	private Component profileFormControllerComponent;
-	private HomePageConfigManager hpcm = HomePageConfigManagerImpl.getInstance();
-	private PortraitUploadController portraitUploadController;
-	private Controller hpDispC;
-	private CloseableModalController clc;
-	protected Identity identityToModify;
-	protected HomePageConfig homePageConfig;
-	private DialogBoxController dialogCtr;
-	private final MailManager mailManager;
-	private RegistrationManager rm = RegistrationManager.getInstance();
-	private static String SEPARATOR = "\n____________________________________________________________________\n";
-
-	private boolean emailChanged = false;
-	protected String changedEmail;
-	protected String currentEmail;
+	private Identity identityToModify;
 	private boolean isAdministrativeUser;
 
 	public ProfileAndHomePageEditController(UserRequest ureq, WindowControl wControl) {		
-		this(ureq,wControl,ureq.getIdentity(),ureq.getUserSession().getRoles().isOLATAdmin());
+		this(ureq,wControl, ureq.getIdentity(), ureq.getUserSession().getRoles().isOLATAdmin());
 	}
 	
 	/**
@@ -120,271 +78,99 @@ public class ProfileAndHomePageEditController extends BasicController implements
 		super(ureq, wControl);
 		this.identityToModify = identityToModify;
 		this.isAdministrativeUser = isAdministrativeUser;
-		this.translator = Util.createPackageTranslator(ProfileAndHomePageEditController.class, ureq.getLocale());
-		this.translator = UserManager.getInstance().getPropertyHandlerTranslator(this.translator);
-		mailManager = CoreSpringFactory.getImpl(MailManager.class);
-
-		this.myContent = new VelocityContainer("homepage", VELOCITY_ROOT + "/homepage.html", this.translator, this);
-		this.previewButton = LinkFactory.createButtonSmall("command.preview", this.myContent, this);
-		previewButton.setIconLeftCSS("o_icon o_icon_preview");
-		this.homePageConfig = this.hpcm.loadConfigFor(this.identityToModify.getName());
-
-		this.profileFormController = new ProfileFormController(ureq, wControl, this.homePageConfig, this.identityToModify, isAdministrativeUser);
-		listenTo(this.profileFormController);
-		this.profileFormControllerComponent = this.profileFormController.getInitialComponent();
-		this.myContent.put("homepageform", this.profileFormControllerComponent);
-
-		this.portraitUploadController = new PortraitUploadController(ureq, getWindowControl(), this.identityToModify, UPLOAD_LIMIT_KB);
-		listenTo(this.portraitUploadController);
+		setTranslator(UserManager.getInstance().getPropertyHandlerTranslator(getTranslator()));
+		
+		myContent = createVelocityContainer("homepage");
+		segmentView = SegmentViewFactory.createSegmentView("segments", myContent, this);
+		profilLink = LinkFactory.createLink("tab.profile", myContent, this);
+		profilLink.setElementCssClass("o_sel_usersettings_profile");
+		segmentView.addSegment(profilLink, true);
+		homePageLink = LinkFactory.createLink("tab.hp", myContent, this);
+		homePageLink.setElementCssClass("o_sel_usersettings_homepage");
+		segmentView.addSegment(homePageLink, false);
+
+		putInitialPanel(myContent);
+	}
 
-		Component c = this.portraitUploadController.getInitialComponent();
-		this.myContent.put("c", c);
-		putInitialPanel(this.myContent);
+	@Override
+	protected void doDispose() {
+		// controllers disposed by basic controller
 	}
 	
 	@Override
 	public boolean isInterceptionRequired(UserRequest ureq) {
 		if (ureq.getUserSession().getRoles() == null || ureq.getUserSession().getRoles().isInvitee()
-				|| ureq.getUserSession().getRoles().isGuestOnly()) return false;
-		else return true; 
+				|| ureq.getUserSession().getRoles().isGuestOnly()) {
+			return false;
+		} else {
+			return true; 
+		}
 	}
 
-	/**
-	 * @see org.olat.core.gui.control.DefaultController#event(org.olat.core.gui.UserRequest,
-	 *      org.olat.core.gui.components.Component,
-	 *      org.olat.core.gui.control.Event)
-	 */
 	@Override
 	public void event(UserRequest ureq, Component source, Event event) {
-		if (source == this.previewButton) {
-			if (this.hpDispC != null) removeAsListenerAndDispose(this.hpDispC);
-			hpDispC = new HomePageDisplayController(ureq, getWindowControl(), identityToModify, homePageConfig);
-			listenTo(hpDispC);
-			if (clc != null) removeAsListenerAndDispose(clc);
-			clc = new CloseableModalController(getWindowControl(), this.translator.translate("command.closehp"), this.hpDispC
-					.getInitialComponent());
-			listenTo(clc);
-			clc.activate();
+		if(source == segmentView) {
+			if(event instanceof SegmentViewEvent) {
+				SegmentViewEvent sve = (SegmentViewEvent)event;
+				String segmentCName = sve.getComponentName();
+				Component clickedLink = myContent.getComponent(segmentCName);
+				Controller selectedController = null;
+				if (clickedLink == profilLink) {
+					selectedController = doOpenProfile(ureq);
+				} else if (clickedLink == homePageLink){
+					selectedController = doOpenHomePageSettings(ureq);
+				}
+				addToHistory(ureq, selectedController);
+			}
 		}
 	}
 
-	/**
-	 * @see org.olat.core.gui.control.DefaultController#event(org.olat.core.gui.UserRequest,
-	 *      org.olat.core.gui.control.Controller, org.olat.core.gui.control.Event)
-	 */
 	@Override
-	protected void event(final UserRequest ureq, Controller source, Event event) {
-		super.event(ureq, source, event);
-		if (source == this.portraitUploadController) {
-			if (event.equals(Event.DONE_EVENT) || event.getCommand().equals(PortraitUploadController.PORTRAIT_DELETED_EVENT.getCommand())) {
-				// should not fire event, as only needed to update identity if useradmin changed it. portrait doesnt change identity and is not shown in table. 
-				// see UserAdminController
-//				fireEvent(ureq, Event.DONE_EVENT);
-			}
-		} else if (source == this.profileFormController) {
-			if (event == Event.DONE_EVENT) {
-				// get the new values from the form
-				this.profileFormController.updateFromFormData(this.homePageConfig, this.identityToModify);
-
-				// update the home page configuration
-				this.hpcm.saveConfigTo(this.identityToModify.getName(), this.homePageConfig);
-				
-				// update the portrait upload (gender specific image)
-				if (portraitUploadController != null) removeAsListenerAndDispose(portraitUploadController);
-				portraitUploadController = new PortraitUploadController(ureq, getWindowControl(), this.identityToModify, UPLOAD_LIMIT_KB);
-				listenTo(this.portraitUploadController);
-				this.myContent.put("c", this.portraitUploadController.getInitialComponent());
-				
-				// fire the appropriate event
-				fireEvent(ureq, Event.DONE_EVENT);
-
-				// update the user profile data
-				CoordinatorManager.getInstance().getCoordinator().getSyncer().doInSync(
-					OresHelper.createOLATResourceableInstance(Identity.class, ProfileAndHomePageEditController.this.identityToModify.getKey()), new SyncerExecutor() {
-						@SuppressWarnings("synthetic-access")
-						public void execute() {
-							UserManager um = UserManager.getInstance();
-							ProfileAndHomePageEditController.this.identityToModify = (Identity) DBFactory.getInstance().loadObject(ProfileAndHomePageEditController.this.identityToModify);
-							currentEmail = ProfileAndHomePageEditController.this.identityToModify.getUser().getProperty("email", null);
-
-							ProfileAndHomePageEditController.this.identityToModify = profileFormController
-									.updateIdentityFromFormData(ProfileAndHomePageEditController.this.identityToModify);
-							changedEmail = ProfileAndHomePageEditController.this.identityToModify.getUser().getProperty("email", null);
-							if (!currentEmail.equals(changedEmail)) {
-								// allow an admin to change email without verification workflow. usermanager is only permitted to do so, if set by config.
-								if ( !(ureq.getUserSession().getRoles().isOLATAdmin() || ( BaseSecurityModule.USERMANAGER_CAN_BYPASS_EMAILVERIFICATION && ureq.getUserSession().getRoles().isUserManager() ))) {
-									emailChanged = true;
-									// change email address to old address until it is verified
-									ProfileAndHomePageEditController.this.identityToModify.getUser().setProperty("email", currentEmail);
-								} else {
-									// fxdiff: FXOLAT-44 delete previous change-workflows
-									String key = ProfileAndHomePageEditController.this.identityToModify.getUser().getProperty("emchangeKey", null);
-									TemporaryKeyImpl tempKey = rm.loadTemporaryKeyByRegistrationKey(key);
-									if (tempKey != null) {
-										rm.deleteTemporaryKey(tempKey);
-									}		
-								}
-							}
-							if (!um.updateUserFromIdentity(ProfileAndHomePageEditController.this.identityToModify)) {
-								getWindowControl().setInfo(translate("profile.unsuccessful"));
-								// reload user data from db
-								ProfileAndHomePageEditController.this.identityToModify = BaseSecurityManager.getInstance().loadIdentityByKey(
-										ProfileAndHomePageEditController.this.identityToModify.getKey());
-							}
-							CoordinatorManager.getInstance().getCoordinator().getEventBus().fireEventToListenersOf(new MultiUserEvent("changed"),
-									OresHelper.createOLATResourceableInstance(Identity.class, ProfileAndHomePageEditController.this.identityToModify.getKey()));
-							if (!emailChanged) resetForm(ureq, getWindowControl());
-						}
-					});
-				if (emailChanged) {
-					if (dialogCtr != null) {
-						dialogCtr.dispose();
-					}
-					String changerEMail = ureq.getIdentity().getUser().getProperty("email", ureq.getLocale());
-					String dialogText = "";
-					if(changerEMail != null && changerEMail.length() > 0 && changerEMail.equals(currentEmail)) {
-						dialogText = translate("email.change.dialog.text");
-					} else {
-						dialogText = translate("email.change.dialog.text.usermanager");
-					}
-					dialogCtr = DialogBoxUIFactory.createYesNoDialog(ureq, getWindowControl(), translate("email.change.dialog.title"), dialogText);
-					dialogCtr.addControllerListener(this);
-					dialogCtr.activate();
-				}
+	protected void event(UserRequest ureq, Controller source, Event event) {
+		if(profileFormController == source) {
+			identityToModify = profileFormController.getIdentityToModify();
+			if(Event.FAILED_EVENT.equals(event)) {
+				resetForm(ureq);
 			}
-		} else if (source == dialogCtr) {
-			dialogCtr.dispose();
-			dialogCtr = null;
-			if (DialogBoxUIFactory.isYesEvent(event)) {
-				if (changedEmail != null) {
-					createChangeEmailWorkflow(ureq);
-				}
+			if(homePageController != null) {
+				homePageController.updateIdentityToModify(ureq, identityToModify);
 			}
-			resetForm(ureq, getWindowControl());
 		}
+		super.event(ureq, source, event);
 	}
 	
-	private void createChangeEmailWorkflow(UserRequest ureq) {
-		// send email
-		changedEmail = changedEmail.trim();
-		String body = null;
-		String subject = null;
-		// get remote address
-		String ip = ureq.getHttpReq().getRemoteAddr();
-		String today = DateFormat.getDateInstance(DateFormat.LONG, ureq.getLocale()).format(new Date());
-		// mailer configuration
-		String serverpath = Settings.getServerContextPathURI();
-		String servername = ureq.getHttpReq().getServerName();
-
-		logDebug("this servername is " + servername + " and serverpath is " + serverpath, null);
-		// load or create temporary key
-		Map<String, String> mailMap = new HashMap<String, String>();
-		mailMap.put("currentEMail", currentEmail);
-		mailMap.put("changedEMail", changedEmail);
-		
-		XStream xml = new XStream();
-		String serMailMap = xml.toXML(mailMap);
-		
-		TemporaryKey tk = loadCleanTemporaryKey(serMailMap);				
-		if (tk == null) {
-			tk = rm.createTemporaryKeyByEmail(serMailMap, ip, RegistrationManager.EMAIL_CHANGE);
-		} else {
-			rm.deleteTemporaryKeyWithId(tk.getRegistrationKey());
-			tk = rm.createTemporaryKeyByEmail(serMailMap, ip, RegistrationManager.EMAIL_CHANGE);
-		}
-		
-		// create date, time string
-		Calendar cal = Calendar.getInstance();
-		cal.setTime(tk.getCreationDate());
-		cal.add(Calendar.DAY_OF_WEEK, ChangeEMailController.TIME_OUT);
-		String time = DateFormat.getDateTimeInstance(DateFormat.SHORT, DateFormat.SHORT, ureq.getLocale()).format(cal.getTime());
-		// create body and subject for email
-		body = this.translator.translate("email.change.body", new String[] { serverpath + "/dmz/emchange/index.html?key=" + tk.getRegistrationKey() + "&lang=" + ureq.getLocale().getLanguage(), time, currentEmail, changedEmail })
-				+ SEPARATOR + this.translator.translate("email.change.wherefrom", new String[] { serverpath, today, ip });
-		subject = translate("email.change.subject");
-		// send email
-		try {
-			
-			MailBundle bundle = new MailBundle();
-			bundle.setFrom(WebappHelper.getMailConfig("mailReplyTo"));
-			bundle.setTo(changedEmail);
-			bundle.setContent(subject, body);
-
-			MailerResult result = mailManager.sendMessage(bundle);
-			boolean isMailSent = result.isSuccessful();
-			if (isMailSent) {
-				tk.setMailSent(true);
-				// set key
-				User user = this.identityToModify.getUser();
-				user.setProperty("emchangeKey", tk.getRegistrationKey());
-				UserManager.getInstance().updateUser(user);
-				getWindowControl().setInfo(this.translator.translate("email.sent"));
-			} else {
-				tk.setMailSent(false);
-				rm.deleteTemporaryKeyWithId(tk.getRegistrationKey());
-				getWindowControl().setError(this.translator.translate("email.notsent"));
-			}
-		} catch (Exception e) {
-			rm.deleteTemporaryKeyWithId(tk.getRegistrationKey());
-			getWindowControl().setError(translator.translate("email.notsent"));
-		}
+	public void resetForm(UserRequest ureq) {
+		removeAsListenerAndDispose(profileFormController);
+		removeAsListenerAndDispose(homePageController);
+		profileFormController = null;
+		homePageController = null;
+		doOpenProfile(ureq);
 	}
 
-	/**
-	 * Load and clean temporary keys with action "EMAIL_CHANGE".
-	 * @param serMailMap
-	 * @return
-	 */
-	private TemporaryKey loadCleanTemporaryKey(String serMailMap) {
-		TemporaryKey tk = rm.loadTemporaryKeyByEmail(serMailMap);
-		if (tk == null) {
-			XStream xml = new XStream();
-			@SuppressWarnings("unchecked")
-			Map<String, String> mails = (Map<String, String>) xml.fromXML(serMailMap);
-			String currentEMail = mails.get("currentEMail");
-			List<TemporaryKey> tks = rm.loadTemporaryKeyByAction(RegistrationManager.EMAIL_CHANGE);
-			if (tks != null) {
-				synchronized (tks) {
-					tks = rm.loadTemporaryKeyByAction(RegistrationManager.EMAIL_CHANGE);
-					int countCurrentEMail = 0;
-					for (TemporaryKey temporaryKey : tks) {
-						@SuppressWarnings("unchecked")
-						Map<String, String> tkMails = (Map<String, String>) xml.fromXML(temporaryKey.getEmailAddress());
-						if (tkMails.get("currentEMail").equals(currentEMail)) {
-							if (countCurrentEMail > 0) {
-								// clean
-								rm.deleteTemporaryKeyWithId(temporaryKey.getRegistrationKey());
-							} else {
-								// load
-								tk = temporaryKey;
-							}
-							countCurrentEMail++;
-						}
-					}
-				}
-			}
+	@Override
+	public void activate(UserRequest ureq, List<ContextEntry> entries, StateEntry state) {
+		if(entries == null || entries.isEmpty()) {
+			doOpenProfile(ureq);
 		}
-		return tk;
 	}
 
+	private ProfileFormController doOpenProfile(UserRequest ureq) {
+		if(profileFormController == null) {
+			profileFormController = new ProfileFormController(ureq, getWindowControl(), identityToModify, isAdministrativeUser);
+			listenTo(profileFormController);
+		}
 
-	/**
-	 * 
-	 * @see org.olat.core.gui.control.DefaultController#doDispose(boolean)
-	 */
-	@Override
-	protected void doDispose() {
-	// controllers disposed by basic controller
+		myContent.put("segmentCmp", profileFormController.getInitialComponent());
+		return profileFormController;
 	}
-
-	public void resetForm(UserRequest ureq, WindowControl wControl) {
-		if (this.profileFormController != null) {
-			this.myContent.remove(this.profileFormControllerComponent);
-			removeAsListenerAndDispose(this.profileFormController);
+	
+	private HomePageSettingsController doOpenHomePageSettings(UserRequest ureq) {
+		if(homePageController == null) {
+			homePageController = new HomePageSettingsController(ureq, getWindowControl(), identityToModify, isAdministrativeUser);
+			listenTo(homePageController);
 		}
-		this.profileFormController = new ProfileFormController(ureq, wControl, this.homePageConfig, this.identityToModify, isAdministrativeUser);
-		listenTo(this.profileFormController);
-		this.profileFormControllerComponent = this.profileFormController.getInitialComponent();
-		this.myContent.put("homepageform", this.profileFormControllerComponent);
+
+		myContent.put("segmentCmp", homePageController.getInitialComponent());
+		return homePageController;
 	}
 }
diff --git a/src/main/java/org/olat/user/ProfileFormController.java b/src/main/java/org/olat/user/ProfileFormController.java
index 9e188d4530b1110e1fbeaa4968ca917caf4f5cd7..dc48d354127ece3513ba10f60a883bb6688c6d7c 100644
--- a/src/main/java/org/olat/user/ProfileFormController.java
+++ b/src/main/java/org/olat/user/ProfileFormController.java
@@ -20,32 +20,59 @@
 
 package org.olat.user;
 
+import java.io.File;
+import java.text.DateFormat;
+import java.util.Calendar;
+import java.util.Date;
 import java.util.HashMap;
+import java.util.HashSet;
 import java.util.List;
 import java.util.Map;
 import java.util.Set;
 
+import org.olat.basesecurity.BaseSecurityManager;
+import org.olat.basesecurity.BaseSecurityModule;
+import org.olat.core.commons.persistence.DBFactory;
 import org.olat.core.gui.UserRequest;
 import org.olat.core.gui.components.form.flexible.FormItem;
 import org.olat.core.gui.components.form.flexible.FormItemContainer;
+import org.olat.core.gui.components.form.flexible.elements.FileElement;
+import org.olat.core.gui.components.form.flexible.elements.FormLink;
 import org.olat.core.gui.components.form.flexible.elements.MultipleSelectionElement;
 import org.olat.core.gui.components.form.flexible.elements.RichTextElement;
 import org.olat.core.gui.components.form.flexible.elements.TextElement;
 import org.olat.core.gui.components.form.flexible.impl.FormBasicController;
+import org.olat.core.gui.components.form.flexible.impl.FormEvent;
 import org.olat.core.gui.components.form.flexible.impl.FormLayoutContainer;
-import org.olat.core.gui.components.velocity.VelocityContainer;
+import org.olat.core.gui.components.link.Link;
 import org.olat.core.gui.control.Controller;
 import org.olat.core.gui.control.Event;
 import org.olat.core.gui.control.WindowControl;
+import org.olat.core.gui.control.generic.modal.DialogBoxController;
+import org.olat.core.gui.control.generic.modal.DialogBoxUIFactory;
+import org.olat.core.helpers.Settings;
 import org.olat.core.id.Identity;
+import org.olat.core.id.OLATResourceable;
 import org.olat.core.id.User;
+import org.olat.core.util.WebappHelper;
+import org.olat.core.util.coordinate.CoordinatorManager;
+import org.olat.core.util.coordinate.SyncerExecutor;
+import org.olat.core.util.event.MultiUserEvent;
+import org.olat.core.util.mail.MailBundle;
+import org.olat.core.util.mail.MailManager;
+import org.olat.core.util.mail.MailerResult;
+import org.olat.core.util.resource.OresHelper;
 import org.olat.core.util.xml.XStreamHelper;
 import org.olat.registration.RegistrationManager;
+import org.olat.registration.TemporaryKey;
 import org.olat.registration.TemporaryKeyImpl;
 import org.olat.user.propertyhandlers.UserPropertyHandler;
+import org.springframework.beans.factory.annotation.Autowired;
 
 import com.thoughtworks.xstream.XStream;
 
+import de.bps.olat.user.ChangeEMailController;
+
 /**
  * Provides a controller which lets the user edit their user profile and choose
  * the fields which are made publicly visible.
@@ -55,24 +82,36 @@ import com.thoughtworks.xstream.XStream;
  */
 public class ProfileFormController extends FormBasicController {
 
-	private HomePageConfig conf;
-
-	private List<UserPropertyHandler> userPropertyHandlers;
-
-	private Map<String, FormItem> formItems;
-
-	private Map<String, String> formContext;
+	private static final String usageIdentifier= ProfileFormController.class.getCanonicalName();
+	private static final String SEPARATOR = "\n____________________________________________________________________\n";
 
+	private final Map<String, FormItem> formItems = new HashMap<String, FormItem>();
+	private final Map<String, String> formContext = new HashMap<String, String>();
 	private RichTextElement textAboutMe;
 
-	private String usageIdentifier;
-
-	private Map<String, MultipleSelectionElement> publishCheckboxes;
-
-	private Identity identity;
-
-	private boolean isAdministrativeUser;
-
+	private Identity identityToModify;
+	private DialogBoxController dialogCtr;
+	
+	private FormLink deletePortrait;
+	private FileElement portraitUpload;
+	
+	private final boolean isAdministrativeUser;
+	private final List<UserPropertyHandler> userPropertyHandlers;
+	
+	private boolean emailChanged = false;
+	private String changedEmail;
+	private String currentEmail;
+	
+	@Autowired
+	private UserManager userManager;
+	@Autowired
+	private RegistrationManager rm;
+	@Autowired
+	private MailManager mailManager;
+	@Autowired
+	private HomePageConfigManager hpcm;
+	@Autowired
+	private DisplayPortraitManager dps;
 
 	/**
 	 * Creates this controller.
@@ -85,71 +124,39 @@ public class ProfileFormController extends FormBasicController {
 	 * @param isAdministrativeUser true: user is editing another users profile as
 	 *          user manager; false: use is editing his own profile
 	 */
-	public ProfileFormController(UserRequest ureq, WindowControl wControl, HomePageConfig conf, Identity identity,
-			boolean isAdministrativeUser) {
-		super(ureq, wControl, "combinedform");
-		UserManager um = UserManager.getInstance();
-		setTranslator(um.getPropertyHandlerTranslator(getTranslator()));		
-		this.publishCheckboxes = new HashMap<String, MultipleSelectionElement>();
-		this.conf = conf;
-		this.usageIdentifier = ProfileFormController.class.getCanonicalName();
-		this.userPropertyHandlers = um.getUserPropertyHandlersFor(this.usageIdentifier, isAdministrativeUser);
-		this.identity = identity;
-		this.formItems = new HashMap<String, FormItem>();
-		this.formContext = new HashMap<String, String>();
+	public ProfileFormController(UserRequest ureq, WindowControl wControl,
+			Identity identityToModify, boolean isAdministrativeUser) {
+		super(ureq, wControl, LAYOUT_BAREBONE);
+		setTranslator(userManager.getPropertyHandlerTranslator(getTranslator()));
+		
+		this.identityToModify = identityToModify;
 		this.isAdministrativeUser = isAdministrativeUser;
+		
+		userPropertyHandlers = userManager.getUserPropertyHandlersFor(usageIdentifier, isAdministrativeUser);
 		initForm(ureq);
 	}
+	
+	public Identity getIdentityToModify() {
+		return identityToModify;
+	}
 
 	/**
 	 * @see org.olat.core.gui.components.form.flexible.impl.FormBasicController#doDispose()
 	 */
 	@Override
 	protected void doDispose() {
-	// nothing to dispose.
-
-	}
-
-	/**
-	 * @see org.olat.core.gui.components.form.flexible.impl.FormBasicController#formOK(org.olat.core.gui.UserRequest)
-	 */
-	@Override
-	protected void formOK(UserRequest ureq) {
-		fireEvent(ureq, Event.DONE_EVENT);
+		// nothing to dispose.
 	}
 
-	/**
-	 * @see org.olat.core.gui.components.form.flexible.impl.FormBasicController#formNOK(org.olat.core.gui.UserRequest)
-	 */
-	@Override
-	protected void formNOK(UserRequest ureq) {
-		fireEvent(ureq, Event.FAILED_EVENT);
-	}
-
-	/**
-	 * @see org.olat.core.gui.components.form.flexible.impl.FormBasicController#formCancelled(org.olat.core.gui.UserRequest)
-	 */
-	@Override
-	protected void formCancelled(UserRequest ureq) {
-		fireEvent(ureq, Event.CANCELLED_EVENT);
-	}
-
-	/*
-	 * (non-Javadoc)
-	 * 
-	 * @see
-	 * org.olat.core.gui.components.form.flexible.impl.FormBasicController#initForm
-	 * (org.olat.core.gui.components.form.flexible.FormItemContainer,
-	 * org.olat.core.gui.control.Controller, org.olat.core.gui.UserRequest)
-	 */
 	@Override
 	protected void initForm(FormItemContainer formLayout, Controller listener, UserRequest ureq) {
-		formContext.put("username", identity.getName());
-		
+
 		String currentGroup = null;
+		User user = identityToModify.getUser();
+
 		// show a form element for each property handler 
 		FormLayoutContainer groupContainer = null;
-		for (UserPropertyHandler userPropertyHandler : this.userPropertyHandlers) {
+		for (UserPropertyHandler userPropertyHandler : userPropertyHandlers) {
 			if (userPropertyHandler == null) {
 				continue;
 			}
@@ -159,45 +166,27 @@ public class ProfileFormController extends FormBasicController {
 			if (!group.equals(currentGroup)) {
 				groupContainer = FormLayoutContainer.createDefaultFormLayout("group." + group, getTranslator());
 				groupContainer.setFormTitle(translate("form.group." + group));
-				this.formItems.put("group." + group, groupContainer);
+				formItems.put("group." + group, groupContainer);
 				formLayout.add(groupContainer);
+				if(currentGroup == null) {
+					groupContainer.setFormContextHelp("org.olat.user","home-vcard.html","help.hover.vcard");
+				}
 				currentGroup = group;
 			}
 			
-//			if (homepagePropertyHanders.contains(userPropertyHandler)) {
-//				// add checkbox to container if configured for homepage usage identifier
-//				String checkboxName = "checkbox_" + userPropertyHandler.getName();
-//				MultipleSelectionElement publishCheckbox = uifactory.addCheckboxesHorizontal(checkboxName, null, groupContainer, new String[] {userPropertyHandler.i18nFormElementLabelKey()}, new String[] {""}, null);
-//				this.publishCheckboxes.put(checkboxName, publishCheckbox);
-//				boolean isEnabled = this.conf.isEnabled(userPropertyHandler.getName());
-//				if (isEnabled) {
-//					publishCheckbox.select(userPropertyHandler.i18nFormElementLabelKey(), true);
-//				} else {
-//					publishCheckbox.select(userPropertyHandler.i18nFormElementLabelKey(), false);
-//				}				
-//				// Mandatory homepage properties can not be changed by user
-//				UserManager um = UserManager.getInstance();
-//				if (um.isMandatoryUserProperty(HomePageConfig.class.getCanonicalName(), userPropertyHandler)) {
-//					publishCheckbox.select(userPropertyHandler.i18nFormElementLabelKey(), true);
-//					publishCheckbox.setEnabled(false);
-//				}
-//			} else {
-//				uifactory.addSpacerElement("spacer_" + userPropertyHandler.getName(), groupContainer, true);
-//			}
-			
 			// add input field to container
-			FormItem formItem = userPropertyHandler.addFormItem(getLocale(), identity.getUser(), this.usageIdentifier, this.isAdministrativeUser, groupContainer);
+			FormItem formItem = userPropertyHandler.addFormItem(getLocale(), user, usageIdentifier, isAdministrativeUser, groupContainer);
 			String propertyName = userPropertyHandler.getName();
-			this.formItems.put(propertyName, formItem);
+			formItems.put(propertyName, formItem);
 			
 			if (formItem instanceof TextElement) {
 				// it's a text field, so get the value of this property into the text field
 				TextElement textElement = (TextElement)formItem;
-				textElement.setValue(this.identity.getUser().getProperty(propertyName, getLocale()));
+				textElement.setValue(user.getProperty(propertyName, getLocale()));
 			} else if (formItem instanceof MultipleSelectionElement) {
 				// it's a checkbox, so set the box to checked if the corresponding property is set to "true"
 				MultipleSelectionElement checkbox = (MultipleSelectionElement)formItem;
-				String value = this.identity.getUser().getProperty(propertyName, getLocale());
+				String value = user.getProperty(propertyName, getLocale());
 				if (value != null) {
 					checkbox.select(propertyName, value.equals("true"));
 				} else {
@@ -209,7 +198,7 @@ public class ProfileFormController extends FormBasicController {
 			// special case for email field
 			if (userPropertyHandler.getName().equals("email")) {
 				RegistrationManager rm = RegistrationManager.getInstance();
-				String key = this.identity.getUser().getProperty("emchangeKey", null);
+				String key = user.getProperty("emchangeKey", null);
 				TemporaryKeyImpl tempKey = rm.loadTemporaryKeyByRegistrationKey(key);
 				if (tempKey != null) {
 					XStream xml = XStreamHelper.createXStreamInstance();
@@ -223,12 +212,38 @@ public class ProfileFormController extends FormBasicController {
 		// add the "about me" text field.
 		groupContainer = FormLayoutContainer.createDefaultFormLayout("group.about", getTranslator());
 		groupContainer.setFormTitle(translate("form.group.about"));
-		this.formItems.put("group.about", groupContainer);
 		formLayout.add(groupContainer);
-
-		textAboutMe = uifactory.addRichTextElementForStringData("form.text", "form.text", this.conf.getTextAboutMe(), 10, -1, false, null, null, groupContainer, ureq.getUserSession(), getWindowControl());
+		
+		HomePageConfig conf = hpcm.loadConfigFor(identityToModify.getName());
+		textAboutMe = uifactory.addRichTextElementForStringData("form.text", "form.text",
+				conf.getTextAboutMe(), 10, -1, false, null, null, groupContainer,
+				ureq.getUserSession(), getWindowControl());
 		textAboutMe.setMaxLength(10000);
-		formItems.put("form.text", this.textAboutMe);
+		
+		//upload image
+		groupContainer = FormLayoutContainer.createDefaultFormLayout("portraitupload", getTranslator());
+		groupContainer.setFormTitle(translate("ul.header"));
+		groupContainer.setFormContextHelp("org.olat.user","home-picture.html","chelp.home-picture.hover");
+		formLayout.add(groupContainer);
+
+		deletePortrait = uifactory.addFormLink("command.delete", groupContainer, Link.BUTTON);
+
+		File portraitFile = dps.getBigPortrait(identityToModify.getName());
+		// Init upload controller
+		Set<String> mimeTypes = new HashSet<String>();
+		mimeTypes.add("image/gif");
+		mimeTypes.add("image/jpg");
+		mimeTypes.add("image/jpeg");
+		mimeTypes.add("image/png");
+
+		portraitUpload = uifactory.addFileElement("ul.select", "ul.select", groupContainer);
+		portraitUpload.setMaxUploadSizeKB(10000, null, null);
+		portraitUpload.setPreview(ureq.getUserSession(), true);
+		portraitUpload.addActionListener(FormEvent.ONCHANGE);
+		if(portraitFile != null) {
+			portraitUpload.setInitialFile(portraitFile);
+		}
+		portraitUpload.limitToMimeType(mimeTypes, null, null);
 		
 		// Create submit and cancel buttons
 		FormLayoutContainer buttonLayoutWrappper = FormLayoutContainer.createDefaultFormLayout("buttonLayoutWrappper", getTranslator());
@@ -237,10 +252,6 @@ public class ProfileFormController extends FormBasicController {
 		buttonLayoutWrappper.add(buttonLayout);
 		uifactory.addFormSubmitButton("save", buttonLayout);
 		uifactory.addFormCancelButton("cancel", buttonLayout, ureq, getWindowControl());
-		formItems.put("buttonLayout", buttonLayout);
-		
-		Set<String> userPropertyNames = formItems.keySet();
-		((VelocityContainer)this.flc.getComponent()).contextPut("userPropertyNames", userPropertyNames);
 	}
 
 	/**
@@ -251,69 +262,46 @@ public class ProfileFormController extends FormBasicController {
 	 *          visible fields).
 	 * @param identity The user's identity
 	 */
-	public void updateFromFormData(final HomePageConfig config, final Identity identity) {
-		User user = identity.getUser();
+	public void updateFromFormData() {
+		User user = identityToModify.getUser();
 		// For each user property...
 		for (UserPropertyHandler userPropertyHandler : userPropertyHandlers) {
-
 			// ...get the value from the form field and store it into the user
 			// property...
 			FormItem formItem = formItems.get(userPropertyHandler.getName());
 			if(formItem.isEnabled()) {
 				userPropertyHandler.updateUserFromFormItem(user, formItem);
 			}
-
-			// ...and store the "publish" flag for each property.
-			MultipleSelectionElement checkbox = publishCheckboxes.get("checkbox_" + userPropertyHandler.getName());
-			if (checkbox != null) {
-				// null when not enabled for the org.olat.user.HomePageConfig usage
-				// identifier key
-				if (checkbox.getSelectedKeys().size() == 0) {
-					config.setEnabled(userPropertyHandler.getName(), false);
-				} else {
-					config.setEnabled(userPropertyHandler.getName(), true);
-				}
-			}
 		}
 		// Store the "about me" text.
+		HomePageConfig conf = hpcm.loadConfigFor(identityToModify.getName());
 		conf.setTextAboutMe(textAboutMe.getValue());
+		hpcm.saveConfigTo(identityToModify.getName(), conf);
 	}
-
-	/**
-	 * Take form data and set it in the user fields for the current subject
-	 * 
-	 * @param id The identity to be updated (transient, does not do any db calls)
-	 * @return the updated identity object
-	 */
-	public Identity updateIdentityFromFormData(Identity id) {
-		identity = id;
-		User user = identity.getUser();
-		// update each user field
+	
+	public Identity updateIdentityFromFormData(Identity identity) {
+		identityToModify = identity;
+		User user = identityToModify.getUser();
 		for (UserPropertyHandler userPropertyHandler : userPropertyHandlers) {
 			FormItem formItem = formItems.get(userPropertyHandler.getName());
 			if(formItem.isEnabled()) {
 				userPropertyHandler.updateUserFromFormItem(user, formItem);
 			}
 		}
-		return identity;
+		return identityToModify;
 	}
 
-	/*
-	 * (non-Javadoc)
-	 * 
-	 * @seeorg.olat.core.gui.components.form.flexible.impl.FormBasicController#
-	 * validateFormLogic(org.olat.core.gui.UserRequest)
-	 */
 	@Override
 	protected boolean validateFormLogic(UserRequest ureq) {
-		boolean formOK = true;
-		User user = identity.getUser();
-		for (UserPropertyHandler userPropertyHandler : this.userPropertyHandlers) {
+		boolean allOk = true;
+		formContext.put("username", identityToModify.getName());
+		
+		User user = identityToModify.getUser();
+		for (UserPropertyHandler userPropertyHandler : userPropertyHandlers) {
 			FormItem formItem = formItems.get(userPropertyHandler.getName());
-			if (!userPropertyHandler.isValid(user, formItem, formContext)) {
-				formOK = false;
-			} else {
+			if(formItem.isEnabled()) {
 				formItem.clearError();
+				allOk &= userPropertyHandler.isValid(user, formItem, formContext);
 			}
 		}
 		
@@ -321,15 +309,247 @@ public class ProfileFormController extends FormBasicController {
 			String aboutMe = textAboutMe.getValue();
 			if(aboutMe.length() > 10000) {
 				textAboutMe.setErrorKey("input.toolong", new String[] {"10000"});
-				formOK = false;
+				allOk = false;
 			} else {
 				textAboutMe.clearError();
 			}
 		} catch (Exception e) {
 			textAboutMe.setErrorKey("input.toolong", new String[] {"10000"});
-			formOK = false;
+			allOk = false;
+		}
+		return allOk & super.validateFormLogic(ureq);
+	}
+
+	@Override
+	protected void formNOK(UserRequest ureq) {
+		fireEvent(ureq, Event.FAILED_EVENT);
+	}
+
+	@Override
+	protected void formCancelled(UserRequest ureq) {
+		fireEvent(ureq, Event.CANCELLED_EVENT);
+	}
+
+	@Override
+	protected void event(UserRequest ureq, Controller source, Event event) {
+		if (source == dialogCtr) {
+			dialogCtr.dispose();
+			dialogCtr = null;
+			if (DialogBoxUIFactory.isYesEvent(event)) {
+				if (changedEmail != null) {
+					createChangeEmailWorkflow(ureq);
+				}
+			}
+			fireEvent(ureq, Event.FAILED_EVENT);
+		}
+		super.event(ureq, source, event);
+	}
+
+	@Override
+	protected void formInnerEvent(UserRequest ureq, FormItem source, FormEvent event) {
+		 if (source == portraitUpload) {
+			if (portraitUpload.isUploadSuccess()) {
+				deletePortrait.setVisible(true);
+					flc.setDirty(true);
+			}
+		} else if (source == deletePortrait) {
+			File img = dps.getBigPortrait(identityToModify.getName());
+			if(portraitUpload.getUploadFile() != null) {
+				portraitUpload.reset();
+				if(img == null) {
+					deletePortrait.setVisible(false);
+				} else {
+					deletePortrait.setVisible(true);
+				}
+			} else if(img != null) {
+				dps.deletePortrait(identityToModify);
+				deletePortrait.setVisible(false);
+				portraitUpload.setInitialFile(null);
+			}
+			flc.setDirty(true);
+		}
+
+		super.formInnerEvent(ureq, source, event);
+	}
+
+	@Override
+	protected void formOK(final UserRequest ureq) {
+		User user = identityToModify.getUser();
+		// update each user field
+		for (UserPropertyHandler userPropertyHandler : userPropertyHandlers) {
+			FormItem formItem = formItems.get(userPropertyHandler.getName());
+			if(formItem.isEnabled()) {
+				userPropertyHandler.updateUserFromFormItem(user, formItem);
+			}
+		}
+		
+		File uploadedImage = portraitUpload.getUploadFile();
+		if(uploadedImage != null) {
+			dps.setPortrait(uploadedImage, identityToModify.getName());
+		}
+
+		// fire the appropriate event
+		fireEvent(ureq, Event.DONE_EVENT);
+
+		// update the user profile data
+		CoordinatorManager.getInstance().getCoordinator().getSyncer().doInSync(
+			OresHelper.createOLATResourceableInstance(Identity.class, identityToModify.getKey()), new SyncerExecutor() {
+			@Override
+			public void execute() {
+				UserManager um = UserManager.getInstance();
+				identityToModify = (Identity) DBFactory.getInstance().loadObject(identityToModify);
+				currentEmail = identityToModify.getUser().getProperty("email", null);
+
+				identityToModify = updateIdentityFromFormData(identityToModify);
+				changedEmail = identityToModify.getUser().getProperty("email", null);
+				if (!currentEmail.equals(changedEmail)) {
+					// allow an admin to change email without verification workflow. usermanager is only permitted to do so, if set by config.
+					if ( !(ureq.getUserSession().getRoles().isOLATAdmin()
+							|| (BaseSecurityModule.USERMANAGER_CAN_BYPASS_EMAILVERIFICATION && ureq.getUserSession().getRoles().isUserManager() ))) {
+						emailChanged = true;
+						// change email address to old address until it is verified
+						identityToModify.getUser().setProperty("email", currentEmail);
+					} else {
+						String key = identityToModify.getUser().getProperty("emchangeKey", null);
+						TemporaryKeyImpl tempKey = rm.loadTemporaryKeyByRegistrationKey(key);
+						if (tempKey != null) {
+							rm.deleteTemporaryKey(tempKey);
+						}		
+					}
+				}
+				if (!um.updateUserFromIdentity(identityToModify)) {
+					getWindowControl().setInfo(translate("profile.unsuccessful"));
+					// reload user data from db
+					identityToModify = BaseSecurityManager.getInstance().loadIdentityByKey(identityToModify.getKey());
+				}
+				
+				OLATResourceable modRes = OresHelper.createOLATResourceableInstance(Identity.class, identityToModify.getKey());
+				CoordinatorManager.getInstance().getCoordinator().getEventBus()
+					.fireEventToListenersOf(new MultiUserEvent("changed"), modRes);
+				
+				if (!emailChanged) {
+					fireEvent(ureq, Event.FAILED_EVENT);
+				}
+			}
+		});
+		
+		if (emailChanged) {
+			removeAsListenerAndDispose(dialogCtr);
+
+			String changerEMail = ureq.getIdentity().getUser().getProperty("email", ureq.getLocale());
+			String dialogText = "";
+			if(changerEMail != null && changerEMail.length() > 0 && changerEMail.equals(currentEmail)) {
+				dialogText = translate("email.change.dialog.text");
+			} else {
+				dialogText = translate("email.change.dialog.text.usermanager");
+			}
+			dialogCtr = DialogBoxUIFactory.createYesNoDialog(ureq, getWindowControl(), translate("email.change.dialog.title"), dialogText);
+			listenTo(dialogCtr);
+			dialogCtr.activate();
+		}
+	}
+	
+	private void createChangeEmailWorkflow(UserRequest ureq) {
+		// send email
+		changedEmail = changedEmail.trim();
+		String body = null;
+		String subject = null;
+		// get remote address
+		String ip = ureq.getHttpReq().getRemoteAddr();
+		String today = DateFormat.getDateInstance(DateFormat.LONG, ureq.getLocale()).format(new Date());
+		// mailer configuration
+		String serverpath = Settings.getServerContextPathURI();
+		String servername = ureq.getHttpReq().getServerName();
+
+		logDebug("this servername is " + servername + " and serverpath is " + serverpath, null);
+		// load or create temporary key
+		Map<String, String> mailMap = new HashMap<String, String>();
+		mailMap.put("currentEMail", currentEmail);
+		mailMap.put("changedEMail", changedEmail);
+		
+		XStream xml = new XStream();
+		String serMailMap = xml.toXML(mailMap);
+		
+		TemporaryKey tk = loadCleanTemporaryKey(serMailMap);				
+		if (tk == null) {
+			tk = rm.createTemporaryKeyByEmail(serMailMap, ip, RegistrationManager.EMAIL_CHANGE);
+		} else {
+			rm.deleteTemporaryKeyWithId(tk.getRegistrationKey());
+			tk = rm.createTemporaryKeyByEmail(serMailMap, ip, RegistrationManager.EMAIL_CHANGE);
+		}
+		
+		// create date, time string
+		Calendar cal = Calendar.getInstance();
+		cal.setTime(tk.getCreationDate());
+		cal.add(Calendar.DAY_OF_WEEK, ChangeEMailController.TIME_OUT);
+		String time = DateFormat.getDateTimeInstance(DateFormat.SHORT, DateFormat.SHORT, ureq.getLocale()).format(cal.getTime());
+		// create body and subject for email
+		body = translate("email.change.body", new String[] { serverpath + "/dmz/emchange/index.html?key=" + tk.getRegistrationKey() + "&lang=" + ureq.getLocale().getLanguage(), time, currentEmail, changedEmail })
+				+ SEPARATOR + translate("email.change.wherefrom", new String[] { serverpath, today, ip });
+		subject = translate("email.change.subject");
+		// send email
+		try {
+			
+			MailBundle bundle = new MailBundle();
+			bundle.setFrom(WebappHelper.getMailConfig("mailReplyTo"));
+			bundle.setTo(changedEmail);
+			bundle.setContent(subject, body);
+
+			MailerResult result = mailManager.sendMessage(bundle);
+			boolean isMailSent = result.isSuccessful();
+			if (isMailSent) {
+				tk.setMailSent(true);
+				// set key
+				User user = this.identityToModify.getUser();
+				user.setProperty("emchangeKey", tk.getRegistrationKey());
+				UserManager.getInstance().updateUser(user);
+				getWindowControl().setInfo(translate("email.sent"));
+			} else {
+				tk.setMailSent(false);
+				rm.deleteTemporaryKeyWithId(tk.getRegistrationKey());
+				getWindowControl().setError(translate("email.notsent"));
+			}
+		} catch (Exception e) {
+			rm.deleteTemporaryKeyWithId(tk.getRegistrationKey());
+			getWindowControl().setError(translate("email.notsent"));
+		}
+	}
+
+	/**
+	 * Load and clean temporary keys with action "EMAIL_CHANGE".
+	 * @param serMailMap
+	 * @return
+	 */
+	private TemporaryKey loadCleanTemporaryKey(String serMailMap) {
+		TemporaryKey tk = rm.loadTemporaryKeyByEmail(serMailMap);
+		if (tk == null) {
+			XStream xml = new XStream();
+			@SuppressWarnings("unchecked")
+			Map<String, String> mails = (Map<String, String>) xml.fromXML(serMailMap);
+			String currentEMail = mails.get("currentEMail");
+			List<TemporaryKey> tks = rm.loadTemporaryKeyByAction(RegistrationManager.EMAIL_CHANGE);
+			if (tks != null) {
+				synchronized (tks) {
+					tks = rm.loadTemporaryKeyByAction(RegistrationManager.EMAIL_CHANGE);
+					int countCurrentEMail = 0;
+					for (TemporaryKey temporaryKey : tks) {
+						@SuppressWarnings("unchecked")
+						Map<String, String> tkMails = (Map<String, String>) xml.fromXML(temporaryKey.getEmailAddress());
+						if (tkMails.get("currentEMail").equals(currentEMail)) {
+							if (countCurrentEMail > 0) {
+								// clean
+								rm.deleteTemporaryKeyWithId(temporaryKey.getRegistrationKey());
+							} else {
+								// load
+								tk = temporaryKey;
+							}
+							countCurrentEMail++;
+						}
+					}
+				}
+			}
 		}
-		return formOK && super.validateFormLogic(ureq);
+		return tk;
 	}
 
 	/**
diff --git a/src/main/java/org/olat/user/_content/combinedform.html b/src/main/java/org/olat/user/_content/combinedform.html
deleted file mode 100644
index ae1533d528e07c460408688f7dbcbf6011409309..0000000000000000000000000000000000000000
--- a/src/main/java/org/olat/user/_content/combinedform.html
+++ /dev/null
@@ -1,30 +0,0 @@
-<div class="o_form form-horizontal" role="form">
-#foreach ($item in $formitemnames)
-					$r.render(${item})
-#*
-	#if ($userPropertyNames.contains($item))
-		#if ($f.isVisible($item))
-			<div class="form-group $f.getElementCssClass($item) #if($f.hasError($item)) has-error #end">
-				#if ($f.hasLabel($item))
-					$r.render("${item}_LABEL", "$f.getItemId($item)", "$f.isMandatory($item)")
-				#end
-			    #if ($r.available("checkbox_${item}"))
-				        $r.render("checkbox_${item}")
-				#else
-					$r.render(${item})
-					#if($f.hasExample($item))
-						<p class="help-block">
-							$r.render("${item}_EXAMPLE")
-						</p>
-					#end
-					#if($f.hasError($item))
-						<span class="o_icon o_icon_error form-control-feedback"></span>
-						$r.render("${item}_ERROR")
-					#end
-				#end
-			</div>
-		#end
-	#end
-*#
-#end
-</div>
diff --git a/src/main/java/org/olat/user/_content/homepage.html b/src/main/java/org/olat/user/_content/homepage.html
index 6ea5c3a5ce2c85865e879976ef136ff00abfc4e1..f70c71d46f469cf5b3ce088bd7678344b3287bea 100644
--- a/src/main/java/org/olat/user/_content/homepage.html
+++ b/src/main/java/org/olat/user/_content/homepage.html
@@ -1,21 +1,7 @@
-<h2>	
-	$r.contextHelpWithWrapper("org.olat.user","home-vcard.html","help.hover.vcard")
-	$r.translate("title.homepage")
+<p class="o_note">$r.translate("form.description")</p>
+$r.render("segments")
+<div class="o_segments_content">
+	$r.render("segmentCmp")
+</div>
 
-</h2>
-<p class="o_note">
-	$r.translate("form.description")
-</p>
-<p>
-	$r.render("command.preview")
-</p>
-	
-$r.render("homepageform")
 
-<fieldset>
-	<legend>
-		$r.contextHelpWithWrapper("org.olat.user","home-picture.html","chelp.home-picture.hover")
-		$r.translate("ul.header")
-	</legend>
-	$r.render("c")
-</fieldset>
\ No newline at end of file
diff --git a/src/main/java/org/olat/user/_content/homepage_preview.html b/src/main/java/org/olat/user/_content/homepage_preview.html
new file mode 100644
index 0000000000000000000000000000000000000000..6f5107451dac5099f9cbc0bec9b425e6bb15e078
--- /dev/null
+++ b/src/main/java/org/olat/user/_content/homepage_preview.html
@@ -0,0 +1,10 @@
+<fieldset>
+	<legend>$!off_title</legend>
+#foreach ($item in $formitemnames)
+	#if ($f.isVisible($item))
+		$r.render(${item})
+	#end
+#end
+</fieldset>
+
+
diff --git a/src/main/java/org/olat/user/_i18n/LocalStrings_de.properties b/src/main/java/org/olat/user/_i18n/LocalStrings_de.properties
index 75f7b71c53df7b09ee0acfcaa0d03b0c1c7a5b18..f1e16e1c42ce80a5abaf15e9b73a839340ba5f16 100644
--- a/src/main/java/org/olat/user/_i18n/LocalStrings_de.properties
+++ b/src/main/java/org/olat/user/_i18n/LocalStrings_de.properties
@@ -85,6 +85,7 @@ chelp.usertools1=Benutzerwerkzeug Hilfe
 command.closehp=Vorschau schliessen
 command.delete=L\u00F6schen
 command.preview=Vorschau anzeigen
+tab.preview=Vorschau
 error.no.props.found=Es wurden keine Properties f\u00FCr diesen Benutzer gefunden
 form.checkPassword=Das Passwort muss mindestens 4 Zeichen haben. Verwenden Sie dabei sowohl Ziffern als auch Buchstaben.
 error.password.empty=Geben Sie Ihr bisheriges Passwort an