Sindbad~EG File Manager

Current Path : /var/www/web3/modules/core/classes/
Upload File :
Current File : //var/www/web3/modules/core/classes/GalleryRepository.class

<?php
/*
 * Gallery - a web based photo album viewer and editor
 * Copyright (C) 2000-2007 Bharat Mediratta
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2 of the License, or (at
 * your option) any later version.
 *
 * This program is distributed in the hope that it will be useful, but
 * WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA  02110-1301, USA.
 */

GalleryCoreApi::requireOnce('modules/core/classes/GalleryRepositoryIndex.class');
GalleryCoreApi::requireOnce('modules/core/classes/GalleryRepositoryUtilities.class');

/**
 * Provides all repository-related functionality.
 * @package GalleryCore
 * @subpackage Classes
 * @author Jozef Selesi <selesi at gmail dot com>
 * @version $Revision: 16127 $
 */
class GalleryRepository {

    /**
     * Repository utilities.
     * @var object GalleryRepositoryUtilities
     * @access private
     */
    var $_utilities;

    /**
     * Local repository index.
     * @var object RepositoryIndex
     * @access private
     */
    var $_index;

    /**
     * The source of this index (released, experimental, community)
     * @var string
     * @access private
     */
    var $_source;

    /**
     * Return a set of all the repositories that are currently active.  The error count indicates
     * the number of repositories that failed to initialize for some reason (perhaps from a
     * malformed local copy of the index).  The fix for this is to download a new version of the
     * repository.
     *
     * @param array $sources (optional) an array of source names, eg 'official', 'community'
     *                       If this is left empty, use the value stored in core.repositories.
     * @param string $repositoryClassName (optional) the name of the repository class to use.
     *               should be GalleryRepository, except for test code.
     * @return array object GalleryStatus a status code
     *               array repository name => object GalleryRepository the repository
     *               int error count (repositories that failed to load for some reason)
     * @static
     */
    function getRepositories($sources=array(), $repositoryClassName='GalleryRepository') {
	if (empty($sources)) {
	    list ($ret, $sources) =
		GalleryCoreApi::getPluginParameter('module', 'core', 'core.repositories');
	    if ($ret) {
		return array($ret, null, null);
	    }
	    $sources = array_keys(unserialize($sources));
	}

	$repositories = array();
	$errorCount = 0;
	foreach ($sources as $source) {
	    $repositories[$source] = new $repositoryClassName;
	    $ret = $repositories[$source]->init($source);
	    if ($ret) {
		if ($ret->getErrorCode() & ERROR_BAD_PARAMETER) {
		    unset($repositories[$source]);
		    $errorCount++;
		} else {
		    return array($ret, null, null);
		}
	    }
	}

	return array(null, $repositories, $errorCount);
    }

    /**
     * Initializes the repository index and utilities.
     *
     * @return GalleryStatus a status code
     */
    function init($source) {
	$this->_source = $source;
	$this->_index = new GalleryRepositoryIndex($source);
	$this->_utilities = new GalleryRepositoryUtilities();

	if ($this->_index->existsInCache()) {
	    $ret = $this->_index->load();
	    if ($ret) {
		return $ret;
	    }
	}
	return null;
    }

