* Bacula(R) - The Network Backup Solution
* Baculum - Bacula web interface
*
- * Copyright (C) 2013-2015 Marcin Haba
+ * Copyright (C) 2013-2016 Marcin Haba
*
* The main author of Baculum is Marcin Haba.
* The original author of Bacula is Kern Sibbald, with contributions
Prado::using('System.Exceptions.TException');
Prado::using('Application.Class.Errors');
-abstract class BaculumAPI extends TPage
-{
+/**
+ * Abstract module from which inherits each of API module.
+ * The module contains methods that are common for all API pages.
+ *
+ * @author Marcin Haba <marcin.haba@bacula.pl>
+ */
+abstract class BaculumAPI extends TPage {
+
+ /**
+ * Storing output from API commands in numeric array.
+ */
protected $output;
+
+ /**
+ * Storing error from API commands as integer value.
+ */
protected $error;
+ /**
+ * Storing currently used Director name for bconsole commands.
+ */
protected $director;
+ /**
+ * Web interface User name that sent request to API.
+ * Null value means administrator, any other value means normal user
+ * (non-admin user).
+ */
protected $user;
/**
- * Actions methods.
+ * Action methods.
*/
+
+ // get elements
const GET_METHOD = 'GET';
+
+ // create new elemenet
const POST_METHOD = 'POST';
+
+ // update elements
const PUT_METHOD = 'PUT';
+
+ // delete element
const DELETE_METHOD = 'DELETE';
+ /**
+ * Get request, login user and do request action.
+ *
+ * @access public
+ * @param mixed $params onInit action params
+ * @return none
+ */
public function onInit($params) {
parent::onInit($params);
/*
*/
$db = new ActiveRecord();
$db->getDbConnection();
+
+ // set Director to bconsole execution
$this->director = isset($this->Request['director']) ? $this->Request['director'] : null;
+ /**
+ * User and password are obligatory for each request. Otherwise authorization
+ * error takes place.
+ * Password is provided in hashed form.
+ */
$user = isset($_SERVER['HTTP_X_BACULUM_USER']) ? $_SERVER['HTTP_X_BACULUM_USER']: null;
- $pwd = isset($_SERVER['HTTP_X_BACULUM_PWD']) ? $_SERVER['HTTP_X_BACULUM_PWD']: null;
- if(!is_null($user) && !is_null($pwd)) {
- $logged = $this->Application->getModule('users')->loginUser($user, $pwd);
+ $pwd_hash = isset($_SERVER['HTTP_X_BACULUM_PWD']) ? $_SERVER['HTTP_X_BACULUM_PWD']: null;
+ if (!is_null($user) && !is_null($pwd_hash)) {
+ // try to log in user
+ $logged = $this->getModule('users')->loginUser($user, $pwd_hash);
if ($logged === true) {
+ /*
+ * User and password are valid.
+ * Log in action finished successfuly.
+ * Now check if logged in user is admin or normal user.
+ * Admin value is null. Normal user value is string with the user name.
+ */
$this->user = ($this->User->getIsAdmin() === false) ? $user : null;
} else {
+ // Invalid credentials. Authorization error.
$this->output = AuthorizationError::MSG_ERROR_AUTHORIZATION_TO_WEBGUI_PROBLEM;
$this->error = AuthorizationError::ERROR_AUTHORIZATION_TO_WEBGUI_PROBLEM;
return;
}
} else {
+ // Not provided user or password. Authorization error.
$this->output = AuthorizationError::MSG_ERROR_AUTHORIZATION_TO_WEBGUI_PROBLEM;
$this->error = AuthorizationError::ERROR_AUTHORIZATION_TO_WEBGUI_PROBLEM;
return;
try {
$this->put();
} catch(TDbException $e) {
- $this->Application->getModule('logging')->log(__FUNCTION__, $e, Logging::CATEGORY_APPLICATION, __FILE__, __LINE__);
+ $this->getModule('logging')->log(
+ __FUNCTION__,
+ $e,
+ Logging::CATEGORY_APPLICATION,
+ __FILE__,
+ __LINE__
+ );
$this->output = DatabaseError::MSG_ERROR_DB_CONNECTION_PROBLEM;
$this->error = DatabaseError::ERROR_DB_CONNECTION_PROBLEM;
}
try {
$this->get();
} catch(TDbException $e) {
- $this->Application->getModule('logging')->log(__FUNCTION__, $e, Logging::CATEGORY_APPLICATION, __FILE__, __LINE__);
+ $this->getModule('logging')->log(
+ __FUNCTION__,
+ $e,
+ Logging::CATEGORY_APPLICATION,
+ __FILE__,
+ __LINE__
+ );
$this->output = DatabaseError::MSG_ERROR_DB_CONNECTION_PROBLEM;
$this->error = DatabaseError::ERROR_DB_CONNECTION_PROBLEM;
}
try {
$this->post();
} catch(TDbException $e) {
- $this->Application->getModule('logging')->log(__FUNCTION__, $e, Logging::CATEGORY_APPLICATION, __FILE__, __LINE__);
+ $this->getModule('logging')->log(
+ __FUNCTION__,
+ $e,
+ Logging::CATEGORY_APPLICATION,
+ __FILE__,
+ __LINE__
+ );
$this->output = DatabaseError::MSG_ERROR_DB_CONNECTION_PROBLEM;
$this->error = DatabaseError::ERROR_DB_CONNECTION_PROBLEM;
}
try {
$this->delete();
} catch(TDbException $e) {
- $this->Application->getModule('logging')->log(__FUNCTION__, $e, Logging::CATEGORY_APPLICATION, __FILE__, __LINE__);
+ $this->getModule('logging')->log(
+ __FUNCTION__,
+ $e,
+ Logging::CATEGORY_APPLICATION,
+ __FILE__,
+ __LINE__
+ );
$this->output = DatabaseError::MSG_ERROR_DB_CONNECTION_PROBLEM;
$this->error = DatabaseError::ERROR_DB_CONNECTION_PROBLEM;
}
}
}
+ /**
+ * Get request result data and pack it in JSON format.
+ * JSON values are: {
+ * "output": (list) output values
+ * "error" : (integer) result exit code (0 - OK, non-zero - error)
+ *
+ * @access private
+ * @return string JSON value with output and error values
+ */
private function getOutput() {
$output = array('output' => $this->output, 'error' => $this->error);
- return json_encode($output);
+ $json = json_encode($output);
+ return $json;
}
+ /**
+ * Return action result which was realized in onInit() method.
+ * On standard output is printed JSON value with request results.
+ *
+ * @access public
+ * @param mixed $params onInit action params
+ * @return none
+ */
public function onLoad($params) {
parent::onLoad($params);
echo $this->getOutput();
}
+ /**
+ * Each of API module should have get() method defined.
+ * Designed to getting data from API.
+ *
+ * @access protected
+ * @return none
+ */
abstract protected function get();
+ /**
+ * Changing/updating values via API.
+ *
+ * @access private
+ * @return none
+ */
private function put() {
$id = isset($this->Request['id']) ? $this->Request['id'] : null;
- if(is_array($this->Request['update']) && count($this->Request['update']) > 0) {
+
+ /**
+ * Check if it is possible to read PUT method data.
+ * Note that some clients sends data in PUT request as PHP input stream which
+ * is not possible to read by $_REQUEST data. From this reason, when is
+ * not possible to ready by superglobal $_REQUEST variable, then is try to
+ * read PUT data by PHP input stream.
+ */
+ if (is_array($this->Request['update']) && count($this->Request['update']) > 0) {
+ // $_REQUEST available to read
$params = (object)$this->Request['update'];
$this->set($id, $params);
} else {
+ // no possibility to read data from $_REQUEST. Try to load from input stream.
$inputstr = file_get_contents("php://input");
+
+ /**
+ * Read using chunks for case large updates (over 1000 values).
+ * Otherwise max_input_vars limitation in php.ini can be reached (usually
+ * set to 1000 variables)
+ * @see http://php.net/manual/en/info.configuration.php#ini.max-input-vars
+ */
$chunks = explode('&', $inputstr);
- $responseData = array();
+
+ $response_data = array();
for($i = 0; $i<count($chunks); $i++) {
- parse_str($chunks[$i], $responseEl);
- if(is_array($responseEl) && array_key_exists('update', $responseEl) && is_array($responseEl['update'])) {
- $key = key($responseEl['update']);
- $responseData['update'][$key] = $responseEl['update'][$key];
+ // if chunks would not be used, then here occurs reach max_input_vars limit
+ parse_str($chunks[$i], $response_el);
+ if (is_array($response_el) && array_key_exists('update', $response_el) && is_array($response_el['update'])) {
+ $key = key($response_el['update']);
+ $response_data['update'][$key] = $response_el['update'][$key];
}
}
- if(is_array($responseData) && array_key_exists('update', $responseData)) {
- $params = (object)$responseData['update'];
+ if (is_array($response_data) && array_key_exists('update', $response_data)) {
+ $params = (object)$response_data['update'];
$this->set($id, $params);
} else {
- $this->set($id, array()); //@TOVERIFY
- //$this->output = GenericError::MSG_ERROR_INVALID_COMMAND;
- //$this->error = GenericError::ERROR_INVALID_COMMAND;
+ /**
+ * This case should never occur because it means that there is
+ * given nothing to update.
+ */
+ $this->set($id, array());
}
}
}
-
+
+ /**
+ * Creating new elements.
+ *
+ * @access private
+ * @return none
+ */
private function post() {
- if(is_array($this->Request['create']) && count($this->Request['create']) > 0) {
+ if (is_array($this->Request['create']) && count($this->Request['create']) > 0) {
$params = (object)$this->Request['create'];
$this->create($params);
}
}
+ /**
+ * Deleting element by element ID.
+ *
+ * @access private
+ * @return none
+ */
private function delete() {
- if(isset($this->Request['id'])) {
+ if (isset($this->Request['id'])) {
$id = intval($this->Request['id']);
$this->remove($id);
}
}
+ /**
+ * Shortcut method for getting application modules instances by
+ * module name.
+ *
+ * @access public
+ * @param string $name application module name
+ * @return object module class instance
+ */
public function getModule($name) {
return $this->Application->getModule($name);
}
* Bacula(R) - The Network Backup Solution
* Baculum - Bacula web interface
*
- * Copyright (C) 2013-2015 Marcin Haba
+ * Copyright (C) 2013-2016 Marcin Haba
*
* The main author of Baculum is Marcin Haba.
* The original author of Bacula is Kern Sibbald, with contributions
*
* Bacula(R) is a registered trademark of Kern Sibbald.
*/
-
-class BaculumPage extends TPage
-{
+
+/**
+ * Base pages module.
+ * The module contains methods that are common for all pages (wizards, main
+ * page and error pages).
+ *
+ * @author Marcin Haba <marcin.haba@bacula.pl>
+ */
+class BaculumPage extends TPage {
public function onPreInit($param) {
parent::onPreInit($param);
- $configuration = $this->getModule('configuration');
$this->Application->getGlobalization()->Culture = $this->getLanguage();
- $this->setPrefixForSubdir();
+ $this->setURLPrefixForSubdir();
}
+ /**
+ * Get curently set language short name (for example: en, pl).
+ * If language short name is not set in session then the language value
+ * is taken from Baculum config file, saved in session and returned.
+ * If the language setting is set in session, then the value from
+ * session is returned.
+ *
+ * @access public
+ * @return string currently set language short name
+ */
public function getLanguage() {
- if(isset($_SESSION['language']) && !empty($_SESSION['language'])) {
+ if (isset($_SESSION['language']) && !empty($_SESSION['language'])) {
$language = $_SESSION['language'];
} else {
$language = $this->getModule('configuration')->getLanguage();
return $language;
}
+ /**
+ * Shortcut method for getting application modules instances by
+ * module name.
+ *
+ * @access public
+ * @param string $name application module name
+ * @return object module class instance
+ */
public function getModule($name) {
return $this->Application->getModule($name);
}
- public function goToPage($pagePath,$getParameters = null) {
- $this->Response->redirect($this->Service->constructUrl($pagePath,$getParameters,false));
+ /**
+ * Redirection to a page.
+ * Page name is given in PRADO notation with "dot", for example: (Home.SomePage).
+ *
+ * @access public
+ * @param string $page_name page name to redirect
+ * @param array $params HTTP GET method parameters in associative array
+ * @return none
+ */
+ public function goToPage($page_name, $params = null) {
+ $url = $this->Service->constructUrl($page_name, $params, false);
+ $this->Response->redirect($url);
}
- public function goToDefaultPage($getParameters = null) {
- $this->goToPage($this->Service->DefaultPage, $getParameters);
+ /**
+ * Redirection to default page defined in application config.
+ *
+ * @access public
+ * @param array $params HTTP GET method parameters in associative array
+ * @return none
+ */
+ public function goToDefaultPage($params = null) {
+ $this->goToPage($this->Service->DefaultPage, $params);
}
- public function setPrefixForSubdir() {
- $fullDocumentRoot = preg_replace('#(\/)$#', '', $this->getFullDocumentRoot());
- $urlPrefix = str_replace($fullDocumentRoot, '', APPLICATION_DIRECTORY);
- if(!empty($urlPrefix)) {
- $this->Application->getModule('friendly-url')->setUrlPrefix($urlPrefix);
+ /**
+ * Set prefix when Baculum is running in document root subdirectory.
+ * For example:
+ * web server document root: /var/www/
+ * Baculum directory /var/www/baculum/
+ * URL prefix: /baculum/
+ * In this case to base url is added '/baculum/' such as:
+ * http://localhost:9095/baculum/
+ *
+ * @access private
+ * @return none
+ */
+ private function setURLPrefixForSubdir() {
+ $full_document_root = preg_replace('#(\/)$#', '', $this->getFullDocumentRoot());
+ $url_prefix = str_replace($full_document_root, '', APPLICATION_DIRECTORY);
+ if (!empty($url_prefix)) {
+ $this->Application->getModule('friendly-url')->setUrlPrefix($url_prefix);
}
}
+ /**
+ * Get full document root directory path.
+ * Symbolic links in document root path are translated to full paths.
+ *
+ * @access private
+ * return string full document root directory path
+ */
private function getFullDocumentRoot() {
- $rootDir = array();
+ $root_dir = array();
$dirs = explode('/', $_SERVER['DOCUMENT_ROOT']);
for($i = 0; $i < count($dirs); $i++) {
- $documentRootPart = implode('/', $rootDir) . '/' . $dirs[$i];
- if(is_link($documentRootPart)) {
- $rootDir = array(readlink($documentRootPart));
+ $document_root_part = implode('/', $root_dir) . '/' . $dirs[$i];
+ if (is_link($document_root_part)) {
+ $root_dir = array(readlink($document_root_part));
} else {
- $rootDir[] = $dirs[$i];
+ $root_dir[] = $dirs[$i];
}
}
- $rootDir = implode('/', $rootDir);
- return $rootDir;
+ $root_dir = implode('/', $root_dir);
+ return $root_dir;
}
}
?>
* Bacula(R) - The Network Backup Solution
* Baculum - Bacula web interface
*
- * Copyright (C) 2013-2015 Marcin Haba
+ * Copyright (C) 2013-2016 Marcin Haba
*
* The main author of Baculum is Marcin Haba.
* The original author of Bacula is Kern Sibbald, with contributions
* read/write application config and usersfiles, get application language
* and others.
*
- * @author Marcin Haba
+ * @author Marcin Haba <marcin.haba@bacula.pl>
*/
class ConfigurationManager extends TModule
{
* @return boolean true if user saved successfully, otherwise false
*/
public function setUsersConfig($user, $password, $firstUsage = false, $oldUser = null) {
- if($firstUsage === true) {
+ if ($firstUsage === true) {
$this->clearUsersConfig();
}
$allUsers[$user] = $password;
}
- if(!is_null($oldUser) && $oldUser !== $user) {
+ if (!is_null($oldUser) && $oldUser !== $user) {
// delete old username with password from configuration file
- if(array_key_exists($oldUser, $allUsers)) {
+ if (array_key_exists($oldUser, $allUsers)) {
unset($allUsers[$oldUser]);
}
}
// add new user if does not exist
- if($userExists === false) {
+ if ($userExists === false) {
$allUsers[$user] = $password;
}
$users = file($usersFile, FILE_IGNORE_NEW_LINES | FILE_SKIP_EMPTY_LINES);
for($i = 0; $i < count($users); $i++) {
- if(preg_match("/^(?P<user>\S+)\:(?P<hash>\S+)$/", $users[$i], $match) === 1) {
+ if (preg_match("/^(?P<user>\S+)\:(?P<hash>\S+)$/", $users[$i], $match) === 1) {
$allUsers[$match['user']] = $match['hash'];
}
}