Файл: adultscript-2.0.3-pro/files/libraries/framework/package.php
Строк: 292
<?php
defined('_VALID') or die('Restricted Access!');
class VPackage
{
private $loaded = array();
private $package = array();
private $error;
private $errors = array(
'not-found' => 'Package %s not found!',
'load-failed' => 'Failed to load package: %s!',
'extract-failed' => 'Failed to extract package %s!',
'info-missing' => 'Failed to find package info file %s!',
'info-failed' => 'Failed to load package info file %s!',
'depends-missing' => 'Following packages are required by %s: %s',
'chars-invalid' => 'Invalid package name. Currently only packages with alpha numberic, dashes, underscores and point are supported!',
'chars-double' => 'Package name cannot contain the ".." characters!',
'folder-missing' => 'Package files folder is missing: %s!',
'files-missing' => 'Following files are missing from the package folder: %s!',
'files-error' => 'Failed to add following files: %s!',
'install-error' => 'Failed to install or upgrade package database entry!',
'database-missing' => 'Package database file %s not found!',
'database-error' => 'Failed to install package database file %s!',
'connect-failed' => 'Filesystem failed to establish a connection with the provided credentials!'
);
private $config = array();
private $modules = array();
private $templates = array();
private $plugins = array();
private $languages = array();
private $log;
private $debug = FALSE;
protected $db;
public function __construct()
{
$this->db = VF::factory('database');
$this->log = TMP_DIR.'/logs/package.log';
$this->load_config();
$this->load_modules();
$this->load_templates();
$this->load_plugins();
$this->load_languages();
}
public function extract($path)
{
$this->debug('Extracting: '.$path);
// lets make sure our package is valid here...it can only contain [a-z][A-Z][0-9]-_.
if (!VFile::exists($path)) {
$this->error = sprintf($this->errors['not-found'], $path);
return FALSE;
}
$filename = basename($path);
$package = VFile::strip_ext($filename);
$folder = TMP_DIR.'/packages';
VF::load('pclzip.pclzip');
$archive = new PclZip($path);
$files = $archive->extract(PCLZIP_OPT_PATH, $folder);
if (empty($files)) {
$this->error = sprintf($this->errors['extract-failed'], $path);
return FALSE;
}
return TRUE;
}
public function load($package)
{
$this->debug('Loading package: '.$package);
$info = TMP_DIR.'/packages/'.$package.'/package.ini';
if (!VFile::exists($info)) {
$this->error = sprintf($this->errors['info-missing'], $info);
return FALSE;
}
$this->package = @parse_ini_file($info);
if (!$this->package) {
$this->error = sprintf($this->errors['info-failed'], $info);
return FALSE;
}
if (!$this->depends()) {
return FALSE;
}
if (!$this->files($package)) {
return FALSE;
}
$function = $this->package['name'].'_pre_install';
if (!function_exists($function)) {
$functions_file = TMP_DIR.'/packages/'.$package.'/package.php';
if (VFile::exists($functions_file)) {
require $functions_file;
}
}
return TRUE;
}
public function install($package, $method=array())
{
$this->debug('Installing package: '.$package);
$upgrade = (isset($this->modules[$this->package['name']])) ? TRUE : FALSE;
if ($upgrade === TRUE) {
$pre_function = $this->package['name'].'_pre_upgrade';
} else {
$pre_function = $this->package['name'].'_pre_install';
}
if ($upgrade === TRUE) {
$this->debug('Upgrading package: '.$package);
}
$pre_function();
$folder = TMP_DIR.'/packages/'.$package.'/files';
if (!file_exists($folder) OR !is_dir($folder)) {
$this->error = sprintf($this->errors['folder-missing'], $folder);
return FALSE;
}
$this->debug('Initializing filesystem...');
$filesystem = VF::factory('filesystem', $method);
if (!$filesystem->connect()) {
$this->error = $filesystem->get_error();
return FALSE;
}
$failed = array();
foreach ($this->package['files'] as $file) {
if (in_array($file, $this->config['exclude'])) {
$this->debug('Excluding '.$file);
// excluded...should we display a warning here?
continue;
}
$local = TMP_DIR.'/packages/'.$package.'/files/'.$file;
$remote = BASE_DIR.'/'.$file;
$this->debug('Adding file (with copy) '.$local.' to '.$remote);
// lets try without FTP first, if suPHP is used it will work
if (!VFolder::create(dirname($local)) OR
!@copy($local, $remote)) {
$this->debug('Adding file (with filesystem) '.$local.' to '.$file);
$filesystem->upload($local, $file);
}
if (!file_exists($remote) OR
!is_file($remote) OR
!is_readable($remote)) {
$failed[] = $file;
}
}
if ($failed) {
$this->error = sprintf($this->errors['files-error'], implode(',', $failed));
return FALSE;
}
// do we need to chmod any files/folders to 0777?
if (isset($this->package['permissions']) && $this->package['permissions']) {
$this->debug('Setting permissions...');
foreach ($this->package['permissions'] as $file) {
if (!@chmod($file, 0777)) {
$filesystem->chmod($file, 0777);
}
}
}
$function = ($upgrade === TRUE) ? 'upgrade_package' : 'install_package';
if (!$this->$function($package)) {
$this->error = $this->errors['install-error'];
return FALSE;
}
if ($upgrade === TRUE) {
$post_function = $this->package['name'].'_post_upgrade';
} else {
$post_function = $this->package['name'].'_post_install';
}
$post_function();
return TRUE;
}
private function install_package($package)
{
if (isset($this->package['database'])) {
$file = TMP_DIR.'/packages/'.$package.'/files/package.sql';
if (!VFile::exists($file)) {
$this->error = sprintf($this->errors['database-missing'], $file);
return FALSE;
}
if (!$this->load_sql($file)) {
$this->error = sprintf($this->errors['database-error'], $file);
return FALSE;
}
}
$this->db->query("INSERT INTO #__module
SET name = '".$this->db->escape($this->package['name'])."',
description = '".$this->db->escape($this->package['description'])."',
type = 'extension',
version = '".$this->db->escape($this->package['version'])."',
provider = '".$this->db->escape($this->package['provider'])."',
add_date = '".date('Y-m-d h:i:s')."',
status = '1'");
return TRUE;
}
private function upgrade_package()
{
// this is just basic right now, future will also bring config updates and other features
VF::factory_remove('database');
$this->db = VF::factory('database');
$this->db->query("UPDATE #__module
SET version = '".$this->db->escape($this->package['version'])."',
update_date = '".date('Y-m-d h:i:s')."'
WHERE name = '".$this->db->escape($this->package['name'])."'
LIMIT 1");
return TRUE;
}
public function depends()
{
$missing = array();
if (isset($this->package['dependencies'])) {
foreach ($this->package['dependencies'] as $module) {
if (!isset($this->modules[$module])) {
$missing[] = $module;
}
}
}
if ($missing) {
$this->error = 'Following modules need to be installed: '.implode(',', $missing).'!';
return FALSE;
}
return TRUE;
}
public function files($package)
{
$missing = array();
foreach ($this->package['files'] as $file) {
$file_path = TMP_DIR.'/packages/'.$package.'/files/'.$file;
if (!file_exists($file_path) OR
!is_file($file_path) OR
!is_readable($file_path)) {
$missing[] = $file;
}
}
if ($missing) {
$this->error = sprintf($this->errors['files-missing'], implode(',', $missing));
return FALSE;
}
return TRUE;
}
public function get_message()
{
if (isset($this->package['name'])) {
$function = $this->package['name'].'_message';
if (function_exists($function)) {
return $function();
}
}
return FALSE;
}
private function load_config()
{
$this->config = require CONFIG_DIR.'/package.php';
}
private function load_modules()
{
$this->db->query("SELECT module_id, name, description, type, version, provider
FROM #__module
ORDER BY module_id ASC");
if ($this->db->affected_rows()) {
$rows = $this->db->fetch_rows();
foreach ($rows as $row) {
$this->modules[$row['name']] = array(
'version' => $row['version'],
'type' => $row['type'],
'description' => $row['description'],
'provider' => $row['provider']
);
}
} else {
throw new VException('Failed to load modules! Aborting!');
}
}
private function load_sql($file)
{
$file = fopen($file, 'r');
if (is_resource($file)) {
VF::factory_remove('database');
$this->db = VF::factory('database');
$prefix = VF::cfg_item('db_prefix');
$query = array();
while (!feof($file)) {
$query[] = fgets($file);
if (preg_match('~' . preg_quote($delimiter, '~') . 's*$~iS', end($query)) === 1) {
$query = trim(implode('', $query));
$query = str_replace(
array(
'CREATE TABLE `',
'DROP TABLE IF EXISTS `',
'LOCK TABLES `',
'INSERT INTO `',
'ALTER TABLE `',
'REPLACE INTO `'
),
array(
'CREATE TABLE `'.$prefix,
'DROP TABLE IF EXISTS `'.$prefix,
'LOCK TABLES `'.$prefix,
'INSERT INTO `'.$prefix,
'ALTER TABLE `'.$prefix,
'REPLACE INTO `'.$prefix
),
$query
);
$this->db->query($query, TRUE);
while(ob_get_level() > 0) {
ob_end_flush();
}
flush();
if (is_string($query)) {
$query = array();
}
}
return fclose($file);
}
}
return FALSE;
}
private function load_templates()
{
}
private function load_plugins()
{
}
private function load_languages()
{
}
public function get_error()
{
return $this->error;
}
public function valid($name)
{
// currently in 1.0 we only support [a-z][A-Z][0-9]-_.
if (!preg_match('/^[A-Za-z0-9_-.]+$/', $name)) {
$this->error = $this->errors['chars-in2valid'];
return FALSE;
}
if (strpos($name, '..') !== FALSE) {
$this->error = $this->errors['chars-double'];
return FALSE;
}
return TRUE;
}
private function log($message)
{
VFile::write($this->log, '['.date('Y-m-d h:i:s').']: '.$message."n", TRUE);
}
private function debug($message)
{
if ($this->debug === TRUE) {
VFile::write($this->log, '['.date('Y-m-d h:i:s').']: '.$message."n", TRUE);
}
}
}