    /**
     * Determines whether a core module upgrade is available.
     *
     * @return array object GalleryStatus a status code
     *		     boolean availability
     *		     array repository core and plugin api versions
     */
    function isCoreUpgradeAvailable() {
	list ($ret, $core) = GalleryCoreApi::loadPlugin('module', 'core');
	if ($ret) {
	    return array($ret, null, null);
	}

	list ($ret, $header) = $this->_index->getPluginHeader('module', 'core');
	if ($ret) {
	    if ($ret->getErrorCode() & ERROR_BAD_PARAMETER) {
		/*
		 * No header for the core module.  Maybe the core package isn't available in any
		 * this repository.
		 */
		return array(null, false, array());
	    }
	    return array($ret, null, null);
	}
	$repositoryVersion = $header['version'];

	/*
	 * We only compare versions, not builds, because upgrading the core module isn't something
	 * that's done very often, at least until it's done manually.
	 */
	list ($ret, $relation) =
	    $this->_utilities->compareVersions($repositoryVersion, $core->getVersion());
	if ($ret) {
	    return array($ret, null, null);
	}

	$apiVersions = array();
	if ($relation == 'newer') {
	    $apiVersions['core'] = implode('.', $header['coreApiVersion']);
	    $apiVersions['module'] = implode('.', $header['moduleApiVersion']);
	    $apiVersions['theme'] = implode('.', $header['themeApiVersion']);
	    $isAvailable = true;
	} else {
	    $apiVersions = array();
	    $isAvailable = false;
	}

	return array(null, $isAvailable, $apiVersions);
    }

    /**
     * Determines which packages of the specified packages are newer in the repository.
     *
     * @return array object GalleryStatus a status code
     *		     array package list
     */
    function getPluginUpgradeInfo($pluginType, $pluginId) {
	global $gallery;
	$upgradeInfo = array('upgradeable' => false);

	/* Get installed packages meta data. */
	list ($ret, $installedPackages) =
	    $this->_utilities->getPluginPackages($pluginType, $pluginId);
	if ($ret) {
	    return array($ret, null);
	}

	/* Get version info from repository index for base files. */
	list ($ret, $header) = $this->_index->getPluginHeader($pluginType, $pluginId);
	if ($ret) {
	    return array($ret, null);
	}
	$repositoryDataVersion = $header['version'];
	$repositoryDataBuild = $header['buildTimestamp'];
	$upgradeInfo['base']['newVersion'] = $repositoryDataVersion;
	$upgradeInfo['base']['newBuild'] = $repositoryDataBuild;
	$upgradeInfo['base']['isCompatible'] = $this->_utilities->isPluginCompatible(
	    $pluginType, $header['requiredCoreApi'], $header['requiredPluginApi']);

	/* Check if this plugin's base files are installed. */
	if (isset($installedPackages['base'])) {
	    $dataVersion = $installedPackages['base']['version'];
	    $dataBuild = $installedPackages['base']['build'];
	    $locked = $installedPackages['base']['locked'];
	} else {
	    $dataVersion = null;
	    $dataBuild = null;
	    $locked = 0;
	}

	/* Compare local base version with the one in the repository. */
	list ($ret, $upgradeInfo['base']['relation']) = $this->_utilities->compareVersions(
	    $dataVersion, $repositoryDataVersion, $dataBuild, $repositoryDataBuild);
	if ($ret) {
	    return array($ret, null);
	}

	if ($upgradeInfo['base']['relation'] == 'older') {
	    $upgradeInfo['upgradeable'] = $upgradeInfo['base']['isCompatible'];
	}
	$upgradeInfo['base']['currentVersion'] = $dataVersion;
	$upgradeInfo['base']['currentBuild'] = $dataBuild;
	$upgradeInfo['base']['locked'] = $locked;

	/* Check if any languages have been updated. */
	list ($ret, $languages) =
	    $this->_index->getAvailableLanguagesInPlugin($pluginType, $pluginId);
	if ($ret) {
	    return array($ret, null);
	}

	$upgradeInfo['languages'] = array();
	$upgradeInfo['complete'] = isset($upgradeInfo['base']['currentVersion']);
	foreach ($languages as $language => $revision) {
	    list ($ret, $languageDescription) =
		$this->_utilities->getLanguageDescription($language);
	    if ($ret) {
		if ($ret->getErrorCode() & ERROR_BAD_PARAMETER) {
		    /* Unsupported language .. ignore it. */
		    continue;
		}
		return array($ret, null);
	    }

	    if (isset($installedPackages['lang-' . $language])) {
		$currentBuild = $installedPackages['lang-' . $language]['build'];
		$locked = $installedPackages['lang-' . $language]['locked'];
	    } else {
		$currentBuild = null;
		$locked = 0;
	    }


	    $relation = $this->_utilities->compareRevisions($currentBuild, $revision);
	    $upgradeInfo['languages'][$language] = array(
		'name' => $languageDescription,
		'currentBuild' => $currentBuild,
		'newBuild' => $revision,
		'relation' => $relation,
		'locked' => $locked);

	    if ($relation == 'older' && $currentBuild) {
		$upgradeInfo['upgradeable'] = $upgradeInfo['base']['isCompatible'];
	    }

	    $upgradeInfo['complete'] &= !empty($currentBuild);
	}

	return array(null, $upgradeInfo);
    }

