See the License here <http://www.gnu.org/licenses/gpl-3.0.html>.
***********************************************************************/
include_once($path_to_root. "/includes/archive.inc");
+include_once($path_to_root. "/includes/remote_url.inc");
+include_once($path_to_root. "/includes/hooks.inc");
define('PKG_CACHE_PATH', $path_to_root.'/modules/_cache');
define('PUBKEY_PATH', $path_to_root);
-define('REPO_URL', "$repository/$FA_repo_version");
-/*
-$pkg_data_basedir = array(
- 'language' => '/lang/',
-// 'module' => '/',
- 'extension' => '/modules/',
-// 'plugin' => '/modules/',
- 'theme' => '/themes/');
-*/
//
-// FrontAccounting package class
+// FrontAccounting package class
//
class package extends gzip_file {
- function package($filename, $basedir=null)
+
+ function __construct($filename, $basedir=null)
{
global $path_to_root;
} else
mkdir($basedir);
}
- $this->archive($filename);
+ parent::__construct($filename);
$this->set_options(array('basedir'=> $basedir));
$this->options['type'] = "pkg";
}
$cachepath = $this->options['basedir'];
$ctrl = get_control_file("$cachepath/_init/config");
-// $targetdir = $pkg_data_basedir[$ctrl['Type']];
-// if ($targetdir)
-// $targetdir = $path_to_root.$targetdir.$ctrl['Package'];
-// else
-// $targetdir = $path_to_root;
$targetdir = $path_to_root.'/'.$ctrl['InstallPath'];
if (!is_dir($targetdir))
$dpackage->extract_files(); //install package in target directory
- $success &= $this->support('install');
+ $install = hook_invoke($ctrl['Package'], 'install_extension', $dummy);
+ $success &= $install===null || $install;
$success &= count($dpackage->error) == 0;
$this->error = array_merge($this->error, $dpackage->error);
return $success;
$cachepath = $this->options['basedir'];
$ctrl = get_control_file("$cachepath/_init/config");
-// $targetdir = $pkg_data_basedir[$ctrl['Type']];
-// if ($targetdir)
-// $targetdir = $path_to_root.$targetdir.$ctrl['Package'];
-// else
-// $targetdir = $path_to_root;
+
$targetdir = $path_to_root.'/'.$ctrl['InstallPath'];
$dpackage = new package("$cachepath/_data", $targetdir);
$success &= copy_files($flist, "$cachepath/_back", $targetdir, true);
- $success &= $this->support('uninstall');
+ if (strpos($ctrl['InstallPath'], 'modules/') === 0) { // flush module directory
+ flush_dir($targetdir, true);
+ rmdir($targetdir);
+ }
+
+ $uninstall = hook_invoke($ctrl['Package'], 'uninstall_extension', $dummy);
+ $success &= $uninstall===null || $uninstall;
return $success;
}
return true;
}
- //
- // Call special function defined in package install class
- //
- function support($name, $params = null)
- {
- $cachepath = $this->options['basedir'];
- if (file_exists("$cachepath/_init/init.php")) {
- include("$cachepath/_init/init.php");
- if (method_exists($installer, $name)) {
- set_include_path("$cachepath/_init".PATH_SEPARATOR.get_include_path());
-// $old = getcwd();
-// chdir("$cachepath/_init");
- $ret = $installer->$name($params);
-// chdir($old);
- return $ret;
- }
- }
- return true;
- }
}
//
// Changes field value read from control file (single, or multiline) into
{
// indexes used in output arrays
$sub_fields = array(
- 'MenuTabs' => array('url', 'access', 'tab_id', 'title', 'section'),
- 'MenuEntries' => array('url', 'access', 'tab_id', 'title'),
+// 'MenuTabs' => array('url', 'access', 'tab_id', 'title', 'section'),
+// 'MenuEntries' => array('url', 'access', 'tab_id', 'title'),
);
if (!isset($sub_fields[$key]))
return $value==='' ? null : $value;
$line = '';
do {
$line = rtrim($line);
- if (@ctype_space($line[0])) { // continuation of multiline property
+ if ($line && ctype_space($line[0])) { // continuation of multiline property
if (strlen(ltrim($line))) {
if ($value !== '' && !is_array($value))
$value = array($value);
if ($index !== true) {
if ($index === false) break;
if (!isset($pkg[$index])) {
- display_error(_("No key field '$index' in file '$file'"));
+ display_error(sprintf(_("No key field '%s' in file '%s'"), $index, $file));
return null;
}
$repo[$pkg[$index]] = $pkg;
$pkg = array();
$key = null; $value = '';
continue;
-// } elseif (preg_match('/([\w-]*):\s*(.*)/', $line, $m)) {
} elseif (preg_match('/([^:]*):\s*(.*)/', $line, $m)) {
$key = $m[1]; $value = $m[2];
if (!strlen($key)) {
}
}
// array elements on subsequent lines starting with white space
- $value = //(count($value) ? "\n " :'').
- implode("\n ", $value);
+ $value = implode("\n ", $value);
}
$zip ? gzwrite($file, "$key: $value\n") : fwrite($file, "$key: $value\n");
}
//
function get_pkg_or_list($type = null, $pkgname = null, $filter=array(), $outkey=null, $download=true) {
- global $path_to_root, $repository, $FA_repo_version;
+ global $path_to_root, $repo_auth;
+
+ $repo = (isset($repo_auth['scheme']) ? $repo_auth['scheme'] : 'http://')
+ .(isset($repo_auth['login']) ? $repo_auth['login'].':' : '')
+ .(isset($repo_auth['pass']) ? $repo_auth['pass'].'@' : '')
+ .(isset($repo_auth['host']) ? $repo_auth['host'].'/' : '')
+ .(isset($repo_auth['path']) ? $repo_auth['path'].'/' : '')
+ .$repo_auth['branch'];
// first download local copy of repo release file
// and check remote signature with local copy of public key
//
$loclist = PKG_CACHE_PATH.'/Release.gz';
-
- if ($type!=null && !is_array($type)) {
+ $target_dir = $download==true ? VARLIB_PATH."/" : $download;
+
+ if (isset($type) && !is_array($type)) {
$type = array($type);
}
$refresh = true;
do{
if (!file_exists($loclist)) {
- copy(REPO_URL.'/Release.gz', $loclist);
+ if (!url_copy($repo.'/Release.gz', $loclist))
+ {
+ display_error(_("Cannot download repo index file." ));
+ return null;
+ }
$refresh = false;
}
- $sig = file_get_contents(REPO_URL.'/Release.sig', 'rb');
+ $sig = url_get_contents($repo.'/Release.sig');
$data = file_get_contents($loclist);
$cert = file_get_contents(PUBKEY_PATH.'/FA.pem');
- if (!openssl_verify($data, $sig, $cert)) {
- if ($refresh)
- @unlink($loclist);
- else {
+ if (!function_exists('openssl_verify')) {
+ display_error(_("OpenSSL have to be available on your server to use extension repository system."));
+ return null;
+ }
+ if (openssl_verify($data, $sig, $cert) <= 0) {
+ if ($refresh) {
+ if (!@unlink($loclist))
+ {
+ display_error(sprintf(_("Cannot delete outdated '%s' file."), $loclist));
+ return null;
+ }
+ } else {
display_error(_('Release file in repository is invalid, or public key is outdated.'));
return null;
}
} else
$refresh = false;
+
} while($refresh);
$Release = get_control_file($loclist, 'Filename');
-
// download and check all indexes containing given package types
// then complete package list or seek for pkg
$Packages = array();
if ($type && !count(array_intersect(explode(' ', $parms['Type']), $type))) {
unset($Release[$fname]); continue; // no packages of selected type in this index
}
- if ($Release[$fname]['Version'] != $FA_repo_version) {
+ if ($Release[$fname]['Version'] != $repo_auth['branch']) {
display_warning(_('Repository version does not match application version.')); // ?
}
- $remoteindex = REPO_URL.'/'.$fname;
+ $remoteindex = $repo.'/'.$fname;
$locindex = PKG_CACHE_PATH.'/'.$fname;
$refresh = true;
do{
if (!file_exists($locindex)) {
- copy($remoteindex, $locindex);
+ if (!url_copy($remoteindex, $locindex)) {
+ display_error(sprintf(_("Cannot download '%s' file." ), $fname));
+ return null;
+ }
$refresh = false;
}
if ($parms['SHA1sum'] != sha1_file($locindex)) { // check subdir index consistency
- if ($refresh)
- @unlink($locindex);
- else {
+ if ($refresh) {
+ if (!@unlink($locindex)) {
+ display_error(sprintf(_("Cannot delete outdated '%s' file."), $locindex));
+ return null;
+ }
+ } else {
display_error(sprintf( _("Security alert: broken index file in repository '%s'. Please inform repository administrator about this issue."),
$fname));
return null;
// scan subdir list and select packages of given type
$pkglist = get_control_file($locindex, 'Package');
foreach($pkglist as $name => $pkg) {
- $pkgfullname = REPO_URL.'/'.$parms['Path']."/".$pkg['Filename'].'.pkg';
- if ($type==null || in_array($pkg['Type'], $type)) {
+ $pkgfullname = $repo.'/'.$parms['Path']."/".$pkg['Filename'].'.pkg';
+ if (!isset($type) || in_array($pkg['Type'], $type)) {
if (empty($filter))
$p = $pkg;
else {
} elseif ($pkgname == $pkg['Package']) {
//download package to temp directory
if ($download) {
- $locname = "$path_to_root/tmp/".$pkg['Filename'].'.pkg';
- copy($pkgfullname, $locname);
+ $locname = $target_dir.$pkg['Filename'].'.pkg';
+ if (!url_copy($pkgfullname, $locname)) {
+ display_error(sprintf(_("Cannot download '%s' file." ), $pkgfullname));
+ return null;
+ }
// checking sha1 hash is expensive proces, so chekc the package
// consistency just before downloading
if ($pkg['SHA1sum'] != sha1_file($locname)) {
}
}
}
-
+
return $Packages;
}
function get_package($pkgname, $type = null)
{
- $all = get_pkg_or_list($type, $pkgname);
- $pkg = array_search_value($all, $pkgname, 'Package');
+ return get_pkg_or_list($type, $pkgname);
}
/*
Returns full name of installed package, or null if package is not installed.
$list = array_search_keys($l['code'], $pkgs, 'code'); // get all packages with this code
foreach ($list as $name) {
if ($l['encoding'] == $pkgs[$name]['encoding']) { // if the same encoding
- $pkgs[$name]['version'] = $l['version']; // set installed version
+ $pkgs[$name]['version'] = @$l['version']; // set installed version
$pkgs[$name]['local_id'] = $id; // index in installed_languages
continue 2;
}
else
$pkgs[$l['package']] = array_merge($pkgs[$l['package']], $l);
}
- ksort($pkgs);
+ if ($pkgs)
+ ksort($pkgs);
return $pkgs;
}
//---------------------------------------------------------------------------------------
//
-// Return merged list of available and installed extensions in inform of local
+// Return merged list of available and installed extensions as a local
// configuration array supplemented with installed versions information.
//
-function get_extensions_list()
+function get_extensions_list($type = null)
{
- $pkgs = get_pkg_or_list('extension', null, array(
+ global $path_to_root;
+
+ if (isset($type) || !is_array($type)) {
+ $type = array($type);
+ }
+
+ $pkgs = get_pkg_or_list($type, null, array(
'Package' => 'package',
'Version' => 'available',
'Name' => 'name',
'Description' => 'Descr',
'Type' => 'type',
- 'DefaultStatus'=> 'active',
- 'MenuTabs' => 'tabs',
- 'MenuEntries' => 'entries',
- 'AccessExtensions' => 'acc_file',
+ 'DefaultStatus' => 'active',
+// 'MenuTabs' => 'tabs',
+// 'MenuEntries' => 'entries',
+ 'Encoding' => 'encoding',
+// 'AccessExtensions' => 'acc_file',
'InstallPath' => 'path'
));
+ // lookup for local extensions
+ $path = $path_to_root.'/modules/';
+ $loc = array();
+ $moddir = opendir($path);
+
+ while(false != ($fname = readdir($moddir)))
+ {
+ if(!in_array($fname, array('.','..','CVS','_cache')) && is_dir($path.$fname))
+ {
+ if (!isset($pkgs[$fname]))
+ $pkgs[$fname] = array(
+ 'package' => $fname,
+ 'name' => $fname,
+ 'version' => '',
+ 'available' => '',
+ 'type' => 'extension',
+ 'path' => 'modules/'.$fname,
+ 'active' => false
+ );
+ }
+ }
+
// add/update extensions already installed
//
- $local = get_company_extensions();
- foreach($local as $extno => $ext) {
- if ($ext['type'] == 'theme') continue;
+ $installed = get_company_extensions();
+ foreach($installed as $extno => $ext) {
+ if (!in_array($ext['type'], $type)) continue;
$ext['local_id'] = $extno;
- if (!isset($pkgs[$ext['package']]) || $ext['package'] == '')
- $pkgs[] = $ext;
- else
+// if (!isset($pkgs[$ext['package']]) || $ext['package'] == '')
+// $pkgs[] = $ext;
+// else
$pkgs[$ext['package']] = array_merge($pkgs[$ext['package']], $ext);
}
- ksort($pkgs);
+ if ($pkgs)
+ ksort($pkgs);
return $pkgs;
}
//
-// Return merged list of available and installed extensions in inform of local
+// Return merged list of available and installed extensions as a local
// configuration array supplemented with installed versions information.
//
function get_themes_list()
$local = get_company_extensions();
foreach($local as $extno => $ext) {
- if (isset($pkgs[$ext['package']])) {
+ if (isset($pkgs[@$ext['package']])) {
$ext['local_id'] = $extno;
$pkgs[$ext['package']] = array_merge($pkgs[$ext['package']], $ext);
}
}
// TODO: Add other themes from themes directory
-
- ksort($pkgs);
+ if ($pkgs)
+ ksort($pkgs);
+ return $pkgs;
+}
+//---------------------------------------------------------------------------------------
+//
+// Return merged list of available and installed COAs as a local
+// configuration array supplemented with installed versions information.
+//
+function get_charts_list()
+{
+ $pkgs = get_pkg_or_list('chart', null, array(
+ 'Package' => 'package',
+ 'Version' => 'available',
+ 'Name' => 'name',
+ 'Description' => 'Descr',
+ 'Type' => 'type',
+ 'InstallPath' => 'path',
+ 'Encoding' => 'encoding',
+ 'SqlScript' => 'sql'
+ ));
+
+ // add/update default charts
+ //
+ $local = get_company_extensions();
+
+ foreach($local as $extno => $ext) {
+ if ($ext['type'] != 'chart') continue;
+ $ext['local_id'] = $extno;
+ if (!isset($pkgs[$ext['package']]) || $ext['package'] == '')
+ $pkgs[] = $ext;
+ else
+ $pkgs[$ext['package']] = array_merge($pkgs[$ext['package']], $ext);
+ }
+ if ($pkgs)
+ ksort($pkgs);
return $pkgs;
}
//---------------------------------------------------------------------------------------------
if ($i === null)
$i = count($installed_languages);
else { // remove another already installed package for this language
- $old_pkg = $installed_languages[$i]['package'];
+ $old_pkg = @$installed_languages[$i]['package'];
if ($old_pkg && ($pkg['Package'] != $old_pkg))
uninstall_package($old_pkg);
}
- $package = new package("$path_to_root/tmp/".$pkg['Filename'].'.pkg');
+ $package = new package(VARLIB_PATH."/".$pkg['Filename'].'.pkg');
if ($package->install()) {
$lang = array(
'name' => $pkg['Name'],
$lang['rtl'] = true;
$installed_languages[$i] = $lang;
write_lang($installed_languages);
- unlink("$path_to_root/tmp/".$pkg['Filename'].'.pkg');
+ unlink(VARLIB_PATH."/".$pkg['Filename'].'.pkg');
$Ajax->activate('lang_tbl');
+ } else {
+ display_error(implode('<br>', $package->error));
+ return false;
}
-
+ } else {
+ display_error(sprintf(_("Package '%s' not found."), $pkg_name));
+ return false;
}
-
+ return true;
}
//---------------------------------------------------------------------------------------------
// Install/update extension or theme package from repository
//
function install_extension($pkg_name)
{
- global $path_to_root, $next_extension_id, $Ajax;
+ global $path_to_root, $installed_extensions, $next_extension_id, $Ajax, $db_connections;
- $pkg = get_pkg_or_list(array('extension', 'theme'), $pkg_name);
+ $pkg = get_pkg_or_list(array('extension', 'theme', 'chart'), $pkg_name);
if ($pkg) {
- $package = new package("$path_to_root/tmp/".$pkg['Filename'].'.pkg');
+ $package = new package(VARLIB_PATH."/".$pkg['Filename'].'.pkg');
$local_exts = get_company_extensions();
if ($package->install()) {
$ext_id = array_search_key($pkg['Package'], $local_exts, 'package');
if ($ext_id === null)
$ext_id = $next_extension_id++;
+ else { // remove another already installed package for this language
+ $old_pkg = $installed_extensions[$ext_id]['package'];
+ if ($old_pkg)
+ uninstall_package($old_pkg);
+ }
$ext = array(
'name' => $pkg['Name'],
'package' => $pkg['Package'],
'version' => $pkg['Version'],
'type' => $pkg['Type'],
- 'active' => true,
+ 'active' => @$pkg['DefaultStatus'] == 'active' ? true : false,
'path' => $pkg['InstallPath'],
-// 'tabs' => $pkg['MenuTabs'],
-// 'entries' => $pkg['MenuEntries'],
-// 'acc_file' => @$pkg['AccessExtensions'],
);
- if (isset($pkg['MenuTabs']))
- $ext['tabs'] = $pkg['MenuTabs'];
- if (isset($pkg['MenuEntries']))
- $ext['entries'] = $pkg['MenuEntries'];
- if (isset($pkg['AccessExtensions']))
- $ext['acc_file'] = $pkg['AccessExtensions'];
+ if (isset($pkg['SqlScript']))
+ $ext['sql'] = $pkg['SqlScript'];
+
$local_exts[$ext_id] = $ext;
- update_extensions($local_exts);
- unlink("$path_to_root/tmp/".$pkg['Filename'].'.pkg');
+ $ret = update_extensions($local_exts);
+
+ if (($ext['active'] == true) && file_exists($path_to_root.'/'.$ext['path'].'/hooks.php'))
+ {
+ // we need to include the new hooks file to activate extension
+ include_once($path_to_root.'/'.$ext['path'].'/hooks.php');
+ foreach($db_connections as $comp => $db)
+ activate_hooks($ext['package'], $comp);
+ }
+
+ unlink(VARLIB_PATH."/".$pkg['Filename'].'.pkg');
$Ajax->activate('ext_tbl');
+ return $ret;
} else {
display_error(implode('<br>', $package->error));
+ return false;
}
+ } else {
+ display_error(sprintf(_("Package '%s' not found."), $pkg_name));
+ return false;
}
+ return true;
}
/*
Returns true if newer package version is available
return get_pkg_or_list($type, $pkg, $filter, null, false);
}
-?>
\ No newline at end of file
+/*
+ Check basic extension source compatibility.
+*/
+function check_src_ext_version($ext_v)
+{
+ global $src_version;
+ if ($ext_v != '-') {
+ $compat_levels = 2; // current policy is keeping compatibility on major version level.
+ $app = explode('.', substr($src_version, 0, strspn($src_version, "0123456789.")));
+ $pkg = explode('.', substr($ext_v, 0, strspn($ext_v, "0123456789.")));
+
+ for ($i=0; $i < min($compat_levels, count($app)); $i++)
+ if ($pkg[$i] < $app[$i])
+ return false;
+ }
+ return true;
+}