Initial commit: Backup der Webseiten

- zoesch.de
- blitzkiste.net
- gruene-hassberge (norbert.zoesch.de)

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
This commit is contained in:
Felix Zösch
2025-12-13 01:17:15 +01:00
commit 07c290a453
4607 changed files with 1202735 additions and 0 deletions

View File

@@ -0,0 +1,172 @@
<?php
// +-----------------------------------------------------------------------+
// | Piwigo - a PHP based photo gallery |
// +-----------------------------------------------------------------------+
// | Copyright(C) 2008-2016 Piwigo Team http://piwigo.org |
// | Copyright(C) 2003-2008 PhpWebGallery Team http://phpwebgallery.net |
// | Copyright(C) 2002-2003 Pierrick LE GALL http://le-gall.net/pierrick |
// +-----------------------------------------------------------------------+
// | 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 |
// | |
// | 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, |
// | USA. |
// +-----------------------------------------------------------------------+
add_event_handler('tabsheet_before_select', 'add_core_tabs', 0);
function add_core_tabs($sheets, $tab_id)
{
switch($tab_id)
{
case 'admin_home':
$sheets[''] = array('caption' => l10n('Administration Home'), 'url' => 'admin.php');
break;
case 'tags':
global $my_base_url;
$sheets[''] = array('caption' => '<span class="icon-tags"></span>'.l10n('Tags'), 'url' => $my_base_url.'tags');
break;
case 'album':
global $admin_album_base_url;
$sheets['properties'] = array('caption' => '<span class="icon-pencil"></span>'.l10n('Properties'), 'url' => $admin_album_base_url.'-properties');
$sheets['sort_order'] = array('caption' => '<span class="icon-shuffle"></span>'.l10n('Manage photo ranks'), 'url' => $admin_album_base_url.'-sort_order');
$sheets['permissions'] = array('caption' => '<span class="icon-lock"></span>'.l10n('Permissions'), 'url' => $admin_album_base_url.'-permissions');
$sheets['notification'] = array('caption' => '<span class="icon-mail-alt"></span>'.l10n('Notification'), 'url' => $admin_album_base_url.'-notification');
break;
case 'albums':
global $my_base_url;
$sheets['list'] = array('caption' => '<span class="icon-menu"></span>'.l10n('List'), 'url' => $my_base_url.'cat_list');
$sheets['move'] = array('caption' => '<span class="icon-move"></span>'.l10n('Move'), 'url' => $my_base_url.'cat_move');
$sheets['permalinks'] = array('caption' => '<span class="icon-link"></span>'.l10n('Permalinks'), 'url' => $my_base_url.'permalinks');
break;
case 'batch_manager':
global $manager_link;
$sheets['global'] = array('caption' => '<span class="icon-th"></span>'.l10n('global mode'), 'url' => $manager_link.'global');
$sheets['unit'] = array('caption' => '<span class="icon-th-list"></span>'.l10n('unit mode'), 'url' => $manager_link.'unit');
break;
case 'cat_options':
global $link_start, $conf;
$sheets['status'] = array('caption' => '<span class="icon-lock"></span>'.l10n('Public / Private'), 'url' => $link_start.'cat_options&amp;section=status');
$sheets['visible'] = array('caption' => '<span class="icon-block"></span>'.l10n('Lock'), 'url' => $link_start.'cat_options&amp;section=visible');
if ($conf['activate_comments'])
$sheets['comments'] = array('caption' => '<span class="icon-chat"></span>'.l10n('Comments'), 'url' => $link_start.'cat_options&amp;section=comments');
if ($conf['allow_random_representative'])
$sheets['representative'] = array('caption' => l10n('Representative'), 'url' => $link_start.'cat_options&amp;section=representative');
break;
case 'comments':
global $my_base_url;
$sheets[''] = array('caption' => l10n('User comments'), 'url' => $my_base_url.'comments');
break;
case 'users':
global $my_base_url;
$sheets[''] = array('caption' => '<span class="icon-users"> </span>'.l10n('User list'), 'url' => $my_base_url.'user_list');
break;
case 'groups':
global $my_base_url;
$sheets[''] = array('caption' => '<span class="icon-group"> </span>'.l10n('Groups'), 'url' => $my_base_url.'group_list');
break;
case 'configuration':
global $conf_link;
$sheets['main'] = array('caption' => l10n('General'), 'url' => $conf_link.'main');
$sheets['sizes'] = array('caption' => l10n('Photo sizes'), 'url' => $conf_link.'sizes');
$sheets['watermark'] = array('caption' => l10n('Watermark'), 'url' => $conf_link.'watermark');
$sheets['display'] = array('caption' => l10n('Display'), 'url' => $conf_link.'display');
$sheets['comments'] = array('caption' => l10n('Comments'), 'url' => $conf_link.'comments');
// $sheets['default'] = array('caption' => l10n('Guest Settings'), 'url' => $conf_link.'default');
break;
case 'help':
global $help_link;
$sheets['add_photos'] = array('caption' => l10n('Add Photos'), 'url' => $help_link.'add_photos');
$sheets['permissions'] = array('caption' => l10n('Permissions'), 'url' => $help_link.'permissions');
$sheets['groups'] = array('caption' => l10n('Groups'), 'url' => $help_link.'groups');
$sheets['virtual_links'] = array('caption' => l10n('Virtual Links'), 'url' => $help_link.'virtual_links');
$sheets['misc'] = array('caption' => l10n('Miscellaneous'), 'url' => $help_link.'misc');
break;
case 'history':
global $link_start;
$sheets['stats'] = array('caption' => '<span class="icon-signal"></span>'.l10n('Statistics'), 'url' => $link_start.'stats');
$sheets['history'] = array('caption' => '<span class="icon-search"></span>'.l10n('Search'), 'url' => $link_start.'history');
break;
case 'languages':
global $my_base_url;
$sheets['installed'] = array('caption' => '<span class="icon-language"></span>'.l10n('Installed Languages'), 'url' => $my_base_url.'&amp;tab=installed');
$sheets['update'] = array('caption' => '<span class="icon-arrows-cw"></span>'.l10n('Check for updates'), 'url' => $my_base_url.'&amp;tab=update');
$sheets['new'] = array('caption' => '<span class="icon-plus-circled"></span>'.l10n('Add New Language'), 'url' => $my_base_url.'&amp;tab=new');
break;
case 'menus':
global $my_base_url;
$sheets[''] = array('caption' => '<span class="icon-menu"></span>'.l10n('Menu Management'), 'url' => $my_base_url.'menubar');
break;
case 'nbm':
global $base_url;
$sheets['param'] = array('caption' => l10n('Parameter'), 'url' => $base_url.'?page=notification_by_mail&amp;mode=param');
$sheets['subscribe'] = array('caption' => l10n('Subscribe'), 'url' => $base_url.'?page=notification_by_mail&amp;mode=subscribe');
$sheets['send'] = array('caption' => l10n('Send'), 'url' => $base_url.'?page=notification_by_mail&amp;mode=send');
break;
case 'photo':
global $admin_photo_base_url;
$sheets['properties'] = array('caption' => l10n('Properties'), 'url' => $admin_photo_base_url.'-properties');
$sheets['coi'] = array('caption' => '<span class="icon-crop"></span>'.l10n('Center of interest'), 'url' => $admin_photo_base_url.'-coi');
break;
case 'photos_add':
global $conf;
$sheets['direct'] = array('caption' => '<span class="icon-upload"></span>'.l10n('Web Form'), 'url' => PHOTOS_ADD_BASE_URL.'&amp;section=direct');
$sheets['applications'] = array('caption' => '<span class="icon-network"></span>'.l10n('Applications'), 'url' => PHOTOS_ADD_BASE_URL.'&amp;section=applications');
if ($conf['enable_synchronization'])
$sheets['ftp'] = array('caption' => '<span class="icon-exchange"></span>'.l10n('FTP + Synchronization'), 'url' => PHOTOS_ADD_BASE_URL.'&amp;section=ftp');
break;
case 'plugins':
global $my_base_url;
$sheets['installed'] = array('caption' => '<span class="icon-equalizer"></span>'.l10n('Plugin list'), 'url' => $my_base_url.'&amp;tab=installed');
$sheets['update'] = array('caption' => '<span class="icon-arrows-cw"></span>'.l10n('Check for updates'), 'url' => $my_base_url.'&amp;tab=update');
$sheets['new'] = array('caption' => '<span class="icon-plus-circled"></span>'.l10n('Other plugins'), 'url' => $my_base_url.'&amp;tab=new');
break;
case 'rating':
$sheets['rating'] = array('caption' => l10n('Photos'), 'url' => get_root_url().'admin.php?page=rating');
$sheets['rating_user'] = array('caption' => l10n('Users'), 'url' => get_root_url().'admin.php?page=rating_user');
break;
case 'themes':
global $my_base_url;
$sheets['installed'] = array('caption' => '<span class="icon-brush"></span>'.l10n('Installed Themes'), 'url' => $my_base_url.'&amp;tab=installed');
$sheets['update'] = array('caption' => '<span class="icon-arrows-cw"></span>'.l10n('Check for updates'), 'url' => $my_base_url.'&amp;tab=update');
$sheets['new'] = array('caption' => '<span class="icon-plus-circled"></span>'.l10n('Add New Theme'), 'url' => $my_base_url.'&amp;tab=new');
break;
case 'updates':
global $my_base_url;
$sheets['pwg'] = array('caption' => l10n('Piwigo Update'), 'url' => $my_base_url);
$sheets['ext'] = array('caption' => l10n('Extensions Update'), 'url' => $my_base_url.'&amp;tab=ext');
break;
}
return $sheets;
}
?>

View File

@@ -0,0 +1,33 @@
<?php
// +-----------------------------------------------------------------------+
// | Piwigo - a PHP based photo gallery |
// +-----------------------------------------------------------------------+
// | Copyright(C) 2008-2016 Piwigo Team http://piwigo.org |
// | Copyright(C) 2003-2008 PhpWebGallery Team http://phpwebgallery.net |
// | Copyright(C) 2002-2003 Pierrick LE GALL http://le-gall.net/pierrick |
// +-----------------------------------------------------------------------+
// | 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 |
// | |
// | 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, |
// | USA. |
// +-----------------------------------------------------------------------+
include_once(PHPWG_ROOT_PATH.'admin/include/tabsheet.class.php');
$my_base_url = get_root_url().'admin.php?page=';
$tabsheet = new tabsheet();
$tabsheet->set_id('albums');
$tabsheet->select($page['tab']);
$tabsheet->assign();
?>

View File

@@ -0,0 +1,258 @@
<?php
// +-----------------------------------------------------------------------+
// | Piwigo - a PHP based photo gallery |
// +-----------------------------------------------------------------------+
// | Copyright(C) 2008-2016 Piwigo Team http://piwigo.org |
// | Copyright(C) 2003-2008 PhpWebGallery Team http://phpwebgallery.net |
// | Copyright(C) 2002-2003 Pierrick LE GALL http://le-gall.net/pierrick |
// +-----------------------------------------------------------------------+
// | 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 |
// | |
// | 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, |
// | USA. |
// +-----------------------------------------------------------------------+
class c13y_internal
{
function __construct()
{
add_event_handler('list_check_integrity', array(&$this, 'c13y_version'));
add_event_handler('list_check_integrity', array(&$this, 'c13y_exif'));
add_event_handler('list_check_integrity', array(&$this, 'c13y_user'));
}
/**
* Check version
*
* @param c13y object
* @return void
*/
function c13y_version($c13y)
{
global $conf;
$check_list = array();
$check_list[] = array(
'type' => 'PHP',
'current' => phpversion(),
'required' => REQUIRED_PHP_VERSION,
);
$check_list[] = array(
'type' => 'MySQL',
'current' => pwg_get_db_version(),
'required' => REQUIRED_MYSQL_VERSION,
);
foreach ($check_list as $elem)
{
if (version_compare($elem['current'], $elem['required'], '<'))
{
$c13y->add_anomaly(
sprintf(l10n('The version of %s [%s] installed is not compatible with the version required [%s]'), $elem['type'], $elem['current'], $elem['required']),
null,
null,
l10n('You need to upgrade your system to take full advantage of the application else the application will not work correctly, or not at all')
.'<br>'.
$c13y->get_htlm_links_more_info());
}
}
}
/**
* Check exif
*
* @param c13y object
* @return void
*/
function c13y_exif($c13y)
{
global $conf;
foreach (array('show_exif', 'use_exif') as $value)
{
if (($conf[$value]) and (!function_exists('read_exif_data')))
{
$c13y->add_anomaly(
sprintf(l10n('%s value is not correct file because exif are not supported'), '$conf[\''.$value.'\']'),
null,
null,
sprintf(l10n('%s must be to set to false in your local/config/config.inc.php file'), '$conf[\''.$value.'\']')
.'<br>'.
$c13y->get_htlm_links_more_info());
}
}
}
/**
* Check user
*
* @param c13y object
* @return void
*/
function c13y_user($c13y)
{
global $conf;
$c13y_users = array();
$c13y_users[$conf['guest_id']] = array(
'status' => 'guest',
'l10n_non_existent' => 'Main "guest" user does not exist',
'l10n_bad_status' => 'Main "guest" user status is incorrect');
if ($conf['guest_id'] != $conf['default_user_id'])
{
$c13y_users[$conf['default_user_id']] = array(
'password' => null,
'l10n_non_existent' => 'Default user does not exist');
}
$c13y_users[$conf['webmaster_id']] = array(
'status' => 'webmaster',
'l10n_non_existent' => 'Main "webmaster" user does not exist',
'l10n_bad_status' => 'Main "webmaster" user status is incorrect');
$query = '
select u.'.$conf['user_fields']['id'].' as id, ui.status
from '.USERS_TABLE.' as u
left join '.USER_INFOS_TABLE.' as ui
on u.'.$conf['user_fields']['id'].' = ui.user_id
where
u.'.$conf['user_fields']['id'].' in ('.implode(',', array_keys($c13y_users)).')
;';
$status = array();
$result = pwg_query($query);
while ($row = pwg_db_fetch_assoc($result))
{
$status[$row['id']] = $row['status'];
}
foreach ($c13y_users as $id => $data)
{
if (!array_key_exists($id, $status))
{
$c13y->add_anomaly(l10n($data['l10n_non_existent']), 'c13y_correction_user',
array('id' => $id, 'action' => 'creation'));
}
else
if (!empty($data['status']) and $status[$id] != $data['status'])
{
$c13y->add_anomaly(l10n($data['l10n_bad_status']), 'c13y_correction_user',
array('id' => $id, 'action' => 'status'));
}
}
}
/**
* Do correction user
*
* @param user_id, action
* @return boolean true if ok else false
*/
function c13y_correction_user($id, $action)
{
global $conf, $page;
$result = false;
if (!empty($id))
{
switch ($action)
{
case 'creation':
if ($id == $conf['guest_id'])
{
$name = 'guest';
$password = null;
}
else if ($id == $conf['default_user_id'])
{
$name = 'guest';
$password = null;
}
else if ($id == $conf['webmaster_id'])
{
$name = 'webmaster';
$password = generate_key(6);
}
if (isset($name))
{
$name_ok = false;
while (!$name_ok)
{
$name_ok = (get_userid($name) === false);
if (!$name_ok)
{
$name .= generate_key(1);
}
}
$inserts = array(
array(
'id' => $id,
'username' => addslashes($name),
'password' => $password
),
);
mass_inserts(USERS_TABLE, array_keys($inserts[0]), $inserts);
create_user_infos($id);
$page['infos'][] = sprintf(l10n('User "%s" created with "%s" like password'), $name, $password);
$result = true;
}
break;
case 'status':
if ($id == $conf['guest_id'])
{
$status = 'guest';
}
else if ($id == $conf['default_user_id'])
{
$status = 'guest';
}
else if ($id == $conf['webmaster_id'])
{
$status = 'webmaster';
}
if (isset($status))
{
$updates = array(
array(
'user_id' => $id,
'status' => $status
),
);
mass_updates(USER_INFOS_TABLE,
array('primary' => array('user_id'),'update' => array('status')),
$updates);
$page['infos'][] = sprintf(l10n('Status of user "%s" updated'), get_username($id));
$result = true;
}
break;
}
}
return $result;
}
}
?>

View File

@@ -0,0 +1,346 @@
<?php
// +-----------------------------------------------------------------------+
// | Piwigo - a PHP based photo gallery |
// +-----------------------------------------------------------------------+
// | Copyright(C) 2008-2016 Piwigo Team http://piwigo.org |
// | Copyright(C) 2003-2008 PhpWebGallery Team http://phpwebgallery.net |
// | Copyright(C) 2002-2003 Pierrick LE GALL http://le-gall.net/pierrick |
// +-----------------------------------------------------------------------+
// | 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 |
// | |
// | 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, |
// | USA. |
// +-----------------------------------------------------------------------+
class check_integrity
{
var $ignore_list;
var $retrieve_list;
var $build_ignore_list;
function __construct()
{
$this->ignore_list = array();
$this->retrieve_list = array();
$this->build_ignore_list = array();
}
/**
* Check integrities
*
* @param void
* @return void
*/
function check()
{
global $page, $header_notes, $conf;
// Ignore list
$conf_c13y_ignore = unserialize($conf['c13y_ignore']);
if (
is_array($conf_c13y_ignore) and
isset($conf_c13y_ignore['version']) and
($conf_c13y_ignore['version'] == PHPWG_VERSION) and
is_array($conf_c13y_ignore['list'])
)
{
$ignore_list_changed = false;
$this->ignore_list = $conf_c13y_ignore['list'];
}
else
{
$ignore_list_changed = true;
$this->ignore_list = array();
}
// Retrieve list
$this->retrieve_list = array();
$this->build_ignore_list = array();
trigger_notify('list_check_integrity', $this);
// Information
if (count($this->retrieve_list) > 0)
{
$header_notes[] = l10n_dec(
'%d anomaly has been detected.', '%d anomalies have been detected.',
count($this->retrieve_list)
);
}
// Treatments
if (isset($_POST['c13y_submit_correction']) and isset($_POST['c13y_selection']))
{
$corrected_count = 0;
$not_corrected_count = 0;
foreach ($this->retrieve_list as $i => $c13y)
{
if (!empty($c13y['correction_fct']) and
$c13y['is_callable'] and
in_array($c13y['id'], $_POST['c13y_selection']))
{
if (is_array($c13y['correction_fct_args']))
{
$args = $c13y['correction_fct_args'];
}
else
if (!is_null($c13y['correction_fct_args']))
{
$args = array($c13y['correction_fct_args']);
}
else
{
$args = array();
}
$this->retrieve_list[$i]['corrected'] = call_user_func_array($c13y['correction_fct'], $args);
if ($this->retrieve_list[$i]['corrected'])
{
$corrected_count += 1;
}
else
{
$not_corrected_count += 1;
}
}
}
if ($corrected_count > 0)
{
$page['infos'][] = l10n_dec(
'%d anomaly has been corrected.', '%d anomalies have been detected corrected.',
$corrected_count
);
}
if ($not_corrected_count > 0)
{
$page['errors'][] = l10n_dec(
'%d anomaly has not been corrected.', '%d anomalies have not been corrected.',
$not_corrected_count
);
}
}
else
{
if (isset($_POST['c13y_submit_ignore']) and isset($_POST['c13y_selection']))
{
$ignored_count = 0;
foreach ($this->retrieve_list as $i => $c13y)
{
if (in_array($c13y['id'], $_POST['c13y_selection']))
{
$this->build_ignore_list[] = $c13y['id'];
$this->retrieve_list[$i]['ignored'] = true;
$ignored_count += 1;
}
}
if ($ignored_count > 0)
{
$page['infos'][] = l10n_dec(
'%d anomaly has been ignored.', '%d anomalies have been ignored.',
$ignored_count
);
}
}
}
$ignore_list_changed =
(
($ignore_list_changed) or
(count(array_diff($this->ignore_list, $this->build_ignore_list)) > 0) or
(count(array_diff($this->build_ignore_list, $this->ignore_list)) > 0)
);
if ($ignore_list_changed)
{
$this->update_conf($this->build_ignore_list);
}
}
/**
* Display anomalies list
*
* @param void
* @return void
*/
function display()
{
global $template;
$check_automatic_correction = false;
$submit_automatic_correction = false;
$submit_ignore = false;
if (isset($this->retrieve_list) and count($this->retrieve_list) > 0)
{
$template->set_filenames(array('check_integrity' => 'check_integrity.tpl'));
foreach ($this->retrieve_list as $i => $c13y)
{
$can_select = false;
$c13y_display = array(
'id' => $c13y['id'],
'anomaly' => $c13y['anomaly'],
'show_ignore_msg' => false,
'show_correction_success_fct' => false,
'correction_error_fct' => '',
'show_correction_fct' => false,
'correction_error_fct' => '',
'show_correction_bad_fct' => false,
'correction_msg' => ''
);
if (isset($c13y['ignored']))
{
if ($c13y['ignored'])
{
$c13y_display['show_ignore_msg'] = true;
}
else
{
die('$c13y[\'ignored\'] cannot be false');
}
}
else
{
if (!empty($c13y['correction_fct']))
{
if (isset($c13y['corrected']))
{
if ($c13y['corrected'])
{
$c13y_display['show_correction_success_fct'] = true;
}
else
{
$c13y_display['correction_error_fct'] = $this->get_htlm_links_more_info();
}
}
else if ($c13y['is_callable'])
{
$c13y_display['show_correction_fct'] = true;
$template->append('c13y_do_check', $c13y['id']);
$submit_automatic_correction = true;
$can_select = true;
}
else
{
$c13y_display['show_correction_bad_fct'] = true;
$can_select = true;
}
}
else
{
$can_select = true;
}
if (!empty($c13y['correction_msg']) and !isset($c13y['corrected']))
{
$c13y_display['correction_msg'] = $c13y['correction_msg'];
}
}
$c13y_display['can_select'] = $can_select;
if ($can_select)
{
$submit_ignore = true;
}
$template->append('c13y_list', $c13y_display);
}
$template->assign('c13y_show_submit_automatic_correction', $submit_automatic_correction);
$template->assign('c13y_show_submit_ignore', $submit_ignore);
$template->concat('ADMIN_CONTENT', $template->parse('check_integrity', true));
}
}
/**
* Add anomaly data
*
* @param anomaly arguments
* @return void
*/
function add_anomaly($anomaly, $correction_fct = null, $correction_fct_args = null, $correction_msg = null)
{
$id = md5($anomaly.$correction_fct.serialize($correction_fct_args).$correction_msg);
if (in_array($id, $this->ignore_list))
{
$this->build_ignore_list[] = $id;
}
else
{
$this->retrieve_list[] =
array(
'id' => $id,
'anomaly' => $anomaly,
'correction_fct' => $correction_fct,
'correction_fct_args' => $correction_fct_args,
'correction_msg' => $correction_msg,
'is_callable' => is_callable($correction_fct));
}
}
/**
* Update table config
*
* @param ignore list array
* @return void
*/
function update_conf($conf_ignore_list = array())
{
$conf_c13y_ignore = array();
$conf_c13y_ignore['version'] = PHPWG_VERSION;
$conf_c13y_ignore['list'] = $conf_ignore_list;
$query = 'update '.CONFIG_TABLE.' set value =\''.serialize($conf_c13y_ignore).'\'where param = \'c13y_ignore\';';
pwg_query($query);
}
/**
* Apply maintenance
*
* @param void
* @return void
*/
function maintenance()
{
$this->update_conf();
}
/**
* Returns links more informations
*
* @param void
* @return html links
*/
function get_htlm_links_more_info()
{
$pwg_links = pwg_URL();
$link_fmt = '<a href="%s" onclick="window.open(this.href, \'\'); return false;">%s</a>';
return
sprintf
(
l10n('Go to %s or %s for more informations'),
sprintf($link_fmt, $pwg_links['FORUM'], l10n('the forum')),
sprintf($link_fmt, $pwg_links['WIKI'], l10n('the wiki'))
);
}
}
?>

View File