    /**
     * Returns a list of plugins of the specified type.
     *
     * It can return a list of compatible plugins with specific core APIs. By default, compatibility
     * is determined by comparing the repository plugin requirements with the currently installed
     * APIs, but API versions can be specified, so it is possible to, for example, get a
     * compatibility list based on future API versions.
     *
     * @param string $pluginType
     * @param boolean $showAllPlugins show incompatible plugins
     * @param array $coreApis core APIs to base compatibility check on
     *		    'core'/'module'/'theme' => array(versionMajor, versionMinor)
     * @return array object GalleryStatus a status code
     *		     array plugin list
     */
    function getRepositoryPluginList($pluginType, $showAllPlugins=false, $coreApis=null) {
	global $gallery;

	list ($ret, $repositoryPluginList) =
	    $this->_index->getPlugins($pluginType, $showAllPlugins, $coreApis);
	if ($ret) {
	    return array($ret, null);
	}

	$pluginList = array();
	foreach ($repositoryPluginList[$pluginType] as $pluginId => $plugin) {
	    $localVersion = '';

	    /* Get active language. */
	    list ($ret, $language) = $gallery->getActiveLanguageCode();
	    if ($ret) {
		return array($ret, null);
	    }

	    /* Load the core module for translation */
	    list ($ret, $core) = GalleryCoreApi::loadPlugin('module', 'core');
	    if ($ret) {
		return array($ret, null);
	    }

	    /* Fall back to en_US if there are no descriptions in the active language. */
	    if (!isset($plugin['descriptions'][$language])) {
		$language = 'en_US';
	    }

	    $isAvailable = isset($plugin['localVersion']);
	    $locked = 0;
	    if ($isAvailable) {
		/*
		 * For locally available plugins we check if they can be upgraded and present
		 * an 'upgrade' action. Maybe we can show some additional info, such as
		 * '3 languages updated' or 'base data upgrade available'.
		 */
		list ($ret, $upgradeInfo) = $this->getPluginUpgradeInfo($pluginType, $pluginId);
		if ($ret) {
		    return array($ret, null);
		}

		$localVersion = $plugin['localVersion'];
		$locked = $upgradeInfo['base']['locked'];
		$isUpgradeable = $upgradeInfo['upgradeable'];
	    } else {
		$isUpgradeable = false;
	    }

	    if (isset($plugin['descriptions'][$language]['groupLabel'])) {
		$groupLabel = $plugin['descriptions'][$language]['groupLabel'];
	    } else if ($pluginType == 'theme') {
		$groupLabel = $core->translate('Themes');
	    } else {
		$groupLabel = $core->translate('General');
	    }

	    list ($providedCoreApiVersion, $providedPluginApiVersion) =
		$this->_utilities->getProvidedApis($pluginType, $coreApis);
	    $pluginList[$pluginId] = array(
		'type' => $pluginType,
		'name' => $plugin['descriptions'][$language]['name'],
		'description' => $plugin['descriptions'][$language]['description'],
		'groupLabel' => $groupLabel,
		'repositoryVersion' => $plugin['header']['version'],
		'localVersion' => $localVersion,
		'isCompatible' => $plugin['isCompatible'],
		'api' => array(
		    'required' => array(
			'core' => implode('.', $plugin['header']['requiredCoreApi']),
			'plugin' => implode('.', $plugin['header']['requiredPluginApi'])),
		    'provided' => array(
			'core' => implode('.', $providedCoreApiVersion),
			'plugin' => implode('.', $providedPluginApiVersion))),
		'locked' => $locked,
		'isUpgradeable' => $isUpgradeable);
	}

	/* Sort plugins by name. */
	if (!uasort($pluginList, array('GalleryRepository', 'comparePluginListEntries'))) {
	    return array(GalleryCoreApi::error(ERROR_BAD_PARAMETER, __FILE__, __LINE__,
					      'Error sorting plugin list.'),
			 null);
	}

	return array(null, $pluginList);
    }

