<?php

	/*
	*	Gekko - Open Source Web Development Framework
	*	------------------------------------------------------------------------
	*	Copyright (C) 2004-2005, J. Carlos Nieto <xiam@users.sourceforge.net>
	*	This program is Free Software.
	*
	*	@package	Gekko
	*	@license	http://www.gnu.org/copyleft/gpl.html GNU/GPL License 2.0
	*	@author		J. Carlos Nieto <xiam@users.sf.net>
	*	@version	CVS: $Id:$
	*	@link		http://gekkoware.sourceforge.net
	*/

	define ("IN-GEKKO", true);

	require_once "../../conf.php";
	require_once GEKKO_ROOT."lib/core.lib.php";
	require_once GEKKO_ROOT."lib/file.lib.php";
	require_once GEKKO_ROOT."lib/compression.lib.php";
	require_once GEKKO_ROOT."modules/packages/main.lib.php";

	db_init();

	require_once GEKKO_ROOT."lib/auth.inc.php";

	if (!gauth("packages"))
		abort(accessDenied());

	gpGet("action", 1);
	gpGet("id", 1);
	gpGet("return", 1);

	// setting writable directory
	$pkgdir = "temp/packages/";

	mkworkdir(GEKKO_ROOT.$pkgdir);

	switch ($action) {

		case "install":

			gpGlobalize("ftp_host, ftp_port, ftp_path, ftp_user, ftp_pass");

			requireVars($ftp_host, $ftp_port, $ftp_path, $ftp_user, $ftp_pass);

			if ($_POST["remote_file"] || $_FILES["local_file"]["size"]) {
				$file = file_get("local_file", "remote_file", "temp/packages");

				// work folder and relative path
				$rworkdir = $pkgdir."work/".$file["basename"];
				$workdir = GEKKO_ROOT.$rworkdir;

				if (file_exists($workdir)) {
					// cleaning workdir
					clean_dir($workdir);
				} else {
					// creating wordir
					mkworkdir($workdir);
				}

				/*
					** Package Type **
					Package format: pkgname-version.pkgtype.tgz
					example:
						foo-1.2.module.tgz
						13375p33k-0.5.lang.tgz
				*/
				if (preg_match("/.*?\.([^.]*?)\.(gpk|tgz)/", $file["basename"], $match)) {
					if (isset($match[1]))
						$pkgtype = $match[1];
				} elseif (preg_match("/gekko-(.*?)\.tar\.(gz|bz2)/", $file["basename"])) {
					$pkgtype = "core";
				} else {
					// old package name format
					$pkgtype = substr($file["basename"], 0, strpos($file["basename"], "_"));
					switch ($pkgtype) {
						case "mod": $pkgtype = "module"; break;
						case "css": $pkgtype = "style"; break;
						case "sml": $pkgtype = "smileys"; break;
						case "ico": $pkgtype = "iconset"; break;
					}
				}

				// extracting file to $workdir
				file_untar($file["abs_loc"], $workdir);

				// scanning package contents
				$pkgcontents = listdir($workdir, true);

				// setting null flags
				$flag = Array();

				/*
					Beginning test phase
				*/

				switch ($pkgtype) {
					case "core":
						$realworkdir = $workdir;
						$release = substr($pkgcontents[0], 0, strpos($pkgcontents[0], "/"));
						$substrl = strlen($release)+5;
						foreach ($pkgcontents as $i => $v) {
							$pkgcontents[$i] = substr($pkgcontents[$i], $substrl);
							switch ($pkgcontents[$i]) {
								case "dbconf.php": case "cgdb.php": case "":
									unset($pkgcontents[$i]);
								break;
							}
						}
						$rworkdir .= "/$release/src";
						$workdir = GEKKO_ROOT.$rworkdir;
					break;
					case "module":
						$pm = false;

						foreach ($pkgcontents as $pkgline) {
							// getting module name
							preg_match("/(.*?)\/(.*?)\/.*?/", $pkgline, $m);
							if ((isset($m[1]) && $m[1] == "modules") && (isset($m[2]) && (($modname = $m[2]) !== false))) {
								$pm = true;
								break;
							}
						}

						if ($pm) {
							// loading and parsing xml
							$mod_xml = $workdir."/modules/$modname/package.xml";
							$xml = "";
							pkg_parse_xml($mod_xml, $xml);

							if (($inform = pkg_checkInstall($xml)) == false) {

								// checking installating type
								$db->query("SELECT Module FROM ".db_table("module")." WHERE Module = '$modname'", __FILE__, __LINE__);

								// setting flag for post-install procedure
								$flag["is_installed"] = ($db->num_rows());

								// checking if cgdb.php needs to be regenerated because some modules needs it's own group
								if (!isset($cgdb[$xml["module"]["name"]])) {
									// adding to $cgdb, will regenerate ./cgdb.php
									$cgdb[$xml["module"]["name"]] = $xml["module"]["group"];
									$flag["cgdb_regen"] = true;
								}

							} else {

								header("content-type: text/plain");
								echo $inform;

								clean_dir($workdir);
								rmdir($workdir);
								unlink($file["abs_loc"]);

								abort();
							}

						} else {
							trigger_error("This seems not to be a package module.", E_USER_ERROR);
						}
					break;
					case "style":
						// css style
						foreach ($pkgcontents as $content) {
							if (preg_match("/templates(.*?)/", $content, $m)) {
								$path = $workdir.'/'.$content;
								if (is_file($path)) {
									switch($ext = file_extension($path)) {
										case "css": case "jpg": case "gif": case "png": case "xcf": case "ttf": case "txt":
										break;
										default:
											trigger_error("This package is not valid. Gekko Styles must not contain '$ext' files. ", E_USER_ERROR);
										break;
									}
								}
							} else {
								trigger_error("This package seems not to contain a css style for Gekko.", E_USER_ERROR);
								break;
							}
						}
					break;
					case "smileys":
						foreach ($pkgcontents as $content) {
							if (preg_match("/media(.*?)/", $content, $m)) {
								$path = $workdir.'/'.$content;
								if (is_file($path)) {
									switch($ext = file_extension($path)) {
										case "jpg": case "gif": case "png": case "xml": case "txt":
										break;
										default:
											trigger_error("This smiley set is not valid. It must not contain '$ext' files. ", E_USER_ERROR);
										break;
									}
								}
							} else {
								trigger_error("This package seems not to contain smileys for Gekko.", E_USER_ERROR);
								break;
							}
						}
					break;
					case "iconset":
						foreach ($pkgcontents as $content) {
							if (preg_match("/media(.*?)/", $content, $m)) {
								$path = $workdir.'/'.$content;
								if (is_file($path)) {
									switch($ext = file_extension($path)) {
										case "jpg": case "gif": case "png": case "txt":
										break;
										default:
											trigger_error("This iconset is not valid. It must not contain '$ext' files. ", E_USER_ERROR);
										break;
									}
								}
							} else {
								trigger_error("This package seems not to contain icons for Gekko.", E_USER_ERROR);
								break;
							}
						}
					break;
					case "lang":

					break;
					default:
						trigger_error("Unknown package type", E_USER_ERROR);
					break;
				}

				/*
					Test phase concluded, now Gekko asummes this package is
					suitable for installing, and copies all files to GEKKO_ROOT
				*/

				// reversing package contents for listing folders before folder content
				$pkgcontents = array_reverse($pkgcontents);

				// ready to install?!
				$ftp = new ftpSession($ftp_host, $ftp_port, $ftp_user, $ftp_pass);

				if ($ftp->auth()) {

					if (@$ftp->cd($ftp_path) && $ftp->mtime("conf.php")) {

						// installation
						foreach ($pkgcontents as $f) {
							// renaming from temp_dir/* to ./*
							$dest = GEKKO_ROOT.$f;
							$r_src = $rworkdir."/".$f;
							$a_src = $workdir."/".$f;
							if (is_dir($a_src)) {
								if (!file_exists($dest)) {
									$ftp->mkdir($f, "0775");
								}
								continue;
							}
							if (file_exists($dest)) {
								$ftp->delete($f);
								@unlink($dest);
							}
							$ftp->rename($r_src, $f);
							chmod ($dest, 0775);
						}

						// saving actual cgdb if neccesary
						if (isset($flag["cgdb_regen"])) {
							$ftp->chmod("cgdb.php", "0777");
							filewrite(GEKKO_ROOT."cgdb.php", cgdb_regen());
							$ftp->chmod("cgdb.php", "0775");
						}

						// post-installation
						switch ($pkgtype) {
							case "module":
								modCore::modInstall($xml["module"]["name"], $flag["is_installed"] ? "P" : "I");
								slog("packages: ".($flag["is_installed"] ? "upgraded" : "installed")." module '{$xml["module"]["name"]}'", "actions", 1);
								$return = "../../index.php/admin/modules#{$xml["module"]["name"]}";
							break;
							// CSS Styles, Smileys
							case "style": case "smileys": case "iconset": case "lang":
								$return = "../../index.php/admin/conf/setup";
							break;
							case "core":
								$workdir = $realworkdir;
							break;
						}

						// cleaning up!
						clean_dir($workdir);
						rmdir($workdir);

						// downloaded file is useless now...
						unlink($file["abs_loc"]);

						// saving ftp information
						conf::setKey("core", "ftp.host", $ftp_host);
						conf::setKey("core", "ftp.user", $ftp_user);
						conf::setKey("core", "ftp.path", $ftp_path);
						conf::setKey("core", "ftp.port", $ftp_port);
						// saving ftp password (when requested)
						if (conf::getKey("core", "ftp.save_pass")) {
							conf::setKey("core", "ftp.pass", $ftp_pass);
						}
					} else {
						$pwd = $ftp->pwd();

						preg_match("/\"(.*?)\"/", $pwd, $mwd);
						// expecting: "/foo/bar" is current directory.
						if (isset($mwd[1])) {
							$wd = $mwd[1];
							if (substr($_SERVER["SCRIPT_FILENAME"], 0, strlen($wd)) == $wd) {
								$prob_path = dirname($path.substr($_SERVER["SCRIPT_FILENAME"], strlen($wd)+1));
							}
						}

						// guessing probable path
						$ftp->bye();
						abort(_l("E_FTP_WRONG_PATH")."<br />".$pwd."<br />".(isset($prob_path) ? "Probable path (just guessing): $prob_path" : ""));

					}

				} else {
					abort(_l("E_FTP_LOGIN_ERROR"));
				}

			} else {
				abort(trigger_error("Couldn't get package...", E_USER_ERROR));
			}
		break;
		default:
			abort(_l("L_UNDEFINED_ACTION"));
		break;
	}

	ssl_normal_redirect($return);

	redirect($return ? $return : $_SERVER["HTTP_REFERER"]);

	db_exit();
?>