@@ -0,0 +1,280 @@
<?php
// +-----------------------------------------------------------------------+
// | Piwigo - a PHP based photo gallery |
// +-----------------------------------------------------------------------+
// | Copyright(C) 2008-2016 Piwigo Team http://piwigo.org |
// | Copyright(C) 2003-2008 PhpWebGallery Team http://phpwebgallery.net |
// | Copyright(C) 2002-2003 Pierrick LE GALL http://le-gall.net/pierrick |
// +-----------------------------------------------------------------------+
// | 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 |
// | |
// | 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, |
// | USA. |
// +-----------------------------------------------------------------------+
if( !defined("PHPWG_ROOT_PATH") )
{
die ("Hacking attempt!");
}
$errors = array();
// original resize
$original_fields = array(
'original_resize',
'original_resize_maxwidth',
'original_resize_maxheight',
'original_resize_quality',
);
$updates = array();
foreach ($original_fields as $field)
{
$value = !empty($_POST[$field]) ? $_POST[$field] : null;
$updates[$field] = $value;
}
save_upload_form_config($updates, $page['errors'], $errors);
if ($_POST['resize_quality'] < 50 or $_POST['resize_quality'] > 98)
{
$errors['resize_quality'] = '[50..98]';
}
$pderivatives = $_POST['d'];
// step 1 - sanitize HTML input
foreach ($pderivatives as $type => &$pderivative)
{
if ($pderivative['must_square'] = ($type==IMG_SQUARE ? true : false))
{
$pderivative['h'] = $pderivative['w'];
$pderivative['minh'] = $pderivative['minw'] = $pderivative['w'];
$pderivative['crop'] = 100;
}
$pderivative['must_enable'] = ($type==IMG_SQUARE || $type==IMG_THUMB || $type==$conf['derivative_default_size'])? true : false;
$pderivative['enabled'] = isset($pderivative['enabled']) || $pderivative['must_enable'] ? true : false;
if (isset($pderivative['crop']))
{
$pderivative['crop'] = 100;
$pderivative['minw'] = $pderivative['w'];
$pderivative['minh'] = $pderivative['h'];
}
else
{
$pderivative['crop'] = 0;
$pderivative['minw'] = null;
$pderivative['minh'] = null;
}
}
unset($pderivative);
// step 2 - check validity
$prev_w = $prev_h = 0;
foreach(ImageStdParams::get_all_types() as $type)
{
$pderivative = $pderivatives[$type];
if (!$pderivative['enabled'])
{
continue;
}
if ($type == IMG_THUMB)
{
$w = intval($pderivative['w']);
if ($w <= 0)
{
$errors[$type]['w'] = '>0';
}
$h = intval($pderivative['h']);
if ($h <= 0)
{
$errors[$type]['h'] = '>0';
}
if (max($w,$h) <= $prev_w)
{
$errors[$type]['w'] = $errors[$type]['h'] = '>'.$prev_w;
}
}
else
{
$v = intval($pderivative['w']);
if ($v <= 0 or $v <= $prev_w)
{
$errors[$type]['w'] = '>'.$prev_w;
}
$v = intval($pderivative['h']);
if ($v <= 0 or $v <= $prev_h)
{
$errors[$type]['h'] = '>'.$prev_h;
}
}
if (count($errors) == 0)
{
$prev_w = intval($pderivative['w']);
$prev_h = intval($pderivative['h']);
}
$v = intval($pderivative['sharpen']);
if ($v<0 || $v>100)
{
$errors[$type]['sharpen'] = '[0..100]';
}
}
// step 3 - save data
if (count($errors) == 0)
{
$quality_changed = ImageStdParams::$quality != intval($_POST['resize_quality']);
ImageStdParams::$quality = intval($_POST['resize_quality']);
$enabled = ImageStdParams::get_defined_type_map();
$disabled = @unserialize( @$conf['disabled_derivatives'] );
if ($disabled === false)
{
$disabled = array();
}
$changed_types = array();
foreach (ImageStdParams::get_all_types() as $type)
{
$pderivative = $pderivatives[$type];
if ($pderivative['enabled'])
{
$new_params = new DerivativeParams(
new SizingParams(
array(intval($pderivative['w']), intval($pderivative['h'])),
round($pderivative['crop'] / 100, 2),
array(intval($pderivative['minw']), intval($pderivative['minh']))
)
);
$new_params->sharpen = intval($pderivative['sharpen']);
ImageStdParams::apply_global($new_params);
if (isset($enabled[$type]))
{
$old_params = $enabled[$type];
$same = true;
if (!size_equals($old_params->sizing->ideal_size, $new_params->sizing->ideal_size)
or $old_params->sizing->max_crop != $new_params->sizing->max_crop)
{
$same = false;
}
if ($same
and $new_params->sizing->max_crop != 0
and !size_equals($old_params->sizing->min_size, $new_params->sizing->min_size))
{
$same = false;
}
if ($quality_changed
|| $new_params->sharpen != $old_params->sharpen)
{
$same = false;
}
if (!$same)
{
$new_params->last_mod_time = time();
$changed_types[] = $type;
}
else
{
$new_params->last_mod_time = $old_params->last_mod_time;
}
$enabled[$type] = $new_params;
}
else
{// now enabled, before was disabled
$enabled[$type] = $new_params;
unset($disabled[$type]);
}
}
else
{// disabled
if (isset($enabled[$type]))
{// now disabled, before was enabled
$changed_types[] = $type;
$disabled[$type] = $enabled[$type];
unset($enabled[$type]);
}
}
}
$enabled_by = array(); // keys ordered by all types
foreach(ImageStdParams::get_all_types() as $type)
{
if (isset($enabled[$type]))
{
$enabled_by[$type] = $enabled[$type];
}
}
foreach( array_keys(ImageStdParams::$custom) as $custom)
{
if (isset($_POST['delete_custom_derivative_'.$custom]))
{
$changed_types[] = $custom;
unset(ImageStdParams::$custom[$custom]);
}
}
ImageStdParams::set_and_save($enabled_by);
if (count($disabled) == 0)
{
$query='DELETE FROM '.CONFIG_TABLE.' WHERE param = \'disabled_derivatives\'';
pwg_query($query);
}
else
{
conf_update_param('disabled_derivatives', addslashes(serialize($disabled)) );
}
$conf['disabled_derivatives'] = serialize($disabled);
if (count($changed_types))
{
clear_derivative_cache($changed_types);
}
$page['infos'][] = l10n('Your configuration settings are saved');
}
else
{
foreach ($original_fields as $field)
{
if (isset($_POST[$field]))
{
$template->append(
'sizes',
array(
$field => $_POST[$field]
),
true
);
}
}
$template->assign('derivatives', $pderivatives);
$template->assign('ferrors', $errors);
$template->assign('resize_quality', $_POST['resize_quality']);
$page['sizes_loaded_in_tpl'] = true;
}
?>

View File

@@ -0,0 +1,215 @@
<?php
// +-----------------------------------------------------------------------+
// | Piwigo - a PHP based photo gallery |
// +-----------------------------------------------------------------------+
// | Copyright(C) 2008-2016 Piwigo Team http://piwigo.org |
// | Copyright(C) 2003-2008 PhpWebGallery Team http://phpwebgallery.net |
// | Copyright(C) 2002-2003 Pierrick LE GALL http://le-gall.net/pierrick |
// +-----------------------------------------------------------------------+
// | 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 |
// | |
// | 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, |
// | USA. |
// +-----------------------------------------------------------------------+
if( !defined("PHPWG_ROOT_PATH") )
{
die ("Hacking attempt!");
}
function get_watermark_filename($list, $candidate, $step = 0)
{
global $change_name;
$change_name = $candidate;
if ($step != 0)
{
$change_name .= '-'.$step;
}
if (in_array($change_name, $list))
{
return get_watermark_filename($list, $candidate, $step+1);
}
return $change_name.'.png';
}
$errors = array();
$pwatermark = $_POST['w'];
// step 0 - manage upload if any
if (isset($_FILES['watermarkImage']) and !empty($_FILES['watermarkImage']['tmp_name']))
{
list($width, $height, $type) = getimagesize($_FILES['watermarkImage']['tmp_name']);
if (IMAGETYPE_PNG != $type)
{
$errors['watermarkImage'] = sprintf(
l10n('Allowed file types: %s.'),
'PNG'
);
}
else
{
$upload_dir = PHPWG_ROOT_PATH.PWG_LOCAL_DIR.'watermarks';
if (mkgetdir($upload_dir, MKGETDIR_DEFAULT&~MKGETDIR_DIE_ON_ERROR))
{
// file name may include exotic chars like single quote, we need a safe name
$new_name = str2url(get_filename_wo_extension($_FILES['watermarkImage']['name']));
// we need existing watermarks to avoid overwritting one
$watermark_files = array();
if ( ($glob=glob(PHPWG_ROOT_PATH.PWG_LOCAL_DIR.'watermarks/*.png')) !== false)
{
foreach ($glob as $file)
{
$watermark_files[] = get_filename_wo_extension(
substr($file, strlen(PHPWG_ROOT_PATH.PWG_LOCAL_DIR.'watermarks/'))
);
}
}
$file_path = $upload_dir.'/'.get_watermark_filename($watermark_files, $new_name);
if (move_uploaded_file($_FILES['watermarkImage']['tmp_name'], $file_path))
{
$pwatermark['file'] = substr($file_path, strlen(PHPWG_ROOT_PATH));
}
else
{
$page['errors'][] = $errors['watermarkImage'] = "$file_path " .l10n('no write access');
}
}
else
{
$page['errors'][] = $errors['watermarkImage'] = sprintf( l10n('Add write access to the "%s" directory'), $upload_dir);
}
}
}
// step 1 - sanitize HTML input
switch ($pwatermark['position'])
{
case 'topleft':
{
$pwatermark['xpos'] = 0;
$pwatermark['ypos'] = 0;
break;
}
case 'topright':
{
$pwatermark['xpos'] = 100;
$pwatermark['ypos'] = 0;
break;
}
case 'middle':
{
$pwatermark['xpos'] = 50;
$pwatermark['ypos'] = 50;
break;
}
case 'bottomleft':
{
$pwatermark['xpos'] = 0;
$pwatermark['ypos'] = 100;
break;
}
case 'bottomright':
{
$pwatermark['xpos'] = 100;
$pwatermark['ypos'] = 100;
break;
}
}
// step 2 - check validity
$v = intval($pwatermark['xpos']);
if ($v < 0 or $v > 100)
{
$errors['watermark']['xpos'] = '[0..100]';
}
$v = intval($pwatermark['ypos']);
if ($v < 0 or $v > 100)
{
$errors['watermark']['ypos'] = '[0..100]';
}
$v = intval($pwatermark['opacity']);
if ($v <= 0 or $v > 100)
{
$errors['watermark']['opacity'] = '(0..100]';
}
// step 3 - save data
if (count($errors) == 0)
{
$watermark = new WatermarkParams();
$watermark->file = $pwatermark['file'];
$watermark->xpos = intval($pwatermark['xpos']);
$watermark->ypos = intval($pwatermark['ypos']);
$watermark->xrepeat = intval($pwatermark['xrepeat']);
$watermark->yrepeat = intval($pwatermark['yrepeat']);
$watermark->opacity = intval($pwatermark['opacity']);
$watermark->min_size = array(intval($pwatermark['minw']),intval($pwatermark['minh']));
$old_watermark = ImageStdParams::get_watermark();
$watermark_changed =
$watermark->file != $old_watermark->file
|| $watermark->xpos != $old_watermark->xpos
|| $watermark->ypos != $old_watermark->ypos
|| $watermark->xrepeat != $old_watermark->xrepeat
|| $watermark->yrepeat != $old_watermark->yrepeat
|| $watermark->opacity != $old_watermark->opacity;
// save the new watermark configuration
ImageStdParams::set_watermark($watermark);
// do we have to regenerate the derivatives (and which types)?
$changed_types = array();
foreach (ImageStdParams::get_defined_type_map() as $type => $params)
{
$old_use_watermark = $params->use_watermark;
ImageStdParams::apply_global($params);
$changed = $params->use_watermark != $old_use_watermark;
if (!$changed and $params->use_watermark)
{
$changed = $watermark_changed;
}
if (!$changed and $params->use_watermark)
{
// if thresholds change and before/after the threshold is lower than the corresponding derivative side -> some derivatives might switch the watermark
$changed |= $watermark->min_size[0]!=$old_watermark->min_size[0] and ($watermark->min_size[0]<$params->max_width() or $old_watermark->min_size[0]<$params->max_width());
$changed |= $watermark->min_size[1]!=$old_watermark->min_size[1] and ($watermark->min_size[1]<$params->max_height() or $old_watermark->min_size[1]<$params->max_height());
}
if ($changed)
{
$params->last_mod_time = time();
$changed_types[] = $type;
}
}
ImageStdParams::save();
if (count($changed_types))
{
clear_derivative_cache($changed_types);
}
$page['infos'][] = l10n('Your configuration settings are saved');
}
else
{
$template->assign('watermark', $pwatermark);
$template->assign('ferrors', $errors);
}
?>

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,486 @@
<?php
// +-----------------------------------------------------------------------+
// | Piwigo - a PHP based photo gallery |
// +-----------------------------------------------------------------------+
// | Copyright(C) 2008-2016 Piwigo Team http://piwigo.org |
// | Copyright(C) 2003-2008 PhpWebGallery Team http://phpwebgallery.net |
// | Copyright(C) 2002-2003 Pierrick LE GALL http://le-gall.net/pierrick |
// +-----------------------------------------------------------------------+
// | 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 |
// | |
// | 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, |
// | USA. |
// +-----------------------------------------------------------------------+
/**
* @package functions\admin\history
*/
include_once(PHPWG_ROOT_PATH.'admin/include/tabsheet.class.php');
/**
* Init tabsheet for history pages
* @ignore
*/
function history_tabsheet()
{
global $page, $link_start;
// TabSheet
$tabsheet = new tabsheet();
$tabsheet->set_id('history');
$tabsheet->select($page['page']);
$tabsheet->assign();
}
/**
* Callback used to sort history entries
*/
function history_compare($a, $b)
{
return strcmp($a['date'].$a['time'], $b['date'].$b['time']);
}
/**
* Perform history search.
*
* @param array $data - used in trigger_change
* @param array $search
* @param string[] $types
* @param array
*/
function get_history($data, $search, $types)
{
if (isset($search['fields']['filename']))
{
$query = '
SELECT
id
FROM '.IMAGES_TABLE.'
WHERE file LIKE \''.$search['fields']['filename'].'\'
;';
$search['image_ids'] = array_from_query($query, 'id');
}
// echo '<pre>'; print_r($search); echo '</pre>';
$clauses = array();
if (isset($search['fields']['date-after']))
{
$clauses[] = "date >= '".$search['fields']['date-after']."'";
}
if (isset($search['fields']['date-before']))
{
$clauses[] = "date <= '".$search['fields']['date-before']."'";
}
if (isset($search['fields']['types']))
{
$local_clauses = array();
foreach ($types as $type) {
if (in_array($type, $search['fields']['types'])) {
$clause = 'image_type ';
if ($type == 'none')
{
$clause.= 'IS NULL';
}
else
{
$clause.= "= '".$type."'";
}
$local_clauses[] = $clause;
}
}
if (count($local_clauses) > 0)
{
$clauses[] = implode(' OR ', $local_clauses);
}
}
if (isset($search['fields']['user'])
and $search['fields']['user'] != -1)
{
$clauses[] = 'user_id = '.$search['fields']['user'];
}
if (isset($search['fields']['image_id']))
{
$clauses[] = 'image_id = '.$search['fields']['image_id'];
}
if (isset($search['fields']['filename']))
{
if (count($search['image_ids']) == 0)
{
// a clause that is always false
$clauses[] = '1 = 2 ';
}
else
{
$clauses[] = 'image_id IN ('.implode(', ', $search['image_ids']).')';
}
}
if (isset($search['fields']['ip']))
{
$clauses[] = 'IP LIKE "'.$search['fields']['ip'].'"';
}
$clauses = prepend_append_array_items($clauses, '(', ')');
$where_separator =
implode(
"\n AND ",
$clauses
);
$query = '
SELECT
date,
time,
user_id,
IP,
section,
category_id,
tag_ids,
image_id,
image_type
FROM '.HISTORY_TABLE.'
WHERE '.$where_separator.'
;';
// LIMIT '.$conf['nb_logs_page'].' OFFSET '.$page['start'].'
$result = pwg_query($query);
while ($row = pwg_db_fetch_assoc($result))
{
$data[] = $row;
}
return $data;
}
/**
* Compute statistics from history table to history_summary table
*
* @param int $max_lines - to only compute the next X lines, not the whole remaining lines
*/
function history_summarize($max_lines=null)
{
// we need to know which was the last line "summarized"
$query = '
SELECT
*
FROM '.HISTORY_SUMMARY_TABLE.'
WHERE history_id_to IS NOT NULL
ORDER BY history_id_to DESC
LIMIT 1
;';
$summary_lines = query2array($query);
$history_min_id = 0;
if (count($summary_lines) > 0)
{
$last_summary = $summary_lines[0];
$history_min_id = $last_summary['history_id_to'];
}
else
{
// if we have no "reference", ie "starting point", we need to find
// one. And "0" is not the right answer here, because history table may
// have been purged already.
$query = '
SELECT
MIN(id) AS min_id
FROM '.HISTORY_TABLE.'
;';
$history_lines = query2array($query);
if (count($history_lines) > 0)
{
$history_min_id = $history_lines[0]['min_id'] - 1;
}
}
$query = '
SELECT
date,
'.pwg_db_get_hour('time').' AS hour,
MIN(id) AS min_id,
MAX(id) AS max_id,
COUNT(*) AS nb_pages
FROM '.HISTORY_TABLE.'
WHERE id > '.$history_min_id;
if (isset($max_lines))
{
$query.= '
AND id <= '.($history_min_id + $max_lines);
}
$query.= '
GROUP BY
date,
hour
ORDER BY
date ASC,
hour ASC
;';
$result = pwg_query($query);
$need_update = array();
$is_first = true;
$first_time_key = null;
while ($row = pwg_db_fetch_assoc($result))
{
$time_keys = array(
substr($row['date'], 0, 4), //yyyy
substr($row['date'], 0, 7), //yyyy-mm
substr($row['date'], 0, 10),//yyyy-mm-dd
sprintf(
'%s-%02u',
$row['date'], $row['hour']
),
);
foreach ($time_keys as $time_key)
{
if (!isset($need_update[$time_key]))
{
$need_update[$time_key] = array(
'nb_pages' => 0,
'history_id_from' => $row['min_id'],
'history_id_to' => $row['max_id'],
);
}
$need_update[$time_key]['nb_pages'] += $row['nb_pages'];
if ($row['min_id'] < $need_update[$time_key]['history_id_from'])
{
$need_update[$time_key]['history_id_from'] = $row['min_id'];
}
if ($row['max_id'] > $need_update[$time_key]['history_id_to'])
{
$need_update[$time_key]['history_id_to'] = $row['max_id'];
}
}
if ($is_first)
{
$is_first = false;
$first_time_key = $time_keys[3];
}
}
// Only the oldest time_key might be already summarized, so we have to
// update the 4 corresponding lines instead of simply inserting them.
//
// For example, if the oldest unsummarized is 2005.08.25.21, the 4 lines
// that can be updated are:
//
// +---------------+----------+
// | id | nb_pages |
// +---------------+----------+
// | 2005 | 241109 |
// | 2005-08 | 20133 |
// | 2005-08-25 | 620 |
// | 2005-08-25-21 | 151 |
// +---------------+----------+
$updates = array();
$inserts = array();
if (isset($first_time_key))
{
list($year, $month, $day, $hour) = explode('-', $first_time_key);
$query = '
SELECT *
FROM '.HISTORY_SUMMARY_TABLE.'
WHERE year='.$year.'
AND ( month IS NULL
OR ( month='.$month.'
AND ( day is NULL
OR (day='.$day.'
AND (hour IS NULL OR hour='.$hour.')
)
)
)
)
;';
$result = pwg_query($query);
while ($row = pwg_db_fetch_assoc($result))
{
$key = sprintf('%4u', $row['year']);
if ( isset($row['month']) )
{
$key .= sprintf('-%02u', $row['month']);
if ( isset($row['day']) )
{
$key .= sprintf('-%02u', $row['day']);
if ( isset($row['hour']) )
{
$key .= sprintf('-%02u', $row['hour']);
}
}
}
if (isset($need_update[$key]))
{
$row['nb_pages'] += $need_update[$key]['nb_pages'];
$row['history_id_to'] = $need_update[$key]['history_id_to'];
$updates[] = $row;
unset($need_update[$key]);
}
}
}
foreach ($need_update as $time_key => $summary)
{
$time_tokens = explode('-', $time_key);
$inserts[] = array(
'year' => $time_tokens[0],
'month' => @$time_tokens[1],
'day' => @$time_tokens[2],
'hour' => @$time_tokens[3],
'nb_pages' => $summary['nb_pages'],
'history_id_from' => $summary['history_id_from'],
'history_id_to' => $summary['history_id_to'],
);
}
if (count($updates) > 0)
{
mass_updates(
HISTORY_SUMMARY_TABLE,
array(
'primary' => array('year','month','day','hour'),
'update' => array('nb_pages','history_id_to'),
),
$updates
);
}
if (count($inserts) > 0)
{
mass_inserts(
HISTORY_SUMMARY_TABLE,
array_keys($inserts[0]),
$inserts
);
}
}
/**
* Smart purge on history table. Keep some lines, purge only summarized lines
*
* @since 2.9
*/
function history_autopurge()
{
global $conf, $logger;
if (0 == $conf['history_autopurge_keep_lines'])
{
return;
}
// we want to purge only if there are too many lines and if the lines are summarized
$query = '
SELECT
COUNT(*)
FROM '.HISTORY_TABLE.'
;';
list($count) = pwg_db_fetch_row(pwg_query($query));
if ($count <= $conf['history_autopurge_keep_lines'])
{
return; // no need to purge for now
}
// 1) find the last summarized history line
$query = '
SELECT
*
FROM '.HISTORY_SUMMARY_TABLE.'
WHERE history_id_to IS NOT NULL
ORDER BY history_id_to DESC
LIMIT 1
;';
$summary_lines = query2array($query);
if (count($summary_lines) == 0)
{
return; // lines not summarized, no purge
}
$history_id_last_summarized = $summary_lines[0]['history_id_to'];
// 2) find the latest history line (and substract the number of lines to keep)
$query = '
SELECT
id
FROM '.HISTORY_TABLE.'
ORDER BY id DESC
LIMIT 1
;';
$history_lines = query2array($query);
if (count($history_lines) == 0)
{
return;
}
$history_id_latest = $history_lines[0]['id'];
// 3) find the oldest history line (and add the number of lines to delete)
$query = '
SELECT
id
FROM '.HISTORY_TABLE.'
ORDER BY id ASC
LIMIT 1
;';
$history_lines = query2array($query);
$history_id_oldest = $history_lines[0]['id'];
$search_min = array(
$history_id_last_summarized,
$history_id_latest - $conf['history_autopurge_keep_lines'],
$history_id_oldest + $conf['history_autopurge_blocksize'],
);
$history_id_delete_before = min($search_min);
$logger->debug(__FUNCTION__.', '.join('/', $search_min));
$query = '
DELETE
FROM '.HISTORY_TABLE.'
WHERE id < '.$history_id_delete_before.'
;';
pwg_query($query);
}
add_event_handler('get_history', 'get_history');
trigger_notify('functions_history_included');
?>

View File

@@ -0,0 +1,128 @@
<?php
// +-----------------------------------------------------------------------+
// | Piwigo - a PHP based photo gallery |
// +-----------------------------------------------------------------------+
// | Copyright(C) 2008-2016 Piwigo Team http://piwigo.org |
// | Copyright(C) 2003-2008 PhpWebGallery Team http://phpwebgallery.net |
// | Copyright(C) 2002-2003 Pierrick LE GALL http://le-gall.net/pierrick |
// +-----------------------------------------------------------------------+
// | 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 |
// | |
// | 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, |
// | USA. |
// +-----------------------------------------------------------------------+
/**
* @package functions\admin\install
*/
/**
* Loads a SQL file and executes all queries.
* Before executing a query, $replaced is... replaced by $replacing. This is
* useful when the SQL file contains generic words. Drop table queries are
* not executed.
*
* @param string $filepath
* @param string $replaced
* @param string $replacing
*/
function execute_sqlfile($filepath, $replaced, $replacing, $dblayer)
{
$sql_lines = file($filepath);
$query = '';
foreach ($sql_lines as $sql_line)
{
$sql_line = trim($sql_line);
if (preg_match('/(^--|^$)/', $sql_line))
{
continue;
}
$query.= ' '.$sql_line;
// if we reached the end of query, we execute it and reinitialize the
// variable "query"
if (preg_match('/;$/', $sql_line))
{
$query = trim($query);
$query = str_replace($replaced, $replacing, $query);
// we don't execute "DROP TABLE" queries
if (!preg_match('/^DROP TABLE/i', $query))
{
if ('mysql' == $dblayer)
{
if ( preg_match('/^(CREATE TABLE .*)[\s]*;[\s]*/im', $query, $matches) )
{
$query = $matches[1].' DEFAULT CHARACTER SET utf8'.';';
}
}
pwg_query($query);
}
$query = '';
}
}
}
/**
* Automatically activate all core themes in the "themes" directory.
*/
function activate_core_themes()
{
include_once(PHPWG_ROOT_PATH.'admin/include/themes.class.php');
$themes = new themes();
foreach ($themes->fs_themes as $theme_id => $fs_theme)
{
if (in_array($theme_id, array('elegant', 'smartpocket')))
{
$themes->perform_action('activate', $theme_id);
}
}
}
/**
* Automatically activate some core plugins
*/
function activate_core_plugins()
{
include_once(PHPWG_ROOT_PATH.'admin/include/plugins.class.php');
$plugins = new plugins();
foreach($plugins->fs_plugins as $plugin_id => $fs_plugin)
{
if (in_array($plugin_id, array('TakeATour')))
{
$plugins->perform_action('activate', $plugin_id);
}
}
}
/**
* Connect to database during installation. Uses $_POST.
*
* @param array &$infos - populated with infos
* @param array &$errors - populated with errors
*/
function install_db_connect(&$infos, &$errors)
{
try
{
pwg_db_connect($_POST['dbhost'], $_POST['dbuser'],
$_POST['dbpasswd'], $_POST['dbname']);
pwg_db_check_version();
}
catch (Exception $e)
{
$errors[] = l10n($e->getMessage());
}
}
?>

View File