    /**
     * Compares two plugin list entries.
     *
     * A plugin list entry is an element of the array returned by getRepositoryPluginList. This
     * is a callback for sorting the plugin list by (group label, plugin name).
     *
     * @param array $plugin1 first plugin list entry
     * @param array $plugin2 second plugin list entry
     * @return boolean see strcmp()
     */
    function comparePluginListEntries($plugin1, $plugin2) {
	global $gallery;

	if (isset($plugin1['groupLabel'])) {
	    $group1 = $plugin1['groupLabel'];
	    $group2 = $plugin2['groupLabel'];
	    if ($group1 != $group2) {
		return strcmp($group1, $group2);
	    }
	}

	$name1 = $plugin1['name'];
	$name2 = $plugin2['name'];
	return strcmp($name1, $name2);
    }

    /**
     * Creates a list of all upgradeable packages.
     *
     * It goes through all installed plugins and checks if an update is available to any of their
     * packages and adds it to a list if it is.
     *
     * @return array object GalleryStatus a status code
     *		     array package list
     */
    function getAllUpgradeablePackages() {
	$packages = array();
	foreach (array('module', 'theme') as $pluginType) {
	    list ($ret, $plugins) = GalleryCoreApi::getAllPluginIds($pluginType);
	    if ($ret) {
		return array($ret, null);
	    }

	    foreach ($plugins as $pluginId) {
		if ($pluginId == 'core' && $pluginType == 'module') {
		    continue;
		}

		list ($ret, $upgradeInfo) = $this->getPluginUpgradeInfo($pluginType, $pluginId);
		if ($ret) {
		    if ($ret->getErrorCode() & ERROR_BAD_PARAMETER) {
			continue;
		    }
		    return array($ret, null);
		}

		if ($upgradeInfo['base']['locked'] || !$upgradeInfo['base']['isCompatible']) {
		    continue;
		}

		if ($upgradeInfo['base']['relation'] == 'older' &&
		    $upgradeInfo['base']['currentVersion']) {
		    $packages[$pluginType][$pluginId]['base'] = 1;
		}

		if (isset($upgradeInfo['languages'])) {
		    foreach ($upgradeInfo['languages'] as $code => $pack) {
			if ($pack['relation'] == 'older' && $pack['currentBuild']) {
			    $packages[$pluginType][$pluginId]['lang-' . $code] = 1;
			}
		    }
		}
	    }
	}

	return array(null, $packages);
    }

