Example #1
0
 /**
  * Constructor
  * Makes sure the cache directory is set
  *
  * @return object
  */
 public function __construct()
 {
     $this->cacheDir = $this->_zula->getDir('tmp') . '/cache';
     if (!is_dir($this->cacheDir)) {
         zula_make_dir($this->cacheDir);
     }
     if (!zula_is_writable($this->cacheDir)) {
         throw new Cache_Exception($this->cacheDir . ' is not writable');
     }
 }
Example #2
0
 /**
  * Main method that is called on all loggers from
  * the Log class.
  *
  * @param string $message
  * @param int $level
  * @param string $file
  * @param int $line
  * @return bool
  */
 public function logMessage($msg, $level, $file = 'unknown', $line = 0)
 {
     $fileName = $this->makeFileName($level);
     $filePath = $this->logDir . '/' . $fileName;
     if (!zula_is_writable($this->logDir)) {
         return false;
     }
     $uid = Registry::has('session') ? $this->_session->getUserId() : 'unknown';
     $msgFormat = '[%1$s] [%2$s | uid %3$s] [%4$s] -- (%5$s:%6$d) %7$s' . "\r\n";
     $entry = sprintf($msgFormat, date('c'), zula_get_client_ip(), $uid, $this->levelName($level), basename($file), $line, $msg);
     return error_log($entry, 3, $filePath);
 }
Example #3
0
 /**
  * Check the environment the installer is running in to
  * ensure all required PHP extensions exist and the needed
  * files/directories are writable
  *
  * @return bool|string
  */
 public function indexSection()
 {
     $this->setTitle(t('Pre-installation checks'));
     $checks = array('exts' => array('title' => t('Required PHP extensions'), 'passed' => false, 'values' => array('ctype', 'date', 'dom', 'filter', 'hash', 'pdo', 'pdo_mysql', 'pcre', 'session', 'json')), 'optExts' => array('title' => t('Optional PHP extensions'), 'passed' => true, 'values' => array('gd', 'FileInfo')), 'files' => array('title' => t('Writable files'), 'passed' => false, 'values' => array($this->_zula->getDir('config') . '/config.ini.php', $this->_zula->getDir('config') . '/layouts/admin-default.xml', $this->_zula->getDir('config') . '/layouts/main-default.xml', $this->_zula->getDir('config') . '/layouts/fpsc-admin.xml', $this->_zula->getDir('config') . '/layouts/fpsc-main.xml')), 'dirs' => array('title' => t('Writable directories'), 'passed' => false, 'values' => array($this->_zula->getDir('config') . '/layouts', $this->_zula->getDir('logs'), $this->_zula->getDir('tmp'), $this->_zula->getDir('uploads'), $this->_zula->getDir('locale'))));
     // Run the various checks
     $passed = true;
     foreach ($checks as $name => $details) {
         $results = array();
         foreach ($details['values'] as $val) {
             switch ($name) {
                 case 'exts':
                 case 'optExts':
                     $results[$val] = extension_loaded($val);
                     break;
                 case 'files':
                 case 'dirs':
                     $results[$val] = zula_is_writable($val);
             }
         }
         if ($name != 'optExts' && in_array(false, $results, true)) {
             $passed = false;
             $checks[$name]['passed'] = false;
         } else {
             $checks[$name]['passed'] = true;
         }
         $checks[$name]['values'] = $results;
     }
     if ($passed) {
         if ($this->_zula->getMode() !== 'cli') {
             $_SESSION['installStage'] = 2;
         }
         $this->_event->success(t('Pre-installation checks were successful'));
         return zula_redirect($this->_router->makeUrl('install', 'sql'));
     } else {
         if ($this->_zula->getMode() == 'cli') {
             $this->_zula->setExitCode(3);
         }
         $this->_event->error(t('Sorry, your server environment does not meet our requirements'));
         $view = $this->loadView('checks' . ($this->_zula->getMode() == 'cli' ? '-cli.txt' : '.html'));
         $view->assign(array('checks' => $checks, 'passed' => $passed));
         return $view->getOutput();
     }
 }