@@ -0,0 +1,400 @@
<?php
// +-----------------------------------------------------------------------+
// | Piwigo - a PHP based photo gallery |
// +-----------------------------------------------------------------------+
// | Copyright(C) 2008-2016 Piwigo Team http://piwigo.org |
// | Copyright(C) 2003-2008 PhpWebGallery Team http://phpwebgallery.net |
// | Copyright(C) 2002-2003 Pierrick LE GALL http://le-gall.net/pierrick |
// +-----------------------------------------------------------------------+
// | 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 |
// | |
// | 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, |
// | USA. |
// +-----------------------------------------------------------------------+
/**
* @package functions\admin\metadata
*/
include_once(PHPWG_ROOT_PATH.'/include/functions_metadata.inc.php');
/**
* Returns IPTC metadata to sync from a file, depending on IPTC mapping.
* @toto : clean code (factorize foreach)
*
* @param string $file
* @return array
*/
function get_sync_iptc_data($file)
{
global $conf;
$map = $conf['use_iptc_mapping'];
$iptc = get_iptc_data($file, $map);
foreach ($iptc as $pwg_key => $value)
{
if (in_array($pwg_key, array('date_creation', 'date_available')))
{
if (preg_match('/(\d{4})(\d{2})(\d{2})/', $value, $matches))
{
$year = $matches[1];
$month = $matches[2];
$day = $matches[3];
if (!checkdate($month, $day, $year))
{
// we suppose the year is correct
$month = 1;
$day = 1;
}
$iptc[$pwg_key] = $year.'-'.$month.'-'.$day;
}
}
}
if (isset($iptc['keywords']))
{
$iptc['keywords'] = metadata_normalize_keywords_string($iptc['keywords']);
}
foreach ($iptc as $pwg_key => $value)
{
$iptc[$pwg_key] = addslashes($iptc[$pwg_key]);
}
return $iptc;
}
/**
* Returns EXIF metadata to sync from a file, depending on EXIF mapping.
*
* @param string $file
* @return array
*/
function get_sync_exif_data($file)
{
global $conf;
$exif = get_exif_data($file, $conf['use_exif_mapping']);
foreach ($exif as $pwg_key => $value)
{
if (in_array($pwg_key, array('date_creation', 'date_available')))
{
if (preg_match('/^(\d{4}).(\d{2}).(\d{2}) (\d{2}).(\d{2}).(\d{2})/', $value, $matches))
{
$exif[$pwg_key] = $matches[1].'-'.$matches[2].'-'.$matches[3].' '.$matches[4].':'.$matches[5].':'.$matches[6];
if ($exif[$pwg_key] == '0000-00-00 00:00:00')
{
$exif[$pwg_key] = Null;
}
}
elseif (preg_match('/^(\d{4}).(\d{2}).(\d{2})/', $value, $matches))
{
$exif[$pwg_key] = $matches[1].'-'.$matches[2].'-'.$matches[3];
}
else
{
unset($exif[$pwg_key]);
continue;
}
}
if (in_array($pwg_key, array('keywords', 'tags')))
{
$exif[$pwg_key] = metadata_normalize_keywords_string($exif[$pwg_key]);
}
$exif[$pwg_key] = addslashes($exif[$pwg_key]);
}
return $exif;
}
/**
* Get all potential file metadata fields, including IPTC and EXIF.
*
* @return string[]
*/
function get_sync_metadata_attributes()
{
global $conf;
$update_fields = array('filesize', 'width', 'height');
if ($conf['use_exif'])
{
$update_fields =
array_merge(
$update_fields,
array_keys($conf['use_exif_mapping']),
array('latitude', 'longitude')
);
}
if ($conf['use_iptc'])
{
$update_fields =
array_merge(
$update_fields,
array_keys($conf['use_iptc_mapping'])
);
}
return array_unique($update_fields);
}
/**
* Get all metadata of a file.
*
* @param array $infos - (path[, representative_ext])
* @return array - includes data provided in $infos
*/
function get_sync_metadata($infos)
{
global $conf;
$file = PHPWG_ROOT_PATH.$infos['path'];
$fs = @filesize($file);
if ($fs===false)
{
return false;
}
$infos['filesize'] = floor($fs/1024);
$is_tiff = false;
if (isset($infos['representative_ext']))
{
if ($image_size = @getimagesize($file))
{
$type = $image_size[2];
if (IMAGETYPE_TIFF_MM == $type or IMAGETYPE_TIFF_II == $type)
{
// in case of TIFF files, we want to use the original file and not
// the representative for EXIF/IPTC, but we need the representative
// for width/height (to compute the multiple size dimensions)
$is_tiff = true;
}
}
$file = original_to_representative($file, $infos['representative_ext']);
}
if ($image_size = @getimagesize($file))
{
$infos['width'] = $image_size[0];
$infos['height'] = $image_size[1];
}
if ($is_tiff)
{
// back to original file
$file = PHPWG_ROOT_PATH.$infos['path'];
}
if ($conf['use_exif'])
{
$exif = get_sync_exif_data($file);
$infos = array_merge($infos, $exif);
}
if ($conf['use_iptc'])
{
$iptc = get_sync_iptc_data($file);
$infos = array_merge($infos, $iptc);
}
return $infos;
}
/**
* Sync all metadata of a list of images.
* Metadata are fetched from original files and saved in database.
*
* @param int[] $ids
*/
function sync_metadata($ids)
{
global $conf;
if (!defined('CURRENT_DATE'))
{
define('CURRENT_DATE', date('Y-m-d'));
}
$datas = array();
$tags_of = array();
$query = '
SELECT id, path, representative_ext
FROM '.IMAGES_TABLE.'
WHERE id IN (
'.wordwrap(implode(', ', $ids), 160, "\n").'
)
;';
$result = pwg_query($query);
while ($data = pwg_db_fetch_assoc($result))
{
$data = get_sync_metadata($data);
if ($data === false)
{
continue;
}
$id = $data['id'];
foreach (array('keywords', 'tags') as $key)
{
if (isset($data[$key]))
{
if (!isset($tags_of[$id]))
{
$tags_of[$id] = array();
}
foreach (explode(',', $data[$key]) as $tag_name)
{
$tags_of[$id][] = tag_id_from_tag_name($tag_name);
}
}
}
$data['date_metadata_update'] = CURRENT_DATE;
$datas[] = $data;
}
if (count($datas) > 0)
{
$update_fields = get_sync_metadata_attributes();
$update_fields[] = 'date_metadata_update';
$update_fields = array_diff(
$update_fields,
array('tags', 'keywords')
);
mass_updates(
IMAGES_TABLE,
array(
'primary' => array('id'),
'update' => $update_fields
),
$datas,
MASS_UPDATES_SKIP_EMPTY
);
}
set_tags_of($tags_of);
}
/**
* Returns an array associating element id (images.id) with its complete
* path in the filesystem
*
* @param int $category_id
* @param int $site_id
* @param boolean $recursive
* @param boolean $only_new
* @return array
*/
function get_filelist($category_id = '', $site_id=1, $recursive = false,
$only_new = false)
{
// filling $cat_ids : all categories required
$cat_ids = array();
$query = '
SELECT id
FROM '.CATEGORIES_TABLE.'
WHERE site_id = '.$site_id.'
AND dir IS NOT NULL';
if (is_numeric($category_id))
{
if ($recursive)
{
$query.= '
AND uppercats '.DB_REGEX_OPERATOR.' \'(^|,)'.$category_id.'(,|$)\'
';
}
else
{
$query.= '
AND id = '.$category_id.'
';
}
}
$query.= '
;';
$result = pwg_query($query);
while ($row = pwg_db_fetch_assoc($result))
{
$cat_ids[] = $row['id'];
}
if (count($cat_ids) == 0)
{
return array();
}
$query = '
SELECT id, path, representative_ext
FROM '.IMAGES_TABLE.'
WHERE storage_category_id IN ('.implode(',', $cat_ids).')';
if ($only_new)
{
$query.= '
AND date_metadata_update IS NULL
';
}
$query.= '
;';
return hash_from_query($query, 'id');
}
/**
* Returns the list of keywords (future tags) correctly separated with
* commas. Other separators are converted into commas.
*
* @param string $keywords_string
* @return string
*/
function metadata_normalize_keywords_string($keywords_string)
{
global $conf;
$keywords_string = preg_replace($conf['metadata_keyword_separator_regex'], ',', $keywords_string);
$keywords_string = preg_replace('/,+/', ',', $keywords_string);
$keywords_string = preg_replace('/^,+|,+$/', '', $keywords_string);
$keywords_string = implode(
',',
array_unique(
explode(
',',
$keywords_string
)
)
);
return $keywords_string;
}
?>

View File

@@ -0,0 +1,546 @@
<?php
// +-----------------------------------------------------------------------+
// | Piwigo - a PHP based photo gallery |
// +-----------------------------------------------------------------------+
// | Copyright(C) 2008-2016 Piwigo Team http://piwigo.org |
// | Copyright(C) 2003-2008 PhpWebGallery Team http://phpwebgallery.net |
// | Copyright(C) 2002-2003 Pierrick LE GALL http://le-gall.net/pierrick |
// +-----------------------------------------------------------------------+
// | 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 |
// | |
// | 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, |
// | USA. |
// +-----------------------------------------------------------------------+
/* nbm_global_var */
$env_nbm = array
(
'start_time' => get_moment(),
'sendmail_timeout' => (intval(ini_get('max_execution_time')) * $conf['nbm_max_treatment_timeout_percent']),
'is_sendmail_timeout' => false
);
if
(
(!isset($env_nbm['sendmail_timeout'])) or
(!is_numeric($env_nbm['sendmail_timeout'])) or
($env_nbm['sendmail_timeout'] <= 0)
)
{
$env_nbm['sendmail_timeout'] = $conf['nbm_treatment_timeout_default'];
}
/*
* Search an available check_key
*
* It's a copy of function find_available_feed_id
*
* @return string nbm identifier
*/
function find_available_check_key()
{
while (true)
{
$key = generate_key(16);
$query = '
select
count(*)
from
'.USER_MAIL_NOTIFICATION_TABLE.'
where
check_key = \''.$key.'\';';
list($count) = pwg_db_fetch_row(pwg_query($query));
if ($count == 0)
{
return $key;
}
}
}
/*
* Check sendmail timeout state
*
* @return true, if it's timeout
*/
function check_sendmail_timeout()
{
global $env_nbm;
$env_nbm['is_sendmail_timeout'] = ((get_moment() - $env_nbm['start_time']) > $env_nbm['sendmail_timeout']);
return $env_nbm['is_sendmail_timeout'];
}
/*
* Add quote to all elements of check_key_list
*
* @return quoted check key list
*/
function quote_check_key_list($check_key_list = array())
{
return array_map(create_function('$s', 'return \'\\\'\'.$s.\'\\\'\';'), $check_key_list);
}
/*
* Execute all main queries to get list of user
*
* Type are the type of list 'subscribe', 'send'
*
* return array of users
*/
function get_user_notifications($action, $check_key_list = array(), $enabled_filter_value = '')
{
global $conf;
$data_users = array();
if (in_array($action, array('subscribe', 'send')))
{
$quoted_check_key_list = quote_check_key_list($check_key_list);
if (count($quoted_check_key_list) != 0 )
{
$query_and_check_key = ' and
check_key in ('.implode(",", $quoted_check_key_list).') ';
}
else
{
$query_and_check_key = '';
}
$query = '
select
N.user_id,
N.check_key,
U.'.$conf['user_fields']['username'].' as username,
U.'.$conf['user_fields']['email'].' as mail_address,
N.enabled,
N.last_send,
UI.status
from '.USER_MAIL_NOTIFICATION_TABLE.' as N
JOIN '.USERS_TABLE.' as U on N.user_id = U.'.$conf['user_fields']['id'].'
JOIN '.USER_INFOS_TABLE.' as UI on UI.user_id = N.user_id
where 1=1';
if ($action == 'send')
{
// No mail empty and all users enabled
$query .= ' and
N.enabled = \'true\' and
U.'.$conf['user_fields']['email'].' is not null';
}
$query .= $query_and_check_key;
if (isset($enabled_filter_value) and ($enabled_filter_value != ''))
{
$query .= ' and
N.enabled = \''.boolean_to_string($enabled_filter_value).'\'';
}
$query .= '
order by';
if ($action == 'send')
{
$query .= '
last_send, username;';
}
else
{
$query .= '
username';
}
$query .= ';';
$result = pwg_query($query);
if (!empty($result))
{
while ($nbm_user = pwg_db_fetch_assoc($result))
{
$data_users[] = $nbm_user;
}
}
}
return $data_users;
}
/*
* Begin of use nbm environment
* Prepare and save current environment and initialize data in order to send mail
*
* Return none
*/
function begin_users_env_nbm($is_to_send_mail = false)
{
global $user, $lang, $lang_info, $conf, $env_nbm;
// Save $user, $lang_info and $lang arrays (include/user.inc.php has been executed)
$env_nbm['save_user'] = $user;
// Save current language to stack, necessary because $user change during NBM
switch_lang_to($user['language']);
$env_nbm['is_to_send_mail'] = $is_to_send_mail;
if ($is_to_send_mail)
{
// Init mail configuration
$env_nbm['email_format'] = get_str_email_format($conf['nbm_send_html_mail']);
$env_nbm['send_as_name'] = ((isset($conf['nbm_send_mail_as']) and !empty($conf['nbm_send_mail_as'])) ? $conf['nbm_send_mail_as'] : get_mail_sender_name());
$env_nbm['send_as_mail_address'] = get_webmaster_mail_address();
$env_nbm['send_as_mail_formated'] = format_email($env_nbm['send_as_name'], $env_nbm['send_as_mail_address']);
// Init mail counter
$env_nbm['error_on_mail_count'] = 0;
$env_nbm['sent_mail_count'] = 0;
// Save sendmail message info and error in the original language
$env_nbm['msg_info'] = l10n('Mail sent to %s [%s].');
$env_nbm['msg_error'] = l10n('Error when sending email to %s [%s].');
}
}
/*
* End of use nbm environment
* Restore environment
*
* Return none
*/
function end_users_env_nbm()
{
global $user, $lang, $lang_info, $env_nbm;
// Restore $user, $lang_info and $lang arrays (include/user.inc.php has been executed)
$user = $env_nbm['save_user'];
// Restore current language to stack, necessary because $user change during NBM
switch_lang_back();
if ($env_nbm['is_to_send_mail'])
{
unset($env_nbm['email_format']);
unset($env_nbm['send_as_name']);
unset($env_nbm['send_as_mail_address']);
unset($env_nbm['send_as_mail_formated']);
// Don t unset counter
//unset($env_nbm['error_on_mail_count']);
//unset($env_nbm['sent_mail_count']);
unset($env_nbm['msg_info']);
unset($env_nbm['msg_error']);
}
unset($env_nbm['save_user']);
unset($env_nbm['is_to_send_mail']);
}
/*
* Set user on nbm enviromnent
*
* Return none
*/
function set_user_on_env_nbm(&$nbm_user, $is_action_send)
{
global $user, $lang, $lang_info, $env_nbm;
$user = build_user( $nbm_user['user_id'], true );
switch_lang_to($user['language']);
if ($is_action_send)
{
$env_nbm['mail_template'] = get_mail_template($env_nbm['email_format']);
$env_nbm['mail_template']->set_filename('notification_by_mail', 'notification_by_mail.tpl');
}
}
/*
* Unset user on nbm enviromnent
*
* Return none
*/
function unset_user_on_env_nbm()
{
global $env_nbm;
switch_lang_back();
unset($env_nbm['mail_template']);
}
/*
* Inc Counter success
*
* Return none
*/
function inc_mail_sent_success($nbm_user)
{
global $page, $env_nbm;
$env_nbm['sent_mail_count'] += 1;
$page['infos'][] = sprintf($env_nbm['msg_info'], stripslashes($nbm_user['username']), $nbm_user['mail_address']);
}
/*
* Inc Counter failed
*
* Return none
*/
function inc_mail_sent_failed($nbm_user)
{
global $page, $env_nbm;
$env_nbm['error_on_mail_count'] += 1;
$page['errors'][] = sprintf($env_nbm['msg_error'], stripslashes($nbm_user['username']), $nbm_user['mail_address']);
}
/*
* Display Counter Info
*
* Return none
*/
function display_counter_info()
{
global $page, $env_nbm;
if ($env_nbm['error_on_mail_count'] != 0)
{
$page['errors'][] = l10n_dec(
'%d mail was not sent.', '%d mails were not sent.',
$env_nbm['error_on_mail_count']
);
if ($env_nbm['sent_mail_count'] != 0)
{
$page['infos'][] = l10n_dec(
'%d mail was sent.', '%d mails were sent.',
$env_nbm['sent_mail_count']
);
}
}
else
{
if ($env_nbm['sent_mail_count'] == 0)
{
$page['infos'][] = l10n('No mail to send.');
}
else
{
$page['infos'][] = l10n_dec(
'%d mail was sent.', '%d mails were sent.',
$env_nbm['sent_mail_count']
);
}
}
}
function assign_vars_nbm_mail_content($nbm_user)
{
global $env_nbm;
set_make_full_url();
$env_nbm['mail_template']->assign
(
array
(
'USERNAME' => stripslashes($nbm_user['username']),
'SEND_AS_NAME' => $env_nbm['send_as_name'],
'UNSUBSCRIBE_LINK' => add_url_params(get_gallery_home_url().'/nbm.php', array('unsubscribe' => $nbm_user['check_key'])),
'SUBSCRIBE_LINK' => add_url_params(get_gallery_home_url().'/nbm.php', array('subscribe' => $nbm_user['check_key'])),
'CONTACT_EMAIL' => $env_nbm['send_as_mail_address']
)
);
unset_make_full_url();
}
/*
* Subscribe or unsubscribe notification by mail
*
* is_subscribe define if action=subscribe or unsubscribe
* check_key list where action will be done
*
* @return check_key list treated
*/
function do_subscribe_unsubscribe_notification_by_mail($is_admin_request, $is_subscribe = false, $check_key_list = array())
{
global $conf, $page, $env_nbm, $conf;
set_make_full_url();
$check_key_treated = array();
$updated_data_count = 0;
$error_on_updated_data_count = 0;
if ($is_subscribe)
{
$msg_info = l10n('User %s [%s] was added to the subscription list.');
$msg_error = l10n('User %s [%s] was not added to the subscription list.');
}
else
{
$msg_info = l10n('User %s [%s] was removed from the subscription list.');
$msg_error = l10n('User %s [%s] was not removed from the subscription list.');
}
if (count($check_key_list) != 0)
{
$updates = array();
$enabled_value = boolean_to_string($is_subscribe);
$data_users = get_user_notifications('subscribe', $check_key_list, !$is_subscribe);
// Prepare message after change language
$msg_break_timeout = l10n('Time to send mail is limited. Others mails are skipped.');
// Begin nbm users environment
begin_users_env_nbm(true);
foreach ($data_users as $nbm_user)
{
if (check_sendmail_timeout())
{
// Stop fill list on 'send', if the quota is override
$page['errors'][] = $msg_break_timeout;
break;
}
// Fill return list
$check_key_treated[] = $nbm_user['check_key'];
$do_update = true;
if ($nbm_user['mail_address'] != '')
{
// set env nbm user
set_user_on_env_nbm($nbm_user, true);
$subject = '['.$conf['gallery_title'].'] '.($is_subscribe ? l10n('Subscribe to notification by mail'): l10n('Unsubscribe from notification by mail'));
// Assign current var for nbm mail
assign_vars_nbm_mail_content($nbm_user);
$section_action_by = ($is_subscribe ? 'subscribe_by_' : 'unsubscribe_by_');
$section_action_by .= ($is_admin_request ? 'admin' : 'himself');
$env_nbm['mail_template']->assign
(
array
(
$section_action_by => true,
'GOTO_GALLERY_TITLE' => $conf['gallery_title'],
'GOTO_GALLERY_URL' => get_gallery_home_url(),
)
);
$ret = pwg_mail(
array(
'name' => stripslashes($nbm_user['username']),
'email' => $nbm_user['mail_address'],
),
array(
'from' => $env_nbm['send_as_mail_formated'],
'subject' => $subject,
'email_format' => $env_nbm['email_format'],
'content' => $env_nbm['mail_template']->parse('notification_by_mail', true),
'content_format' => $env_nbm['email_format'],
)
);
if ($ret)
{
inc_mail_sent_success($nbm_user);
}
else
{
inc_mail_sent_failed($nbm_user);
$do_update = false;
}
// unset env nbm user
unset_user_on_env_nbm();
}
if ($do_update)
{
$updates[] = array(
'check_key' => $nbm_user['check_key'],
'enabled' => $enabled_value
);
$updated_data_count += 1;
$page['infos'][] = sprintf($msg_info, stripslashes($nbm_user['username']), $nbm_user['mail_address']);
}
else
{
$error_on_updated_data_count += 1;
$page['errors'][] = sprintf($msg_error, stripslashes($nbm_user['username']), $nbm_user['mail_address']);
}
}
// Restore nbm environment
end_users_env_nbm();
display_counter_info();
mass_updates(
USER_MAIL_NOTIFICATION_TABLE,
array(
'primary' => array('check_key'),
'update' => array('enabled')
),
$updates
);
}
$page['infos'][] = l10n_dec(
'%d user was updated.', '%d users were updated.',
$updated_data_count
);
if ($error_on_updated_data_count != 0)
{
$page['errors'][] = l10n_dec(
'%d user was not updated.', '%d users were not updated.',
$error_on_updated_data_count
);
}
unset_make_full_url();
return $check_key_treated;
}
/*
* Unsubscribe notification by mail
*
* check_key list where action will be done
*
* @return check_key list treated
*/
function unsubscribe_notification_by_mail($is_admin_request, $check_key_list = array())
{
return do_subscribe_unsubscribe_notification_by_mail($is_admin_request, false, $check_key_list);
}
/*
* Subscribe notification by mail
*
* check_key list where action will be done
*
* @return check_key list treated
*/
function subscribe_notification_by_mail($is_admin_request, $check_key_list = array())
{
return do_subscribe_unsubscribe_notification_by_mail($is_admin_request, true, $check_key_list);
}
?>

View File