    /**
     * Saves the specified package meta data into the database.
     *
     * @param string $pluginType
     * @param string $pluginId
     * @param string $packageName
     * @param string $packageVersion
     * @param string $packageBuild
     * @return object GalleryStatus a status code
     */
    function updatePackageMetaData(
	$pluginType, $pluginId, $packageName, $packageVersion, $packageBuild, $locked) {

	/* Check if specified package exists in the database. */
	list ($ret, $searchResults) = GalleryCoreApi::getMapEntry('GalleryPluginPackageMap',
	    array('packageVersion', 'packageBuild'),
	    array('pluginType' => $pluginType, 'pluginId' => $pluginId,
		  'packageName' => $packageName));
	if ($ret) {
	    return $ret;
	}

	if ($searchResults->resultCount() > 1) {
	    return GalleryCoreApi::error(
		ERROR_STORAGE_FAILURE, __FILE__, __LINE__,
		"Multiple records found [$pluginType] [$pluginId] [$package]");
	}
	$existsInDatabase = $searchResults->resultCount() > 0;

	/* Add or update package data. */
	if ($existsInDatabase) {
	    $ret = GalleryCoreApi::updateMapEntry(
		'GalleryPluginPackageMap',
		array('pluginType' => $pluginType, 'pluginId' => $pluginId,
		      'packageName' => $packageName),
		array('packageVersion' => $packageVersion, 'packageBuild' => $packageBuild,
		      'locked' => $locked));
	} else {
	    $ret = GalleryCoreApi::addMapEntry(
		'GalleryPluginPackageMap',
		array('pluginType' => $pluginType, 'pluginId' => $pluginId,
		      'packageName' => $packageName, 'packageVersion' => $packageVersion,
		      'packageBuild' => $packageBuild, 'locked' => $locked));
	}
	if ($ret) {
	    return $ret;
	}

	return null;
    }

    /**
     * Checks if the plugins directory exists and creates a subdirectory for each plugin type.
     *
     * @return boolean indicates whether the plugins directory is correctly set up
     *	       string user-friendly error message
     */
    function createPluginsDirectory() {
	global $gallery;

	/* Create repository cache directory if it doesn't exist. */
	$repositoryCachePath = $gallery->getConfig('repository.cache');
	$platform =& $gallery->getPlatform();

	list ($success, $created) = GalleryUtilities::guaranteeDirExists($repositoryCachePath);
	if (!$success) {
	    return array(false, $gallery->i18n('Couldn\'t create repository cache path.'));
	}

	/* Create repository cache subdirectories. */
	foreach (array('modules', 'themes') as $cacheDir) {
	    $cacheDirectory = $repositoryCachePath . $cacheDir;
	    if (!@$platform->is_dir($cacheDirectory) && !@$platform->mkdir($cacheDirectory)) {
		return array(false, $gallery->i18n('Couldn\'t create cache subdirectory. '
			     . 'Make sure the web server has write permissions in it.'));
	    }
	}

	return array(true, '');
    }

    /**
     * Creates a list of URLs that
     *
     * @param array $pluginData array(pluginType => array(pluginId => array(packages)))
     * @return array object GalleryStatus a status code
     *		     array list of packages with corresponding URLs
     */
    function getDownloadFileList($pluginData) {
	$files = array();
	foreach ($pluginData as $pluginType => $plugin) {
	    foreach ($plugin as $pluginId => $packages) {
		list ($ret, $pluginName) = $this->_index->getPluginName($pluginType, $pluginId);
		if ($ret) {
		    return array($ret, null);
		}

		list ($ret, $descriptorUrl) =
		    $this->_index->getDescriptorUrl($pluginType, $pluginId);
		if ($ret) {
		    return array($ret, null);
		}

		$files[$pluginType][$pluginId]['name'] = $pluginName;
		$files[$pluginType][$pluginId]['files']['descriptor'] = $descriptorUrl;
		foreach ($packages as $package => $value) {
		    list ($ret, $packageUrl) =
			$this->_index->getPackageUrl($pluginType, $pluginId, $package);
		    if ($ret) {
			print($ret->getAsHtml());
			return array($ret, null);
		    }

		    $files[$pluginType][$pluginId]['files'][$package] = $packageUrl;
		}
	    }
	}

	return array(null, $files);
    }

