mirror of
https://github.com/kleeja-official/kleeja.git
synced 2025-12-14 20:19:43 +01:00
501 lines
18 KiB
PHP
Executable File
501 lines
18 KiB
PHP
Executable File
<?php
|
|
/**
|
|
*
|
|
* @package adm
|
|
* @copyright (c) 2007 Kleeja.net
|
|
* @license ./docs/license.txt
|
|
*
|
|
*/
|
|
|
|
// not for directly open
|
|
if (! defined('IN_ADMIN'))
|
|
{
|
|
exit();
|
|
}
|
|
|
|
//set _get form key
|
|
$GET_FORM_KEY = kleeja_add_form_key_get('adm_styles_get');
|
|
$H_FORM_KEYS = kleeja_add_form_key('adm_styles');
|
|
|
|
|
|
$action = ADMIN_PATH . '?cp=' . basename(__file__, '.php');
|
|
$style_select_link = $action . '&case=select&' . $GET_FORM_KEY . '&style=';
|
|
$style_download_link = $action . '&case=download&' . $GET_FORM_KEY . '&style=';
|
|
$style_delete_link = $action . '&case=dfolder&' . $GET_FORM_KEY . '&style=';
|
|
$style_upload_link = $action . '&case=upload';
|
|
|
|
$stylee = 'admin_styles';
|
|
$case = g('case', 'str', 'local');
|
|
|
|
//check _GET Csrf token
|
|
if (! empty($case) && in_array($case, ['select', 'download', 'dfolder']))
|
|
{
|
|
if (! kleeja_check_form_key_get('adm_styles_get'))
|
|
{
|
|
header('HTTP/1.0 401 Unauthorized');
|
|
kleeja_admin_err($lang['INVALID_GET_KEY'], $action);
|
|
}
|
|
}
|
|
|
|
//check _POST Csrf token
|
|
if (ip('newstyle'))
|
|
{
|
|
if (! kleeja_check_form_key('adm_styles'))
|
|
{
|
|
header('HTTP/1.0 401 Unauthorized');
|
|
kleeja_admin_err($lang['INVALID_FORM_KEY'], true, $lang['ERROR'], true, $action);
|
|
}
|
|
|
|
$case = 'upload';
|
|
}
|
|
|
|
switch ($case):
|
|
default:
|
|
case 'local':
|
|
case 'store':
|
|
|
|
//get styles
|
|
$available_styles = [];
|
|
|
|
if ($dh = @opendir(PATH . 'styles'))
|
|
{
|
|
while (false !== ($folder_name = readdir($dh)))
|
|
{
|
|
if (is_dir(PATH . 'styles/' . $folder_name) && preg_match('/[a-z0-9_.]{3,}/', $folder_name))
|
|
{
|
|
//info
|
|
$style_info_arr = [
|
|
'name' => $folder_name,
|
|
'desc' => '',
|
|
'copyright' => '',
|
|
'version' => ''
|
|
];
|
|
|
|
if (($style_info = kleeja_style_info($folder_name)) != false)
|
|
{
|
|
foreach (['name', 'desc', 'copyright', 'version'] as $InfoKey)
|
|
{
|
|
if (array_key_exists($InfoKey, $style_info))
|
|
{
|
|
if (is_array($style_info[$InfoKey]))
|
|
{
|
|
$style_info_arr[$InfoKey] = ! empty($style_info[$InfoKey][$config['language']])
|
|
? htmlspecialchars($style_info[$InfoKey][$config['language']])
|
|
: htmlspecialchars($style_info[$InfoKey]['en']);
|
|
}
|
|
else
|
|
{
|
|
$style_info_arr[$InfoKey] = htmlspecialchars($style_info[$InfoKey]);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
$available_styles[$folder_name] = [
|
|
'name' => $folder_name,
|
|
'is_default' => $config['style'] == $folder_name ? true : false,
|
|
'link_mk_default' => basename(ADMIN_PATH) . '?cp=' . basename(__file__, '.php') . '&style_choose=' . $folder_name,
|
|
'icon' => file_exists(PATH . 'styles/' . $folder_name . '/screenshot.png')
|
|
? PATH . 'styles/' . $folder_name . '/screenshot.png'
|
|
: $STYLE_PATH_ADMIN . 'images/style.png',
|
|
'info' => $style_info_arr
|
|
];
|
|
}
|
|
}
|
|
|
|
@closedir($dh);
|
|
}
|
|
|
|
//do not proceed if not store case
|
|
if (! in_array($case, ['store', 'check']))
|
|
{
|
|
break;
|
|
}
|
|
|
|
// plugins avilable in kleeja remote catalog
|
|
if (! ($store_catalog = $cache->get('store_catalog')))
|
|
{
|
|
$store_link = 'https://raw.githubusercontent.com/kleeja-official/store-catalog/master/catalog.json';
|
|
|
|
$store_catalog = FetchFile::make($store_link)->get();
|
|
$store_catalog = json_decode($store_catalog, true);
|
|
|
|
if (json_last_error() == JSON_ERROR_NONE)
|
|
{
|
|
$cache->save('store_catalog', $store_catalog);
|
|
}
|
|
}
|
|
|
|
// make an array for all styles in kleeja remote catalog
|
|
// that are not exsisted locally.
|
|
$store_styles = [];
|
|
$available_styles_names = array_column($available_styles, 'name');
|
|
|
|
foreach ($store_catalog as $style_info)
|
|
{
|
|
if ($style_info['type'] != 'style')
|
|
{
|
|
continue;
|
|
}
|
|
|
|
if ($case == 'store' && ! empty($available_styles[$style_info['name']]))
|
|
{
|
|
continue;
|
|
}
|
|
|
|
// is there a new version of this in the store
|
|
elseif (
|
|
$case == 'check' && (! empty($available_styles[$style_info['name']]['info']['version']) &&
|
|
version_compare(
|
|
strtolower($available_styles[$style_info['name']]['info']['version']),
|
|
strtolower($style_info['file']['version']),
|
|
'>='
|
|
) || empty($available_styles[$style_info['name']]['info']['version']))
|
|
) {
|
|
continue;
|
|
}
|
|
|
|
$store_styles[$style_info['name']] = [
|
|
'name' => $style_info['name'],
|
|
'developer' => $style_info['developer'],
|
|
'version' => $style_info['file']['version'],
|
|
'title' => ! empty($style_info['title'][$config['language']]) ? $style_info['title'][$config['language']] : $style_info['title']['en'],
|
|
'website' => $style_info['website'],
|
|
'current_version' => ! empty($available_styles[$style_info['name']]) ? strtolower($available_styles[$style_info['name']]['info']['version']) : '',
|
|
'kj_min_version' => $style_info['kleeja_version']['min'],
|
|
'kj_max_version' => $style_info['kleeja_version']['max'],
|
|
'kj_version_cmtp' => sprintf($lang['KLJ_VER_NO_PLUGIN'], $style_info['kleeja_version']['min'], $style_info['kleeja_version']['max']),
|
|
'icon' => $style_info['icon'],
|
|
'NotCompatible' => version_compare(strtolower($style_info['kleeja_version']['min']), KLEEJA_VERSION, '<=')
|
|
&& version_compare(strtolower($style_info['kleeja_version']['max']), KLEEJA_VERSION, '>=')
|
|
? false : true,
|
|
];
|
|
}
|
|
|
|
$store_styles_count = sizeof($store_styles);
|
|
|
|
break;
|
|
|
|
case 'select':
|
|
|
|
$style_name = preg_replace('/[^a-z0-9_\-\.]/i', '', g('style'));
|
|
|
|
//if empty, let's ignore it
|
|
if (empty($style_name))
|
|
{
|
|
redirect(basename(ADMIN_PATH) . '?cp=' . basename(__file__, '.php'));
|
|
}
|
|
|
|
//
|
|
//check if this style depend on other style and
|
|
//check kleeja version that required by this style
|
|
//
|
|
if (($style_info = kleeja_style_info($style_name)) != false)
|
|
{
|
|
if (isset($style_info['depend_on']) && ! is_dir(PATH . 'styles/' . $style_info['depend_on']))
|
|
{
|
|
kleeja_admin_err(sprintf($lang['DEPEND_ON_NO_STYLE_ERR'], $style_info['depend_on']));
|
|
}
|
|
|
|
if (isset($style_info['kleeja_version']) && version_compare(strtolower($style_info['kleeja_version']), strtolower(KLEEJA_VERSION), '>'))
|
|
{
|
|
kleeja_admin_err(sprintf($lang['KLJ_VER_NO_STYLE_ERR'], $style_info['kleeja_version']));
|
|
}
|
|
|
|
//is this style require some plugins to be installed
|
|
if (isset($style_info['plugins_required']))
|
|
{
|
|
$plugins_required = explode(',', $style_info['plugins_required']);
|
|
$plugins_required = array_map('trim', $plugins_required);
|
|
|
|
$query = [
|
|
'SELECT' => 'plg_name, plg_disabled',
|
|
'FROM' => "{$dbprefix}plugins",
|
|
];
|
|
|
|
$result = $SQL->build($query);
|
|
|
|
if ($SQL->num_rows($result) != 0)
|
|
{
|
|
$plugins_required = array_flip($plugins_required);
|
|
while ($row = $SQL->fetch_array($result))
|
|
{
|
|
if (in_array($row['plg_name'], $plugins_required) and $row['plg_disabled'] != 1)
|
|
{
|
|
unset($plugins_required[$row['plg_name']]);
|
|
}
|
|
}
|
|
}
|
|
|
|
$SQL->freeresult($result);
|
|
|
|
$plugins_required = array_flip($plugins_required);
|
|
|
|
if (sizeof($plugins_required))
|
|
{
|
|
kleeja_admin_err(sprintf($lang['PLUGINS_REQ_NO_STYLE_ERR'], implode(', ', $plugins_required)));
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
//make it as default
|
|
update_config('style', $style_name);
|
|
update_config('style_depend_on', isset($style_info['depend_on']) ? $style_info['depend_on'] : '');
|
|
|
|
//delete all cache to get new style
|
|
delete_cache('', true);
|
|
|
|
//show msg
|
|
kleeja_admin_info(sprintf($lang['STYLE_NOW_IS_DEFAULT'], $style_name), $action);
|
|
|
|
break;
|
|
|
|
case 'upload':
|
|
|
|
if (intval($userinfo['founder']) !== 1)
|
|
{
|
|
$ERRORS[] = $lang['HV_NOT_PRVLG_ACCESS'];
|
|
}
|
|
|
|
|
|
$ERRORS = [];
|
|
|
|
//is uploaded?
|
|
if (empty($_FILES['style_file']['tmp_name']))
|
|
{
|
|
$ERRORS[] = $lang['CHOSE_F'];
|
|
}
|
|
|
|
|
|
//extract it to plugins folder
|
|
if (! sizeof($ERRORS))
|
|
{
|
|
if (class_exists('ZipArchive'))
|
|
{
|
|
$zip = new ZipArchive;
|
|
|
|
if ($zip->open($_FILES['style_file']['tmp_name']) === true)
|
|
{
|
|
if (! $zip->extractTo(PATH . 'styles'))
|
|
{
|
|
$ERRORS[] = sprintf($lang['EXTRACT_ZIP_FAILED'], 'styles');
|
|
}
|
|
$zip->close();
|
|
}
|
|
else
|
|
{
|
|
$ERRORS[] = sprintf($lang['EXTRACT_ZIP_FAILED'], 'styles');
|
|
}
|
|
}
|
|
else
|
|
{
|
|
$ERRORS[] = $lang['NO_ZIP_ARCHIVE'];
|
|
}
|
|
}
|
|
|
|
if (! empty($_FILES['style_file']['tmp_name']))
|
|
{
|
|
@unlink($_FILES['style_file']['tmp_name']);
|
|
}
|
|
|
|
|
|
if (! sizeof($ERRORS))
|
|
{
|
|
kleeja_admin_info($lang['NO_PROBLEM_AFTER_ZIP'], true, '', true, $action);
|
|
}
|
|
else
|
|
{
|
|
kleeja_admin_err('- ' . implode('<br>- ', $ERRORS), $action);
|
|
}
|
|
|
|
break;
|
|
|
|
case 'dfolder':
|
|
|
|
$style_name = preg_replace('/[^a-z0-9_\-\.]/i', '', g('style'));
|
|
|
|
//can not delete default style
|
|
if ($config['style'] === $style_name)
|
|
{
|
|
kleeja_admin_info($lang['CANT_DEL_DEFAULT_STYLE'], true, '', true, $action);
|
|
}
|
|
|
|
$style_folder_path = PATH . 'styles/' . $style_name;
|
|
|
|
if (file_exists($style_folder_path))
|
|
{
|
|
if (! is_writable($style_folder_path))
|
|
{
|
|
@chmod($style_folder_path, K_DIR_CHMOD);
|
|
}
|
|
|
|
kleeja_unlink($style_folder_path);
|
|
}
|
|
|
|
|
|
if (! file_exists($style_folder_path))
|
|
{
|
|
kleeja_admin_info(sprintf($lang['ITEM_DELETED'], $style_name), $action);
|
|
}
|
|
|
|
kleeja_admin_err($lang['ERROR_TRY_AGAIN'], $action);
|
|
|
|
break;
|
|
|
|
|
|
case 'download':
|
|
|
|
if (intval($userinfo['founder']) !== 1)
|
|
{
|
|
header('HTTP/1.0 401 Unauthorized');
|
|
kleeja_admin_err($lang['HV_NOT_PRVLG_ACCESS']);
|
|
}
|
|
|
|
$style_name = g('style');
|
|
|
|
$is_update = false;
|
|
|
|
|
|
if (! is_writable(PATH . 'styles'))
|
|
{
|
|
@chmod(PATH . 'styles', K_DIR_CHMOD);
|
|
}
|
|
|
|
//if style exists before, then trigger update action. rename folder to rollback in case of failure
|
|
if (file_exists(PATH . 'styles/' . $style_name))
|
|
{
|
|
$is_update = true;
|
|
|
|
if (! rename(
|
|
PATH . 'styles/' . $style_name,
|
|
PATH . 'styles/' . $style_name . '_backup'
|
|
))
|
|
{
|
|
if (file_exists(PATH . 'styles/' . $style_name))
|
|
{
|
|
kleeja_unlink(PATH . 'styles/' . $style_name);
|
|
}
|
|
}
|
|
}
|
|
|
|
// plugins avilable in kleeja store
|
|
$store_link = 'https://raw.githubusercontent.com/kleeja-official/store-catalog/master/catalog.json';
|
|
|
|
$catalog_styles = FetchFile::make($store_link)->get();
|
|
|
|
if ($catalog_styles)
|
|
{
|
|
$catalog_styles = json_decode($catalog_styles, true);
|
|
|
|
$store_styles = [];
|
|
|
|
// make an arry for all plugins in kleeja store that not included in our server
|
|
foreach ($catalog_styles as $style_info)
|
|
{
|
|
if ($style_info['type'] != 'style')
|
|
{
|
|
continue;
|
|
}
|
|
|
|
$store_styles[$style_info['name']] = [
|
|
'name' => $style_info['name'] ,
|
|
'plg_version' => $style_info['file']['version'] ,
|
|
'url' => $style_info['file']['url'] ,
|
|
'kj_min_version' => $style_info['kleeja_version']['min'] ,
|
|
'kj_max_version' => $style_info['kleeja_version']['max'] ,
|
|
];
|
|
}
|
|
|
|
// this style is hosted in our store
|
|
if (isset($store_styles[$style_name]))
|
|
{
|
|
// check if the version of the plugin is compatible with our kleeja version or not
|
|
if (
|
|
version_compare(strtolower($store_styles[$style_name]['kj_min_version']), KLEEJA_VERSION, '<=')
|
|
&& version_compare(strtolower($store_styles[$style_name]['kj_max_version']), KLEEJA_VERSION, '>=')
|
|
) {
|
|
$style_name_link = $store_styles[$style_name]['url'];
|
|
|
|
$style_archive = FetchFile::make($style_name_link)
|
|
->setDestinationPath(PATH . 'cache/' . $style_name . '.zip')
|
|
->isBinaryFile(true)
|
|
->get();
|
|
|
|
if ($style_archive)
|
|
{
|
|
if (file_exists(PATH . 'cache/' . $style_name . '.zip'))
|
|
{
|
|
$zip = new ZipArchive();
|
|
|
|
if ($zip->open(PATH . 'cache/' . $style_name . '.zip') === true)
|
|
{
|
|
if ($zip->extractTo(PATH . 'styles'))
|
|
{
|
|
// we dont need the zip file anymore
|
|
kleeja_unlink(PATH . 'cache/' . $style_name . '.zip');
|
|
|
|
// uploaded style's archive has different name, so we change it
|
|
rename(
|
|
PATH . 'styles/' . trim($zip->getNameIndex(0), '/'),
|
|
PATH . 'styles/' . $style_name
|
|
);
|
|
|
|
$zip->close();
|
|
|
|
// download or update msg
|
|
$adminAjaxContent = '1:::' . sprintf($lang[$is_update ? 'ITEM_UPDATED' : 'ITEM_DOWNLOADED'], $style_name);
|
|
|
|
//in case of update, delete back up version
|
|
if (file_exists(PATH . 'styles/' . $style_name . '_backup'))
|
|
{
|
|
kleeja_unlink(PATH . 'styles/' . $style_name . '_backup');
|
|
}
|
|
}
|
|
else
|
|
{
|
|
$adminAjaxContent = '1003:::' . sprintf($lang['EXTRACT_ZIP_FAILED'], PATH . 'styles');
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
$adminAjaxContent = '1004:::' . $lang['DOWNLOADED_FILE_NOT_FOUND'];
|
|
}
|
|
}
|
|
else
|
|
{
|
|
$adminAjaxContent = '1005:::' . $lang['STORE_SERVER_ERROR'];
|
|
}
|
|
}
|
|
else
|
|
{
|
|
$adminAjaxContent = '1006:::' . $lang['PACKAGE_N_CMPT_KLJ'];
|
|
}
|
|
}
|
|
else
|
|
{
|
|
$adminAjaxContent = '1007:::' . sprintf($lang['PACKAGE_REMOTE_FILE_MISSING'], $style_name);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
$adminAjaxContent = '1008:::' . $lang['STORE_SERVER_ERROR'];
|
|
}
|
|
|
|
|
|
//in case of update failure, rollback to current plugin version
|
|
if (strpos($adminAjaxContent, '1:::') === false)
|
|
{
|
|
if (file_exists(PATH . 'styles/' . $style_name . '_backup'))
|
|
{
|
|
rename(
|
|
PATH . 'styles/' . $style_name . '_backup',
|
|
PATH . 'styles/' . $style_name
|
|
);
|
|
}
|
|
}
|
|
|
|
break;
|
|
endswitch;
|