Example #4
0
 /**
  * Checks which directories and files are writable to the user
  * the script is running as
  *
  * @return string
  */
 public function writableSection()
 {
     $this->setTitle(t('Writable files/directories'));
     $this->setOutputType(self::_OT_INFORMATIVE);
     // Generate array of all files/dirs
     $items = array();
     $directoryIterator = new RecursiveDirectoryIterator($this->_zula->getDir('config'));
     foreach (new RecursiveIteratorIterator($directoryIterator) as $file) {
         if (substr($file->getFileName(), 0, 1) != '.' && $file->isFile()) {
             $items['files'][] = array('path' => $file->getPathName(), 'result' => zula_is_writable($file->getPathName()));
         }
     }
     // Dirs
     $dirs = array($this->_zula->getDir('config') . '/layouts', $this->_zula->getDir('logs'), $this->_zula->getDir('tmp'), $this->_zula->getDir('uploads'), $this->_zula->getDir('locale'));
     foreach ($dirs as $dir) {
         $items['dirs'][] = array('path' => $dir, 'result' => zula_is_writable($dir));
     }
     $view = $this->loadView('index/writable.html');
     $view->assign(array('DIRS' => $items['dirs'], 'FILES' => $items['files']));
     return $view->getOutput();
 }
Example #5
0
 /**
  * Gets all available cache types that can be used with
  * the current environment
  *
  * @return array
  */
 public static function getAvailable()
 {
     $types = array();
     foreach (new DirectoryIterator(Registry::get('zula')->getDir('libs') . '/Cache') as $file) {
         if (!$file->isDot() && substr($file, 0, 1) != '.') {
             $extension = null;
             $type = basename($file, '.php');
             // Ensure all extensions are there to be used
             switch ($type) {
                 case 'Disabled':
                 case 'Tmp':
                     break;
                 case 'Apc':
                     $extension = 'apc';
                     break;
                 case 'Eaccelerator':
                     $extension = 'eaccelerator';
                     if (!function_exists('eaccelerator_put')) {
                         continue 2;
                     }
                     break;
                 case 'File':
                     if (!zula_is_writable(Registry::get('zula')->getDir('tmp') . '/cache')) {
                         continue 2;
                     }
                     break;
                 case 'Memcached':
                     $extension = 'memcached';
                     break;
                 default:
                     continue 2;
             }
             if (!isset($extension) || extension_loaded($extension)) {
                 $types[] = $type;
             }
         }
     }
     return $types;
 }
Example #6
0
 /**
  * Pre-upgrade checks to ensure the environment is how we
  * require it.
  *
  * @return bool|string
  */
 public function indexSection()
 {
     $this->setTitle(t('Pre-upgrade checks'));
     if ($this->_zula->getMode() != 'cli' && (!isset($_SESSION['upgradeStage']) || $_SESSION['upgradeStage'] !== 3)) {
         return zula_redirect($this->_router->makeUrl('upgrade', 'version'));
     }
     /**
      * All the checks that need to be run, and then actualy run the needed checks
      */
     $tests = array('files' => array($this->_zula->getConfigPath() => ''), 'dirs' => array($this->_zula->getDir('config') => ''));
     $passed = true;
     foreach ($tests as $type => &$items) {
         foreach ($items as $itemName => $status) {
             $writable = zula_is_writable($itemName);
             $items[$itemName] = $writable;
             if ($writable === false) {
                 $passed = false;
             }
         }
     }
     if ($passed) {
         if (isset($_SESSION['upgradeStage'])) {
             ++$_SESSION['upgradeStage'];
         }
         $this->_event->success(t('Pre-upgrade checks were successful'));
         return zula_redirect($this->_router->makeUrl('upgrade', 'migrate'));
     } else {
         if ($this->_zula->getMode() == 'cli') {
             $this->_zula->setExitCode(3);
         }
         $this->_event->error(t('Sorry, your server environment does not meet our requirements'));
         $view = $this->loadView('checks' . ($this->_zula->getMode() == 'cli' ? '-cli.txt' : '.html'));
         $view->assign(array('file_results' => $tests['files'], 'dir_results' => $tests['dirs'], 'passed' => $passed));
         return $view->getOutput();
     }
 }
