chaw / branches / master / models / ssh_key.php

history
<?php
/**
 * Chaw : source code and project management
 *
 * @copyright  Copyright 2009, Garrett J. Woodworth (gwoohoo@gmail.com)
 * @license    GNU AFFERO GENERAL PUBLIC LICENSE v3 (http://opensource.org/licenses/agpl-v3.html)
 *
 */
/**
 * undocumented class
 *
 * @package default
 */
class SshKey extends AppModel {

	/**
	 * undocumented variable
	 *
	 * @var string
	 */
	var $name = 'SshKey';

	/**
	 * undocumented variable
	 *
	 * @var string
	 */
	var $type = 'git';

	/**
	 * undocumented variable
	 *
	 * @var string
	 */
	var $lines = array();

	/**
	 * undocumented variable
	 *
	 * @var string
	 */
	var $user = array();

	/**
	 * undocumented variable
	 *
	 * @var string
	 */
	var $_File = null;

	/**
	 * undocumented variable
	 *
	 * @var string
	 */
	var $useTable = false;

	/**
	 * undocumented function
	 *
	 * @param string $data
	 * @return void
	 */
	function set($data = array()) {
		parent::set($data);

		if (empty($this->data['SshKey']['type'])) {
			return false;
		}
		$this->type = strtolower($this->data['SshKey']['type']);
		$path = Configure::read("Content.{$this->type}") . 'repo' . DS . '.ssh' . DS . 'authorized_keys';
		if (!empty($this->_File) && $this->_File->path == $path) {
			if ($this->_File->exists() != true) {
				$this->_File->create();
				$this->lines = $this->user = array();
			}
			return true;
		}
		$this->_File = new File($path, true);
		$this->lines = $this->user = array();
		return true;
	}

	/**
	 * undocumented function
	 *
	 * @param string $data
	 * @return void
	 */
	function save($data = array()) {
		if ($this->set($data) === false) {
			return false;
		}

		if (empty($this->data['SshKey']['content']) || empty($this->data['SshKey']['username'])) {
			return false;
		}

		if ($this->_File->writable() !== true) {
			return false;
		}

		$key = $this->data['SshKey']['content'];
		$username = $this->data['SshKey']['username'];

		$new = $this->__strip($key);

		$exists = false;
		$userKeys = $this->read();

		foreach ((array)$userKeys as $oldKey) {
			if ($oldKey == $new) {
				$exists = true;
				break;
			}
		}

		if (!$exists) {
			$this->lines[] = $this->command($username) . $new;
			$this->user[$username][] = $new;
		}

		return $this->write();
	}

	/**
	 * read lines from file
	 * is username is present in $data, return only user keys
	 * sets $lines to an array of contents in the file
	 *
	 * @return array
	 */
	function read($data = array()) {
		if ($this->set($data) === false) {
			return false;
		}

		$hasUsername = $username = false;
		if (array_key_exists('username', $this->data['SshKey'])) {
			$hasUsername = true;
			$username = $this->data['SshKey']['username'];
		}

		if ($username && !empty($this->user[$username])) {
			return $this->user[$username];
		}

		if (!$username && !empty($this->lines)) {
			return $this->lines;
		}

		if ($this->_File->readable() !== true) {
			return false;
		}

		$this->_File->lock = null;
		if ($keys = $this->_File->read()) {
			$this->lines = explode("\n", $keys);
		}

		if ($username) {
			$this->user[$username] = array();
			if ($userKeys = preg_grep("/-user\s{$username}\"/", $this->lines)) {
				foreach ($userKeys as $line) {
					$this->user[$username][] = str_replace($this->command($username), "", $line);
				}
			}
		}

		if ($username) {
			return $this->user[$username];
		}

		if (!$hasUsername) {
			return $this->lines;
		}

		return array();
	}

	/**
	 * write lines to file
	 *
	 * @return void
	 */
	function write() {
		$this->_File->lock = true;
		$result = $this->_File->write(join("\n", $this->lines), 'w', true);
		return $result;
	}

	/**
	 * delete a key
	 *
	 * @return void
	 */
	function delete($data = array()) {
		if ($this->set($data) === false) {
			return false;
		}

		if (empty($this->data['SshKey']['content']) || empty($this->data['SshKey']['username'])) {
			return false;
		}

		if ($this->_File->writable() !== true) {
			return false;
		}

		$username = $this->data['SshKey']['username'];
		unset($this->data['SshKey']['username']);

		$keys = $this->data['SshKey']['content'];
		if (!is_array($keys)) {
			$keys = array($keys);
		}

		if (empty($this->lines)) {
			$this->read();
		}

		$oldKeys = array_flip($this->lines);

		$deleted = false;
		foreach ($keys as $key) {
			$key = $this->command($username) . $key;
			if (isset($oldKeys[$key])) {
				unset($oldKeys[$key]);
				$deleted = true;
			}
		}

		if ($deleted === true) {
			$this->lines = array_keys($oldKeys);
			$this->user[$username] = array();
			return $this->write();
		}
		return true;
	}

	/**
	 * get command for a given user
	 *
	 * @param string $username
	 * @return void
	 */
	function command($type, $username = null) {
		if ($username === null) {
			$username = $type;
			$type = $this->type;
		} else {
			$type = strtolower($type);
		}
		return 'command="../../chaw ' . $type . '_shell $SSH_ORIGINAL_COMMAND -user ' . $username. '",no-port-forwarding,no-X11-forwarding,no-agent-forwarding,no-pty ';
	}

/**
 * strip stuff
 *
 * @return void
 */
	function __strip($key) {
		return preg_replace('/=\w(.+)$/', '=',
			str_replace(
				array("\n", "\r", "\t", " ", 'ssh-rsa', 'ssh-dss'),
				array("", "", "", "", 'ssh-rsa ', 'ssh-dss '),
				trim($key)
			)
		);
	}
}
?>