From f4e4617be7a22a0191bf1bc21f6d8462d215108e Mon Sep 17 00:00:00 2001
From: Robin Appelman <icewind1991@gmail.com>
Date: Sat, 28 May 2011 17:33:25 +0200
Subject: [PATCH] App installer backend.

Not yet attached to the gui
---
 lib/app.php       | 15 +++++---
 lib/helper.php    | 42 +++++++++++++++++++-
 lib/installer.php | 97 ++++++++++++++++++++++++++++++++++++++++++++++-
 3 files changed, 146 insertions(+), 8 deletions(-)

diff --git a/lib/app.php b/lib/app.php
index 83c80f6356..cec7468c8e 100644
--- a/lib/app.php
+++ b/lib/app.php
@@ -317,20 +317,23 @@ class OC_APP{
 	
 	/**
 	 * @brief Read app metadata from the info.xml file
-	 * @param string $appid id of the app
+	 * @param string $appid id of the app or the path of the info.xml file
 	 * @returns array
 	*/
 	public static function getAppInfo($appid){
-		$file='apps/'.$appid.'/appinfo/info.xml';
-		if(!is_file($file)){
-			return array();
+		if(is_file($appid)){
+			$file=$appid;
+		}else{
+			$file='apps/'.$appid.'/appinfo/info.xml';
+			if(!is_file($file)){
+				return array();
+			}
 		}
 		$data=array();
 		$content=file_get_contents($file);
 		$xml = new SimpleXMLElement($content);
-		$info=$xml->info[0];
 		$data['info']=array();
-		foreach($info->children() as $child){
+		foreach($xml->children() as $child){
 			$data[$child->getName()]=(string)$child;
 		}
 		return $data;
diff --git a/lib/helper.php b/lib/helper.php
index fbca94dc7a..281761c590 100644
--- a/lib/helper.php
+++ b/lib/helper.php
@@ -164,7 +164,6 @@ class OC_HELPER {
 	 * @param $path path to file or folder
 	 * @param $filemode unix style file permissions as integer
 	 *
-	 * Makes 2048 to 2 kB.
 	 */
 	static function chmodr($path, $filemode) {
 		if (!is_dir($path))
@@ -187,6 +186,47 @@ class OC_HELPER {
 		else
 			return FALSE;
 	}
+
+	/**
+	 * @brief Recusive copying of folders
+	 * @param string $src source folder
+	 * @param string $dest target folder
+	 *
+	 */
+	static function copyr($src, $dest) {
+		if(is_dir($src)){
+			if(!is_dir($dest)){
+				mkdir($dest);
+			}
+			$files = scandir($src);
+			foreach ($files as $file){
+				if ($file != "." && $file != ".."){
+					self::copyr("$src/$file", "$dest/$file");
+				}
+			}
+		}elseif(file_exists($src)){
+			copy($src, $dest);
+		}
+	}
+	
+	/**
+	 * @brief Recusive deletion of folders
+	 * @param string $dir path to the folder
+	 *
+	 */
+	static function rmdirr($dir) {
+		if(is_dir($dir)) {
+			$files=scandir($dir);
+			foreach($files as $file){
+				if ($file != "." && $file != ".."){
+					self::rmdirr("$dir/$file");
+				}
+			}
+			rmdir($dir);
+		}elseif(file_exists($dir)){
+			unlink($dir);
+		}
+	}
 	
 	/**
 	 * @brief Checks $_REQUEST contains a var for the $s key. If so, returns the html-escaped value of this var; otherwise returns the default value provided by $d.
diff --git a/lib/installer.php b/lib/installer.php
index c389fe9c0c..7ab07bf507 100644
--- a/lib/installer.php
+++ b/lib/installer.php
@@ -47,6 +47,7 @@ class OC_INSTALLER{
 	 * This function works as follows
 	 *   -# fetching the file
 	 *   -# unzipping it
+	 *   -# installing the database at appinfo/database.xml
 	 *   -# including appinfo/install.php
 	 *   -# setting the installed version
 	 *
@@ -54,7 +55,101 @@ class OC_INSTALLER{
 	 * needed to get the app working.
 	 */
 	public static function installApp( $data = array()){
-		// TODO: write function
+		global $SERVERROOT;
+		
+		if(!isset($data['source'])){
+			error_log("No source specified when installing app");
+			return;
+		}
+		
+		//download the file if necesary
+		if($data['source']=='http'){
+			$path=tempnam(sys_get_temp_dir(),'oc_installer_');
+			if(!isset($data['href'])){
+				error_log("No href specified when installing app from http");
+				return;
+			}
+			copy($data['href'],$path);
+		}else{
+			if(!isset($data['path'])){
+				error_log("No path specified when installing app from local file");
+				return;
+			}
+			$path=$data['path'];
+		}
+		
+		//extract the archive in a temporary folder
+		$extractDir=tempnam(sys_get_temp_dir(),'oc_installer_uncompressed_');
+		unlink($extractDir);
+		mkdir($extractDir);
+		$zip = new ZipArchive;
+		if($zip->open($path)===true){
+			$zip->extractTo($extractDir);
+			$zip->close();
+		} else {
+			error_log("Failed to open archive when installing app");
+			OC_HELPER::rmdirr($extractDir);
+			if($data['source']=='http'){
+				unlink($path);
+			}
+			return;
+		}
+		
+		//load the info.xml file of the app
+		if(!is_file($extractDir.'/appinfo/info.xml')){
+			error_log("App does not provide an info.xml file");
+			OC_HELPER::rmdirr($extractDir);
+			if($data['source']=='http'){
+				unlink($path);
+			}
+			return;
+		}
+		$info=OC_APP::getAppInfo($extractDir.'/appinfo/info.xml');
+		$basedir=$SERVERROOT.'/apps/'.$info['id'];
+		
+		//check if an app with the same id is already installed
+		if(is_dir($basedir)){
+			error_log("App already installed");
+			OC_HELPER::rmdirr($extractDir);
+			if($data['source']=='http'){
+				unlink($path);
+			}
+			return;
+		}
+		
+		if(isset($data['pretent']) and $data['pretent']==true){
+			return;
+		}
+		
+		//copy the app to the correct place
+		if(!mkdir($basedir)){
+			error_log('Can\'t create app folder ('.$basedir.')');
+			OC_HELPER::rmdirr($extractDir);
+			if($data['source']=='http'){
+				unlink($path);
+			}
+			return;
+		}
+		OC_HELPER::copyr($extractDir,$basedir);
+		
+		//remove temporary files
+		OC_HELPER::rmdirr($extractDir);
+		if($data['source']=='http'){
+			unlink($path);
+		}
+		
+		//install the database
+		if(is_file($basedir.'/appinfo/database.xml')){
+			OC_DB::createDbFromStructure($basedir.'/appinfo/database.xml');
+		}
+		
+		//run appinfo/install.php
+		if(!isset($data['noinstall']) or $data['noinstall']==false and is_file($basedir.'/appinfo/install.php')){
+			include($basedir.'/appinfo/install.php');
+		}
+		
+		//set the installed version
+		OC_APPCONFIG::setValue($info['id'],'installed_version',$info['version']);
 		return true;
 	}
 
-- 
GitLab