Example #7
0
 /**
  * Update the settings based on the post-data provided
  *
  * @param string $name
  * @param array $args
  * @return string
  */
 public function __call($name, $args)
 {
     $name = substr($name, 0, -7);
     if (!$this->_acl->check('settings_update')) {
         throw new Module_NoPermission();
     } else {
         if (!in_array($name, $this->categories)) {
             throw new Module_ControllerNoExist();
         } else {
             if (!$this->_input->checkToken()) {
                 $this->_event->error(Input::csrfMsg());
                 return zula_redirect($this->_router->makeUrl('settings', $name));
             }
         }
     }
     $this->setTitle(t('Update settings'));
     // Update all of the provided settings, or insert if they don't exist
     foreach ($this->_input->post('setting') as $key => $val) {
         if (strpos($key, 'cache') !== 0) {
             if (substr($key, 8, 9) == 'mail/smtp' && !$this->_acl->check('settings_access_smtp')) {
                 continue;
             }
             try {
                 $this->_config_sql->update($key, $val);
             } catch (Config_KeyNoExist $e) {
                 $this->_sql->insert('config', array('name' => $key, 'value' => $val));
             }
         }
     }
     /**
      * Category specific things to do when updating
      * the settings or other things (ACL forms etc).
      */
     switch ($name) {
         case 'general':
             $this->_cache->delete('view_default_tags');
             break;
         case 'cache':
             try {
                 $this->_config_ini->update('cache/type', $this->_input->post('setting/cache\\/type'));
                 $this->_config_ini->update('cache/ttl', $this->_input->post('setting/cache\\/ttl'));
                 $this->_config_ini->update('cache/js_aggregate', $this->_input->post('setting/cache\\/js_aggregate'));
                 $this->_config_ini->update('cache/google_cdn', $this->_input->post('setting/cache\\/google_cdn'));
                 $this->_config_ini->writeIni();
                 // Clear cache if needbe
                 if ($this->_input->post('cache_purge')) {
                     $this->_cache->purge();
                 }
             } catch (Exception $e) {
                 $this->_event->error($e->getMessage());
                 $this->_log->message($e->getMessage(), Log::L_WARNING);
             }
             break;
         case 'locale':
             try {
                 $this->_config_ini->update('locale/default', $this->_input->post('setting/locale\\/default'));
                 $this->_config_ini->writeIni();
             } catch (Exception $e) {
                 $this->_event->error($e->getMessage());
                 $this->_log->message($e->getMessage(), Log::L_WARNING);
             }
             if (($pkg = $this->_input->post('lang_pkg')) !== 'none') {
                 // Download and install a new locale
                 if (!zula_supports('zipExtraction')) {
                     $this->_event->error(t('Cannot install locale, server does not support zip extraction'));
                 } else {
                     if (!preg_match('#^[a-z]{2}_[A-Z]{2}$#', $pkg)) {
                         $this->_event->error(t('Provided locale is invalid, unable to install'));
                     } else {
                         if (!zula_is_writable($this->_zula->getDir('locale'))) {
                             $this->_event->error(t('Locale directory is not writable, unable to install'));
                         } else {
                             $version = str_replace('-', '/', zula_version_map(_PROJECT_VERSION));
                             $zipDest = $this->_zula->getDir('tmp') . '/i18n-' . $pkg . '.zip';
                             $copyResult = @copy('http://releases.tangocms.org/' . $version . '/i18n/' . $pkg . '.zip', $zipDest);
                             if ($copyResult) {
                                 // Extract the archive to the locale dir
                                 $zip = new ZipArchive();
                                 if ($zip->open($zipDest)) {
                                     $zip->extractTo($this->_zula->getDir('locale'));
                                     $zip->close();
                                     $this->_event->success(t('Locale successfully installed'));
                                 } else {
                                     $this->_event->error(t('Could not install locale, zip extraction failed'));
                                 }
                                 unlink($zipDest);
                             } else {
                                 $this->_event->error(t('Failed to get remote language archive'));
                             }
                         }
                     }
                 }
             }
             break;
     }
     $this->_event->success(t('Updated settings'));
     return zula_redirect($this->_router->makeUrl('settings', $name));
 }