    /**
     * Downloads a file from the repository.
     *
     * If the file is a package, it will be put in the local cache and unpacked in the plugins/
     * directory. If it is a descriptor, it will be deserialized and returned to the calling
     * function.
     *
     * @todo Split this into two separate functions, one that downloads the file, the other that
     *       returns the descriptor.  The function that downloads the file should take the
     *       descriptor so that it can verify that the file that got downloaded is the right
     *       length.
     *
     * @param string $pluginType
     * @param string $pluginId
     * @param string $packageName
     * @param string $relativePackageUrl URL of the package to download relative to repository URL
     * @return array object GalleryStatus a status code
     *		     array descriptor
     */
    function downloadAndUnpack($pluginType, $pluginId, $packageName, $relativePackageUrl) {
	global $gallery;
	$platform =& $gallery->getPlatform();
	$phpVm = $gallery->getPhpVm();

	/* Download package from the Gallery server. */
	$packageUrl =
	    $gallery->getConfig('repository.url') . $this->_source . '/' . $relativePackageUrl;

	list ($wasDownloaded, $packageContents) = $this->_utilities->downloadFile($packageUrl);
	if (!$wasDownloaded) {
	    return array(GalleryCoreApi::error(
			     ERROR_STORAGE_FAILURE, __FILE__, __LINE__,
			     "Error downloading package from '$packageUrl'."), null);
	}

	/* Make sure output directory exists. */
	$pluginOutputDir = sprintf(
	    '%s/%ss/%s/', dirname(dirname(dirname(dirname(__FILE__)))), $pluginType, $pluginId);
	if (!$platform->file_exists($pluginOutputDir)
		&& !$platform->mkdir($pluginOutputDir)) {
	    $ret = GalleryCoreApi::error(ERROR_PLATFORM_FAILURE, __FILE__, __LINE__,
					 "Couldn't create directory [$pluginOutputDir]");
	    return array($ret, null);
	}

	/* Write package to the local repository cache directory. */
	$absolutePackagePath =
	    $gallery->getConfig('repository.cache') . $this->_source . '/' . $relativePackageUrl;
	if (false === $platform->file_put_contents($absolutePackagePath, $packageContents)) {
	    return array(GalleryCoreApi::error(ERROR_PLATFORM_FAILURE, __FILE__, __LINE__,
					       "Error writing package [$absolutePackagePath]"),
			 null);
	}

	$descriptor = array();
	if (preg_match('/^.*package$/', $relativePackageUrl)) {
	    /* Unpack files from package. */
	    include($absolutePackagePath);
	    call_user_func($unpackFunction, $pluginOutputDir);
	 } else {
	    /* Unserialize descriptor. */
	    $descriptor = array('pluginId' => $pluginId, 'pluginType' => $pluginType,
				'contents' => unserialize($packageContents));
	}

	return array(null, $descriptor);
    }

    /**
     * Verify that a package will install cleanly by examining all of its paths and making sure
     * that any file operations that we intend to make will be successful.
     *
     * @param string $packageName name of the package to check
     * @param array $descriptor descriptor of the plugin the package belongs to
     * @return array of files that can't be overwritten (empty array if everything is ok)
     */
    function preVerifyPackage($packageName, $descriptor) {
	global $gallery;
	$platform =& $gallery->getPlatform();

	$errorMessages = array();

	$pluginType = $descriptor['pluginType'];
	$pluginId = $descriptor['pluginId'];
	$pluginOutputDir = sprintf(
	    '%s/%ss/%s/', dirname(dirname(dirname(dirname(__FILE__)))), $pluginType, $pluginId);

	if ($platform->file_exists($pluginOutputDir)) {
	    if (!$platform->is_writeable($pluginOutputDir) ||
		!$platform->is_dir($pluginOutputDir)) {
		return array($pluginOutputDir);
	    }
	} else {
	    return array();
	}

	foreach ($descriptor['contents']['files'] as $relativePath => $metaData) {
	    foreach ($metaData['packages'] as $descriptorPackage) {
		$gallery->guaranteeTimeLimit(10);

		if ($descriptorPackage == $packageName) {
		    $filePath = $pluginOutputDir . $relativePath;

		    if ($platform->file_exists($filePath)) {
			if (!$platform->is_writeable($filePath)) {
			    $errorMessages[$filePath] = 1;
			}
		    } else {
			$checkPath = dirname($filePath) . '/';
			while ($checkPath != $pluginOutputDir && $checkPath != '.') {
			    if ($platform->file_exists($checkPath) &&
				    (!$platform->is_writeable($checkPath) ||
				     !$platform->is_dir($checkPath))) {
				$errorMessages[$filePath] = 1;
				break;
			    }
			    $checkPath = dirname($checkPath) . '/';
			}
		    }
		}
	    }
	}

	return array_keys($errorMessages);
    }