@@ -0,0 +1,204 @@
<?php
// +-----------------------------------------------------------------------+
// | Piwigo - a PHP based photo gallery |
// +-----------------------------------------------------------------------+
// | Copyright(C) 2008-2016 Piwigo Team http://piwigo.org |
// | Copyright(C) 2003-2008 PhpWebGallery Team http://phpwebgallery.net |
// | Copyright(C) 2002-2003 Pierrick LE GALL http://le-gall.net/pierrick |
// +-----------------------------------------------------------------------+
// | 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 |
// | |
// | 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, |
// | USA. |
// +-----------------------------------------------------------------------+
/** returns a category id that corresponds to the given permalink (or null)
* @param string permalink
*/
function get_cat_id_from_permalink( $permalink )
{
$query ='
SELECT id FROM '.CATEGORIES_TABLE.'
WHERE permalink=\''.$permalink.'\'';
$ids = array_from_query($query, 'id');
if (!empty($ids))
{
return $ids[0];
}
return null;
}
/** returns a category id that has used before this permalink (or null)
* @param string permalink
* @param boolean is_hit if true update the usage counters on the old permalinks
*/
function get_cat_id_from_old_permalink($permalink)
{
$query='
SELECT c.id
FROM '.OLD_PERMALINKS_TABLE.' op INNER JOIN '.CATEGORIES_TABLE.' c
ON op.cat_id=c.id
WHERE op.permalink=\''.$permalink.'\'
LIMIT 1';
$result = pwg_query($query);
$cat_id = null;
if ( pwg_db_num_rows($result) )
list( $cat_id ) = pwg_db_fetch_row($result);
return $cat_id;
}
/** deletes the permalink associated with a category
* returns true on success
* @param int cat_id the target category id
* @param boolean save if true, the current category-permalink association
* is saved in the old permalinks table in case external links hit it
*/
function delete_cat_permalink( $cat_id, $save )
{
global $page, $cache;
$query = '
SELECT permalink
FROM '.CATEGORIES_TABLE.'
WHERE id=\''.$cat_id.'\'
;';
$result = pwg_query($query);
if ( pwg_db_num_rows($result) )
{
list($permalink) = pwg_db_fetch_row($result);
}
if ( !isset($permalink) )
{// no permalink; nothing to do
return true;
}
if ($save)
{
$old_cat_id = get_cat_id_from_old_permalink($permalink);
if ( isset($old_cat_id) and $old_cat_id!=$cat_id )
{
$page['errors'][] =
sprintf(
l10n('Permalink %s has been previously used by album %s. Delete from the permalink history first'),
$permalink, $old_cat_id
);
return false;
}
}
$query = '
UPDATE '.CATEGORIES_TABLE.'
SET permalink=NULL
WHERE id='.$cat_id.'
LIMIT 1';
pwg_query($query);
unset( $cache['cat_names'] ); //force regeneration
if ($save)
{
if ( isset($old_cat_id) )
{
$query = '
UPDATE '.OLD_PERMALINKS_TABLE.'
SET date_deleted=NOW()
WHERE cat_id='.$cat_id.' AND permalink=\''.$permalink.'\'';
}
else
{
$query = '
INSERT INTO '.OLD_PERMALINKS_TABLE.'
(permalink, cat_id, date_deleted)
VALUES
( \''.$permalink.'\','.$cat_id.',NOW() )';
}
pwg_query( $query );
}
return true;
}
/** sets a new permalink for a category
* returns true on success
* @param int cat_id the target category id
* @param string permalink the new permalink
* @param boolean save if true, the current category-permalink association
* is saved in the old permalinks table in case external links hit it
*/
function set_cat_permalink( $cat_id, $permalink, $save )
{
global $page, $cache;
$sanitized_permalink = preg_replace( '#[^a-zA-Z0-9_/-]#', '' ,$permalink);
$sanitized_permalink = trim($sanitized_permalink, '/');
$sanitized_permalink = str_replace('//', '/', $sanitized_permalink);
if ( $sanitized_permalink != $permalink
or preg_match( '#^(\d)+(-.*)?$#', $permalink) )
{
$page['errors'][] = l10n('The permalink name must be composed of a-z, A-Z, 0-9, "-", "_" or "/". It must not be numeric or start with number followed by "-"');
return false;
}
// check if the new permalink is actively used
$existing_cat_id = get_cat_id_from_permalink( $permalink );
if ( isset($existing_cat_id) )
{
if ( $existing_cat_id==$cat_id )
{// no change required
return true;
}
else
{
$page['errors'][] =
sprintf(
l10n('Permalink %s is already used by album %s'),
$permalink, $existing_cat_id
);
return false;
}
}
// check if the new permalink was historically used
$old_cat_id = get_cat_id_from_old_permalink($permalink);
if ( isset($old_cat_id) and $old_cat_id!=$cat_id )
{
$page['errors'][] =
sprintf(
l10n('Permalink %s has been previously used by album %s. Delete from the permalink history first'),
$permalink, $old_cat_id
);
return false;
}
if ( !delete_cat_permalink($cat_id, $save ) )
{
return false;
}
if ( isset($old_cat_id) )
{// the new permalink must not be active and old at the same time
assert( $old_cat_id==$cat_id );
$query = '
DELETE FROM '.OLD_PERMALINKS_TABLE.'
WHERE cat_id='.$old_cat_id.' AND permalink=\''.$permalink.'\'';
pwg_query($query);
}
$query = '
UPDATE '.CATEGORIES_TABLE.'
SET permalink=\''.$permalink.'\'
WHERE id='.$cat_id;
// LIMIT 1';
pwg_query($query);
unset( $cache['cat_names'] ); //force regeneration
return true;
}
?>

View File

@@ -0,0 +1,46 @@
<?php
// +-----------------------------------------------------------------------+
// | Piwigo - a PHP based photo gallery |
// +-----------------------------------------------------------------------+
// | Copyright(C) 2008-2016 Piwigo Team http://piwigo.org |
// | Copyright(C) 2003-2008 PhpWebGallery Team http://phpwebgallery.net |
// | Copyright(C) 2002-2003 Pierrick LE GALL http://le-gall.net/pierrick |
// +-----------------------------------------------------------------------+
// | 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 |
// | |
// | 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, |
// | USA. |
// +-----------------------------------------------------------------------+
/**
* Retrieves an url for a plugin page.
* @param string file - php script full name
*/
function get_admin_plugin_menu_link($file)
{
global $page;
$real_file = realpath($file);
$url = get_root_url().'admin.php?page=plugin';
if (false!==$real_file)
{
$real_plugin_path = rtrim(realpath(PHPWG_PLUGINS_PATH), '\\/');
$file = substr($real_file, strlen($real_plugin_path)+1);
$file = str_replace('\\', '/', $file);//Windows
$url .= '&amp;section='.urlencode($file);
}
else if (isset($page['errors']))
{
$page['errors'][] = 'PLUGIN ERROR: "'.$file.'" is not a valid file';
}
return $url;
}
?>

View File

@@ -0,0 +1,322 @@
<?php
// +-----------------------------------------------------------------------+
// | Piwigo - a PHP based photo gallery |
// +-----------------------------------------------------------------------+
// | Copyright(C) 2008-2016 Piwigo Team http://piwigo.org |
// | Copyright(C) 2003-2008 PhpWebGallery Team http://phpwebgallery.net |
// | Copyright(C) 2002-2003 Pierrick LE GALL http://le-gall.net/pierrick |
// +-----------------------------------------------------------------------+
// | 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 |
// | |
// | 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, |
// | USA. |
// +-----------------------------------------------------------------------+
function check_upgrade()
{
if (defined('PHPWG_IN_UPGRADE'))
{
return PHPWG_IN_UPGRADE;
}
return false;
}
// concerning upgrade, we use the default tables
function prepare_conf_upgrade()
{
global $prefixeTable;
// $conf is not used for users tables
// define cannot be re-defined
define('CATEGORIES_TABLE', $prefixeTable.'categories');
define('COMMENTS_TABLE', $prefixeTable.'comments');
define('CONFIG_TABLE', $prefixeTable.'config');
define('FAVORITES_TABLE', $prefixeTable.'favorites');
define('GROUP_ACCESS_TABLE', $prefixeTable.'group_access');
define('GROUPS_TABLE', $prefixeTable.'groups');
define('HISTORY_TABLE', $prefixeTable.'history');
define('HISTORY_SUMMARY_TABLE', $prefixeTable.'history_summary');
define('IMAGE_CATEGORY_TABLE', $prefixeTable.'image_category');
define('IMAGES_TABLE', $prefixeTable.'images');
define('SESSIONS_TABLE', $prefixeTable.'sessions');
define('SITES_TABLE', $prefixeTable.'sites');
define('USER_ACCESS_TABLE', $prefixeTable.'user_access');
define('USER_GROUP_TABLE', $prefixeTable.'user_group');
define('USERS_TABLE', $prefixeTable.'users');
define('USER_INFOS_TABLE', $prefixeTable.'user_infos');
define('USER_FEED_TABLE', $prefixeTable.'user_feed');
define('RATE_TABLE', $prefixeTable.'rate');
define('USER_CACHE_TABLE', $prefixeTable.'user_cache');
define('USER_CACHE_CATEGORIES_TABLE', $prefixeTable.'user_cache_categories');
define('CADDIE_TABLE', $prefixeTable.'caddie');
define('UPGRADE_TABLE', $prefixeTable.'upgrade');
define('SEARCH_TABLE', $prefixeTable.'search');
define('USER_MAIL_NOTIFICATION_TABLE', $prefixeTable.'user_mail_notification');
define('TAGS_TABLE', $prefixeTable.'tags');
define('IMAGE_TAG_TABLE', $prefixeTable.'image_tag');
define('PLUGINS_TABLE', $prefixeTable.'plugins');
define('OLD_PERMALINKS_TABLE', $prefixeTable.'old_permalinks');
define('THEMES_TABLE', $prefixeTable.'themes');
define('LANGUAGES_TABLE', $prefixeTable.'languages');
}
// Deactivate all non-standard plugins
function deactivate_non_standard_plugins()
{
global $page;
$standard_plugins = array(
'AdminTools',
'TakeATour',
'language_switch',
'LocalFilesEditor'
);
$query = '
SELECT id
FROM '.PREFIX_TABLE.'plugins
WHERE state = \'active\'
AND id NOT IN (\'' . implode('\',\'', $standard_plugins) . '\')
;';
$result = pwg_query($query);
$plugins = array();
while ($row = pwg_db_fetch_assoc($result))
{
$plugins[] = $row['id'];
}
if (!empty($plugins))
{
$query = '
UPDATE '.PREFIX_TABLE.'plugins
SET state=\'inactive\'
WHERE id IN (\'' . implode('\',\'', $plugins) . '\')
;';
pwg_query($query);
$page['infos'][] = l10n('As a precaution, following plugins have been deactivated. You must check for plugins upgrade before reactiving them:')
.'<p><i>'.implode(', ', $plugins).'</i></p>';
}
}
// Deactivate all non-standard themes
function deactivate_non_standard_themes()
{
global $page, $conf;
$standard_themes = array(
'clear',
'Sylvia',
'dark',
'elegant',
'smartpocket',
);
$query = '
SELECT
id,
name
FROM '.PREFIX_TABLE.'themes
WHERE id NOT IN (\''.implode("','", $standard_themes).'\')
;';
$result = pwg_query($query);
$theme_ids = array();
$theme_names = array();
while ($row = pwg_db_fetch_assoc($result))
{
$theme_ids[] = $row['id'];
$theme_names[] = $row['name'];
}
if (!empty($theme_ids))
{
$query = '
DELETE
FROM '.PREFIX_TABLE.'themes
WHERE id IN (\''.implode("','", $theme_ids).'\')
;';
pwg_query($query);
$page['infos'][] = l10n('As a precaution, following themes have been deactivated. You must check for themes upgrade before reactiving them:')
.'<p><i>'.implode(', ', $theme_names).'</i></p>';
// what is the default theme?
$query = '
SELECT theme
FROM '.PREFIX_TABLE.'user_infos
WHERE user_id = '.$conf['default_user_id'].'
;';
list($default_theme) = pwg_db_fetch_row(pwg_query($query));
// if the default theme has just been deactivated, let's set another core theme as default
if (in_array($default_theme, $theme_ids))
{
$query = '
UPDATE '.PREFIX_TABLE.'user_infos
SET theme = \'elegant\'
WHERE user_id = '.$conf['default_user_id'].'
;';
pwg_query($query);
}
}
}
// Deactivate all templates
function deactivate_templates()
{
conf_update_param('extents_for_templates', array());
}
// Check access rights
function check_upgrade_access_rights()
{
global $conf, $page, $current_release;
if (version_compare($current_release, '2.0', '>=') and isset($_COOKIE[session_name()]))
{
// Check if user is already connected as webmaster
session_start();
if (!empty($_SESSION['pwg_uid']))
{
$query = '
SELECT status
FROM '.USER_INFOS_TABLE.'
WHERE user_id = '.$_SESSION['pwg_uid'].'
;';
pwg_query($query);
$row = pwg_db_fetch_assoc(pwg_query($query));
if (isset($row['status']) and $row['status'] == 'webmaster')
{
define('PHPWG_IN_UPGRADE', true);
return;
}
}
}
if (!isset($_POST['username']) or !isset($_POST['password']))
{
return;
}
$username = $_POST['username'];
$password = $_POST['password'];
if(!@get_magic_quotes_gpc())
{
$username = pwg_db_real_escape_string($username);
}
if (version_compare($current_release, '2.0', '<'))
{
$username = utf8_decode($username);
$password = utf8_decode($password);
}
if (version_compare($current_release, '1.5', '<'))
{
$query = '
SELECT password, status
FROM '.USERS_TABLE.'
WHERE username = \''.$username.'\'
;';
}
else
{
$query = '
SELECT u.password, ui.status
FROM '.USERS_TABLE.' AS u
INNER JOIN '.USER_INFOS_TABLE.' AS ui
ON u.'.$conf['user_fields']['id'].'=ui.user_id
WHERE '.$conf['user_fields']['username'].'=\''.$username.'\'
;';
}
$row = pwg_db_fetch_assoc(pwg_query($query));
if (!$conf['password_verify']($password, $row['password']))
{
$page['errors'][] = l10n('Invalid password!');
}
elseif ($row['status'] != 'admin' and $row['status'] != 'webmaster')
{
$page['errors'][] = l10n('You do not have access rights to run upgrade');
}
else
{
define('PHPWG_IN_UPGRADE', true);
}
}
/**
* which upgrades are available ?
*
* @return array
*/
function get_available_upgrade_ids()
{
$upgrades_path = PHPWG_ROOT_PATH.'install/db';
$available_upgrade_ids = array();
if ($contents = opendir($upgrades_path))
{
while (($node = readdir($contents)) !== false)
{
if (is_file($upgrades_path.'/'.$node)
and preg_match('/^(.*?)-database\.php$/', $node, $match))
{
$available_upgrade_ids[] = $match[1];
}
}
}
natcasesort($available_upgrade_ids);
return $available_upgrade_ids;
}
/**
* returns true if there are available upgrade files
*/
function check_upgrade_feed()
{
// retrieve already applied upgrades
$query = '
SELECT id
FROM '.UPGRADE_TABLE.'
;';
$applied = array_from_query($query, 'id');
// retrieve existing upgrades
$existing = get_available_upgrade_ids();
// which upgrades need to be applied?
return (count(array_diff($existing, $applied)) > 0);
}
function upgrade_db_connect()
{
global $conf;
try
{
pwg_db_connect($conf['db_host'], $conf['db_user'],
$conf['db_password'], $conf['db_base']);
pwg_db_check_version();
}
catch (Exception $e)
{
my_error(l10n($e->getMessage()), true);
}
}
?>

View File

@@ -0,0 +1,752 @@
<?php
// +-----------------------------------------------------------------------+
// | Piwigo - a PHP based photo gallery |
// +-----------------------------------------------------------------------+
// | Copyright(C) 2008-2016 Piwigo Team http://piwigo.org |
// | Copyright(C) 2003-2008 PhpWebGallery Team http://phpwebgallery.net |
// | Copyright(C) 2002-2003 Pierrick LE GALL http://le-gall.net/pierrick |
// +-----------------------------------------------------------------------+
// | 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 |
// | |
// | 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, |
// | USA. |
// +-----------------------------------------------------------------------+
include_once(PHPWG_ROOT_PATH.'admin/include/functions.php');
include_once(PHPWG_ROOT_PATH.'admin/include/image.class.php');
// add default event handler for image and thumbnail resize
add_event_handler('upload_image_resize', 'pwg_image_resize');
add_event_handler('upload_thumbnail_resize', 'pwg_image_resize');
function get_upload_form_config()
{
// default configuration for upload
$upload_form_config = array(
'original_resize' => array(
'default' => false,
'can_be_null' => false,
),
'original_resize_maxwidth' => array(
'default' => 2000,
'min' => 500,
'max' => 20000,
'pattern' => '/^\d+$/',
'can_be_null' => false,
'error_message' => l10n('The original maximum width must be a number between %d and %d'),
),
'original_resize_maxheight' => array(
'default' => 2000,
'min' => 300,
'max' => 20000,
'pattern' => '/^\d+$/',
'can_be_null' => false,
'error_message' => l10n('The original maximum height must be a number between %d and %d'),
),
'original_resize_quality' => array(
'default' => 95,
'min' => 50,
'max' => 98,
'pattern' => '/^\d+$/',
'can_be_null' => false,
'error_message' => l10n('The original image quality must be a number between %d and %d'),
),
);
return $upload_form_config;
}
function save_upload_form_config($data, &$errors=array(), &$form_errors=array())
{
if (!is_array($data) or empty($data))
{
return false;
}
$upload_form_config = get_upload_form_config();
$updates = array();
foreach ($data as $field => $value)
{
if (!isset($upload_form_config[$field]))
{
continue;
}
if (is_bool($upload_form_config[$field]['default']))
{
if (isset($value))
{
$value = true;
}
else
{
$value = false;
}
$updates[] = array(
'param' => $field,
'value' => boolean_to_string($value)
);
}
elseif ($upload_form_config[$field]['can_be_null'] and empty($value))
{
$updates[] = array(
'param' => $field,
'value' => 'false'
);
}
else
{
$min = $upload_form_config[$field]['min'];
$max = $upload_form_config[$field]['max'];
$pattern = $upload_form_config[$field]['pattern'];
if (preg_match($pattern, $value) and $value >= $min and $value <= $max)
{
$updates[] = array(
'param' => $field,
'value' => $value
);
}
else
{
$errors[] = sprintf(
$upload_form_config[$field]['error_message'],
$min, $max
);
$form_errors[$field] = '['.$min.' .. '.$max.']';
}
}
}
if (count($errors) == 0)
{
mass_updates(
CONFIG_TABLE,
array(
'primary' => array('param'),
'update' => array('value')
),
$updates
);
return true;
}
return false;
}
function add_uploaded_file($source_filepath, $original_filename=null, $categories=null, $level=null, $image_id=null, $original_md5sum=null)
{
// 1) move uploaded file to upload/2010/01/22/20100122003814-449ada00.jpg
//
// 2) keep/resize original
//
// 3) register in database
// TODO
// * check md5sum (already exists?)
global $conf, $user;
if (!is_null($original_filename))
{
$original_filename = htmlspecialchars($original_filename);
}
if (isset($original_md5sum))
{
$md5sum = $original_md5sum;
}
else
{
$md5sum = md5_file($source_filepath);
}
$file_path = null;
$is_tiff = false;
if (isset($image_id))
{
// this photo already exists, we update it
$query = '
SELECT
path
FROM '.IMAGES_TABLE.'
WHERE id = '.$image_id.'
;';
$result = pwg_query($query);
while ($row = pwg_db_fetch_assoc($result))
{
$file_path = $row['path'];
}
if (!isset($file_path))
{
die('['.__FUNCTION__.'] this photo does not exist in the database');
}
// delete all physical files related to the photo (thumbnail, web site, HD)
delete_element_files(array($image_id));
}
else
{
// this photo is new
// current date
list($dbnow) = pwg_db_fetch_row(pwg_query('SELECT NOW();'));
list($year, $month, $day) = preg_split('/[^\d]/', $dbnow, 4);
// upload directory hierarchy
$upload_dir = sprintf(
PHPWG_ROOT_PATH.$conf['upload_dir'].'/%s/%s/%s',
$year,
$month,
$day
);
// compute file path
$date_string = preg_replace('/[^\d]/', '', $dbnow);
$random_string = substr($md5sum, 0, 8);
$filename_wo_ext = $date_string.'-'.$random_string;
$file_path = $upload_dir.'/'.$filename_wo_ext.'.';
list($width, $height, $type) = getimagesize($source_filepath);
if (IMAGETYPE_PNG == $type)
{
$file_path.= 'png';
}
elseif (IMAGETYPE_GIF == $type)
{
$file_path.= 'gif';
}
elseif (IMAGETYPE_TIFF_MM == $type or IMAGETYPE_TIFF_II == $type)
{
$is_tiff = true;
$file_path.= 'tif';
}
elseif (IMAGETYPE_JPEG == $type)
{
$file_path.= 'jpg';
}
elseif (isset($conf['upload_form_all_types']) and $conf['upload_form_all_types'])
{
$original_extension = strtolower(get_extension($original_filename));
if (in_array($original_extension, $conf['file_ext']))
{
$file_path.= $original_extension;
}
else
{
die('unexpected file type');
}
}
else
{
die('forbidden file type');
}
prepare_directory($upload_dir);
}
if (is_uploaded_file($source_filepath))
{
move_uploaded_file($source_filepath, $file_path);
}
else
{
rename($source_filepath, $file_path);
}
@chmod($file_path, 0644);
// handle the uploaded file type by potentially making a
// pwg_representative file.
$representative_ext = trigger_change('upload_file', null, $file_path);
global $logger;
$logger->info("Handling " . (string)$file_path . " got " . (string)$representative_ext);
// If it is set to either true (the file didn't need a
// representative generated) or false (the generation of the
// representative failed), set it to null because we have no
// representative file.
if (is_bool($representative_ext)) {
$representative_ext = null;
}
if (pwg_image::get_library() != 'gd')
{
if ($conf['original_resize'])
{
$need_resize = need_resize($file_path, $conf['original_resize_maxwidth'], $conf['original_resize_maxheight']);
if ($need_resize)
{
$img = new pwg_image($file_path);
$img->pwg_resize(
$file_path,
$conf['original_resize_maxwidth'],
$conf['original_resize_maxheight'],
$conf['original_resize_quality'],
$conf['upload_form_automatic_rotation'],
false
);
$img->destroy();
}
}
}
// we need to save the rotation angle in the database to compute
// width/height of "multisizes"
$rotation_angle = pwg_image::get_rotation_angle($file_path);
$rotation = pwg_image::get_rotation_code_from_angle($rotation_angle);
$file_infos = pwg_image_infos($file_path);
if (isset($image_id))
{
$update = array(
'file' => pwg_db_real_escape_string(isset($original_filename) ? $original_filename : basename($file_path)),
'filesize' => $file_infos['filesize'],
'width' => $file_infos['width'],
'height' => $file_infos['height'],
'md5sum' => $md5sum,
'added_by' => $user['id'],
'rotation' => $rotation,
);
if (isset($level))
{
$update['level'] = $level;
}
single_update(
IMAGES_TABLE,
$update,
array('id' => $image_id)
);
}
else
{
// database registration
$file = pwg_db_real_escape_string(isset($original_filename) ? $original_filename : basename($file_path));
$insert = array(
'file' => $file,
'name' => get_name_from_file($file),
'date_available' => $dbnow,
'path' => preg_replace('#^'.preg_quote(PHPWG_ROOT_PATH).'#', '', $file_path),
'filesize' => $file_infos['filesize'],
'width' => $file_infos['width'],
'height' => $file_infos['height'],
'md5sum' => $md5sum,
'added_by' => $user['id'],
'rotation' => $rotation,
);
if (isset($level))
{
$insert['level'] = $level;
}
if (isset($representative_ext))
{
$insert['representative_ext'] = $representative_ext;
}
single_insert(IMAGES_TABLE, $insert);
$image_id = pwg_db_insert_id(IMAGES_TABLE);
}
if (isset($categories) and count($categories) > 0)
{
associate_images_to_categories(
array($image_id),
$categories
);
}
// update metadata from the uploaded file (exif/iptc)
if ($conf['use_exif'] and !function_exists('read_exif_data'))
{
$conf['use_exif'] = false;
}
sync_metadata(array($image_id));
invalidate_user_cache();
// cache thumbnail
$query = '
SELECT
id,
path
FROM '.IMAGES_TABLE.'
WHERE id = '.$image_id.'
;';
$image_infos = pwg_db_fetch_assoc(pwg_query($query));
set_make_full_url();
// in case we are on uploadify.php, we have to replace the false path
$thumb_url = preg_replace('#admin/include/i#', 'i', DerivativeImage::thumb_url($image_infos));
unset_make_full_url();
fetchRemote($thumb_url, $dest);
return $image_id;
}
add_event_handler('upload_file', 'upload_file_pdf');
function upload_file_pdf($representative_ext, $file_path)
{
global $logger, $conf;
$logger->info(__FUNCTION__.', $file_path = '.$file_path.', $representative_ext = '.$representative_ext);
if (isset($representative_ext))
{
return $representative_ext;
}
if (pwg_image::get_library() != 'ext_imagick')
{
return $representative_ext;
}
if (!in_array(strtolower(get_extension($file_path)), array('pdf')))
{
return $representative_ext;
}
$ext = conf_get_param('pdf_representative_ext', 'jpg');
$jpg_quality = conf_get_param('pdf_jpg_quality', 90);
// move the uploaded file to pwg_representative sub-directory
$representative_file_path = original_to_representative($file_path, $ext);
prepare_directory(dirname($representative_file_path));
$exec = $conf['ext_imagick_dir'].'convert';
if ('jpg' == $ext)
{
$exec.= ' -quality '.$jpg_quality;
}
$exec.= ' "'.realpath($file_path).'"[0]';
$exec.= ' "'.$representative_file_path.'"';
$exec.= ' 2>&1';
@exec($exec, $returnarray);
// Return the extension (if successful) or false (if failed)
if (file_exists($representative_file_path))
{
$representative_ext = $ext;
}
return $representative_ext;
}
add_event_handler('upload_file', 'upload_file_tiff');
function upload_file_tiff($representative_ext, $file_path)
{
global $logger, $conf;
$logger->info(__FUNCTION__.', $file_path = '.$file_path.', $representative_ext = '.$representative_ext);
if (isset($representative_ext))
{
return $representative_ext;
}
if (pwg_image::get_library() != 'ext_imagick')
{
return $representative_ext;
}
if (!in_array(strtolower(get_extension($file_path)), array('tif', 'tiff')))
{
return $representative_ext;
}
// move the uploaded file to pwg_representative sub-directory
$representative_file_path = dirname($file_path).'/pwg_representative/';
$representative_file_path.= get_filename_wo_extension(basename($file_path)).'.';
$representative_ext = $conf['tiff_representative_ext'];
$representative_file_path.= $representative_ext;
prepare_directory(dirname($representative_file_path));
$exec = $conf['ext_imagick_dir'].'convert';
if ('jpg' == $conf['tiff_representative_ext'])
{
$exec .= ' -quality 98';
}
$exec .= ' "'.realpath($file_path).'"';
$dest = pathinfo($representative_file_path);
$exec .= ' "'.realpath($dest['dirname']).'/'.$dest['basename'].'"';
$exec .= ' 2>&1';
@exec($exec, $returnarray);
// sometimes ImageMagick creates file-0.jpg (full size) + file-1.jpg
// (thumbnail). I don't know how to avoid it.
$representative_file_abspath = realpath($dest['dirname']).'/'.$dest['basename'];
if (!file_exists($representative_file_abspath))
{
$first_file_abspath = preg_replace(
'/\.'.$representative_ext.'$/',
'-0.'.$representative_ext,
$representative_file_abspath
);
if (file_exists($first_file_abspath))
{
rename($first_file_abspath, $representative_file_abspath);
}
}
return get_extension($representative_file_abspath);
}
add_event_handler('upload_file', 'upload_file_video');
function upload_file_video($representative_ext, $file_path)
{
global $logger, $conf;
$logger->info(__FUNCTION__.', $file_path = '.$file_path.', $representative_ext = '.$representative_ext);
if (isset($representative_ext))
{
return $representative_ext;
}
$ffmpeg_video_exts = array( // extensions tested with FFmpeg
'wmv','mov','mkv','mp4','mpg','flv','asf','xvid','divx','mpeg',
'avi','rm', 'm4v', 'ogg', 'ogv', 'webm', 'webmv',
);
if (!in_array(strtolower(get_extension($file_path)), $ffmpeg_video_exts))
{
return $representative_ext;
}
$representative_file_path = dirname($file_path).'/pwg_representative/';
$representative_file_path.= get_filename_wo_extension(basename($file_path)).'.';
$representative_ext = 'jpg';
$representative_file_path.= $representative_ext;
prepare_directory(dirname($representative_file_path));
$second = 1;
$ffmpeg = $conf['ffmpeg_dir'].'ffmpeg';
$ffmpeg.= ' -i "'.$file_path.'"';
$ffmpeg.= ' -an -ss '.$second;
$ffmpeg.= ' -t 1 -r 1 -y -vcodec mjpeg -f mjpeg';
$ffmpeg.= ' "'.$representative_file_path.'"';
@exec($ffmpeg);
if (!file_exists($representative_file_path))
{
return null;
}
return $representative_ext;
}
function prepare_directory($directory)
{
if (!is_dir($directory)) {
if (substr(PHP_OS, 0, 3) == 'WIN')
{
$directory = str_replace('/', DIRECTORY_SEPARATOR, $directory);
}
umask(0000);
$recursive = true;
if (!@mkdir($directory, 0777, $recursive))
{
die('[prepare_directory] cannot create directory "'.$directory.'"');
}
}
if (!is_writable($directory))
{
// last chance to make the directory writable
@chmod($directory, 0777);
if (!is_writable($directory))
{
die('[prepare_directory] directory "'.$directory.'" has no write access');
}
}
secure_directory($directory);
}
function need_resize($image_filepath, $max_width, $max_height)
{
// TODO : the resize check should take the orientation into account. If a
// rotation must be applied to the resized photo, then we should test
// invert width and height.
list($width, $height) = getimagesize($image_filepath);
if ($width > $max_width or $height > $max_height)
{
return true;
}
return false;
}
function pwg_image_infos($path)
{
list($width, $height) = getimagesize($path);
$filesize = floor(filesize($path)/1024);
return array(
'width' => $width,
'height' => $height,
'filesize' => $filesize,
);
}
function is_valid_image_extension($extension)
{
global $conf;
if (isset($conf['upload_form_all_types']) and $conf['upload_form_all_types'])
{
$extensions = $conf['file_ext'];
}
else
{
$extensions = $conf['picture_ext'];
}
return array_unique(array_map('strtolower', $extensions));
}
function file_upload_error_message($error_code)
{
switch ($error_code) {
case UPLOAD_ERR_INI_SIZE:
return sprintf(
l10n('The uploaded file exceeds the upload_max_filesize directive in php.ini: %sB'),
get_ini_size('upload_max_filesize', false)
);
case UPLOAD_ERR_FORM_SIZE:
return l10n('The uploaded file exceeds the MAX_FILE_SIZE directive that was specified in the HTML form');
case UPLOAD_ERR_PARTIAL:
return l10n('The uploaded file was only partially uploaded');
case UPLOAD_ERR_NO_FILE:
return l10n('No file was uploaded');
case UPLOAD_ERR_NO_TMP_DIR:
return l10n('Missing a temporary folder');
case UPLOAD_ERR_CANT_WRITE:
return l10n('Failed to write file to disk');
case UPLOAD_ERR_EXTENSION:
return l10n('File upload stopped by extension');
default:
return l10n('Unknown upload error');
}
}
function get_ini_size($ini_key, $in_bytes=true)
{
$size = ini_get($ini_key);
if ($in_bytes)
{
$size = convert_shorthand_notation_to_bytes($size);
}
return $size;
}
function convert_shorthand_notation_to_bytes($value)
{
$suffix = substr($value, -1);
$multiply_by = null;
if ('K' == $suffix)
{
$multiply_by = 1024;
}
else if ('M' == $suffix)
{
$multiply_by = 1024*1024;
}
else if ('G' == $suffix)
{
$multiply_by = 1024*1024*1024;
}
if (isset($multiply_by))
{
$value = substr($value, 0, -1);
$value*= $multiply_by;
}
return $value;
}
function add_upload_error($upload_id, $error_message)
{
$_SESSION['uploads_error'][$upload_id][] = $error_message;
}
function ready_for_upload_message()
{
global $conf;
$relative_dir = preg_replace('#^'.PHPWG_ROOT_PATH.'#', '', $conf['upload_dir']);
if (!is_dir($conf['upload_dir']))
{
if (!is_writable(dirname($conf['upload_dir'])))
{
return sprintf(
l10n('Create the "%s" directory at the root of your Piwigo installation'),
$relative_dir
);
}
}
else
{
if (!is_writable($conf['upload_dir']))
{
@chmod($conf['upload_dir'], 0777);
if (!is_writable($conf['upload_dir']))
{
return sprintf(
l10n('Give write access (chmod 777) to "%s" directory at the root of your Piwigo installation'),
$relative_dir
);
}
}
}
return null;
}
?>

View File

@@ -0,0 +1,828 @@
<?php
// +-----------------------------------------------------------------------+
// | Piwigo - a PHP based photo gallery |
// +-----------------------------------------------------------------------+
// | Copyright(C) 2008-2016 Piwigo Team http://piwigo.org |
// | Copyright(C) 2003-2008 PhpWebGallery Team http://phpwebgallery.net |
// | Copyright(C) 2002-2003 Pierrick LE GALL http://le-gall.net/pierrick |
// +-----------------------------------------------------------------------+
// | 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 |
// | |
// | 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, |
// | USA. |
// +-----------------------------------------------------------------------+
// +-----------------------------------------------------------------------+
// | Image Interface |
// +-----------------------------------------------------------------------+
// Define all needed methods for image class
interface imageInterface
{
function get_width();
function get_height();
function set_compression_quality($quality);
function crop($width, $height, $x, $y);
function strip();
function rotate($rotation);
function resize($width, $height);
function sharpen($amount);
function compose($overlay, $x, $y, $opacity);
function write($destination_filepath);
}
// +-----------------------------------------------------------------------+
// | Main Image Class |
// +-----------------------------------------------------------------------+
class pwg_image
{
var $image;
var $library = '';
var $source_filepath = '';
static $ext_imagick_version = '';
function __construct($source_filepath, $library=null)
{
$this->source_filepath = $source_filepath;
trigger_notify('load_image_library', array(&$this) );
if (is_object($this->image))
{
return; // A plugin may have load its own library
}
$extension = strtolower(get_extension($source_filepath));
if (!in_array($extension, array('jpg', 'jpeg', 'png', 'gif')))
{
die('[Image] unsupported file extension');
}
if (!($this->library = self::get_library($library, $extension)))
{
die('No image library available on your server.');
}
$class = 'image_'.$this->library;
$this->image = new $class($source_filepath);
}
// Unknow methods will be redirected to image object
function __call($method, $arguments)
{
return call_user_func_array(array($this->image, $method), $arguments);
}
// Piwigo resize function
function pwg_resize($destination_filepath, $max_width, $max_height, $quality, $automatic_rotation=true, $strip_metadata=false, $crop=false, $follow_orientation=true)
{
$starttime = get_moment();
// width/height
$source_width = $this->image->get_width();
$source_height = $this->image->get_height();
$rotation = null;
if ($automatic_rotation)
{
$rotation = self::get_rotation_angle($this->source_filepath);
}
$resize_dimensions = self::get_resize_dimensions($source_width, $source_height, $max_width, $max_height, $rotation, $crop, $follow_orientation);
// testing on height is useless in theory: if width is unchanged, there
// should be no resize, because width/height ratio is not modified.
if ($resize_dimensions['width'] == $source_width and $resize_dimensions['height'] == $source_height)
{
// the image doesn't need any resize! We just copy it to the destination
copy($this->source_filepath, $destination_filepath);
return $this->get_resize_result($destination_filepath, $resize_dimensions['width'], $resize_dimensions['height'], $starttime);
}
$this->image->set_compression_quality($quality);
if ($strip_metadata)
{
// we save a few kilobytes. For example a thumbnail with metadata weights 25KB, without metadata 7KB.
$this->image->strip();
}
if (isset($resize_dimensions['crop']))
{
$this->image->crop($resize_dimensions['crop']['width'], $resize_dimensions['crop']['height'], $resize_dimensions['crop']['x'], $resize_dimensions['crop']['y']);
}
$this->image->resize($resize_dimensions['width'], $resize_dimensions['height']);
if (!empty($rotation))
{
$this->image->rotate($rotation);
}
$this->image->write($destination_filepath);
// everything should be OK if we are here!
return $this->get_resize_result($destination_filepath, $resize_dimensions['width'], $resize_dimensions['height'], $starttime);
}
static function get_resize_dimensions($width, $height, $max_width, $max_height, $rotation=null, $crop=false, $follow_orientation=true)
{
$rotate_for_dimensions = false;
if (isset($rotation) and in_array(abs($rotation), array(90, 270)))
{
$rotate_for_dimensions = true;
}
if ($rotate_for_dimensions)
{
list($width, $height) = array($height, $width);
}
if ($crop)
{
$x = 0;
$y = 0;
if ($width < $height and $follow_orientation)
{
list($max_width, $max_height) = array($max_height, $max_width);
}
$img_ratio = $width / $height;
$dest_ratio = $max_width / $max_height;
if($dest_ratio > $img_ratio)
{
$destHeight = round($width * $max_height / $max_width);
$y = round(($height - $destHeight) / 2 );
$height = $destHeight;
}
elseif ($dest_ratio < $img_ratio)
{
$destWidth = round($height * $max_width / $max_height);
$x = round(($width - $destWidth) / 2 );
$width = $destWidth;
}
}
$ratio_width = $width / $max_width;
$ratio_height = $height / $max_height;
$destination_width = $width;
$destination_height = $height;
// maximal size exceeded ?
if ($ratio_width > 1 or $ratio_height > 1)
{
if ($ratio_width < $ratio_height)
{
$destination_width = round($width / $ratio_height);
$destination_height = $max_height;
}
else
{
$destination_width = $max_width;
$destination_height = round($height / $ratio_width);
}
}
if ($rotate_for_dimensions)
{
list($destination_width, $destination_height) = array($destination_height, $destination_width);
}
$result = array(
'width' => $destination_width,
'height'=> $destination_height,
);
if ($crop and ($x or $y))
{
$result['crop'] = array(
'width' => $width,
'height' => $height,
'x' => $x,
'y' => $y,
);
}
return $result;
}
static function get_rotation_angle($source_filepath)
{
list($width, $height, $type) = getimagesize($source_filepath);
if (IMAGETYPE_JPEG != $type)
{
return null;
}
if (!function_exists('exif_read_data'))
{
return null;
}
$rotation = 0;
$exif = @exif_read_data($source_filepath);
if (isset($exif['Orientation']) and preg_match('/^\s*(\d)/', $exif['Orientation'], $matches))
{
$orientation = $matches[1];
if (in_array($orientation, array(3, 4)))
{
$rotation = 180;
}
elseif (in_array($orientation, array(5, 6)))
{
$rotation = 270;
}
elseif (in_array($orientation, array(7, 8)))
{
$rotation = 90;
}
}
return $rotation;
}
static function get_rotation_code_from_angle($rotation_angle)
{
switch($rotation_angle)
{
case 0: return 0;
case 90: return 1;
case 180: return 2;
case 270: return 3;
}
}
static function get_rotation_angle_from_code($rotation_code)
{
switch($rotation_code%4)
{
case 0: return 0;
case 1: return 90;
case 2: return 180;
case 3: return 270;
}
}
/** Returns a normalized convolution kernel for sharpening*/
static function get_sharpen_matrix($amount)
{
// Amount should be in the range of 48-10
$amount = round(abs(-48 + ($amount * 0.38)), 2);
$matrix = array(
array(-1, -1, -1),
array(-1, $amount, -1),
array(-1, -1, -1),
);
$norm = array_sum(array_map('array_sum', $matrix));
for ($i=0; $i<3; $i++)
{
for ($j=0; $j<3; $j++)
{
$matrix[$i][$j] /= $norm;
}
}
return $matrix;
}
private function get_resize_result($destination_filepath, $width, $height, $time=null)
{
return array(
'source' => $this->source_filepath,
'destination' => $destination_filepath,
'width' => $width,
'height' => $height,
'size' => floor(filesize($destination_filepath) / 1024).' KB',
'time' => $time ? number_format((get_moment() - $time) * 1000, 2, '.', ' ').' ms' : null,
'library' => $this->library,
);
}
static function is_imagick()
{
return (extension_loaded('imagick') and class_exists('Imagick'));
}
static function is_ext_imagick()
{
global $conf;
if (!function_exists('exec'))
{
return false;
}
@exec($conf['ext_imagick_dir'].'convert -version', $returnarray);
if (is_array($returnarray) and !empty($returnarray[0]) and preg_match('/ImageMagick/i', $returnarray[0]))
{
if (preg_match('/Version: ImageMagick (\d+\.\d+\.\d+-?\d*)/', $returnarray[0], $match))
{
self::$ext_imagick_version = $match[1];
}
return true;
}
return false;
}
static function is_gd()
{
return function_exists('gd_info');
}
static function get_library($library=null, $extension=null)
{
global $conf;
if (is_null($library))
{
$library = $conf['graphics_library'];
}
// Choose image library
switch (strtolower($library))
{
case 'auto':
case 'imagick':
if ($extension != 'gif' and self::is_imagick())
{
return 'imagick';
}
case 'ext_imagick':
if ($extension != 'gif' and self::is_ext_imagick())
{
return 'ext_imagick';
}
case 'gd':
if (self::is_gd())
{
return 'gd';
}
default:
if ($library != 'auto')
{
// Requested library not available. Try another library
return self::get_library('auto', $extension);
}
}
return false;
}
function destroy()
{
if (method_exists($this->image, 'destroy'))
{
return $this->image->destroy();
}
return true;
}
}
// +-----------------------------------------------------------------------+
// | Class for Imagick extension |
// +-----------------------------------------------------------------------+
class image_imagick implements imageInterface
{
var $image;
function __construct($source_filepath)
{
// A bug cause that Imagick class can not be extended
$this->image = new Imagick($source_filepath);
}
function get_width()
{
return $this->image->getImageWidth();
}
function get_height()
{
return $this->image->getImageHeight();
}
function set_compression_quality($quality)
{
return $this->image->setImageCompressionQuality($quality);
}
function crop($width, $height, $x, $y)
{
return $this->image->cropImage($width, $height, $x, $y);
}
function strip()
{
return $this->image->stripImage();
}
function rotate($rotation)
{
$this->image->rotateImage(new ImagickPixel(), -$rotation);
$this->image->setImageOrientation(Imagick::ORIENTATION_TOPLEFT);
return true;
}
function resize($width, $height)
{
$this->image->setInterlaceScheme(Imagick::INTERLACE_LINE);
// TODO need to explain this condition
if ($this->get_width()%2 == 0
&& $this->get_height()%2 == 0
&& $this->get_width() > 3*$width)
{
$this->image->scaleImage($this->get_width()/2, $this->get_height()/2);
}
return $this->image->resizeImage($width, $height, Imagick::FILTER_LANCZOS, 0.9);
}
function sharpen($amount)
{
$m = pwg_image::get_sharpen_matrix($amount);
return $this->image->convolveImage($m);
}
function compose($overlay, $x, $y, $opacity)
{
$ioverlay = $overlay->image->image;
/*if ($ioverlay->getImageAlphaChannel() !== Imagick::ALPHACHANNEL_OPAQUE)
{
// Force the image to have an alpha channel
$ioverlay->setImageAlphaChannel(Imagick::ALPHACHANNEL_OPAQUE);
}*/
global $dirty_trick_xrepeat;
if ( !isset($dirty_trick_xrepeat) && $opacity < 100)
{// NOTE: Using setImageOpacity will destroy current alpha channels!
$ioverlay->evaluateImage(Imagick::EVALUATE_MULTIPLY, $opacity / 100, Imagick::CHANNEL_ALPHA);
$dirty_trick_xrepeat = true;
}
return $this->image->compositeImage($ioverlay, Imagick::COMPOSITE_DISSOLVE, $x, $y);
}
function write($destination_filepath)
{
// use 4:2:2 chroma subsampling (reduce file size by 20-30% with "almost" no human perception)
$this->image->setSamplingFactors( array(2,1) );
return $this->image->writeImage($destination_filepath);
}
}
// +-----------------------------------------------------------------------+
// | Class for ImageMagick external installation |
// +-----------------------------------------------------------------------+
class image_ext_imagick implements imageInterface
{
var $imagickdir = '';
var $source_filepath = '';
var $width = '';
var $height = '';
var $commands = array();
function __construct($source_filepath)
{
global $conf;
$this->source_filepath = $source_filepath;
$this->imagickdir = $conf['ext_imagick_dir'];
if (strpos(@$_SERVER['SCRIPT_FILENAME'], '/kunden/') === 0) // 1and1
{
@putenv('MAGICK_THREAD_LIMIT=1');
}
$command = $this->imagickdir.'identify -format "%wx%h" "'.realpath($source_filepath).'"';
@exec($command, $returnarray);
if(!is_array($returnarray) or empty($returnarray[0]) or !preg_match('/^(\d+)x(\d+)$/', $returnarray[0], $match))
{
die("[External ImageMagick] Corrupt image\n" . var_export($returnarray, true));
}
$this->width = $match[1];
$this->height = $match[2];
}
function add_command($command, $params=null)
{
$this->commands[$command] = $params;
}
function get_width()
{
return $this->width;
}
function get_height()
{
return $this->height;
}
function crop($width, $height, $x, $y)
{
$this->width = $width;
$this->height = $height;
$this->add_command('crop', $width.'x'.$height.'+'.$x.'+'.$y);
return true;
}
function strip()
{
$this->add_command('strip');
return true;
}
function rotate($rotation)
{
if (empty($rotation))
{
return true;
}
if ($rotation==90 || $rotation==270)
{
$tmp = $this->width;
$this->width = $this->height;
$this->height = $tmp;
}
$this->add_command('rotate', -$rotation);
$this->add_command('orient', 'top-left');
return true;
}
function set_compression_quality($quality)
{
$this->add_command('quality', $quality);
return true;
}
function resize($width, $height)
{
$this->width = $width;
$this->height = $height;
$this->add_command('filter', 'Lanczos');
$this->add_command('resize', $width.'x'.$height.'!');
return true;
}
function sharpen($amount)
{
$m = pwg_image::get_sharpen_matrix($amount);
$param ='convolve "'.count($m).':';
foreach ($m as $line)
{
$param .= ' ';
$param .= implode(',', $line);
}
$param .= '"';
$this->add_command('morphology', $param);
return true;
}
function compose($overlay, $x, $y, $opacity)
{
$param = 'compose dissolve -define compose:args='.$opacity;
$param .= ' '.escapeshellarg(realpath($overlay->image->source_filepath));
$param .= ' -gravity NorthWest -geometry +'.$x.'+'.$y;
$param .= ' -composite';
$this->add_command($param);
return true;
}
function write($destination_filepath)
{
global $logger;
$this->add_command('interlace', 'line'); // progressive rendering
// use 4:2:2 chroma subsampling (reduce file size by 20-30% with "almost" no human perception)
//
// option deactivated for Piwigo 2.4.1, it doesn't work fo old versions
// of ImageMagick, see bug:2672. To reactivate once we have a better way
// to detect IM version and when we know which version supports this
// option
//
if (version_compare(pwg_image::$ext_imagick_version, '6.6') > 0)
{
$this->add_command('sampling-factor', '4:2:2' );
}
$exec = $this->imagickdir.'convert';
$exec .= ' "'.realpath($this->source_filepath).'"';
foreach ($this->commands as $command => $params)
{
$exec .= ' -'.$command;
if (!empty($params))
{
$exec .= ' '.$params;
}
}
$dest = pathinfo($destination_filepath);
$exec .= ' "'.realpath($dest['dirname']).'/'.$dest['basename'].'" 2>&1';
$logger->debug($exec, 'i.php');
@exec($exec, $returnarray);
if (is_array($returnarray) && (count($returnarray)>0) )
{
$logger->error('', 'i.php', $returnarray);
foreach ($returnarray as $line)
trigger_error($line, E_USER_WARNING);
}
return is_array($returnarray);
}
}
// +-----------------------------------------------------------------------+
// | Class for GD library |
// +-----------------------------------------------------------------------+
class image_gd implements imageInterface
{
var $image;
var $quality = 95;
function __construct($source_filepath)
{
$gd_info = gd_info();
$extension = strtolower(get_extension($source_filepath));
if (in_array($extension, array('jpg', 'jpeg')))
{
$this->image = imagecreatefromjpeg($source_filepath);
}
else if ($extension == 'png')
{
$this->image = imagecreatefrompng($source_filepath);
}
elseif ($extension == 'gif' and $gd_info['GIF Read Support'] and $gd_info['GIF Create Support'])
{
$this->image = imagecreatefromgif($source_filepath);
}
else
{
die('[Image GD] unsupported file extension');
}
}
function get_width()
{
return imagesx($this->image);
}
function get_height()
{
return imagesy($this->image);
}
function crop($width, $height, $x, $y)
{
$dest = imagecreatetruecolor($width, $height);
imagealphablending($dest, false);
imagesavealpha($dest, true);
if (function_exists('imageantialias'))
{
imageantialias($dest, true);
}
$result = imagecopymerge($dest, $this->image, 0, 0, $x, $y, $width, $height, 100);
if ($result !== false)
{
imagedestroy($this->image);
$this->image = $dest;
}
else
{
imagedestroy($dest);
}
return $result;
}
function strip()
{
return true;
}
function rotate($rotation)
{
$dest = imagerotate($this->image, $rotation, 0);
imagedestroy($this->image);
$this->image = $dest;
return true;
}
function set_compression_quality($quality)
{
$this->quality = $quality;
return true;
}
function resize($width, $height)
{
$dest = imagecreatetruecolor($width, $height);
imagealphablending($dest, false);
imagesavealpha($dest, true);
if (function_exists('imageantialias'))
{
imageantialias($dest, true);
}
$result = imagecopyresampled($dest, $this->image, 0, 0, 0, 0, $width, $height, $this->get_width(), $this->get_height());
if ($result !== false)
{
imagedestroy($this->image);
$this->image = $dest;
}
else
{
imagedestroy($dest);
}
return $result;
}
function sharpen($amount)
{
$m = pwg_image::get_sharpen_matrix($amount);
return imageconvolution($this->image, $m, 1, 0);
}
function compose($overlay, $x, $y, $opacity)
{
$ioverlay = $overlay->image->image;
/* A replacement for php's imagecopymerge() function that supports the alpha channel
See php bug #23815: http://bugs.php.net/bug.php?id=23815 */
$ow = imagesx($ioverlay);
$oh = imagesy($ioverlay);
// Create a new blank image the site of our source image
$cut = imagecreatetruecolor($ow, $oh);
// Copy the blank image into the destination image where the source goes
imagecopy($cut, $this->image, 0, 0, $x, $y, $ow, $oh);
// Place the source image in the destination image
imagecopy($cut, $ioverlay, 0, 0, 0, 0, $ow, $oh);
imagecopymerge($this->image, $cut, $x, $y, 0, 0, $ow, $oh, $opacity);
imagedestroy($cut);
return true;
}
function write($destination_filepath)
{
$extension = strtolower(get_extension($destination_filepath));
if ($extension == 'png')
{
imagepng($this->image, $destination_filepath);
}
elseif ($extension == 'gif')
{
imagegif($this->image, $destination_filepath);
}
else
{
imagejpeg($this->image, $destination_filepath, $this->quality);
}
}
function destroy()
{
imagedestroy($this->image);
}
}
?>

View File

@@ -0,0 +1,30 @@
<?php
// +-----------------------------------------------------------------------+
// | Piwigo - a PHP based photo gallery |
// +-----------------------------------------------------------------------+
// | Copyright(C) 2008-2016 Piwigo Team http://piwigo.org |
// | Copyright(C) 2003-2008 PhpWebGallery Team http://phpwebgallery.net |
// | Copyright(C) 2002-2003 Pierrick LE GALL http://le-gall.net/pierrick |
// +-----------------------------------------------------------------------+
// | 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 |
// | |
// | 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, |
// | USA. |
// +-----------------------------------------------------------------------+
// Recursive call
$url = '../';
header( 'Request-URI: '.$url );
header( 'Content-Location: '.$url );
header( 'Location: '.$url );
exit();
?>

View File

@@ -0,0 +1,441 @@
<?php
// +-----------------------------------------------------------------------+
// | Piwigo - a PHP based photo gallery |
// +-----------------------------------------------------------------------+
// | Copyright(C) 2008-2016 Piwigo Team http://piwigo.org |
// | Copyright(C) 2003-2008 PhpWebGallery Team http://phpwebgallery.net |
// | Copyright(C) 2002-2003 Pierrick LE GALL http://le-gall.net/pierrick |
// +-----------------------------------------------------------------------+
// | 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 |
// | |
// | 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, |
// | USA. |
// +-----------------------------------------------------------------------+
class languages
{
var $fs_languages = array();
var $db_languages = array();
var $server_languages = array();
/**
* Initialize $fs_languages and $db_languages
*/
function __construct($target_charset = null)
{
$this->get_fs_languages($target_charset);
}
/**
* Perform requested actions
* @param string - action
* @param string - language id
* @param array - errors
*/
function perform_action($action, $language_id)
{
global $conf;
if (isset($this->db_languages[$language_id]))
{
$crt_db_language = $this->db_languages[$language_id];
}
$errors = array();
switch ($action)
{
case 'activate':
if (isset($crt_db_language))
{
$errors[] = 'CANNOT ACTIVATE - LANGUAGE IS ALREADY ACTIVATED';
break;
}
$query = '
INSERT INTO '.LANGUAGES_TABLE.'
(id, version, name)
VALUES(\''.$language_id.'\',
\''.$this->fs_languages[$language_id]['version'].'\',
\''.$this->fs_languages[$language_id]['name'].'\')
;';
pwg_query($query);
break;
case 'deactivate':
if (!isset($crt_db_language))
{
$errors[] = 'CANNOT DEACTIVATE - LANGUAGE IS ALREADY DEACTIVATED';
break;
}
if ($language_id == get_default_language())
{
$errors[] = 'CANNOT DEACTIVATE - LANGUAGE IS DEFAULT LANGUAGE';
break;
}
$query = '
DELETE
FROM '.LANGUAGES_TABLE.'
WHERE id= \''.$language_id.'\'
;';
pwg_query($query);
break;
case 'delete':
if (!empty($crt_db_language))
{
$errors[] = 'CANNOT DELETE - LANGUAGE IS ACTIVATED';
break;
}
if (!isset($this->fs_languages[$language_id]))
{
$errors[] = 'CANNOT DELETE - LANGUAGE DOES NOT EXIST';
break;
}
// Set default language to user who are using this language
$query = '
UPDATE '.USER_INFOS_TABLE.'
SET language = \''.get_default_language().'\'
WHERE language = \''.$language_id.'\'
;';
pwg_query($query);
deltree(PHPWG_ROOT_PATH.'language/'.$language_id, PHPWG_ROOT_PATH.'language/trash');
break;
case 'set_default':
$query = '
UPDATE '.USER_INFOS_TABLE.'
SET language = \''.$language_id.'\'
WHERE user_id IN ('.$conf['default_user_id'].', '.$conf['guest_id'].')
;';
pwg_query($query);
break;
}
return $errors;
}
/**
* Get languages defined in the language directory
*/
function get_fs_languages($target_charset = null)
{
if ( empty($target_charset) )
{
$target_charset = get_pwg_charset();
}
$target_charset = strtolower($target_charset);
$dir = opendir(PHPWG_ROOT_PATH.'language');
while ($file = readdir($dir))
{
if ($file!='.' and $file!='..')
{
$path = PHPWG_ROOT_PATH.'language/'.$file;
if (is_dir($path) and !is_link($path)
and preg_match('/^[a-zA-Z0-9-_]+$/', $file )
and file_exists($path.'/common.lang.php')
)
{
$language = array(
'name'=>$file,
'code'=>$file,
'version'=>'0',
'uri'=>'',
'author'=>'',
);
$plg_data = implode( '', file($path.'/common.lang.php') );
if (preg_match("|Language Name:\\s*(.+)|", $plg_data, $val))
{
$language['name'] = trim( $val[1] );
$language['name'] = convert_charset($language['name'], 'utf-8', $target_charset);
}
if (preg_match("|Version:\\s*([\\w.-]+)|", $plg_data, $val))
{
$language['version'] = trim($val[1]);
}
if (preg_match("|Language URI:\\s*(https?:\\/\\/.+)|", $plg_data, $val))
{
$language['uri'] = trim($val[1]);
}
if (preg_match("|Author:\\s*(.+)|", $plg_data, $val))
{
$language['author'] = trim($val[1]);
}
if (preg_match("|Author URI:\\s*(https?:\\/\\/.+)|", $plg_data, $val))
{
$language['author uri'] = trim($val[1]);
}
if (!empty($language['uri']) and strpos($language['uri'] , 'extension_view.php?eid='))
{
list( , $extension) = explode('extension_view.php?eid=', $language['uri']);
if (is_numeric($extension)) $language['extension'] = $extension;
}
// IMPORTANT SECURITY !
$language = array_map('htmlspecialchars', $language);
$this->fs_languages[$file] = $language;
}
}
}
closedir($dir);
@uasort($this->fs_languages, 'name_compare');
}
function get_db_languages()
{
$query = '
SELECT id, name
FROM '.LANGUAGES_TABLE.'
ORDER BY name ASC
;';
$result = pwg_query($query);
while ($row = pwg_db_fetch_assoc($result))
{
$this->db_languages[ $row['id'] ] = $row['name'];
}
}
/**
* Retrieve PEM server datas to $server_languages
*/
function get_server_languages($new=false)
{
global $user, $conf;
$get_data = array(
'category_id' => $conf['pem_languages_category'],
'format' => 'php',
);
// Retrieve PEM versions
$version = PHPWG_VERSION;
$versions_to_check = array();
$url = PEM_URL . '/api/get_version_list.php';
if (fetchRemote($url, $result, $get_data) and $pem_versions = @unserialize($result))
{
if (!preg_match('/^\d+\.\d+\.\d+$/', $version))
{
$version = $pem_versions[0]['name'];
}
$branch = get_branch_from_version($version);
foreach ($pem_versions as $pem_version)
{
if (strpos($pem_version['name'], $branch) === 0)
{
$versions_to_check[] = $pem_version['id'];
}
}
}
if (empty($versions_to_check))
{
return false;
}
// Languages to check
$languages_to_check = array();
foreach($this->fs_languages as $fs_language)
{
if (isset($fs_language['extension']))
{
$languages_to_check[] = $fs_language['extension'];
}
}
// Retrieve PEM languages infos
$url = PEM_URL . '/api/get_revision_list.php';
$get_data = array_merge($get_data, array(
'last_revision_only' => 'true',
'version' => implode(',', $versions_to_check),
'lang' => $user['language'],
'get_nb_downloads' => 'true',
)
);
if (!empty($languages_to_check))
{
if ($new)
{
$get_data['extension_exclude'] = implode(',', $languages_to_check);
}
else
{
$get_data['extension_include'] = implode(',', $languages_to_check);
}
}
if (fetchRemote($url, $result, $get_data))
{
$pem_languages = @unserialize($result);
if (!is_array($pem_languages))
{
return false;
}
foreach ($pem_languages as $language)
{
if (preg_match('/^.*? \[[A-Z]{2}\]$/', $language['extension_name']))
{
$this->server_languages[$language['extension_id']] = $language;
}
}
@uasort($this->server_languages, array($this, 'extension_name_compare'));
return true;
}
return false;
}
/**
* Extract language files from archive
*
* @param string - install or upgrade
* @param string - remote revision identifier (numeric)
* @param string - language id or extension id
*/
function extract_language_files($action, $revision, $dest='')
{
global $logger;
if ($archive = tempnam( PHPWG_ROOT_PATH.'language', 'zip'))
{
$url = PEM_URL . '/download.php';
$get_data = array(
'rid' => $revision,
'origin' => 'piwigo_'.$action,
);
if ($handle = @fopen($archive, 'wb') and fetchRemote($url, $handle, $get_data))
{
fclose($handle);
include_once(PHPWG_ROOT_PATH.'admin/include/pclzip.lib.php');
$zip = new PclZip($archive);
if ($list = $zip->listContent())
{
foreach ($list as $file)
{
// we search common.lang.php in archive
if (basename($file['filename']) == 'common.lang.php'
and (!isset($main_filepath)
or strlen($file['filename']) < strlen($main_filepath)))
{
$main_filepath = $file['filename'];
}
}
$logger->debug(__FUNCTION__.', $main_filepath = '.$main_filepath);
if (isset($main_filepath))
{
$root = basename(dirname($main_filepath)); // common.lang.php path in archive
if (preg_match('/^[a-z]{2}_[A-Z]{2}$/', $root))
{
if ($action == 'install')
{
$dest = $root;
}
$extract_path = PHPWG_ROOT_PATH.'language/'.$dest;
$logger->debug(__FUNCTION__.', $extract_path = '.$extract_path);
if (
$result = $zip->extract(
PCLZIP_OPT_PATH, $extract_path,
PCLZIP_OPT_REMOVE_PATH, $root,
PCLZIP_OPT_REPLACE_NEWER
)
)
{
foreach ($result as $file)
{
if ($file['stored_filename'] == $main_filepath)
{
$status = $file['status'];
break;
}
}
if ($status == 'ok')
{
$this->get_fs_languages();
if ($action == 'install')
{
$this->perform_action('activate', $dest);
}
}
if (file_exists($extract_path.'/obsolete.list')
and $old_files = file($extract_path.'/obsolete.list', FILE_IGNORE_NEW_LINES)
and !empty($old_files))
{
$old_files[] = 'obsolete.list';
$logger->debug(__FUNCTION__.', $old_files = {'.join('},{', $old_files).'}');
$extract_path_realpath = realpath($extract_path);
foreach($old_files as $old_file)
{
$old_file = trim($old_file);
$old_file = trim($old_file, '/'); // prevent path starting with a "/"
if (empty($old_file)) // empty here means the extension itself
{
continue;
}
$path = $extract_path.'/'.$old_file;
// make sure the obsolete file is withing the extension directory, prevent traversal path
$realpath = realpath($path);
if ($realpath === false or strpos($realpath, $extract_path_realpath) !== 0)
{
continue;
}
$logger->debug(__FUNCTION__.', to delete = '.$path);
if (is_file($path))
{
@unlink($path);
}
elseif (is_dir($path))
{
deltree($path, PHPWG_ROOT_PATH.'language/trash');
}
}
}
}
else $status = 'extract_error';
}
else $status = 'archive_error';
}
else $status = 'archive_error';
}
else $status = 'archive_error';
}
else $status = 'dl_archive_error';
}
else $status = 'temp_path_error';
@unlink($archive);
return $status;
}
/**
* Sort functions
*/
function extension_name_compare($a, $b)
{
return strcmp(strtolower($a['extension_name']), strtolower($b['extension_name']));
}
}
?>

View File

@@ -0,0 +1,421 @@
<?php
/**
* Dump MySQL database
*
* Here is an inline example:
* <code>
* $connection = @mysql_connect($dbhost,$dbuser,$dbpsw);
* $dumper = new MySQLDump($dbname,'filename.sql',false,false);
* $dumper->doDump();
* </code>
*
* Special thanks to:
* - Andrea Ingaglio <andrea@coders4fun.com> helping in development of all class code
* - Dylan Pugh for precious advices halfing the size of the output file and for helping in debug
*
* @name MySQLDump
* @author Daniele Vigan<61> - CreativeFactory.it <daniele.vigano@creativefactory.it>
* @version 2.20 - 02/11/2007
* @license http://opensource.org/licenses/gpl-license.php GNU Public License
*/
class MySQLDump {
/**
* @access private
*/
var $database = null;
/**
* @access private
*/
var $compress = false;
/**
* @access private
*/
var $hexValue = false;
/**
* The output filename
* @access private
*/
var $filename = null;
/**
* The pointer of the output file
* @access private
*/
var $file = null;
/**
* @access private
*/
var $isWritten = false;
/**
* Class constructor
* @param string $db The database name
* @param string $filepath The file where the dump will be written
* @param boolean $compress It defines if the output file is compress (gzip) or not
* @param boolean $hexValue It defines if the outup values are base-16 or not
*/
function __construct($db = null, $filepath = 'dump.sql', $compress = false, $hexValue = false){
$this->compress = $compress;
if ( !$this->setOutputFile($filepath) )
return false;
return $this->setDatabase($db);
}
/**
* Sets the database to work on
* @param string $db The database name
*/
function setDatabase($db){
$this->database = $db;
if ( !@mysql_select_db($this->database) )
return false;
return true;
}
/**
* Returns the database where the class is working on
* @return string
*/
function getDatabase(){
return $this->database;
}
/**
* Sets the output file type (It can be made only if the file hasn't been already written)
* @param boolean $compress If it's true, the output file will be compressed
*/
function setCompress($compress){
if ( $this->isWritten )
return false;
$this->compress = $compress;
$this->openFile($this->filename);
return true;
}
/**
* Returns if the output file is or not compressed
* @return boolean
*/
function getCompress(){
return $this->compress;
}
/**
* Sets the output file
* @param string $filepath The file where the dump will be written
*/
function setOutputFile($filepath){
if ( $this->isWritten )
return false;
$this->filename = $filepath;
$this->file = $this->openFile($this->filename);
return $this->file;
}
/**
* Returns the output filename
* @return string
*/
function getOutputFile(){
return $this->filename;
}
/**
* Writes to file the $table's structure
* @param string $table The table name
*/
function getTableStructure($table){
if ( !$this->setDatabase($this->database) )
return false;
// Structure Header
$structure = "-- \n";
$structure .= "-- Table structure for table `{$table}` \n";
$structure .= "-- \n\n";
// Dump Structure
$structure .= 'DROP TABLE IF EXISTS `'.$table.'`;'."\n";
$structure .= "CREATE TABLE `".$table."` (\n";
$records = @mysql_query('SHOW FIELDS FROM `'.$table.'`');
if ( @mysql_num_rows($records) == 0 )
return false;
while ( $record = mysql_fetch_assoc($records) ) {
$structure .= '`'.$record['Field'].'` '.$record['Type'];
if ( isset($record['Default']) )
$structure .= ' DEFAULT \''.$record['Default'].'\'';
if ( @strcmp($record['Null'],'YES') != 0 )
$structure .= ' NOT NULL';
elseif ( is_null($record['Default']) )
$structure .= ' DEFAULT NULL';
if ( !empty($record['Extra']) )
$structure .= ' '.$record['Extra'];
$structure .= ",\n";
}
$structure = @ereg_replace(",\n$", null, $structure);
// Save all Column Indexes
$structure .= $this->getSqlKeysTable($table);
$structure .= "\n)";
//Save table engine
$records = @mysql_query("SHOW TABLE STATUS LIKE '".$table."'");
if ( $record = @mysql_fetch_assoc($records) ) {
if ( !empty($record['Engine']) )
$structure .= ' ENGINE='.$record['Engine'];
if ( !empty($record['Auto_increment']) )
$structure .= ' AUTO_INCREMENT='.$record['Auto_increment'];
}
$structure .= ";\n\n-- --------------------------------------------------------\n\n";
$this->saveToFile($this->file,$structure);
}
/**
* Writes to file the $table's data
* @param string $table The table name
* @param boolean $hexValue It defines if the output is base 16 or not
*/
function getTableData($table,$hexValue = true) {
if ( !$this->setDatabase($this->database) )
return false;
// Header
$data = "-- \n";
$data .= "-- Dumping data for table `$table` \n";
$data .= "-- \n\n";
$records = mysql_query('SHOW FIELDS FROM `'.$table.'`');
$num_fields = @mysql_num_rows($records);
if ( $num_fields == 0 )
return false;
// Field names
$selectStatement = "SELECT ";
$insertStatement = "INSERT INTO `$table` (";
$hexField = array();
for ($x = 0; $x < $num_fields; $x++) {
$record = @mysql_fetch_assoc($records);
if ( ($hexValue) && ($this->isTextValue($record['Type'])) ) {
$selectStatement .= 'HEX(`'.$record['Field'].'`)';
$hexField [$x] = true;
}
else
$selectStatement .= '`'.$record['Field'].'`';
$insertStatement .= '`'.$record['Field'].'`';
$insertStatement .= ", ";
$selectStatement .= ", ";
}
$insertStatement = @substr($insertStatement,0,-2).') VALUES'."\n";
$selectStatement = @substr($selectStatement,0,-2).' FROM `'.$table.'`';
$records = @mysql_query($selectStatement);
$num_rows = @mysql_num_rows($records);
$num_fields = @mysql_num_fields($records);
// Dump data
if ( $num_rows > 0 ) {
$data .= $insertStatement;
for ($i = 0; $i < $num_rows; $i++) {
$record = @mysql_fetch_assoc($records);
$data .= ' (';
for ($j = 0; $j < $num_fields; $j++) {
$field_name = @mysql_field_name($records, $j);
if ( @$hexField[$j] && (@strlen($record[$field_name]) > 0) )
$data .= "0x".$record[$field_name];
elseif (is_null($record[$field_name]))
$data .= "NULL";
else
$data .= "'".@str_replace('\"','"',@mysql_real_escape_string($record[$field_name]))."'";
$data .= ',';
}
$data = @substr($data,0,-1).")";
$data .= ( $i < ($num_rows-1) ) ? ',' : ';';
$data .= "\n";
//if data in greather than 1MB save
if (strlen($data) > 1048576) {
$this->saveToFile($this->file,$data);
$data = '';
}
}
$data .= "\n-- --------------------------------------------------------\n\n";
$this->saveToFile($this->file,$data);
}
}
/**
* Writes to file all the selected database tables structure
* @return boolean
*/
function getDatabaseStructure(){
$records = @mysql_query('SHOW TABLES');
if ( @mysql_num_rows($records) == 0 )
return false;
$structure = '';
while ( $record = @mysql_fetch_row($records) ) {
$structure .= $this->getTableStructure($record[0]);
}
return true;
}
/**
* Writes to file all the selected database tables data
* @param boolean $hexValue It defines if the output is base-16 or not
*/
function getDatabaseData($hexValue = true){
$records = @mysql_query('SHOW TABLES');
if ( @mysql_num_rows($records) == 0 )
return false;
while ( $record = @mysql_fetch_row($records) ) {
$this->getTableData($record[0],$hexValue);
}
}
/**
* Writes to file the selected database dump
*/
function doDump() {
$this->saveToFile($this->file,"SET FOREIGN_KEY_CHECKS = 0;\n\n");
$this->getDatabaseStructure();
$this->getDatabaseData($this->hexValue);
$this->saveToFile($this->file,"SET FOREIGN_KEY_CHECKS = 1;\n\n");
$this->closeFile($this->file);
return true;
}
/**
* @deprecated Look at the doDump() method
*/
function writeDump($filename) {
if ( !$this->setOutputFile($filename) )
return false;
$this->doDump();
$this->closeFile($this->file);
return true;
}
/**
* @access private
*/
function getSqlKeysTable ($table) {
$primary = "";
$unique = array();
$index = array();
$fulltext = array();
$results = mysql_query("SHOW KEYS FROM `{$table}`");
if ( @mysql_num_rows($results) == 0 )
return false;
while($row = mysql_fetch_object($results)) {
if (($row->Key_name == 'PRIMARY') AND ($row->Index_type == 'BTREE')) {
if ( $primary == "" )
$primary = " PRIMARY KEY (`{$row->Column_name}`";
else
$primary .= ", `{$row->Column_name}`";
}
if (($row->Key_name != 'PRIMARY') AND ($row->Non_unique == '0') AND ($row->Index_type == 'BTREE')) {
if ( (empty($unique)) OR (empty($unique[$row->Key_name])) )
$unique[$row->Key_name] = " UNIQUE KEY `{$row->Key_name}` (`{$row->Column_name}`";
else
$unique[$row->Key_name] .= ", `{$row->Column_name}`";
}
if (($row->Key_name != 'PRIMARY') AND ($row->Non_unique == '1') AND ($row->Index_type == 'BTREE')) {
if ( (empty($index)) OR (empty($index[$row->Key_name])) )
$index[$row->Key_name] = " KEY `{$row->Key_name}` (`{$row->Column_name}`";
else
$index[$row->Key_name] .= ", `{$row->Column_name}`";
}
if (($row->Key_name != 'PRIMARY') AND ($row->Non_unique == '1') AND ($row->Index_type == 'FULLTEXT')) {
if ( (empty($fulltext)) OR (empty($fulltext[$row->Key_name])) )
$fulltext[$row->Key_name] = " FULLTEXT `{$row->Key_name}` (`{$row->Column_name}`";
else
$fulltext[$row->Key_name] .= ", `{$row->Column_name}`";
}
}
$sqlKeyStatement = '';
// generate primary, unique, key and fulltext
if ( $primary != "" ) {
$sqlKeyStatement .= ",\n";
$primary .= ")";
$sqlKeyStatement .= $primary;
}
if (!empty($unique)) {
foreach ($unique as $keyName => $keyDef) {
$sqlKeyStatement .= ",\n";
$keyDef .= ")";
$sqlKeyStatement .= $keyDef;
}
}
if (!empty($index)) {
foreach ($index as $keyName => $keyDef) {
$sqlKeyStatement .= ",\n";
$keyDef .= ")";
$sqlKeyStatement .= $keyDef;
}
}
if (!empty($fulltext)) {
foreach ($fulltext as $keyName => $keyDef) {
$sqlKeyStatement .= ",\n";
$keyDef .= ")";
$sqlKeyStatement .= $keyDef;
}
}
return $sqlKeyStatement;
}
/**
* @access private
*/
function isTextValue($field_type) {
switch ($field_type) {
case "tinytext":
case "text":
case "mediumtext":
case "longtext":
case "binary":
case "varbinary":
case "tinyblob":
case "blob":
case "mediumblob":
case "longblob":
return True;
break;
default:
return False;
}
}
/**
* @access private
*/
function openFile($filename) {
$file = false;
if ( $this->compress )
$file = @gzopen($filename, "w9");
else
$file = @fopen($filename, "w");
return $file;
}
/**
* @access private
*/
function saveToFile($file, $data) {
if ( $this->compress )
@gzwrite($file, $data);
else
@fwrite($file, $data);
$this->isWritten = true;
}
/**
* @access private
*/
function closeFile($file) {
if ( $this->compress )
@gzclose($file);
else
@fclose($file);
}
}
?>

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,227 @@
<?php
// +-----------------------------------------------------------------------+
// | Piwigo - a PHP based photo gallery |
// +-----------------------------------------------------------------------+
// | Copyright(C) 2008-2016 Piwigo Team http://piwigo.org |
// | Copyright(C) 2003-2008 PhpWebGallery Team http://phpwebgallery.net |
// | Copyright(C) 2002-2003 Pierrick LE GALL http://le-gall.net/pierrick |
// +-----------------------------------------------------------------------+
// | 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 |
// | |
// | 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, |
// | USA. |
// +-----------------------------------------------------------------------+
// +-----------------------------------------------------------------------+
// | Photo selection |
// +-----------------------------------------------------------------------+
$template->assign(
array(
'F_ADD_ACTION'=> PHOTOS_ADD_BASE_URL,
'chunk_size' => $conf['upload_form_chunk_size'],
)
);
// what is the maximum number of pixels permitted by the memory_limit?
if (pwg_image::get_library() == 'gd')
{
$fudge_factor = 1.7;
$available_memory = get_ini_size('memory_limit') - memory_get_usage();
$max_upload_width = round(sqrt($available_memory/(2 * $fudge_factor)));
$max_upload_height = round(2 * $max_upload_width / 3);
// we don't want dimensions like 2995x1992 but 3000x2000
$max_upload_width = round($max_upload_width/100)*100;
$max_upload_height = round($max_upload_height/100)*100;
$max_upload_resolution = floor($max_upload_width * $max_upload_height / (1000000));
// no need to display a limitation warning if the limitation is huge like 20MP
if ($max_upload_resolution < 25)
{
$template->assign(
array(
'max_upload_width' => $max_upload_width,
'max_upload_height' => $max_upload_height,
'max_upload_resolution' => $max_upload_resolution,
)
);
}
}
//warn the user if the picture will be resized after upload
if ($conf['original_resize'])
{
$template->assign(
array(
'original_resize_maxwidth' => $conf['original_resize_maxwidth'],
'original_resize_maxheight' => $conf['original_resize_maxheight'],
)
);
}
$template->assign(
array(
'form_action' => PHOTOS_ADD_BASE_URL,
'pwg_token' => get_pwg_token(),
)
);
$unique_exts = array_unique(
array_map(
'strtolower',
$conf['upload_form_all_types'] ? $conf['file_ext'] : $conf['picture_ext']
)
);
$template->assign(
array(
'upload_file_types' => implode(', ', $unique_exts),
'file_exts' => implode(',', $unique_exts),
)
);
// +-----------------------------------------------------------------------+
// | Categories |
// +-----------------------------------------------------------------------+
// we need to know the category in which the last photo was added
$selected_category = array();
if (isset($_GET['album']))
{
// set the category from get url or ...
check_input_parameter('album', $_GET, false, PATTERN_ID);
// test if album really exists
$query = '
SELECT id
FROM '.CATEGORIES_TABLE.'
WHERE id = '.$_GET['album'].'
;';
$result = pwg_query($query);
if (pwg_db_num_rows($result) == 1)
{
$selected_category = array($_GET['album']);
// lets put in the session to persist in case of upload method switch
$_SESSION['selected_category'] = $selected_category;
}
else
{
fatal_error('[Hacking attempt] the album id = "'.$_GET['album'].'" is not valid');
}
}
else if (isset($_SESSION['selected_category']))
{
$selected_category = $_SESSION['selected_category'];
}
else
{
// we need to know the category in which the last photo was added
$query = '
SELECT category_id
FROM '.IMAGES_TABLE.' AS i
JOIN '.IMAGE_CATEGORY_TABLE.' AS ic ON image_id = i.id
JOIN '.CATEGORIES_TABLE.' AS c ON category_id = c.id
ORDER BY i.id DESC
LIMIT 1
;
';
$result = pwg_query($query);
if (pwg_db_num_rows($result) > 0)
{
$row = pwg_db_fetch_assoc($result);
$selected_category = array($row['category_id']);
}
}
// existing album
$template->assign('selected_category', $selected_category);
// image level options
$selected_level = isset($_POST['level']) ? $_POST['level'] : 0;
$template->assign(
array(
'level_options'=> get_privacy_level_options(),
'level_options_selected' => array($selected_level)
)
);
// +-----------------------------------------------------------------------+
// | Setup errors/warnings |
// +-----------------------------------------------------------------------+
// Errors
$setup_errors = array();
$error_message = ready_for_upload_message();
if (!empty($error_message))
{
$setup_errors[] = $error_message;
}
if (!function_exists('gd_info'))
{
$setup_errors[] = l10n('GD library is missing');
}
$template->assign(array(
'setup_errors'=> $setup_errors,
'CACHE_KEYS' => get_admin_client_cache_keys(array('categories')),
));
// Warnings
if (isset($_GET['hide_warnings']))
{
$_SESSION['upload_hide_warnings'] = true;
}
if (!isset($_SESSION['upload_hide_warnings']))
{
$setup_warnings = array();
if ($conf['use_exif'] and !function_exists('read_exif_data'))
{
$setup_warnings[] = l10n('Exif extension not available, admin should disable exif use');
}
if (get_ini_size('upload_max_filesize') > get_ini_size('post_max_size'))
{
$setup_warnings[] = l10n(
'In your php.ini file, the upload_max_filesize (%sB) is bigger than post_max_size (%sB), you should change this setting',
get_ini_size('upload_max_filesize', false),
get_ini_size('post_max_size', false)
);
}
if (get_ini_size('upload_max_filesize') < $conf['upload_form_chunk_size']*1024)
{
$setup_warnings[] = sprintf(
'Piwigo setting upload_form_chunk_size (%ukB) should be smaller than PHP configuration setting upload_max_filesize (%ukB)',
$conf['upload_form_chunk_size'],
ceil(get_ini_size('upload_max_filesize') / 1024)
);
}
$template->assign(
array(
'setup_warnings' => $setup_warnings,
'hide_warnings_link' => PHOTOS_ADD_BASE_URL.'&amp;hide_warnings=1'
)
);
}
?>

View File

@@ -0,0 +1,747 @@
<?php
// +-----------------------------------------------------------------------+
// | Piwigo - a PHP based photo gallery |
// +-----------------------------------------------------------------------+
// | Copyright(C) 2008-2016 Piwigo Team http://piwigo.org |
// | Copyright(C) 2003-2008 PhpWebGallery Team http://phpwebgallery.net |
// | Copyright(C) 2002-2003 Pierrick LE GALL http://le-gall.net/pierrick |
// +-----------------------------------------------------------------------+
// | 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 |
// | |
// | 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, |
// | USA. |
// +-----------------------------------------------------------------------+
/**
* class DummyPlugin_maintain
* used when a plugin uses the old procedural declaration of maintenance methods
*/
class DummyPlugin_maintain extends PluginMaintain
{
function install($plugin_version, &$errors=array())
{
if (is_callable('plugin_install'))
{
return plugin_install($this->plugin_id, $plugin_version, $errors);
}
}
function activate($plugin_version, &$errors=array())
{
if (is_callable('plugin_activate'))
{
return plugin_activate($this->plugin_id, $plugin_version, $errors);
}
}
function deactivate()
{
if (is_callable('plugin_deactivate'))
{
return plugin_deactivate($this->plugin_id);
}
}
function uninstall()
{
if (is_callable('plugin_uninstall'))
{
return plugin_uninstall($this->plugin_id);
}
}
function update($old_version, $new_version, &$errors=array()) {}
}
class plugins
{
var $fs_plugins = array();
var $db_plugins_by_id = array();
var $server_plugins = array();
var $default_plugins = array('LocalFilesEditor', 'language_switch', 'TakeATour', 'AdminTools');
/**
* Initialize $fs_plugins and $db_plugins_by_id
*/
function __construct()
{
$this->get_fs_plugins();
foreach (get_db_plugins() as $db_plugin)
{
$this->db_plugins_by_id[$db_plugin['id']] = $db_plugin;
}
}
/**
* Returns the maintain class of a plugin
* or build a new class with the procedural methods
* @param string $plugin_id
*/
private static function build_maintain_class($plugin_id)
{
$file_to_include = PHPWG_PLUGINS_PATH . $plugin_id . '/maintain';
$classname = $plugin_id.'_maintain';
// 2.7 pattern (OO only)
if (file_exists($file_to_include.'.class.php'))
{
include_once($file_to_include.'.class.php');
return new $classname($plugin_id);
}
// before 2.7 pattern (OO or procedural)
if (file_exists($file_to_include.'.inc.php'))
{
include_once($file_to_include.'.inc.php');
if (class_exists($classname))
{
return new $classname($plugin_id);
}
}
return new DummyPlugin_maintain($plugin_id);
}
/**
* Perform requested actions
* @param string - action
* @param string - plugin id
* @param array - errors
*/
function perform_action($action, $plugin_id, $options=array())
{
if (isset($this->db_plugins_by_id[$plugin_id]))
{
$crt_db_plugin = $this->db_plugins_by_id[$plugin_id];
}
if ($action !== 'update')
{ // wait for files to be updated
$plugin_maintain = self::build_maintain_class($plugin_id);
}
$errors = array();
switch ($action)
{
case 'install':
if (!empty($crt_db_plugin) or !isset($this->fs_plugins[$plugin_id]))
{
break;
}
$plugin_maintain->install($this->fs_plugins[$plugin_id]['version'], $errors);
if (empty($errors))
{
$query = '
INSERT INTO '. PLUGINS_TABLE .' (id,version)
VALUES (\''. $plugin_id .'\', \''. $this->fs_plugins[$plugin_id]['version'] .'\')
;';
pwg_query($query);
}
break;
case 'update':
$previous_version = $this->fs_plugins[$plugin_id]['version'];
$errors[0] = $this->extract_plugin_files('upgrade', $options['revision'], $plugin_id);
if ($errors[0] === 'ok')
{
$this->get_fs_plugin($plugin_id); // refresh plugins list
$new_version = $this->fs_plugins[$plugin_id]['version'];
$plugin_maintain = self::build_maintain_class($plugin_id);
$plugin_maintain->update($previous_version, $new_version, $errors);
if ($new_version != 'auto')
{
$query = '
UPDATE '. PLUGINS_TABLE .'
SET version=\''. $new_version .'\'
WHERE id=\''. $plugin_id .'\'
;';
pwg_query($query);
}
}
break;
case 'activate':
if (!isset($crt_db_plugin))
{
$errors = $this->perform_action('install', $plugin_id);
list($crt_db_plugin) = get_db_plugins(null, $plugin_id);
load_conf_from_db();
}
elseif ($crt_db_plugin['state'] == 'active')
{
break;
}
if (empty($errors))
{
$plugin_maintain->activate($crt_db_plugin['version'], $errors);
}
if (empty($errors))
{
$query = '
UPDATE '. PLUGINS_TABLE .'
SET state=\'active\'
WHERE id=\''. $plugin_id .'\'
;';
pwg_query($query);
}
break;
case 'deactivate':
if (!isset($crt_db_plugin) or $crt_db_plugin['state'] != 'active')
{
break;
}
$query = '
UPDATE '. PLUGINS_TABLE .'
SET state=\'inactive\'
WHERE id=\''. $plugin_id .'\'
;';
pwg_query($query);
$plugin_maintain->deactivate();
break;
case 'uninstall':
if (!isset($crt_db_plugin))
{
break;
}
if ($crt_db_plugin['state'] == 'active')
{
$this->perform_action('deactivate', $plugin_id);
}
$query = '
DELETE FROM '. PLUGINS_TABLE .'
WHERE id=\''. $plugin_id .'\'
;';
pwg_query($query);
$plugin_maintain->uninstall();
break;
case 'restore':
$this->perform_action('uninstall', $plugin_id);
unset($this->db_plugins_by_id[$plugin_id]);
$errors = $this->perform_action('activate', $plugin_id);
break;
case 'delete':
if (!empty($crt_db_plugin))
{
$this->perform_action('uninstall', $plugin_id);
}
if (!isset($this->fs_plugins[$plugin_id]))
{
break;
}
deltree(PHPWG_PLUGINS_PATH . $plugin_id, PHPWG_PLUGINS_PATH . 'trash');
break;
}
return $errors;
}
/**
* Get plugins defined in the plugin directory
*/
function get_fs_plugins()
{
$dir = opendir(PHPWG_PLUGINS_PATH);
while ($file = readdir($dir))
{
if ($file!='.' and $file!='..')
{
if (preg_match('/^[a-zA-Z0-9-_]+$/', $file))
{
$this->get_fs_plugin($file);
}
}
}
closedir($dir);
}
/**
* Load metadata of a plugin in `fs_plugins` array
* @from 2.7
* @param $plugin_id
* @return false|array
*/
function get_fs_plugin($plugin_id)
{
$path = PHPWG_PLUGINS_PATH.$plugin_id;
if (is_dir($path) and !is_link($path)
and file_exists($path.'/main.inc.php')
)
{
$plugin = array(
'name'=>$plugin_id,
'version'=>'0',
'uri'=>'',
'description'=>'',
'author'=>'',
);
$plg_data = file_get_contents($path.'/main.inc.php', null, null, 0, 2048);
if (preg_match("|Plugin Name:\\s*(.+)|", $plg_data, $val))
{
$plugin['name'] = trim( $val[1] );
}
if (preg_match("|Version:\\s*([\\w.-]+)|", $plg_data, $val))
{
$plugin['version'] = trim($val[1]);
}
if (preg_match("|Plugin URI:\\s*(https?:\\/\\/.+)|", $plg_data, $val))
{
$plugin['uri'] = trim($val[1]);
}
if ($desc = load_language('description.txt', $path.'/', array('return' => true)))
{
$plugin['description'] = trim($desc);
}
elseif (preg_match("|Description:\\s*(.+)|", $plg_data, $val))
{
$plugin['description'] = trim($val[1]);
}
if (preg_match("|Author:\\s*(.+)|", $plg_data, $val))
{
$plugin['author'] = trim($val[1]);
}
if (preg_match("|Author URI:\\s*(https?:\\/\\/.+)|", $plg_data, $val))
{
$plugin['author uri'] = trim($val[1]);
}
if (!empty($plugin['uri']) and strpos($plugin['uri'] , 'extension_view.php?eid='))
{
list( , $extension) = explode('extension_view.php?eid=', $plugin['uri']);
if (is_numeric($extension)) $plugin['extension'] = $extension;
}
// IMPORTANT SECURITY !
$plugin = array_map('htmlspecialchars', $plugin);
$this->fs_plugins[$plugin_id] = $plugin;
return $plugin;
}
return false;
}
/**
* Sort fs_plugins
*/
function sort_fs_plugins($order='name')
{
switch ($order)
{
case 'name':
uasort($this->fs_plugins, 'name_compare');
break;
case 'status':
$this->sort_plugins_by_state();
break;
case 'author':
uasort($this->fs_plugins, array($this, 'plugin_author_compare'));
break;
case 'id':
uksort($this->fs_plugins, 'strcasecmp');
break;
}
}
// Retrieve PEM versions
function get_versions_to_check($version=PHPWG_VERSION)
{
global $conf;
$versions_to_check = array();
$url = PEM_URL . '/api/get_version_list.php?category_id='. $conf['pem_plugins_category'] .'&format=php';
if (fetchRemote($url, $result) and $pem_versions = @unserialize($result))
{
if (!preg_match('/^\d+\.\d+\.\d+$/', $version))
{
$version = $pem_versions[0]['name'];
}
$branch = get_branch_from_version($version);
foreach ($pem_versions as $pem_version)
{
if (strpos($pem_version['name'], $branch) === 0)
{
$versions_to_check[] = $pem_version['id'];
}
}
}
return $versions_to_check;
}
/**
* Retrieve PEM server datas to $server_plugins
*/
function get_server_plugins($new=false)
{
global $user, $conf;
$versions_to_check = $this->get_versions_to_check();
if (empty($versions_to_check))
{
return false;
}
// Plugins to check
$plugins_to_check = array();
foreach($this->fs_plugins as $fs_plugin)
{
if (isset($fs_plugin['extension']))
{
$plugins_to_check[] = $fs_plugin['extension'];
}
}
// Retrieve PEM plugins infos
$url = PEM_URL . '/api/get_revision_list.php';
$get_data = array(
'category_id' => $conf['pem_plugins_category'],
'format' => 'php',
'last_revision_only' => 'true',
'version' => implode(',', $versions_to_check),
'lang' => substr($user['language'], 0, 2),
'get_nb_downloads' => 'true',
);
if (!empty($plugins_to_check))
{
if ($new)
{
$get_data['extension_exclude'] = implode(',', $plugins_to_check);
}
else
{
$get_data['extension_include'] = implode(',', $plugins_to_check);
}
}
if (fetchRemote($url, $result, $get_data))
{
$pem_plugins = @unserialize($result);
if (!is_array($pem_plugins))
{
return false;
}
foreach ($pem_plugins as $plugin)
{
$this->server_plugins[$plugin['extension_id']] = $plugin;
}
return true;
}
return false;
}
function get_incompatible_plugins($actualize=false)
{
if (isset($_SESSION['incompatible_plugins']) and !$actualize
and $_SESSION['incompatible_plugins']['~~expire~~'] > time())
{
return $_SESSION['incompatible_plugins'];
}
$_SESSION['incompatible_plugins'] = array('~~expire~~' => time() + 300);
$versions_to_check = $this->get_versions_to_check();
if (empty($versions_to_check))
{
return false;
}
global $conf;
// Plugins to check
$plugins_to_check = array();
foreach($this->fs_plugins as $fs_plugin)
{
if (isset($fs_plugin['extension']))
{
$plugins_to_check[] = $fs_plugin['extension'];
}
}
// Retrieve PEM plugins infos
$url = PEM_URL . '/api/get_revision_list.php';
$get_data = array(
'category_id' => $conf['pem_plugins_category'],
'format' => 'php',
'version' => implode(',', $versions_to_check),
'extension_include' => implode(',', $plugins_to_check),
);
if (fetchRemote($url, $result, $get_data))
{
$pem_plugins = @unserialize($result);
if (!is_array($pem_plugins))
{
return false;
}
$server_plugins = array();
foreach ($pem_plugins as $plugin)
{
if (!isset($server_plugins[$plugin['extension_id']]))
{
$server_plugins[$plugin['extension_id']] = array();
}
$server_plugins[$plugin['extension_id']][] = $plugin['revision_name'];
}
foreach ($this->fs_plugins as $plugin_id => $fs_plugin)
{
if (isset($fs_plugin['extension'])
and !in_array($plugin_id, $this->default_plugins)
and $fs_plugin['version'] != 'auto'
and (!isset($server_plugins[$fs_plugin['extension']]) or !in_array($fs_plugin['version'], $server_plugins[$fs_plugin['extension']])))
{
$_SESSION['incompatible_plugins'][$plugin_id] = $fs_plugin['version'];
}
}
return $_SESSION['incompatible_plugins'];
}
return false;
}
/**
* Sort $server_plugins
*/
function sort_server_plugins($order='date')
{
switch ($order)
{
case 'date':
krsort($this->server_plugins);
break;
case 'revision':
usort($this->server_plugins, array($this, 'extension_revision_compare'));
break;
case 'name':
uasort($this->server_plugins, array($this, 'extension_name_compare'));
break;
case 'author':
uasort($this->server_plugins, array($this, 'extension_author_compare'));
break;
case 'downloads':
usort($this->server_plugins, array($this, 'extension_downloads_compare'));
break;
}
}
/**
* Extract plugin files from archive
* @param string - install or upgrade
* @param string - archive URL
* @param string - plugin id or extension id
*/
function extract_plugin_files($action, $revision, $dest, &$plugin_id=null)
{
global $logger;
if ($archive = tempnam( PHPWG_PLUGINS_PATH, 'zip'))
{
$url = PEM_URL . '/download.php';
$get_data = array(
'rid' => $revision,
'origin' => 'piwigo_'.$action,
);
if ($handle = @fopen($archive, 'wb') and fetchRemote($url, $handle, $get_data))
{
fclose($handle);
include_once(PHPWG_ROOT_PATH.'admin/include/pclzip.lib.php');
$zip = new PclZip($archive);
if ($list = $zip->listContent())
{
foreach ($list as $file)
{
// we search main.inc.php in archive
if (basename($file['filename']) == 'main.inc.php'
and (!isset($main_filepath)
or strlen($file['filename']) < strlen($main_filepath)))
{
$main_filepath = $file['filename'];
}
}
$logger->debug(__FUNCTION__.', $main_filepath = '.$main_filepath);
if (isset($main_filepath))
{
$root = dirname($main_filepath); // main.inc.php path in archive
if ($action == 'upgrade')
{
$plugin_id = $dest;
}
else
{
$plugin_id = ($root == '.' ? 'extension_' . $dest : basename($root));
}
$extract_path = PHPWG_PLUGINS_PATH . $plugin_id;
$logger->debug(__FUNCTION__.', $extract_path = '.$extract_path);
if($result = $zip->extract(PCLZIP_OPT_PATH, $extract_path,
PCLZIP_OPT_REMOVE_PATH, $root,
PCLZIP_OPT_REPLACE_NEWER))
{
foreach ($result as $file)
{
if ($file['stored_filename'] == $main_filepath)
{
$status = $file['status'];
break;
}
}
if (file_exists($extract_path.'/obsolete.list')
and $old_files = file($extract_path.'/obsolete.list', FILE_IGNORE_NEW_LINES)
and !empty($old_files))
{
$old_files[] = 'obsolete.list';
$logger->debug(__FUNCTION__.', $old_files = {'.join('},{', $old_files).'}');
$extract_path_realpath = realpath($extract_path);
foreach($old_files as $old_file)
{
$old_file = trim($old_file);
$old_file = trim($old_file, '/'); // prevent path starting with a "/"
if (empty($old_file)) // empty here means the extension itself
{
continue;
}
$path = $extract_path.'/'.$old_file;
// make sure the obsolete file is withing the extension directory, prevent traversal path
$realpath = realpath($path);
if ($realpath === false or strpos($realpath, $extract_path_realpath) !== 0)
{
continue;
}
$logger->debug(__FUNCTION__.', to delete = '.$path);
if (is_file($path))
{
@unlink($path);
}
elseif (is_dir($path))
{
deltree($path, PHPWG_PLUGINS_PATH . 'trash');
}
}
}
}
else $status = 'extract_error';
}
else $status = 'archive_error';
}
else $status = 'archive_error';
}
else $status = 'dl_archive_error';
}
else $status = 'temp_path_error';
@unlink($archive);
return $status;
}
function get_merged_extensions($version=PHPWG_VERSION)
{
$file = PHPWG_ROOT_PATH.'install/obsolete_extensions.list';
$merged_extensions = array();
if (file_exists($file) and $obsolete_ext = file($file, FILE_IGNORE_NEW_LINES) and !empty($obsolete_ext))
{
foreach ($obsolete_ext as $ext)
{
if (preg_match('/^(\d+) ?: ?(.*?)$/', $ext, $matches))
{
$merged_extensions[$matches[1]] = $matches[2];
}
}
}
return $merged_extensions;
}
/**
* Sort functions
*/
function extension_revision_compare($a, $b)
{
if ($a['revision_date'] < $b['revision_date']) return 1;
else return -1;
}
function extension_name_compare($a, $b)
{
return strcmp(strtolower($a['extension_name']), strtolower($b['extension_name']));
}
function extension_author_compare($a, $b)
{
$r = strcasecmp($a['author_name'], $b['author_name']);
if ($r == 0) return $this->extension_name_compare($a, $b);
else return $r;
}
function plugin_author_compare($a, $b)
{
$r = strcasecmp($a['author'], $b['author']);
if ($r == 0) return name_compare($a, $b);
else return $r;
}
function extension_downloads_compare($a, $b)
{
if ($a['extension_nb_downloads'] < $b['extension_nb_downloads']) return 1;
else return -1;
}
function sort_plugins_by_state()
{
uasort($this->fs_plugins, 'name_compare');
$active_plugins = array();
$inactive_plugins = array();
$not_installed = array();
foreach($this->fs_plugins as $plugin_id => $plugin)
{
if (isset($this->db_plugins_by_id[$plugin_id]))
{
$this->db_plugins_by_id[$plugin_id]['state'] == 'active' ?
$active_plugins[$plugin_id] = $plugin : $inactive_plugins[$plugin_id] = $plugin;
}
else
{
$not_installed[$plugin_id] = $plugin;
}
}
$this->fs_plugins = $active_plugins + $inactive_plugins + $not_installed;
}
}
?>

View File

@@ -0,0 +1,159 @@
<?php
// +-----------------------------------------------------------------------+
// | Piwigo - a PHP based photo gallery |
// +-----------------------------------------------------------------------+
// | Copyright(C) 2008-2016 Piwigo Team http://piwigo.org |
// | Copyright(C) 2003-2008 PhpWebGallery Team http://phpwebgallery.net |
// | Copyright(C) 2002-2003 Pierrick LE GALL http://le-gall.net/pierrick |
// +-----------------------------------------------------------------------+
// | 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 |
// | |
// | 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, |
// | USA. |
// +-----------------------------------------------------------------------+
class tabsheet
{
var $sheets;
var $uniqid;
var $name;
var $titlename;
var $selected;
/*
$name is the tabsheet's name inside the template .tpl file
$titlename in the template is affected by $titlename value
*/
function __construct($name = 'TABSHEET', $titlename = 'TABSHEET_TITLE')
{
$this->sheets = array();
$this->uniqid = null;
$this->name = $name;
$this->titlename = $titlename;
$this->selected = "";
}
function set_id($id)
{
$this->uniqid = $id;
}
/*
add a tab
*/
function add($name, $caption, $url, $selected = false)
{
if (!isset($this->sheets[$name]))
{
$this->sheets[$name] = array('caption' => $caption,
'url' => $url);
if($selected)
{
$this->selected=$name;
}
return true;
}
return false;
}
/*
remove a tab
*/
function delete($name)
{
if (isset($this->sheets[$name]))
{
array_splice($this->sheets, $name, 1);
if ($this->selected == $name)
{
$this->selected = "";
}
return true;
}
return false;
}
/*
select a tab to be active
*/
function select($name)
{
$this->sheets = trigger_change('tabsheet_before_select', $this->sheets, $this->uniqid);
if (!array_key_exists($name, $this->sheets))
{
$keys = array_keys($this->sheets);
$name = $keys[0];
}
$this->selected = $name;
}
/*
set $titlename value
*/
function set_titlename($titlename)
{
$this->titlename = $titlename;
return $this->titlename;
}
/*
returns $titlename value
*/
function get_titlename()
{
return $this->titlename;
}
/*
returns properties of selected tab
*/
function get_selected()
{
if (!empty($this->selected))
{
return $this->sheets[$this->selected];
}
else
{
return null;
}
}
/*
* Build TabSheet and assign this content to current page
*
* Fill $this->$name {default value = TABSHEET} with HTML code for tabsheet
* Fill $this->titlename {default value = TABSHEET_TITLE} with formated caption of the selected tab
*/
function assign()
{
global $template;
$template->set_filename('tabsheet', 'tabsheet.tpl');
$template->assign('tabsheet', $this->sheets);
$template->assign('tabsheet_selected', $this->selected);
$selected_tab = $this->get_selected();
if (isset($selected_tab))
{
$template->assign(
array($this->titlename => '['.$selected_tab['caption'].']'));
}
$template->assign_var_from_handle($this->name, 'tabsheet');
$template->clear_assign('tabsheet');
}
}
?>

View File

@@ -0,0 +1,771 @@
<?php
// +-----------------------------------------------------------------------+
// | Piwigo - a PHP based photo gallery |
// +-----------------------------------------------------------------------+
// | Copyright(C) 2008-2016 Piwigo Team http://piwigo.org |
// | Copyright(C) 2003-2008 PhpWebGallery Team http://phpwebgallery.net |
// | Copyright(C) 2002-2003 Pierrick LE GALL http://le-gall.net/pierrick |
// +-----------------------------------------------------------------------+
// | 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 |
// | |
// | 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, |
// | USA. |
// +-----------------------------------------------------------------------+
/**
* class DummyTheme_maintain
* used when a theme uses the old procedural declaration of maintenance methods
*/
class DummyTheme_maintain extends ThemeMaintain
{
function activate($theme_version, &$errors=array())
{
if (is_callable('theme_activate'))
{
return theme_activate($this->theme_id, $theme_version, $errors);
}
}
function deactivate()
{
if (is_callable('theme_deactivate'))
{
return theme_deactivate($this->theme_id);
}
}
function delete()
{
if (is_callable('theme_delete'))
{
return theme_delete($this->theme_id);
}
}
}
class themes
{
var $fs_themes = array();
var $db_themes_by_id = array();
var $server_themes = array();
/**
* Initialize $fs_themes and $db_themes_by_id
*/
function __construct()
{
$this->get_fs_themes();
foreach ($this->get_db_themes() as $db_theme)
{
$this->db_themes_by_id[$db_theme['id']] = $db_theme;
}
}
/**
* Returns the maintain class of a theme
* or build a new class with the procedural methods
* @param string $theme_id
*/
private static function build_maintain_class($theme_id)
{
$file_to_include = PHPWG_THEMES_PATH.'/'.$theme_id.'/admin/maintain.inc.php';
$classname = $theme_id.'_maintain';
if (file_exists($file_to_include))
{
include_once($file_to_include);
if (class_exists($classname))
{
return new $classname($theme_id);
}
}
return new DummyTheme_maintain($theme_id);
}
/**
* Perform requested actions
* @param string - action
* @param string - theme id
* @param array - errors
*/
function perform_action($action, $theme_id)
{
global $conf;
if (isset($this->db_themes_by_id[$theme_id]))
{
$crt_db_theme = $this->db_themes_by_id[$theme_id];
}
$theme_maintain = self::build_maintain_class($theme_id);
$errors = array();
switch ($action)
{
case 'activate':
if (isset($crt_db_theme))
{
// the theme is already active
break;
}
if ('default' == $theme_id)
{
// you can't activate the "default" theme
break;
}
$missing_parent = $this->missing_parent_theme($theme_id);
if (isset($missing_parent))
{
$errors[] = l10n(
'Impossible to activate this theme, the parent theme is missing: %s',
$missing_parent
);
break;
}
if ($this->fs_themes[$theme_id]['mobile']
and !empty($conf['mobile_theme'])
and $conf['mobile_theme'] != $theme_id)
{
$errors[] = l10n('You can activate only one mobile theme.');
break;
}
$theme_maintain->activate($this->fs_themes[$theme_id]['version'], $errors);
if (empty($errors))
{
$query = '
INSERT INTO '.THEMES_TABLE.'
(id, version, name)
VALUES(\''.$theme_id.'\',
\''.$this->fs_themes[$theme_id]['version'].'\',
\''.$this->fs_themes[$theme_id]['name'].'\')
;';
pwg_query($query);
if ($this->fs_themes[$theme_id]['mobile'])
{
conf_update_param('mobile_theme', $theme_id);
}
}
break;
case 'deactivate':
if (!isset($crt_db_theme))
{
// the theme is already inactive
break;
}
// you can't deactivate the last theme
if (count($this->db_themes_by_id) <= 1)
{
$errors[] = l10n('Impossible to deactivate this theme, you need at least one theme.');
break;
}
if ($theme_id == get_default_theme())
{
// find a random theme to replace
$new_theme = null;
$query = '
SELECT id
FROM '.THEMES_TABLE.'
WHERE id != \''.$theme_id.'\'
;';
$result = pwg_query($query);
if (pwg_db_num_rows($result) == 0)
{
$new_theme = 'default';
}
else
{
list($new_theme) = pwg_db_fetch_row($result);
}
$this->set_default_theme($new_theme);
}
$theme_maintain->deactivate();
$query = '
DELETE
FROM '.THEMES_TABLE.'
WHERE id= \''.$theme_id.'\'
;';
pwg_query($query);
if ($this->fs_themes[$theme_id]['mobile'])
{
conf_update_param('mobile_theme', '');
}
break;
case 'delete':
if (!empty($crt_db_theme))
{
$errors[] = 'CANNOT DELETE - THEME IS INSTALLED';
break;
}
if (!isset($this->fs_themes[$theme_id]))
{
// nothing to do here
break;
}
$children = $this->get_children_themes($theme_id);
if (count($children) > 0)
{
$errors[] = l10n(
'Impossible to delete this theme. Other themes depends on it: %s',
implode(', ', $children)
);
break;
}
$theme_maintain->delete();
include_once(PHPWG_ROOT_PATH.'admin/include/functions.php');
deltree(PHPWG_THEMES_PATH.$theme_id, PHPWG_THEMES_PATH . 'trash');
break;
case 'set_default':
// first we need to know which users are using the current default theme
$this->set_default_theme($theme_id);
break;
}
return $errors;
}
function missing_parent_theme($theme_id)
{
if (!isset($this->fs_themes[$theme_id]['parent']))
{
return null;
}
$parent = $this->fs_themes[$theme_id]['parent'];
if ('default' == $parent)
{
return null;
}
if (!isset($this->fs_themes[$parent]))
{
return $parent;
}
return $this->missing_parent_theme($parent);
}
function get_children_themes($theme_id)
{
$children = array();
foreach ($this->fs_themes as $test_child)
{
if (isset($test_child['parent']) and $test_child['parent'] == $theme_id)
{
$children[] = $test_child['name'];
}
}
return $children;
}
function set_default_theme($theme_id)
{
global $conf;
// first we need to know which users are using the current default theme
$default_theme = get_default_theme();
$query = '
SELECT
user_id
FROM '.USER_INFOS_TABLE.'
WHERE theme = \''.$default_theme.'\'
;';
$user_ids = array_unique(
array_merge(
array_from_query($query, 'user_id'),
array($conf['guest_id'], $conf['default_user_id'])
)
);
// $user_ids can't be empty, at least the default user has the default
// theme
$query = '
UPDATE '.USER_INFOS_TABLE.'
SET theme = \''.$theme_id.'\'
WHERE user_id IN ('.implode(',', $user_ids).')
;';
pwg_query($query);
}
function get_db_themes($id='')
{
$query = '
SELECT
*
FROM '.THEMES_TABLE;
$clauses = array();
if (!empty($id))
{
$clauses[] = 'id = \''.$id.'\'';
}
if (count($clauses) > 0)
{
$query .= '
WHERE '. implode(' AND ', $clauses);
}
$result = pwg_query($query);
$themes = array();
while ($row = pwg_db_fetch_assoc($result))
{
$themes[] = $row;
}
return $themes;
}
/**
* Get themes defined in the theme directory
*/
function get_fs_themes()
{
$dir = opendir(PHPWG_THEMES_PATH);
while ($file = readdir($dir))
{
if ($file!='.' and $file!='..')
{
$path = PHPWG_THEMES_PATH.$file;
if (is_dir($path)
and preg_match('/^[a-zA-Z0-9-_]+$/', $file)
and file_exists($path.'/themeconf.inc.php')
)
{
$theme = array(
'id' => $file,
'name' => $file,
'version' => '0',
'uri' => '',
'description' => '',
'author' => '',
'mobile' => false,
);
$theme_data = implode('', file($path.'/themeconf.inc.php'));
if (preg_match("|Theme Name:\\s*(.+)|", $theme_data, $val))
{
$theme['name'] = trim( $val[1] );
}
if (preg_match("|Version:\\s*([\\w.-]+)|", $theme_data, $val))
{
$theme['version'] = trim($val[1]);
}
if (preg_match("|Theme URI:\\s*(https?:\\/\\/.+)|", $theme_data, $val))
{
$theme['uri'] = trim($val[1]);
}
if ($desc = load_language('description.txt', $path.'/', array('return' => true)))
{
$theme['description'] = trim($desc);
}
elseif (preg_match("|Description:\\s*(.+)|", $theme_data, $val))
{
$theme['description'] = trim($val[1]);
}
if (preg_match("|Author:\\s*(.+)|", $theme_data, $val))
{
$theme['author'] = trim($val[1]);
}
if (preg_match("|Author URI:\\s*(https?:\\/\\/.+)|", $theme_data, $val))
{
$theme['author uri'] = trim($val[1]);
}
if (!empty($theme['uri']) and strpos($theme['uri'] , 'extension_view.php?eid='))
{
list( , $extension) = explode('extension_view.php?eid=', $theme['uri']);
if (is_numeric($extension)) $theme['extension'] = $extension;
}
if (preg_match('/["\']parent["\'][^"\']+["\']([^"\']+)["\']/', $theme_data, $val))
{
$theme['parent'] = $val[1];
}
if (preg_match('/["\']activable["\'].*?(true|false)/i', $theme_data, $val))
{
$theme['activable'] = get_boolean($val[1]);
}
if (preg_match('/["\']mobile["\'].*?(true|false)/i', $theme_data, $val))
{
$theme['mobile'] = get_boolean($val[1]);
}
// screenshot
$screenshot_path = $path.'/screenshot.png';
if (file_exists($screenshot_path))
{
$theme['screenshot'] = $screenshot_path;
}
else
{
global $conf;
$theme['screenshot'] =
PHPWG_ROOT_PATH.'admin/themes/'
.$conf['admin_theme']
.'/images/missing_screenshot.png'
;
}
$admin_file = $path.'/admin/admin.inc.php';
if (file_exists($admin_file))
{
$theme['admin_uri'] = get_root_url().'admin.php?page=theme&theme='.$file;
}
// IMPORTANT SECURITY !
$theme = array_map('htmlspecialchars', $theme);
$this->fs_themes[$file] = $theme;
}
}
}
closedir($dir);
}
/**
* Sort fs_themes
*/
function sort_fs_themes($order='name')
{
switch ($order)
{
case 'name':
uasort($this->fs_themes, 'name_compare');
break;
case 'status':
$this->sort_themes_by_state();
break;
case 'author':
uasort($this->fs_themes, array($this, 'theme_author_compare'));
break;
case 'id':
uksort($this->fs_themes, 'strcasecmp');
break;
}
}
/**
* Retrieve PEM server datas to $server_themes
*/
function get_server_themes($new=false)
{
global $user, $conf;
$get_data = array(
'category_id' => $conf['pem_themes_category'],
'format' => 'php',
);
// Retrieve PEM versions
$version = PHPWG_VERSION;
$versions_to_check = array();
$url = PEM_URL . '/api/get_version_list.php';
if (fetchRemote($url, $result, $get_data) and $pem_versions = @unserialize($result))
{
if (!preg_match('/^\d+\.\d+\.\d+$/', $version))
{
$version = $pem_versions[0]['name'];
}
$branch = get_branch_from_version($version);
foreach ($pem_versions as $pem_version)
{
if (strpos($pem_version['name'], $branch) === 0)
{
$versions_to_check[] = $pem_version['id'];
}
}
}
if (empty($versions_to_check))
{
return false;
}
// Themes to check
$themes_to_check = array();
foreach($this->fs_themes as $fs_theme)
{
if (isset($fs_theme['extension']))
{
$themes_to_check[] = $fs_theme['extension'];
}
}
// Retrieve PEM themes infos
$url = PEM_URL . '/api/get_revision_list.php';
$get_data = array_merge($get_data, array(
'last_revision_only' => 'true',
'version' => implode(',', $versions_to_check),
'lang' => substr($user['language'], 0, 2),
'get_nb_downloads' => 'true',
)
);
if (!empty($themes_to_check))
{
if ($new)
{
$get_data['extension_exclude'] = implode(',', $themes_to_check);
}
else
{
$get_data['extension_include'] = implode(',', $themes_to_check);
}
}
if (fetchRemote($url, $result, $get_data))
{
$pem_themes = @unserialize($result);
if (!is_array($pem_themes))
{
return false;
}
foreach ($pem_themes as $theme)
{
$this->server_themes[$theme['extension_id']] = $theme;
}
return true;
}
return false;
}
/**
* Sort $server_themes
*/
function sort_server_themes($order='date')
{
switch ($order)
{
case 'date':
krsort($this->server_themes);
break;
case 'revision':
usort($this->server_themes, array($this, 'extension_revision_compare'));
break;
case 'name':
uasort($this->server_themes, array($this, 'extension_name_compare'));
break;
case 'author':
uasort($this->server_themes, array($this, 'extension_author_compare'));
break;
case 'downloads':
usort($this->server_themes, array($this, 'extension_downloads_compare'));
break;
}
}
/**
* Extract theme files from archive
*
* @param string - install or upgrade
* @param string - remote revision identifier (numeric)
* @param string - theme id or extension id
*/
function extract_theme_files($action, $revision, $dest)
{
global $logger;
if ($archive = tempnam( PHPWG_THEMES_PATH, 'zip'))
{
$url = PEM_URL . '/download.php';
$get_data = array(
'rid' => $revision,
'origin' => 'piwigo_'.$action,
);
if ($handle = @fopen($archive, 'wb') and fetchRemote($url, $handle, $get_data))
{
fclose($handle);
include_once(PHPWG_ROOT_PATH.'admin/include/pclzip.lib.php');
$zip = new PclZip($archive);
if ($list = $zip->listContent())
{
foreach ($list as $file)
{
// we search main.inc.php in archive
if (basename($file['filename']) == 'themeconf.inc.php'
and (!isset($main_filepath)
or strlen($file['filename']) < strlen($main_filepath)))
{
$main_filepath = $file['filename'];
}
}
$logger->debug(__FUNCTION__.', $main_filepath = '.$main_filepath);
if (isset($main_filepath))
{
$root = dirname($main_filepath); // main.inc.php path in archive
if ($action == 'upgrade')
{
$extract_path = PHPWG_THEMES_PATH . $dest;
}
else
{
$extract_path = PHPWG_THEMES_PATH . ($root == '.' ? 'extension_' . $dest : basename($root));
}
$logger->debug(__FUNCTION__.', $extract_path = '.$extract_path);
if (
$result = $zip->extract(
PCLZIP_OPT_PATH, $extract_path,
PCLZIP_OPT_REMOVE_PATH, $root,
PCLZIP_OPT_REPLACE_NEWER
)
)
{
foreach ($result as $file)
{
if ($file['stored_filename'] == $main_filepath)
{
$status = $file['status'];
break;
}
}
if (file_exists($extract_path.'/obsolete.list')
and $old_files = file($extract_path.'/obsolete.list', FILE_IGNORE_NEW_LINES)
and !empty($old_files))
{
$old_files[] = 'obsolete.list';
$logger->debug(__FUNCTION__.', $old_files = {'.join('},{', $old_files).'}');
$extract_path_realpath = realpath($extract_path);
foreach($old_files as $old_file)
{
$old_file = trim($old_file);
$old_file = trim($old_file, '/'); // prevent path starting with a "/"
if (empty($old_file)) // empty here means the extension itself
{
continue;
}
$path = $extract_path.'/'.$old_file;
// make sure the obsolete file is withing the extension directory, prevent traversal path
$realpath = realpath($path);
if ($realpath === false or strpos($realpath, $extract_path_realpath) !== 0)
{
continue;
}
$logger->debug(__FUNCTION__.', to delete = '.$path);
if (is_file($path))
{
@unlink($path);
}
elseif (is_dir($path))
{
deltree($path, PHPWG_THEMES_PATH . 'trash');
}
}
}
}
else $status = 'extract_error';
}
else $status = 'archive_error';
}
else $status = 'archive_error';
}
else $status = 'dl_archive_error';
}
else $status = 'temp_path_error';
@unlink($archive);
return $status;
}
/**
* Sort functions
*/
function extension_revision_compare($a, $b)
{
if ($a['revision_date'] < $b['revision_date']) return 1;
else return -1;
}
function extension_name_compare($a, $b)
{
return strcmp(strtolower($a['extension_name']), strtolower($b['extension_name']));
}
function extension_author_compare($a, $b)
{
$r = strcasecmp($a['author_name'], $b['author_name']);
if ($r == 0) return $this->extension_name_compare($a, $b);
else return $r;
}
function theme_author_compare($a, $b)
{
$r = strcasecmp($a['author'], $b['author']);
if ($r == 0) return name_compare($a, $b);
else return $r;
}
function extension_downloads_compare($a, $b)
{
if ($a['extension_nb_downloads'] < $b['extension_nb_downloads']) return 1;
else return -1;
}
function sort_themes_by_state()
{
uasort($this->fs_themes, 'name_compare');
$active_themes = array();
$inactive_themes = array();
$not_installed = array();
foreach($this->fs_themes as $theme_id => $theme)
{
if (isset($this->db_themes_by_id[$theme_id]))
{
$this->db_themes_by_id[$theme_id]['state'] == 'active' ?
$active_themes[$theme_id] = $theme : $inactive_themes[$theme_id] = $theme;
}
else
{
$not_installed[$theme_id] = $theme;
}
}
$this->fs_themes = $active_themes + $inactive_themes + $not_installed;
}
}
?>

View File

@@ -0,0 +1,648 @@
<?php
// +-----------------------------------------------------------------------+
// | Piwigo - a PHP based photo gallery |
// +-----------------------------------------------------------------------+
// | Copyright(C) 2008-2016 Piwigo Team http://piwigo.org |
// | Copyright(C) 2003-2008 PhpWebGallery Team http://phpwebgallery.net |
// | Copyright(C) 2002-2003 Pierrick LE GALL http://le-gall.net/pierrick |
// +-----------------------------------------------------------------------+
// | 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 |
// | |
// | 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, |
// | USA. |
// +-----------------------------------------------------------------------+
if (!defined('PHPWG_ROOT_PATH')) die('Hacking attempt!');
class updates
{
var $types = array();
var $plugins;
var $themes;
var $languages;
var $missing = array();
var $default_plugins = array();
var $default_themes = array();
var $default_languages = array();
var $merged_extensions = array();
var $merged_extension_url = 'http://piwigo.org/download/merged_extensions.txt';
function __construct($page='updates')
{
$this->types = array('plugins', 'themes', 'languages');
if (in_array($page, $this->types))
{
$this->types = array($page);
}
$this->default_themes = array('clear', 'dark', 'Sylvia', 'elegant', 'smartpocket');
$this->default_plugins = array('AdminTools', 'TakeATour', 'language_switch', 'LocalFilesEditor');
foreach ($this->types as $type)
{
include_once(PHPWG_ROOT_PATH.'admin/include/'.$type.'.class.php');
$this->$type = new $type();
}
}
static function check_piwigo_upgrade()
{
$_SESSION['need_update'.PHPWG_VERSION] = null;
if (preg_match('/(\d+\.\d+)\.(\d+)/', PHPWG_VERSION, $matches)
and @fetchRemote(PHPWG_URL.'/download/all_versions.php?rand='.md5(uniqid(rand(), true)), $result))
{
$all_versions = @explode("\n", $result);
$new_version = trim($all_versions[0]);
$_SESSION['need_update'.PHPWG_VERSION] = version_compare(PHPWG_VERSION, $new_version, '<');
}
}
/**
* finds new versions of Piwigo on Piwigo.org.
*
* @since 2.9
* @return array (
* 'piwigo.org-checked' => has piwigo.org been checked?,
* 'is_dev' => are we on a dev version?,
* 'minor_version' => new minor version available,
* 'major_version' => new major version available,
* )
*/
function get_piwigo_new_versions()
{
$new_versions = array(
'piwigo.org-checked' => false,
'is_dev' => true,
);
if (preg_match('/^(\d+\.\d+)\.(\d+)$/', PHPWG_VERSION))
{
$new_versions['is_dev'] = false;
$actual_branch = get_branch_from_version(PHPWG_VERSION);
$url = PHPWG_URL.'/download/all_versions.php';
$url.= '?rand='.md5(uniqid(rand(), true)); // Avoid server cache
if (@fetchRemote($url, $result)
and $all_versions = @explode("\n", $result)
and is_array($all_versions))
{
$new_versions['piwigo.org-checked'] = true;
$last_version = trim($all_versions[0]);
if (version_compare(PHPWG_VERSION, $last_version, '<'))
{
$last_branch = get_branch_from_version($last_version);
if ($last_branch == $actual_branch)
{
$new_versions['minor'] = $last_version;
}
else
{
$new_versions['major'] = $last_version;
// Check if new version exists in same branch
foreach ($all_versions as $version)
{
$branch = get_branch_from_version($version);
if ($branch == $actual_branch)
{
if (version_compare(PHPWG_VERSION, $version, '<'))
{
$new_versions['minor'] = $version;
}
break;
}
}
}
}
}
}
return $new_versions;
}
/**
* Checks for new versions of Piwigo. Notify webmasters if new versions are available, but not too often, see
* $conf['update_notify_reminder_period'] parameter.
*
* @since 2.9
*/
function notify_piwigo_new_versions()
{
global $conf;
$new_versions = $this->get_piwigo_new_versions();
conf_update_param('update_notify_last_check', date('c'));
if ($new_versions['is_dev'])
{
return;
}
$new_versions_string = join(
' & ',
array_intersect_key(
$new_versions,
array_fill_keys(array('minor', 'major'), 1)
)
);
if (empty($new_versions_string))
{
return;
}
// In which case should we notify?
// 1. never notified
// 2. new versions
// 3. no new versions but reminder needed
$notify = false;
if (!isset($conf['update_notify_last_notification']))
{
$notify = true;
}
else
{
$conf['update_notify_last_notification'] = safe_unserialize($conf['update_notify_last_notification']);
$last_notification = $conf['update_notify_last_notification']['notified_on'];
if ($new_versions_string != $conf['update_notify_last_notification']['version'])
{
$notify = true;
}
elseif (
$conf['update_notify_reminder_period'] > 0
and strtotime($last_notification) < strtotime($conf['update_notify_reminder_period'].' seconds ago')
)
{
$notify = true;
}
}
if ($notify)
{
// send email
include_once(PHPWG_ROOT_PATH.'include/functions_mail.inc.php');
switch_lang_to(get_default_language());
$content = l10n('Hello,');
$content.= "\n\n".l10n(
'Time has come to update your Piwigo with version %s, go to %s',
$new_versions_string,
get_absolute_root_url().'admin.php?page=updates'
);
$content.= "\n\n".l10n('It only takes a few clicks.');
$content.= "\n\n".l10n('Running on an up-to-date Piwigo is important for security.');
pwg_mail_admins(
array(
'subject' => l10n('Piwigo %s is available, please update', $new_versions_string),
'content' => $content,
'content_format' => 'text/plain',
),
array(
'filename' => 'notification_admin',
),
false, // do not exclude current user
true // only webmasters
);
switch_lang_back();
// save notify
conf_update_param(
'update_notify_last_notification',
array(
'version' => $new_versions_string,
'notified_on' => date('c'),
)
);
}
}
function get_server_extensions($version=PHPWG_VERSION)
{
global $user;
$get_data = array(
'format' => 'php',
);
// Retrieve PEM versions
$versions_to_check = array();
$url = PEM_URL . '/api/get_version_list.php';
if (fetchRemote($url, $result, $get_data) and $pem_versions = @unserialize($result))
{
if (!preg_match('/^\d+\.\d+\.\d+$/', $version))
{
$version = $pem_versions[0]['name'];
}
$branch = get_branch_from_version($version);
foreach ($pem_versions as $pem_version)
{
if (strpos($pem_version['name'], $branch) === 0)
{
$versions_to_check[] = $pem_version['id'];
}
}
}
if (empty($versions_to_check))
{
return false;
}
// Extensions to check
$ext_to_check = array();
foreach ($this->types as $type)
{
$fs = 'fs_'.$type;
foreach ($this->$type->$fs as $ext)
{
if (isset($ext['extension']))
{
$ext_to_check[$ext['extension']] = $type;
}
}
}
// Retrieve PEM plugins infos
$url = PEM_URL . '/api/get_revision_list.php';
$get_data = array_merge($get_data, array(
'last_revision_only' => 'true',
'version' => implode(',', $versions_to_check),
'lang' => substr($user['language'], 0, 2),
'get_nb_downloads' => 'true',
)
);
$post_data = array();
if (!empty($ext_to_check))
{
$post_data['extension_include'] = implode(',', array_keys($ext_to_check));
}
if (fetchRemote($url, $result, $get_data, $post_data))
{
$pem_exts = @unserialize($result);
if (!is_array($pem_exts))
{
return false;
}
$servers = array();
foreach ($pem_exts as $ext)
{
if (isset($ext_to_check[$ext['extension_id']]))
{
$type = $ext_to_check[$ext['extension_id']];
if (!isset($servers[$type]))
{
$servers[$type] = array();
}
$servers[$type][ $ext['extension_id'] ] = $ext;
unset($ext_to_check[$ext['extension_id']]);
}
}
foreach ($servers as $server_type => $extension_list)
{
$server_string = 'server_'.$server_type;
$this->$server_type->$server_string = $extension_list;
}
$this->check_missing_extensions($ext_to_check);
return true;
}
return false;
}
// Check all extensions upgrades
function check_extensions()
{
global $conf;
if (!$this->get_server_extensions())
{
return false;
}
$_SESSION['extensions_need_update'] = array();
foreach ($this->types as $type)
{
$fs = 'fs_'.$type;
$server = 'server_'.$type;
$server_ext = $this->$type->$server;
$fs_ext = $this->$type->$fs;
$ignore_list = array();
$need_upgrade = array();
foreach($fs_ext as $ext_id => $fs_ext)
{
if (isset($fs_ext['extension']) and isset($server_ext[$fs_ext['extension']]))
{
$ext_info = $server_ext[$fs_ext['extension']];
if (!safe_version_compare($fs_ext['version'], $ext_info['revision_name'], '>='))
{
if (in_array($ext_id, $conf['updates_ignored'][$type]))
{
$ignore_list[] = $ext_id;
}
else
{
$_SESSION['extensions_need_update'][$type][$ext_id] = $ext_info['revision_name'];
}
}
}
}
$conf['updates_ignored'][$type] = $ignore_list;
}
conf_update_param('updates_ignored', pwg_db_real_escape_string(serialize($conf['updates_ignored'])));
}
// Check if extension have been upgraded since last check
function check_updated_extensions()
{
foreach ($this->types as $type)
{
if (!empty($_SESSION['extensions_need_update'][$type]))
{
$fs = 'fs_'.$type;
foreach($this->$type->$fs as $ext_id => $fs_ext)
{
if (isset($_SESSION['extensions_need_update'][$type][$ext_id])
and safe_version_compare($fs_ext['version'], $_SESSION['extensions_need_update'][$type][$ext_id], '>='))
{
// Extension have been upgraded
$this->check_extensions();
break;
}
}
}
}
}
function check_missing_extensions($missing)
{
foreach ($missing as $id => $type)
{
$fs = 'fs_'.$type;
$default = 'default_'.$type;
foreach ($this->$type->$fs as $ext_id => $ext)
{
if (isset($ext['extension']) and $id == $ext['extension']
and !in_array($ext_id, $this->$default)
and !in_array($ext['extension'], $this->merged_extensions))
{
$this->missing[$type][] = $ext;
break;
}
}
}
}
function get_merged_extensions($version)
{
if (fetchRemote($this->merged_extension_url, $result))
{
$rows = explode("\n", $result);
foreach ($rows as $row)
{
if (preg_match('/^(\d+\.\d+): *(.*)$/', $row, $match))
{
if (version_compare($version, $match[1], '>='))
{
$extensions = explode(',', trim($match[2]));
$this->merged_extensions = array_merge($this->merged_extensions, $extensions);
}
}
}
}
}
static function process_obsolete_list($file)
{
if (file_exists(PHPWG_ROOT_PATH.$file)
and $old_files = file(PHPWG_ROOT_PATH.$file, FILE_IGNORE_NEW_LINES)
and !empty($old_files))
{
$old_files[] = $file;
foreach($old_files as $old_file)
{
$path = PHPWG_ROOT_PATH.$old_file;
if (is_file($path))
{
@unlink($path);
}
elseif (is_dir($path))
{
deltree($path, PHPWG_ROOT_PATH.'_trash');
}
}
}
}
static function dump_database($include_history=false)
{
global $page, $conf, $cfgBase;
if (version_compare(PHPWG_VERSION, '2.1', '<'))
{
$conf['db_base'] = $cfgBase;
}
include(PHPWG_ROOT_PATH.'admin/include/mysqldump.php');
$path = PHPWG_ROOT_PATH.$conf['data_location'].'update';
if (@mkgetdir($path)
and ($backupFile = tempnam($path, 'sql'))
and ($dumper = new MySQLDump($conf['db_base'],$backupFile,false,false)))
{
foreach (get_defined_constants() as $constant => $value)
{
if (preg_match('/_TABLE$/', $constant))
{
$dumper->getTableStructure($value);
if ($constant == 'HISTORY_TABLE' and !$include_history)
{
continue;
}
$dumper->getTableData($value);
}
}
}
if (@filesize($backupFile))
{
$http_headers = array(
'Content-Length: '.@filesize($backupFile),
'Content-Type: text/x-sql',
'Content-Disposition: attachment; filename="database.sql";',
'Content-Transfer-Encoding: binary',
);
foreach ($http_headers as $header) {
header($header);
}
@readfile($backupFile);
deltree(PHPWG_ROOT_PATH.$conf['data_location'].'update');
exit();
}
else
{
$page['errors'][] = l10n('Unable to dump database.');
}
}
static function upgrade_to($upgrade_to, &$step, $check_current_version=true)
{
global $page, $conf, $template;
if ($check_current_version and !version_compare($upgrade_to, PHPWG_VERSION, '>'))
{
redirect(get_root_url().'admin.php?page=plugin-'.basename(dirname(__FILE__)));
}
if ($step == 2)
{
preg_match('/(\d+\.\d+)\.(\d+)/', PHPWG_VERSION, $matches);
$code = $matches[1].'.x_to_'.$upgrade_to;
$dl_code = str_replace(array('.', '_'), '', $code);
$remove_path = $code;
$obsolete_list = 'obsolete.list';
}
else
{
$code = $upgrade_to;
$dl_code = $code;
$remove_path = version_compare($code, '2.0.8', '>=') ? 'piwigo' : 'piwigo-'.$code;
$obsolete_list = PHPWG_ROOT_PATH.'install/obsolete.list';
}
if (empty($page['errors']))
{
$path = PHPWG_ROOT_PATH.$conf['data_location'].'update';
$filename = $path.'/'.$code.'.zip';
@mkgetdir($path);
$chunk_num = 0;
$end = false;
$zip = @fopen($filename, 'w');
while (!$end)
{
$chunk_num++;
if (@fetchRemote(PHPWG_URL.'/download/dlcounter.php?code='.$dl_code.'&chunk_num='.$chunk_num, $result)
and $input = @unserialize($result))
{
if (0 == $input['remaining'])
{
$end = true;
}
@fwrite($zip, base64_decode($input['data']));
}
else
{
$end = true;
}
}
@fclose($zip);
if (@filesize($filename))
{
$zip = new PclZip($filename);
if ($result = $zip->extract(PCLZIP_OPT_PATH, PHPWG_ROOT_PATH,
PCLZIP_OPT_REMOVE_PATH, $remove_path,
PCLZIP_OPT_SET_CHMOD, 0755,
PCLZIP_OPT_REPLACE_NEWER))
{
//Check if all files were extracted
$error = '';
foreach($result as $extract)
{
if (!in_array($extract['status'], array('ok', 'filtered', 'already_a_directory')))
{
// Try to change chmod and extract
if (@chmod(PHPWG_ROOT_PATH.$extract['filename'], 0777)
and ($res = $zip->extract(PCLZIP_OPT_BY_NAME, $remove_path.'/'.$extract['filename'],
PCLZIP_OPT_PATH, PHPWG_ROOT_PATH,
PCLZIP_OPT_REMOVE_PATH, $remove_path,
PCLZIP_OPT_SET_CHMOD, 0755,
PCLZIP_OPT_REPLACE_NEWER))
and isset($res[0]['status'])
and $res[0]['status'] == 'ok')
{
continue;
}
else
{
$error .= $extract['filename'].': '.$extract['status']."\n";
}
}
}
if (empty($error))
{
self::process_obsolete_list($obsolete_list);
deltree(PHPWG_ROOT_PATH.$conf['data_location'].'update');
invalidate_user_cache(true);
$template->delete_compiled_templates();
if ($step == 2)
{
$page['infos'][] = l10n('Update Complete');
$page['infos'][] = $upgrade_to;
$step = -1;
}
else
{
redirect(PHPWG_ROOT_PATH.'upgrade.php?now=');
}
}
else
{
file_put_contents(PHPWG_ROOT_PATH.$conf['data_location'].'update/log_error.txt', $error);
$page['errors'][] = l10n(
'An error has occured during extract. Please check files permissions of your piwigo installation.<br><a href="%s">Click here to show log error</a>.',
get_root_url().$conf['data_location'].'update/log_error.txt'
);
}
}
else
{
deltree(PHPWG_ROOT_PATH.$conf['data_location'].'update');
$page['errors'][] = l10n('An error has occured during upgrade.');
}
}
else
{
$page['errors'][] = l10n('Piwigo cannot retrieve upgrade file from server');
}
}
}
}
?>