Example #8
0
 /**
  * Allows for shorter URLs. Selects a CSS file to edit, will use
  * the first CSS file if none is specified
  *
  * @param string $name
  * @param array $args
  * @return string|bool
  */
 public function __call($name, $args)
 {
     if (!$this->_acl->check('theme_view_css')) {
         throw new Module_NoPermission();
     }
     $this->setTitle(t('Edit CSS files'));
     $this->setOutputType(self::_OT_CONFIG);
     /**
      * Gather details of the theme and check if the CSS file exists
      */
     try {
         $theme = new Theme(substr($name, 0, -7));
         $this->setTitle(sprintf(t('"%s" stylesheets'), $theme->getDetail('title')));
         // All CSS files for this theme
         $themeCssFiles = $theme->getAllCss();
         if (empty($themeCssFiles)) {
             $this->_event->error(t('There are no CSS files available'));
             return zula_redirect($this->_router->makeUrl('theme'));
         } else {
             try {
                 $selectedCss = $this->_router->getArgument('file');
             } catch (Router_ArgNoExist $e) {
                 $cssDetails = reset($themeCssFiles);
                 $selectedCss = $cssDetails['name'];
             }
             if (isset($themeCssFiles[$selectedCss])) {
                 $cssDetails = $themeCssFiles[$selectedCss];
             } else {
                 // Eek, the CSS file does not exist!
                 $this->_event->error(sprintf(t('Stylesheet "%1$s" does not exist'), $selectedCss));
                 return zula_redirect($this->_router->makeUrl('theme', 'css', $theme->getDetail('name')));
             }
         }
     } catch (Theme_NoExist $e) {
         $this->_event->error(t('Theme does not exist'));
         return zula_redirect($this->_router->makeUrl('theme'));
     }
     /**
      * Setup the form and validation for the contents
      */
     $form = new View_form('css.html', 'theme');
     $form->addElement('theme/body', file_get_contents($cssDetails['path']), t('Stylesheet'), new Validator_length(0, 10000));
     if ($form->hasInput() && $form->isValid()) {
         if (!$this->_acl->check('theme_edit_css')) {
             throw new Module_NoPermission();
         } else {
             if (zula_is_writable($cssDetails['path'])) {
                 file_put_contents($cssDetails['path'], $form->getValues('theme/body'));
                 $this->_event->success(t('Stylesheet updated'));
                 return zula_redirect($this->_router->makeUrl('theme', 'css', $theme->getDetail('name'), null, array('file' => $cssDetails['name'])));
             } else {
                 $this->_event->error(sprintf(t('CSS file "%s" is not writable'), $cssDetails['path']));
             }
         }
     }
     // Assign other data to be provided to the view file
     $this->addAsset('js/editor.js');
     $this->_theme->addCssFile('jquery.linedtextarea.css');
     $this->_theme->addJsFile('jquery.linedtextarea');
     $form->assign(array('CSS_FILES' => $themeCssFiles, 'CSS_NAME' => $selectedCss, 'THEME' => array('NAME' => $theme->getDetail('name'))));
     return $form->getOutput();
 }
Example #9
0
 /**
  * Zula Exception Handler for all uncaught exceptions
  *
  * @param object $exception
  * @return bool
  */
 public function exceptionHandler(Exception $e)
 {
     $formatCode = sprintf('ZULA-%03d', $e->getCode());
     if (!Registry::has('error')) {
         try {
             $this->loadLib('error');
         } catch (Exception $e) {
         }
     }
     /**
      * Create the correct title for the exception
      */
     if ($e instanceof Zula_Exception) {
         $title = 'Uncaught internal (Zula) exception';
     } else {
         if ($e instanceof PDOException) {
             $title = 'Uncaught SQL (PDO) exception';
         } else {
             $title = 'Uncaught application exception';
         }
     }
     // Attempt to write a dump log file
     $logDir = $this->getDir('logs');
     if (zula_is_writable($logDir)) {
         $i = 1;
         do {
             $file = $logDir . '/zula-dump.' . $i . '.log';
             $i++;
         } while (file_exists($file));
         $body = 'Uncaught exception in "' . $e->getFile() . '" on line ' . $e->getLine() . ' with code "' . $formatCode . '"';
         $body .= "\n\nProject Version: " . (defined('_PROJECT_VERSION') ? _PROJECT_VERSION : 'unknown');
         $body .= "\nTime & Date: " . date('c');
         $body .= "\nRequest Method: " . (PHP_SAPI == 'cli' ? 'cli' : $_SERVER['REQUEST_METHOD']);
         if (Registry::has('router')) {
             $body .= "\nRequest Path: " . Registry::get('router')->getRequestPath();
             $body .= "\nRaw Request Path: " . Registry::get('router')->getRawRequestPath();
         }
         $body .= "\nException Thrown: " . get_class($e);
         $body .= "\nMessage: " . $e->getMessage();
         $body .= "\n\nStack Trace:\n";
         $body .= $e->getTraceAsString();
         file_put_contents($file, $body);
     }
     if (Registry::has('error')) {
         return Registry::get('error')->report($e->getMessage(), E_USER_ERROR, $e->getFile(), $e->getLine(), $title);
     } else {
         trigger_error($e->getMessage(), E_USER_ERROR);
     }
 }
Example #10
0
/**
 * Checks if a file can be deleted
 *
 * @param string $file
 * @return bool
 */