    /**
     * Verifies the integrity of the specified packages' unpacked files.
     *
     * @param string $packageName name of the package to check
     * @param array $descriptor descriptor of the plugin the package belongs to
     * @return object GalleryStatus a status code
     */
    function verifyPackageIntegrity($packageName, $descriptor) {
	global $gallery;
	$errorMessages = array();

	$pluginType = $descriptor['pluginType'];
	$pluginId = $descriptor['pluginId'];
	$pluginOutputDir = sprintf(
	    '%s/%ss/%s/', dirname(dirname(dirname(dirname(__FILE__)))), $pluginType, $pluginId);

	$platform =& $gallery->getPlatform();
	foreach ($descriptor['contents']['files'] as $filePath => $metaData) {
	    foreach ($metaData['packages'] as $descriptorPackage) {
		if ($descriptorPackage == $packageName) {
		    $filePath = $pluginOutputDir . $filePath;

		    if (!$platform->file_exists($filePath)) {
			$errorMessage = "'$filePath' doesn't exist.";
		    }

		    if ($platform->filesize($filePath) != $metaData['bytes']) {
			$errorMessage = "Size of '$filePath' not {$metaData['bytes']}.";
		    }

		    if (false === ($contents = $platform->file_get_contents($filePath))) {
			$errorMessage = "Couldn't read '$filePath'.";
		    }

		    $checksum = strlen($metaData['hash']) == 32
			? md5($contents)
			: sprintf("%u", crc32($contents));
		    if ($checksum != $metaData['hash']) {
			$errorMessage = "Integrity check failed for '$filePath'.";
		    }

		    if (!empty($errorMessage)) {
			return GalleryCoreApi::error(ERROR_PLATFORM_FAILURE, __FILE__, __LINE__,
						    $errorMessage);
		    }
		}
	    }
	}

	return null;
    }

