diff --git a/lib/app.php b/lib/app.php
index 73bee11a69c6ca798a4887a72ca263a593e355aa..7aafeb362951932cc7b9e46e5f7a382c7e0ac3e4 100644
--- a/lib/app.php
+++ b/lib/app.php
@@ -142,6 +142,8 @@ class OC_App{
 	 * check if app is shipped
 	 * @param string $appid the id of the app to check
 	 * @return bool
+	 *
+	 * Check if an app that is installed is a shipped app or installed from the appstore.
 	 */
 	public static function isShipped($appid){
 		$info = self::getAppInfo($appid);
@@ -177,7 +179,7 @@ class OC_App{
 	 * This function checks whether or not an app is enabled.
 	 */
 	public static function isEnabled( $app ) {
-		if( 'files'==$app or 'yes' == OC_Appconfig::getValue( $app, 'enabled' )) {
+		if( 'files'==$app or ('yes' == OC_Appconfig::getValue( $app, 'enabled' ))) {
 			return true;
 		}
 
@@ -197,9 +199,10 @@ class OC_App{
 			if(!is_numeric($app)) {
 				$app = OC_Installer::installShippedApp($app);
 			}else{
+				$appdata=OC_OCSClient::getApplication($app);
 				$download=OC_OCSClient::getApplicationDownload($app, 1);
 				if(isset($download['downloadlink']) and $download['downloadlink']!='') {
-					$app=OC_Installer::installApp(array('source'=>'http', 'href'=>$download['downloadlink']));
+					$app=OC_Installer::installApp(array('source'=>'http', 'href'=>$download['downloadlink'],'appdata'=>$appdata));
 				}
 			}
 		}
@@ -212,6 +215,9 @@ class OC_App{
 				return false;
 			}else{
 				OC_Appconfig::setValue( $app, 'enabled', 'yes' );
+				if(isset($appdata['id'])) {
+					OC_Appconfig::setValue( $app, 'ocsid', $appdata['id'] );
+				}
 				return true;
 			}
 		}else{
@@ -227,8 +233,13 @@ class OC_App{
 	 * This function set an app as disabled in appconfig.
 	 */
 	public static function disable( $app ) {
-		// check if app is a shiped app or not. if not delete
+		// check if app is a shipped app or not. if not delete
 		OC_Appconfig::setValue( $app, 'enabled', 'no' );
+
+		// check if app is a shipped app or not. if not delete
+		if(!OC_App::isShipped( $app )){
+			OC_Installer::removeApp( $app );
+		}
 	}
 
 	/**
@@ -621,9 +632,13 @@ class OC_App{
 				if(isset($info['shipped']) and ($info['shipped']=='true')) {
 					$info['internal']=true;
 					$info['internallabel']='Internal App';
+					$info['internalclass']='';
+					$info['update']=false;
 				} else {
 					$info['internal']=false;
 					$info['internallabel']='3rd Party App';
+					$info['internalclass']='externalapp';
+					$info['update']=OC_Installer::isUpdateAvailable($app);
 				}
 
 				$info['preview'] = OC_Helper::imagePath('settings', 'trans.png');
@@ -633,15 +648,15 @@ class OC_App{
 		}
 		$remoteApps = OC_App::getAppstoreApps();
 		if ( $remoteApps ) {
-	// Remove duplicates
+			// Remove duplicates
 			foreach ( $appList as $app ) {
 				foreach ( $remoteApps AS $key => $remote ) {
 					if (
 						$app['name'] == $remote['name']
-			// To set duplicate detection to use OCS ID instead of string name,
-			// enable this code, remove the line of code above,
-			// and add <ocs_id>[ID]</ocs_id> to info.xml of each 3rd party app:
-			// OR $app['ocs_id'] == $remote['ocs_id']
+						// To set duplicate detection to use OCS ID instead of string name,
+						// enable this code, remove the line of code above,
+						// and add <ocs_id>[ID]</ocs_id> to info.xml of each 3rd party app:
+						// OR $app['ocs_id'] == $remote['ocs_id']
 						) {
 						unset( $remoteApps[$key]);
 				}
@@ -675,6 +690,15 @@ class OC_App{
 				$app1[$i]['author'] = $app['personid'];
 				$app1[$i]['ocs_id'] = $app['id'];
 				$app1[$i]['internal'] = $app1[$i]['active'] = 0;
+				$app1[$i]['update'] = false;
+				if($app['label']=='recommended'){
+					$app1[$i]['internallabel'] = 'Recommended';
+					$app1[$i]['internalclass'] = 'recommendedapp';
+				}else{
+					$app1[$i]['internallabel'] = '3rd Party';
+					$app1[$i]['internalclass'] = 'externalapp';
+				}
+
 
 				// rating img
 				if($app['score']>=0     and $app['score']<5)	$img=OC_Helper::imagePath( "core", "rating/s1.png" );
diff --git a/lib/installer.php b/lib/installer.php
index 7dc8b0cef8ddfbbe2db16814dc92c3f67ef9765e..c86f801b5fcf68cdb59045c59a284879021bdaba 100644
--- a/lib/installer.php
+++ b/lib/installer.php
@@ -141,13 +141,17 @@ class OC_Installer{
 			return false;
 		}
 
-		//check if an app with the same id is already installed
-		if(self::isInstalled( $info['id'] )) {
-			OC_Log::write('core', 'App already installed', OC_Log::WARN);
+		// check if shipped tag is set which is only allowed for apps that are shipped with ownCloud
+		if(isset($info['shipped']) and ($info['shipped']=='true')) {
+			OC_Log::write('core', 'App can\'t be installed because it contains the <shipped>true</shippe> tag which is not allowed for non shipped apps', OC_Log::ERROR);
+			OC_Helper::rmdirr($extractDir);
+			return false;
+		}
+
+		// check if the ocs version is the same as the version in info.xml/version
+		if(!isset($info['version']) or ($info['version']<>$data['appdata']['version'])) {
+			OC_Log::write('core', 'App can\'t be installed because the version in info.xml/version is not the same as the version reported from the app store', OC_Log::ERROR);
 			OC_Helper::rmdirr($extractDir);
-			if($data['source']=='http') {
-				unlink($path);
-			}
 			return false;
 		}
 
@@ -226,7 +230,6 @@ class OC_Installer{
 	/**
 	 * @brief Update an application
 	 * @param $data array with all information
-	 * @returns integer
 	 *
 	 * This function installs an app. All information needed are passed in the
 	 * associative array $data.
@@ -250,9 +253,55 @@ class OC_Installer{
 	 *
 	 * upgrade.php can determine the current installed version of the app using "OC_Appconfig::getValue($appid, 'installed_version')"
 	 */
-	public static function upgradeApp( $data = array()) {
-		// TODO: write function
-		return true;
+	public static function updateApp( $app ) {
+		$ocsid=OC_Appconfig::getValue( $app, 'ocsid');
+		OC_App::disable($app);
+		OC_App::enable($ocsid);
+		return(true);
+	}
+
+	/**
+	 * @brief Check if an update for the app is available
+	 * @param $name name of the application
+	 * @returns empty string is no update available or the version number of the update
+	 *
+	 * The function will check if an update for a version is available
+	 */
+	public static function isUpdateAvailable( $app ) {
+		$ocsid=OC_Appconfig::getValue( $app, 'ocsid', '');
+
+		if($ocsid<>''){
+
+			$ocsdata=OC_OCSClient::getApplication($ocsid);
+			$ocsversion= (string) $ocsdata['version'];
+			$currentversion=OC_App::getAppVersion($app);
+			if($ocsversion<>$currentversion){
+				return($ocsversion);
+
+			}else{
+				return('');
+			}
+
+		}else{
+			return('');
+		}
+
+	}
+
+	/**
+	 * @brief Check if app is already downloaded
+	 * @param $name name of the application to remove
+	 * @returns true/false
+	 *
+	 * The function will check if the app is already downloaded in the apps repository
+	 */
+	public static function isDownloaded( $name ) {
+
+		$downloaded=false;
+		foreach(OC::$APPSROOTS as $dir) {
+			if(is_dir($dir['path'].'/'.$name)) $downloaded=true;
+		}
+		return($downloaded);
 	}
 
 	/**
@@ -276,8 +325,36 @@ class OC_Installer{
 	 * this has to be done by the function oc_app_uninstall().
 	 */
 	public static function removeApp( $name, $options = array()) {
-		// TODO: write function
-		return true;
+
+		if(isset($options['keeppreferences']) and $options['keeppreferences']==false ){
+			// todo
+			// remove preferences
+		}
+
+		if(isset($options['keepappconfig']) and $options['keepappconfig']==false ){
+			// todo
+			// remove app config
+		}
+
+		if(isset($options['keeptables']) and $options['keeptables']==false ){
+			// todo
+			// remove app database tables
+		}
+
+		if(isset($options['keepfiles']) and $options['keepfiles']==false ){
+			// todo
+			// remove user files
+		}
+
+		if(OC_Installer::isDownloaded( $name )) {
+			$appdir=OC_App::getInstallPath().'/'.$name;
+			OC_Helper::rmdirr($appdir);
+
+		}else{
+			OC_Log::write('core', 'can\'t remove app '.$name.'. It is not installed.', OC_Log::ERROR);
+
+		}
+
 	}
 
 	/**
diff --git a/lib/ocsclient.php b/lib/ocsclient.php
index ca0665da436a080f16f25403bc7b89c59c7bec4a..30163c1e403f27ffb5eabd43e3f802f31362b372 100644
--- a/lib/ocsclient.php
+++ b/lib/ocsclient.php
@@ -123,6 +123,8 @@ class OC_OCSClient{
 			$app=array();
 			$app['id']=(string)$tmp[$i]->id;
 			$app['name']=(string)$tmp[$i]->name;
+			$app['label']=(string)$tmp[$i]->label;
+			$app['version']=(string)$tmp[$i]->version;
 			$app['type']=(string)$tmp[$i]->typeid;
 			$app['typename']=(string)$tmp[$i]->typename;
 			$app['personid']=(string)$tmp[$i]->personid;
@@ -162,7 +164,9 @@ class OC_OCSClient{
 		$app=array();
 		$app['id']=$tmp->id;
 		$app['name']=$tmp->name;
+		$app['version']=$tmp->version;
 		$app['type']=$tmp->typeid;
+		$app['label']=$tmp->label;
 		$app['typename']=$tmp->typename;
 		$app['personid']=$tmp->personid;
 		$app['detailpage']=$tmp->detailpage;
diff --git a/settings/ajax/apps/ocs.php b/settings/ajax/apps/ocs.php
index 1ffba26ad1d693d2404379b830761cbb5a779ecd..d0205a1ba34a0b0229bcc2621c70e2378376deaf 100644
--- a/settings/ajax/apps/ocs.php
+++ b/settings/ajax/apps/ocs.php
@@ -44,6 +44,11 @@ if(is_array($catagoryNames)) {
 			} else {
 				$pre=$app['preview'];
 			}
+			if($app['label']=='recommended') {
+				$label='3rd Party App';
+			} else {
+				$label='Recommended';
+			}
 			$apps[]=array(
 				'name'=>$app['name'],
 				'id'=>$app['id'],
@@ -53,7 +58,8 @@ if(is_array($catagoryNames)) {
 				'license'=>$app['license'],
 				'preview'=>$pre,
 				'internal'=>false,
-				'internallabel'=>'3rd Party App',
+				'internallabel'=>$label,
+				'update'=>false,
 			);
 		}
 	}
diff --git a/settings/ajax/updateapp.php b/settings/ajax/updateapp.php
new file mode 100644
index 0000000000000000000000000000000000000000..77c0bbc3e36cc3af4f266068c8ee405e87af004c
--- /dev/null
+++ b/settings/ajax/updateapp.php
@@ -0,0 +1,17 @@
+<?php
+
+OC_JSON::checkAdminUser();
+OCP\JSON::callCheck();
+
+$appid = $_POST['appid'];
+
+$result = OC_Installer::updateApp($appid);
+if($result !== false) {
+	OC_JSON::success(array('data' => array('appid' => $appid)));
+} else {
+	$l = OC_L10N::get('settings');	
+	OC_JSON::error(array("data" => array( "message" => $l->t("Couldn't update app.") )));
+}
+
+
+
diff --git a/settings/apps.php b/settings/apps.php
index b6426a31c976439ea1e04941863e863b9effa66e..4f8eba159c2270189dcad22b09232c281c61ee3d 100644
--- a/settings/apps.php
+++ b/settings/apps.php
@@ -31,13 +31,13 @@ OC_App::setActiveNavigationEntry( "core_apps" );
 function app_sort( $a, $b ) {
 
 	if ($a['active'] != $b['active']) {
-	
+
 		return $b['active'] - $a['active'];
-		
+
 	}
-	
+
 	return strcmp($a['name'], $b['name']);
-	
+
 }
 
 $combinedApps = OC_App::listAllApps();
@@ -52,3 +52,4 @@ $appid = (isset($_GET['appid'])?strip_tags($_GET['appid']):'');
 $tmpl->assign('appid', $appid);
 
 $tmpl->printPage();
+
diff --git a/settings/css/settings.css b/settings/css/settings.css
index 8fad055f2e6ca0d7978a66bb1c2afd2d4040557d..35c7176d45e6db4447056ed29658d7b108b2b6aa 100644
--- a/settings/css/settings.css
+++ b/settings/css/settings.css
@@ -50,10 +50,13 @@ li { color:#888; }
 li.active { color:#000; }
 small.externalapp { color:#FFF; background-color:#BBB; font-weight:bold; font-size: 0.6em; margin: 0; padding: 0.1em 0.2em; border-radius: 4px;}
 small.externalapp.list { float: right; }
+small.recommendedapp { color:#FFF; background-color:#888; font-weight:bold; font-size: 0.6em; margin: 0; padding: 0.1em 0.2em; border-radius: 4px;}
+small.recommendedapp.list { float: right; }
 span.version { margin-left:1em; margin-right:1em; color:#555; }
 
 .app { position: relative; display: inline-block; padding: 0.2em 0 0.2em 0 !important; text-overflow: hidden; overflow: hidden; white-space: nowrap; /*transition: .2s max-width linear; -o-transition: .2s max-width linear; -moz-transition: .2s max-width linear; -webkit-transition: .2s max-width linear; -ms-transition: .2s max-width linear;*/ }
 .app.externalapp { max-width: 12.5em; z-index: 100; }
+.app.recommendedapp { max-width: 12.5em; z-index: 100; }
 /* Transition to complete width! */
 .app:hover, .app:active { max-width: inherit; }
 
diff --git a/settings/js/apps.js b/settings/js/apps.js
index c4c36b4bb12a84b85c3deb0e47b58847e68af9ce..68a3fa54de7930757b1904d23c8098fceec69de5 100644
--- a/settings/js/apps.js
+++ b/settings/js/apps.js
@@ -24,6 +24,14 @@ OC.Settings.Apps = OC.Settings.Apps || {
 		page.find('span.author').text(app.author);
 		page.find('span.licence').text(app.licence);
 
+		if (app.update != false) {
+			page.find('input.update').show();
+			page.find('input.update').data('appid', app.id);
+			page.find('input.update').attr('value',t('settings', 'Update to {appversion}', {appversion:app.update}));
+		} else {
+			page.find('input.update').hide();
+		}
+
 		page.find('input.enable').show();
 		page.find('input.enable').val((app.active) ? t('settings', 'Disable') : t('settings', 'Enable'));
 		page.find('input.enable').data('appid', app.id);
@@ -44,6 +52,7 @@ OC.Settings.Apps = OC.Settings.Apps || {
 		appData = appitem.data('app');
 		appData.active = !active;
 		appitem.data('app', appData);
+		element.val(t('settings','Please wait....'));
 		if(active) {
 			$.post(OC.filePath('settings','ajax','disableapp.php'),{appid:appid},function(result) {
 				if(!result || result.status!='success') {
@@ -70,6 +79,20 @@ OC.Settings.Apps = OC.Settings.Apps || {
 			$('#leftcontent li[data-id="'+appid+'"]').addClass('active');
 		}
 	},
+	updateApp:function(appid, element) {
+		console.log('updateApp:', appid, element);
+		element.val(t('settings','Updateing....'));
+		$.post(OC.filePath('settings','ajax','updateapp.php'),{appid:appid},function(result) {
+			if(!result || result.status!='success') {
+				OC.dialogs.alert(t('settings','Error while updating app'),t('settings','Error'));
+			}
+			else {
+				element.val(t('settings','Updated'));
+				element.hide();
+			}
+		},'json');
+	},
+
 	insertApp:function(appdata) {
 		var applist = $('#leftcontent li');
 		var app =
@@ -154,6 +177,13 @@ $(document).ready(function(){
 			OC.Settings.Apps.enableApp(appid, active, element);
 		}
 	});
+	$('#rightcontent input.update').click(function(){
+		var element = $(this);
+		var appid=$(this).data('appid');
+		if(appid) {
+			OC.Settings.Apps.updateApp(appid, element);
+		}
+	});
 
 	if(appid) {
 		var item = $('#leftcontent li[data-id="'+appid+'"]');
diff --git a/settings/routes.php b/settings/routes.php
index 0a5b2fbfd38b37cc77f75e41c4e19a0ebf6c7eb8..0a8af0dde2b35ba068b5d77ed2b0994d475722fd 100644
--- a/settings/routes.php
+++ b/settings/routes.php
@@ -53,6 +53,8 @@ $this->create('settings_ajax_enableapp', '/settings/ajax/enableapp.php')
 	->actionInclude('settings/ajax/enableapp.php');
 $this->create('settings_ajax_disableapp', '/settings/ajax/disableapp.php')
 	->actionInclude('settings/ajax/disableapp.php');
+$this->create('settings_ajax_updateapp', '/settings/ajax/updateapp.php')
+	->actionInclude('settings/ajax/updateapp.php');
 $this->create('settings_ajax_navigationdetect', '/settings/ajax/navigationdetect.php')
 	->actionInclude('settings/ajax/navigationdetect.php');
 $this->create('apps_custom', '/settings/js/apps-custom.js')
diff --git a/settings/templates/apps.php b/settings/templates/apps.php
index d418b9a66a1d96847a0057f718faf7f2752ce04b..3f0d2a9d1c6462941e48cbcbf5cc0e68093f7dc0 100644
--- a/settings/templates/apps.php
+++ b/settings/templates/apps.php
@@ -7,7 +7,7 @@
  <script type="text/javascript" src="<?php echo OC_Helper::linkTo('settings/js', 'apps.js');?>"></script>
 
 <div id="controls">
-	<a class="button" target="_blank" href="http://owncloud.org/dev/apps/getting-started/"><?php echo $l->t('Add your App');?></a>
+	<a class="button" target="_blank" href="http://owncloud.org/dev"><?php echo $l->t('Add your App');?></a>
 	<a class="button" target="_blank" href="http://apps.owncloud.com"><?php echo $l->t('More Apps');?></a>
 </div>
 <ul id="leftcontent" class="applist">
@@ -15,7 +15,7 @@
 	<li <?php if($app['active']) echo 'class="active"'?> data-id="<?php echo $app['id'] ?>" <?php if ( isset( $app['ocs_id'] ) ) { echo "data-id-ocs=\"{$app['ocs_id']}\""; } ?>
 		data-type="<?php echo $app['internal'] ? 'internal' : 'external' ?>" data-installed="1">
 		<a class="app<?php if(!$app['internal']) echo ' externalapp' ?>" href="?appid=<?php echo $app['id'] ?>"><?php echo htmlentities($app['name']) ?></a>
-		<?php  if(!$app['internal']) echo '<small class="externalapp list">3rd party</small>' ?>
+		<?php  if(!$app['internal']) echo '<small class="'.$app['internalclass'].' list">'.$app['internallabel'].'</small>' ?>
 	</li>
 	<?php endforeach;?>
 </ul>
@@ -28,5 +28,6 @@
 	<p class="appslink hidden"><a href="#" target="_blank"><?php echo $l->t('See application page at apps.owncloud.com');?></a></p>
 	<p class="license hidden"><?php echo $l->t('<span class="licence"></span>-licensed by <span class="author"></span>');?></p>
 	<input class="enable hidden" type="submit" />
+	<input class="update hidden" type="submit" value="<?php echo($l->t('Update')); ?>" />
 	</div>
-</div>
\ No newline at end of file
+</div>