function zula_is_deletable($file)
{
    return zula_is_writable(dirname($file));
}
Example #11
0
 /**
  * Takes the provided destination and checks that it does not exist first
  * if so, remove it - and check that directory is writable
  *
  * @param string $destination
  * @return string
  */
 protected function prepareDestination($destination)
 {
     if ($destination == false) {
         $destination = $this->dirname . '/' . $this->filename;
         switch ($this->mime) {
             case 'image/jpeg':
             case 'image/jpg':
                 $destination .= '.jpg';
                 break;
             case '':
             case 'image/png':
                 $destination .= '.png';
                 break;
             case 'image/gif':
                 $destination .= '.gif';
                 break;
             default:
                 $destination .= '.' . $this->extension;
         }
     }
     $directory = dirname($destination);
     if (file_exists($destination)) {
         if (!@unlink($destination)) {
             throw new Image_SaveFailed($destination . ' already exists and could not be removed');
         }
     } else {
         if (!zula_make_dir($directory)) {
             throw new Image_SaveFailed($directory . ' directory could not be created');
         }
     }
     if (!zula_is_writable($directory)) {
         throw new Image_SaveFailed($directory . ' is not writable');
     }
     return $destination;
 }
Example #12
0
    /**
     * Save the layout file and updates/inserts SQL entry if needed
     *
     * @param string $path
     * @return bool
     */
    public function save($path = null)
    {
        $path = trim($path) ? $path : $this->path;
        if ((file_exists($path) && zula_is_writable($path) || !file_exists($path) && zula_is_writable(dirname($path))) && $this->dom->save($path)) {
            if (Registry::has('sql')) {
                if ($regex = $this->getRegex()) {
                    $pdoSt = $this->_sql->prepare('INSERT INTO {PREFIX}layouts (name, regex) VALUES (?, ?)
														ON DUPLICATE KEY UPDATE regex = VALUES(regex)');
                    $pdoSt->execute(array($this->name, $this->getRegex()));
                } else {
                    $pdoSt = $this->_sql->prepare('DELETE FROM {PREFIX}layouts WHERE name = ?');
                    $pdoSt->execute(array($this->name));
                }
            }
            return true;
        } else {
            return false;
        }
    }
Example #13
0
 /**
  * Rewrites the configuration ini file back, leaving it as
  * in-take as possible (ie, keeping all comments) in place
  *  and same sort of structure.
  *
  * @return bool
  */
 public function writeIni()
 {
     if (!zula_is_writable($this->iniFile)) {
         throw new Config_ini_FileNotWriteable($this->iniFile . ' is not writeable');
     }
     $iniContent = '';
     /**
      * Open the file and read line by line, rewriting it as
      * it goes a long
      */
     $fHandle = fopen($this->iniFile, 'rb');
     $sections = array();
     # Store the sections and values which have been written
     while (!feof($fHandle)) {
         $line = trim(fgets($fHandle)) . "\n";
         if (zula_substr($line, 0, 1) == ';') {
             // Line is a comment
             $iniContent .= $line;
         } else {
             if (zula_substr($line, 0, 1) == '[') {
                 preg_match('#\\[(.*?)\\]#', $line, $matches);
                 try {
                     $values = $this->get($matches[1]);
                     $sections[] = $matches[1];
                     $iniContent .= $matches[0] . "\n";
                     foreach ($values as $key => $val) {
                         if (preg_match('#[^A-Z0-9_\\-./]#i', $val)) {
                             $val = '"' . $val . '"';
                         }
                         $iniContent .= $key . ' = ' . $val . "\n";
                     }
                     // Add a spacer to the bottom
                     $iniContent .= "\n";
                 } catch (Config_KeyNoExist $e) {
                     continue;
                 }
             }
         }
     }
     /**
      * Add on the extra values that need to be added to the ini file
      */
     foreach ($this->getAll() as $section => $values) {
         if (empty($values)) {
             continue;
             # No need to add empty sections in
         } else {
             if (!in_array($section, $sections)) {
                 $iniContent .= '[' . $section . "]\n";
                 foreach ($values as $key => $val) {
                     $val = (string) $val;
                     if (preg_match('#[^A-Z0-9_\\-./]#i', $val)) {
                         $val = '"' . $val . '"';
                     }
                     $iniContent .= $key . ' = ' . $val . "\n";
                 }
             }
         }
     }
     file_put_contents($this->iniFile, trim($iniContent));
     return true;
 }