    /**
     * Scan one plugin and update its entries in the GalleryPluginPackageMap.
     *
     * @param $pluginType the plugin type ('module' or 'theme')
     * @param $pluginId the plugin id (eg 'albumselect' or 'cart')
     * @return object GalleryStatus a status code
     */
    function scanPlugin($pluginType, $pluginId) {
	global $gallery;

	/* Erase all data for this plugin */
	$ret = GalleryCoreApi::removeMapEntry(
	    'GalleryPluginPackageMap', array('pluginType' => $pluginType, 'pluginId' => $pluginId));
	if ($ret) {
	    return $ret;
	}

	$platform =& $gallery->getPlatform();
	$g2base = dirname(dirname(dirname(dirname(__FILE__))));
	$pluginDir = sprintf('%s/%ss/%s', $g2base, $pluginType, $pluginId);
	$manifestPath = "$pluginDir/MANIFEST";

	if (!$platform->file_exists($manifestPath)) {
	    /*
	     * We won't know the revision of this module, so ignore it.  TODO: perhaps we should
	     * fall back on the revision of the module.inc file?  But if this is a user-written or
	     * a contrib module, then it is probably not in svn which means that isn't valid
	     * anyway.  Ignoring it is probably safest.
	     */
	    return null;
	}

	list($ret, $plugin) = GalleryCoreApi::loadPlugin($pluginType, $pluginId, true);
	if ($ret) {
	    return $ret;
	}

	list ($ret, $tag) = $this->_utilities->getFirstBytesFromFile($manifestPath, 128);
	if ($ret) {
	    return $ret;
	}

	list ($ret, $revision) = $this->_utilities->extractRevision($tag);
	if ($ret) {
	    return $ret;
	}

	$locked = $platform->is_writeable($manifestPath) ? 0 : 1;
	$ret = GalleryCoreApi::addMapEntry(
	    'GalleryPluginPackageMap',
	    array('pluginType' => $pluginType,
		  'pluginId' => $pluginId,
		  'packageName' => 'base',
		  'packageVersion' => $plugin->getVersion(),
		  'packageBuild' => $revision,
		  'locked' => $locked));
	if ($ret) {
	    return $ret;
	}

	$stringsRawFile = "$pluginDir/po/strings.raw";
	if ($platform->file_exists($stringsRawFile)) {
	    list ($ret, $tag) = $this->_utilities->getFirstBytesFromFile($stringsRawFile, 128);
	    if ($ret) {
		return $ret;
	    }
	    list ($ret, $stringsRevision) = $this->_utilities->extractRevision($tag);
	    if ($ret) {
		return $ret;
	    }

	    $poFiles = $platform->glob("$pluginDir/po/*.po");
	    if ($poFiles) {
		foreach ($poFiles as $file) {
		    list ($ret, $tag) = $this->_utilities->getFirstBytesFromFile($file, 128);
		    if ($ret) {
			return $ret;
		    }

		    list ($ret, $revision) = $this->_utilities->extractRevision($tag);
		    if ($ret) {
			return $ret;
		    }
		    $ret = GalleryCoreApi::addMapEntry(
			'GalleryPluginPackageMap',
			array('pluginType' => $pluginType,
			      'pluginId' => $pluginId,
			      'packageName' => (
				  'lang-' . GalleryUtilities::getFileBase(basename($file))),
			      'packageVersion' => $stringsRevision,
			      'packageBuild' => $revision,
			      'locked' => $platform->is_writeable($file) ? 0 : 1));
		    if ($ret) {
			return $ret;
		    }
		}
	    }
	}

	return null;
    }

    /**
     * Translate the repository tag to its localized name
     *
     * @param $source string the name (released, experimental, community)
     * @return array object GalleryStatus a status code
     *               string the localized name
     * @static
     * @public
     */
    function translateRepositoryName($source) {
	list ($ret, $module) = GalleryCoreApi::loadPlugin('module', 'core');
	if ($ret) {
	    return array($ret, null);
	}

	switch($source) {
	case 'released':
	    return array(null, $module->translate('Official Release Repository'));

	case 'experimental':
	    return array(null, $module->translate('Experimental Repository'));

	case 'community':
	    return array(null, $module->translate('Community Repository'));

	default:
	    return array(null, '');
	}
    }

    /**
     * @see GalleryRepositoryIndex::existsInCache
     */
    function localIndexExists() {
	return $this->_index->existsInCache();
    }

    /**
     * @see GalleryRepositoryIndex::update
     */
    function downloadIndex() {
	return $this->_index->update();
    }

    /**
     * @see GalleryRepositoryIndex::containsPlugin
     */
    function pluginExistsInIndex($pluginType, $pluginId) {
	return $this->_index->containsPlugin($pluginType, $pluginId);
    }

    /**
     * @see GalleryRepositoryIndex::getMetaData
     */
    function getIndexMetaData() {
	return $this->_index->getMetaData();
    }

    /**
     * @see GalleryRepositoryIndex::getPackageVersionAndBuild
     */
    function getPackageVersionAndBuild($pluginType, $pluginId, $packageName) {
	return $this->_index->getPackageVersionAndBuild($pluginType, $pluginId, $packageName);
    }

    /**
     * @see GalleryRepositoryIndex::getPluginName
     */
    function getPluginName($pluginType, $pluginId) {
	return $this->_index->getPluginName($pluginType, $pluginId);
    }
}
?>

Sindbad File Manager Version 1.0, Coded By Sindbad EG ~ The Terrorists