First commit

This commit is contained in:
Nathan
2026-09-18 20:29:17 -06:00
commit 3b09abe571
2840 changed files with 467153 additions and 0 deletions
@@ -0,0 +1 @@
11.8.6-MariaDB
+23
View File
@@ -0,0 +1,23 @@
# Piwigo specific directories
/_data
/plugins/*
!/plugins/index.php
/themes/*
!/themes/index.php
!/themes/default
!/themes/standard_pages
/upload
/galleries/*
!/galleries/index.php
/local/*
!/local/**/index.php
# IntelliJ
.idea
*.iml
*.ipr
*.iws
# Eclipse
.settings
.project
+18
View File
@@ -0,0 +1,18 @@
COPYRIGHT
Piwigo - a photo library manager
Copyright(C) 2008-2024 Piwigo Team https://piwigo.org
Copyright(C) 2003-2008 PhpWebGallery Team http://phpwebgallery.net
Copyright(C) 2002-2003 Pierrick LE GALL http://pierrick.le-gall.net
SOFTWARE LICENSE
The free software license of Piwigo is GNU General Public License v2
or later. See LICENSE.txt to get a full copy.
TRADEMARK
Piwigo is a registered trademark.
+339
View File
@@ -0,0 +1,339 @@
GNU GENERAL PUBLIC LICENSE
Version 2, June 1991
Copyright (C) 1989, 1991 Free Software Foundation, Inc.,
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
Everyone is permitted to copy and distribute verbatim copies
of this license document, but changing it is not allowed.
Preamble
The licenses for most software are designed to take away your
freedom to share and change it. By contrast, the GNU General Public
License is intended to guarantee your freedom to share and change free
software--to make sure the software is free for all its users. This
General Public License applies to most of the Free Software
Foundation's software and to any other program whose authors commit to
using it. (Some other Free Software Foundation software is covered by
the GNU Lesser General Public License instead.) You can apply it to
your programs, too.
When we speak of free software, we are referring to freedom, not
price. Our General Public Licenses are designed to make sure that you
have the freedom to distribute copies of free software (and charge for
this service if you wish), that you receive source code or can get it
if you want it, that you can change the software or use pieces of it
in new free programs; and that you know you can do these things.
To protect your rights, we need to make restrictions that forbid
anyone to deny you these rights or to ask you to surrender the rights.
These restrictions translate to certain responsibilities for you if you
distribute copies of the software, or if you modify it.
For example, if you distribute copies of such a program, whether
gratis or for a fee, you must give the recipients all the rights that
you have. You must make sure that they, too, receive or can get the
source code. And you must show them these terms so they know their
rights.
We protect your rights with two steps: (1) copyright the software, and
(2) offer you this license which gives you legal permission to copy,
distribute and/or modify the software.
Also, for each author's protection and ours, we want to make certain
that everyone understands that there is no warranty for this free
software. If the software is modified by someone else and passed on, we
want its recipients to know that what they have is not the original, so
that any problems introduced by others will not reflect on the original
authors' reputations.
Finally, any free program is threatened constantly by software
patents. We wish to avoid the danger that redistributors of a free
program will individually obtain patent licenses, in effect making the
program proprietary. To prevent this, we have made it clear that any
patent must be licensed for everyone's free use or not licensed at all.
The precise terms and conditions for copying, distribution and
modification follow.
GNU GENERAL PUBLIC LICENSE
TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
0. This License applies to any program or other work which contains
a notice placed by the copyright holder saying it may be distributed
under the terms of this General Public License. The "Program", below,
refers to any such program or work, and a "work based on the Program"
means either the Program or any derivative work under copyright law:
that is to say, a work containing the Program or a portion of it,
either verbatim or with modifications and/or translated into another
language. (Hereinafter, translation is included without limitation in
the term "modification".) Each licensee is addressed as "you".
Activities other than copying, distribution and modification are not
covered by this License; they are outside its scope. The act of
running the Program is not restricted, and the output from the Program
is covered only if its contents constitute a work based on the
Program (independent of having been made by running the Program).
Whether that is true depends on what the Program does.
1. You may copy and distribute verbatim copies of the Program's
source code as you receive it, in any medium, provided that you
conspicuously and appropriately publish on each copy an appropriate
copyright notice and disclaimer of warranty; keep intact all the
notices that refer to this License and to the absence of any warranty;
and give any other recipients of the Program a copy of this License
along with the Program.
You may charge a fee for the physical act of transferring a copy, and
you may at your option offer warranty protection in exchange for a fee.
2. You may modify your copy or copies of the Program or any portion
of it, thus forming a work based on the Program, and copy and
distribute such modifications or work under the terms of Section 1
above, provided that you also meet all of these conditions:
a) You must cause the modified files to carry prominent notices
stating that you changed the files and the date of any change.
b) You must cause any work that you distribute or publish, that in
whole or in part contains or is derived from the Program or any
part thereof, to be licensed as a whole at no charge to all third
parties under the terms of this License.
c) If the modified program normally reads commands interactively
when run, you must cause it, when started running for such
interactive use in the most ordinary way, to print or display an
announcement including an appropriate copyright notice and a
notice that there is no warranty (or else, saying that you provide
a warranty) and that users may redistribute the program under
these conditions, and telling the user how to view a copy of this
License. (Exception: if the Program itself is interactive but
does not normally print such an announcement, your work based on
the Program is not required to print an announcement.)
These requirements apply to the modified work as a whole. If
identifiable sections of that work are not derived from the Program,
and can be reasonably considered independent and separate works in
themselves, then this License, and its terms, do not apply to those
sections when you distribute them as separate works. But when you
distribute the same sections as part of a whole which is a work based
on the Program, the distribution of the whole must be on the terms of
this License, whose permissions for other licensees extend to the
entire whole, and thus to each and every part regardless of who wrote it.
Thus, it is not the intent of this section to claim rights or contest
your rights to work written entirely by you; rather, the intent is to
exercise the right to control the distribution of derivative or
collective works based on the Program.
In addition, mere aggregation of another work not based on the Program
with the Program (or with a work based on the Program) on a volume of
a storage or distribution medium does not bring the other work under
the scope of this License.
3. You may copy and distribute the Program (or a work based on it,
under Section 2) in object code or executable form under the terms of
Sections 1 and 2 above provided that you also do one of the following:
a) Accompany it with the complete corresponding machine-readable
source code, which must be distributed under the terms of Sections
1 and 2 above on a medium customarily used for software interchange; or,
b) Accompany it with a written offer, valid for at least three
years, to give any third party, for a charge no more than your
cost of physically performing source distribution, a complete
machine-readable copy of the corresponding source code, to be
distributed under the terms of Sections 1 and 2 above on a medium
customarily used for software interchange; or,
c) Accompany it with the information you received as to the offer
to distribute corresponding source code. (This alternative is
allowed only for noncommercial distribution and only if you
received the program in object code or executable form with such
an offer, in accord with Subsection b above.)
The source code for a work means the preferred form of the work for
making modifications to it. For an executable work, complete source
code means all the source code for all modules it contains, plus any
associated interface definition files, plus the scripts used to
control compilation and installation of the executable. However, as a
special exception, the source code distributed need not include
anything that is normally distributed (in either source or binary
form) with the major components (compiler, kernel, and so on) of the
operating system on which the executable runs, unless that component
itself accompanies the executable.
If distribution of executable or object code is made by offering
access to copy from a designated place, then offering equivalent
access to copy the source code from the same place counts as
distribution of the source code, even though third parties are not
compelled to copy the source along with the object code.
4. You may not copy, modify, sublicense, or distribute the Program
except as expressly provided under this License. Any attempt
otherwise to copy, modify, sublicense or distribute the Program is
void, and will automatically terminate your rights under this License.
However, parties who have received copies, or rights, from you under
this License will not have their licenses terminated so long as such
parties remain in full compliance.
5. You are not required to accept this License, since you have not
signed it. However, nothing else grants you permission to modify or
distribute the Program or its derivative works. These actions are
prohibited by law if you do not accept this License. Therefore, by
modifying or distributing the Program (or any work based on the
Program), you indicate your acceptance of this License to do so, and
all its terms and conditions for copying, distributing or modifying
the Program or works based on it.
6. Each time you redistribute the Program (or any work based on the
Program), the recipient automatically receives a license from the
original licensor to copy, distribute or modify the Program subject to
these terms and conditions. You may not impose any further
restrictions on the recipients' exercise of the rights granted herein.
You are not responsible for enforcing compliance by third parties to
this License.
7. If, as a consequence of a court judgment or allegation of patent
infringement or for any other reason (not limited to patent issues),
conditions are imposed on you (whether by court order, agreement or
otherwise) that contradict the conditions of this License, they do not
excuse you from the conditions of this License. If you cannot
distribute so as to satisfy simultaneously your obligations under this
License and any other pertinent obligations, then as a consequence you
may not distribute the Program at all. For example, if a patent
license would not permit royalty-free redistribution of the Program by
all those who receive copies directly or indirectly through you, then
the only way you could satisfy both it and this License would be to
refrain entirely from distribution of the Program.
If any portion of this section is held invalid or unenforceable under
any particular circumstance, the balance of the section is intended to
apply and the section as a whole is intended to apply in other
circumstances.
It is not the purpose of this section to induce you to infringe any
patents or other property right claims or to contest validity of any
such claims; this section has the sole purpose of protecting the
integrity of the free software distribution system, which is
implemented by public license practices. Many people have made
generous contributions to the wide range of software distributed
through that system in reliance on consistent application of that
system; it is up to the author/donor to decide if he or she is willing
to distribute software through any other system and a licensee cannot
impose that choice.
This section is intended to make thoroughly clear what is believed to
be a consequence of the rest of this License.
8. If the distribution and/or use of the Program is restricted in
certain countries either by patents or by copyrighted interfaces, the
original copyright holder who places the Program under this License
may add an explicit geographical distribution limitation excluding
those countries, so that distribution is permitted only in or among
countries not thus excluded. In such case, this License incorporates
the limitation as if written in the body of this License.
9. The Free Software Foundation may publish revised and/or new versions
of the General Public License from time to time. Such new versions will
be similar in spirit to the present version, but may differ in detail to
address new problems or concerns.
Each version is given a distinguishing version number. If the Program
specifies a version number of this License which applies to it and "any
later version", you have the option of following the terms and conditions
either of that version or of any later version published by the Free
Software Foundation. If the Program does not specify a version number of
this License, you may choose any version ever published by the Free Software
Foundation.
10. If you wish to incorporate parts of the Program into other free
programs whose distribution conditions are different, write to the author
to ask for permission. For software which is copyrighted by the Free
Software Foundation, write to the Free Software Foundation; we sometimes
make exceptions for this. Our decision will be guided by the two goals
of preserving the free status of all derivatives of our free software and
of promoting the sharing and reuse of software generally.
NO WARRANTY
11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN
OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS
TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE
PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
REPAIR OR CORRECTION.
12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
POSSIBILITY OF SUCH DAMAGES.
END OF TERMS AND CONDITIONS
How to Apply These Terms to Your New Programs
If you develop a new program, and you want it to be of the greatest
possible use to the public, the best way to achieve this is to make it
free software which everyone can redistribute and change under these terms.
To do so, attach the following notices to the program. It is safest
to attach them to the start of each source file to most effectively
convey the exclusion of warranty; and each file should have at least
the "copyright" line and a pointer to where the full notice is found.
<one line to give the program's name and a brief idea of what it does.>
Copyright (C) <year> <name of author>
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License along
with this program; if not, write to the Free Software Foundation, Inc.,
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
Also add information on how to contact you by electronic and paper mail.
If the program is interactive, make it output a short notice like this
when it starts in an interactive mode:
Gnomovision version 69, Copyright (C) year name of author
Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
This is free software, and you are welcome to redistribute it
under certain conditions; type `show c' for details.
The hypothetical commands `show w' and `show c' should show the appropriate
parts of the General Public License. Of course, the commands you use may
be called something other than `show w' and `show c'; they could even be
mouse-clicks or menu items--whatever suits your program.
You should also get your employer (if you work as a programmer) or your
school, if any, to sign a "copyright disclaimer" for the program, if
necessary. Here is a sample; alter the names:
Yoyodyne, Inc., hereby disclaims all copyright interest in the program
`Gnomovision' (which makes passes at compilers) written by James Hacker.
<signature of Ty Coon>, 1 April 1989
Ty Coon, President of Vice
This General Public License does not permit incorporating your program into
proprietary programs. If your program is a subroutine library, you may
consider it more useful to permit linking proprietary applications with the
library. If this is what you want to do, use the GNU Lesser General
Public License instead of this License.
+42
View File
@@ -0,0 +1,42 @@
<img src="https://piwigo.org/plugins/piwigo-piwigodotorg/images/piwigo.org.svg" width="200" alt="Piwigo logo">
Manage your photo library. Piwigo is open source photo gallery software for the web. Designed for organisations, teams and individuals.
![screenshot](https://piwigo.org/screenshots/github-screenshot-2.10.jpg)
The [piwigo.org](https://piwigo.org) website introduces you to Piwigo. You'll find a demo, forums, wiki and news.
## Requirements
* A webserver (Apache or nginx recommended)
* PHP 7.4+. Piwigo can run with PHP 7.0+ but these end-of-life versions are no longer maintained and may expose your site to security vulnerabilities.
* MySQL 5 or greater or MariaDB equivalent
* ImageMagick (recommended) or PHP GD
## Quick start install
### NetInstall
* Download the [NetInstall script](https://piwigo.org/download/dlcounter.php?code=netinstall)
* Transfer the script to your web space with any FTP client
* Open the script in you web browser (for example http://example.com/piwigo-netinstall.php) and follow the steps
[More information](https://piwigo.org/guides/install/netinstall)
### Manual
* Download the [latest stable version](https://piwigo.org/download/dlcounter.php?code=latest) and unzip it
* Transfer everything to your web space with any FTP client
* Open your website (for example http://example.com/piwigo) and follow the steps
[More information](https://piwigo.org/guides/install/manual)
If you do not have your own server, consider the [piwigo.com](https://piwigo.com/) hosting solution.
## Contributing
Piwigo is widely driven by its community; if you want to improve the code, fork this repo and submit your changes to the `master` branch. See our [Contribution guide](https://github.com/Piwigo/Piwigo/blob/master/docs/CONTRIBUTING.md).
## License
Piwigo is released under the GPL v2 license. See our [Copying details](https://github.com/Piwigo/Piwigo/blob/master/COPYING.txt).
+36
View File
@@ -0,0 +1,36 @@
# Piwigo Security Policy
The Piwigo team and community take security bugs seriously. We appreciate your efforts
to responsibly disclose your findings.
## Supported Versions
Security updates will typically only be applied to the latest release. Exceptionally,
we may release a new version of an old branch but that won't be the standard way we process.
## Reporting a Vulnerability
**Please contact us at [security@piwigo.org](mailto:security@piwigo.org) when you have
discovered a potential security issue.** Please do not create a public issue for now. At a minimum, your report by email should include the following:
- version of Piwigo, version of PHP, version of MySQL/MariaDB
- vulnerability description
- reproduction steps
You will receive a response from us within 72 hours. If the issue is confirmed we will
then work on fixing it and release a new fixed version of Piwigo, following these steps:
- Confirm the problem and determine the affected versions.
- Audit code to find any potential similar problems.
- Prepare a fix for `master` branch and backport it on the current stable branch.
- Release a new version of Piwigo on its current stable branch as fast as possible, historically within a few days.
## Responsible Disclosure
1. Confirm that the vulnerability applies to a current version and is reproducible.
2. First share the vulnerability details with us so that users are not put at risk.
3. Wait before publishing details until everyone has had a chance to update.
4. Respect the privacy of others.
*Avoid activities that disrupt, degrade, or interrupt our services or compromise other
users' data, such as spam, brute force attacks, denial of service attacks, and malicious file distribution.*
+48
View File
@@ -0,0 +1,48 @@
<?php
// +-----------------------------------------------------------------------+
// | This file is part of Piwigo. |
// | |
// | For copyright and license information, please view the COPYING.txt |
// | file that was distributed with this source code. |
// +-----------------------------------------------------------------------+
//----------------------------------------------------------- include
define('PHPWG_ROOT_PATH','./');
include_once( PHPWG_ROOT_PATH.'include/common.inc.php' );
// +-----------------------------------------------------------------------+
// | Check Access and exit when user status is not ok |
// +-----------------------------------------------------------------------+
check_status(ACCESS_GUEST);
//----------------------------------------------------- template initialization
//
// Start output of page
//
$title= l10n('About Piwigo');
$page['body_id'] = 'theAboutPage';
trigger_notify('loc_begin_about');
$template->set_filename('about', 'about.tpl');
$template->assign('ABOUT_MESSAGE', load_language('about.html','', array('return'=>true)) );
$theme_about = load_language('about.html', PHPWG_THEMES_PATH.$user['theme'].'/', array('return' => true));
if ( $theme_about !== false )
{
$template->assign('THEME_ABOUT', $theme_about);
}
// include menubar
$themeconf = $template->get_template_vars('themeconf');
if (!isset($themeconf['hide_menu_on']) OR !in_array('theAboutPage', $themeconf['hide_menu_on']))
{
include( PHPWG_ROOT_PATH.'include/menubar.inc.php');
}
include(PHPWG_ROOT_PATH.'include/page_header.php');
flush_page_messages();
$template->pparse('about');
include(PHPWG_ROOT_PATH.'include/page_tail.php');
?>
+236
View File
@@ -0,0 +1,236 @@
<?php
// +-----------------------------------------------------------------------+
// | This file is part of Piwigo. |
// | |
// | For copyright and license information, please view the COPYING.txt |
// | file that was distributed with this source code. |
// +-----------------------------------------------------------------------+
define('PHPWG_ROOT_PATH','./');
session_cache_limiter('public');
include_once(PHPWG_ROOT_PATH.'include/common.inc.php');
// Check Access and exit when user status is not ok
check_status(ACCESS_GUEST);
function guess_mime_type($ext)
{
switch ( strtolower($ext) )
{
case "jpe": case "jpeg":
case "jpg": $ctype="image/jpeg"; break;
case "png": $ctype="image/png"; break;
case "gif": $ctype="image/gif"; break;
case "webp": $ctype="image/webp"; break;
case "tiff":
case "tif": $ctype="image/tiff"; break;
case "txt": $ctype="text/plain"; break;
case "html":
case "htm": $ctype="text/html"; break;
case "xml": $ctype="text/xml"; break;
case "pdf": $ctype="application/pdf"; break;
case "zip": $ctype="application/zip"; break;
case "ogg": $ctype="application/ogg"; break;
default: $ctype="application/octet-stream";
}
return $ctype;
}
function do_error( $code, $str )
{
set_status_header( $code );
echo $str ;
exit();
}
if ($conf['enable_formats'] and isset($_GET['format']))
{
check_input_parameter('format', $_GET, false, PATTERN_ID);
$query = '
SELECT
*
FROM '.IMAGE_FORMAT_TABLE.'
WHERE format_id = '.$_GET['format'].'
;';
$formats = query2array($query);
if (count($formats) == 0)
{
do_error(400, 'Invalid request - format');
}
$format = $formats[0];
$_GET['id'] = $format['image_id'];
$_GET['part'] = 'f'; // "f" for "format"
}
if (!isset($_GET['id'])
or !is_numeric($_GET['id'])
or !isset($_GET['part'])
or !in_array($_GET['part'], array('e','r','f') ) )
{
do_error(400, 'Invalid request - id/part');
}
$query = '
SELECT * FROM '. IMAGES_TABLE.'
WHERE id='.$_GET['id'].'
;';
$element_info = pwg_db_fetch_assoc(pwg_query($query));
if ( empty($element_info) )
{
do_error(404, 'Requested id not found');
}
// special download action for admins
$is_admin_download = false;
if (is_admin() and isset($_GET['pwg_token']) and get_pwg_token() == $_GET['pwg_token'])
{
$is_admin_download = true;
$user['enabled_high'] = true;
}
$src_image = new SrcImage($element_info);
// $filter['visible_categories'] and $filter['visible_images']
// are not used because it's not necessary (filter <> restriction)
$query='
SELECT id
FROM '.CATEGORIES_TABLE.'
INNER JOIN '.IMAGE_CATEGORY_TABLE.' ON category_id = id
WHERE image_id = '.$_GET['id'].'
'.get_sql_condition_FandF(
array(
'forbidden_categories' => 'category_id',
'forbidden_images' => 'image_id',
),
' AND'
).'
LIMIT 1
;';
if (!$is_admin_download and pwg_db_num_rows(pwg_query($query))<1 )
{
do_error(401, 'Access denied');
}
include_once(PHPWG_ROOT_PATH.'include/functions_picture.inc.php');
$file='';
switch ($_GET['part'])
{
case 'e':
if ( $src_image->is_original() and !$user['enabled_high'] )
{// we have a photo and the user has no access to HD
$deriv = new DerivativeImage(IMG_XXLARGE, $src_image);
if ( !$deriv->same_as_source() )
{
do_error(401, 'Access denied e');
}
}
$file = get_element_path($element_info);
break;
case 'r':
$file = original_to_representative( get_element_path($element_info), $element_info['representative_ext'] );
break;
case 'f' :
$file = original_to_format(get_element_path($element_info), $format['ext']);
$element_info['file'] = get_filename_wo_extension($element_info['file']).'.'.$format['ext'];
break;
}
if ( empty($file) )
{
do_error(404, 'Requested file not found');
}
if ($_GET['part'] == 'e') {
pwg_log($_GET['id'], 'high');
}
else if ($_GET['part'] == 'e')
{
pwg_log($_GET['id'], 'other');
}
else if ($_GET['part'] == 'f')
{
pwg_log($_GET['id'], 'high', $format['format_id']);
}
trigger_notify('loc_action_before_http_headers');
$http_headers = array();
$ctype = null;
if (!url_is_remote($file))
{
if ( !@is_readable($file) )
{
do_error(404, "Requested file not found - $file");
}
$http_headers[] = 'Content-Length: '.@filesize($file);
if ( function_exists('mime_content_type') )
{
$ctype = mime_content_type($file);
}
$gmt_mtime = gmdate('D, d M Y H:i:s', filemtime($file)).' GMT';
$http_headers[] = 'Last-Modified: '.$gmt_mtime;
// following lines would indicate how the client should handle the cache
/* $max_age=300;
$http_headers[] = 'Expires: '.gmdate('D, d M Y H:i:s', time()+$max_age).' GMT';
// HTTP/1.1 only
$http_headers[] = 'Cache-Control: private, must-revalidate, max-age='.$max_age;*/
if ('f' != $_GET['part'] and isset( $_SERVER['HTTP_IF_MODIFIED_SINCE'] ) )
{
set_status_header(304);
foreach ($http_headers as $header)
{
header( $header );
}
exit();
}
}
if (!isset($ctype))
{ // give it a guess
$ctype = guess_mime_type( get_extension($file) );
}
$http_headers[] = 'Content-Type: '.$ctype;
if (isset($_GET['download']))
{
$http_headers[] = 'Content-Disposition: attachment; filename="'.htmlspecialchars_decode($element_info['file']).'";';
$http_headers[] = 'Content-Transfer-Encoding: binary';
}
else
{
$http_headers[] = 'Content-Disposition: inline; filename="'
.basename($file).'";';
}
foreach ($http_headers as $header)
{
header( $header );
}
// Looking at the safe_mode configuration for execution time
if (ini_get('safe_mode') == 0)
{
@set_time_limit(0);
}
// Without clean and flush there may be some image download problems, or image can be corrupted after download
if (ob_get_length() !== FALSE)
{
ob_flush();
}
flush();
@readfile($file);
?>
+428
View File
@@ -0,0 +1,428 @@
<?php
// +-----------------------------------------------------------------------+
// | This file is part of Piwigo. |
// | |
// | For copyright and license information, please view the COPYING.txt |
// | file that was distributed with this source code. |
// +-----------------------------------------------------------------------+
// +-----------------------------------------------------------------------+
// | Basic constants and includes |
// +-----------------------------------------------------------------------+
define('PHPWG_ROOT_PATH','./');
define('IN_ADMIN', true);
include_once(PHPWG_ROOT_PATH.'include/common.inc.php');
include_once(PHPWG_ROOT_PATH.'admin/include/functions.php');
include_once(PHPWG_ROOT_PATH.'admin/include/functions_plugins.inc.php');
include_once(PHPWG_ROOT_PATH.'admin/include/add_core_tabs.inc.php');
trigger_notify('loc_begin_admin');
// +-----------------------------------------------------------------------+
// | Check Access and exit when user status is not ok |
// +-----------------------------------------------------------------------+
check_status(ACCESS_ADMINISTRATOR);
check_input_parameter('page', $_GET, false, '/^[a-zA-Z\d_-]+$/');
check_input_parameter('section', $_GET, false, '/^[a-z]+[a-z_\/-]*(\.php)?$/i');
// +-----------------------------------------------------------------------+
// | Filesystem checks |
// +-----------------------------------------------------------------------+
if ($conf['fs_quick_check_period'] > 0)
{
$perform_fsqc = false;
if (isset($conf['fs_quick_check_last_check']))
{
if (strtotime($conf['fs_quick_check_last_check']) < strtotime($conf['fs_quick_check_period'].' seconds ago'))
{
$perform_fsqc = true;
}
}
else
{
$perform_fsqc = true;
}
if ($perform_fsqc)
{
fs_quick_check();
}
}
// +-----------------------------------------------------------------------+
// | Direct actions |
// +-----------------------------------------------------------------------+
// save plugins_new display order (AJAX action)
if (isset($_GET['plugins_new_order']))
{
pwg_set_session_var('plugins_new_order', $_GET['plugins_new_order']);
exit;
}
// theme changer
if (isset($_GET['change_theme']))
{
$admin_themes = array('roma', 'clear');
$admin_theme_array = array(userprefs_get_param('admin_theme', 'clear'));
$result = array_diff(
$admin_themes,
$admin_theme_array
);
$new_admin_theme = array_pop(
$result
);
userprefs_update_param('admin_theme', $new_admin_theme);
$url_params = array();
foreach (array('page', 'tab', 'section') as $url_param)
{
if (isset($_GET[$url_param]))
{
$url_params[] = $url_param.'='.$_GET[$url_param];
}
}
$redirect_url = 'admin.php';
if (count($url_params) > 0)
{
$redirect_url.= '?'.implode('&amp;', $url_params);
}
redirect($redirect_url);
}
// +-----------------------------------------------------------------------+
// | Synchronize user informations |
// +-----------------------------------------------------------------------+
// sync_user() is only useful when external authentication is activated
if ($conf['external_authentification'])
{
sync_users();
}
// +-----------------------------------------------------------------------+
// | Variables init |
// +-----------------------------------------------------------------------+
$change_theme_url = PHPWG_ROOT_PATH.'admin.php?';
$test_get = $_GET;
unset($test_get['page']);
unset($test_get['section']);
unset($test_get['tag']);
if (count($test_get) == 0 and !empty($_SERVER['QUERY_STRING']))
{
$change_theme_url.= str_replace('&', '&amp;', $_SERVER['QUERY_STRING']).'&amp;';
}
$change_theme_url.= 'change_theme=1';
// ?page=plugin-community-pendings is an clean alias of
// ?page=plugin&section=community/admin.php&tab=pendings
if (isset($_GET['page']) and preg_match('/^plugin-([^-]*)(?:-(.*))?$/', $_GET['page'], $matches))
{
$_GET['page'] = 'plugin';
if (preg_match('/^piwigo_(videojs|openstreetmap)$/', $matches[1]))
{
$matches[1] = str_replace('_', '-', $matches[1]);
}
$_GET['section'] = $matches[1].'/admin.php';
if (isset($matches[2]))
{
$_GET['tab'] = $matches[2];
}
}
// ?page=album-134-properties is an clean alias of
// ?page=album&cat_id=134&tab=properties
if (isset($_GET['page']) and preg_match('/^album-(\d+)(?:-(.*))?$/', $_GET['page'], $matches))
{
$_GET['page'] = 'album';
$_GET['cat_id'] = $matches[1];
if (isset($matches[2]))
{
$_GET['tab'] = $matches[2];
}
}
// ?page=photo-1234-properties is an clean alias of
// ?page=photo&image_id=1234&tab=properties
if (isset($_GET['page']) and preg_match('/^photo-(\d+)(?:-(.*))?$/', $_GET['page'], $matches))
{
$_GET['page'] = 'photo';
$_GET['image_id'] = $matches[1];
if (isset($matches[2]))
{
$_GET['tab'] = $matches[2];
}
}
if (isset($_GET['page'])
and preg_match('/^[a-z_]*$/', $_GET['page'])
and is_file(PHPWG_ROOT_PATH.'admin/'.$_GET['page'].'.php'))
{
$page['page'] = $_GET['page'];
}
else
{
$page['page'] = 'intro';
}
$link_start = PHPWG_ROOT_PATH.'admin.php?page=';
$conf_link = $link_start.'configuration&amp;section=';
// $_GET['tab'] is often used to perform and
// include('admin_page_'.$_GET['tab'].'.php') : we need to protect it to
// avoid any unexpected file inclusion
check_input_parameter('tab', $_GET, false, '/^[a-zA-Z\d_-]+$/');
// +-----------------------------------------------------------------------+
// | Template init |
// +-----------------------------------------------------------------------+
$title = l10n('Piwigo Administration'); // for include/page_header.php
$page['page_banner'] = '<h1>'.l10n('Piwigo Administration').'</h1>';
$page['body_id'] = 'theAdminPage';
$template->set_filenames(array('admin' => 'admin.tpl'));
$template->assign(
array(
'USERNAME' => $user['username'],
'ENABLE_SYNCHRONIZATION' => $conf['enable_synchronization'],
'U_SITE_MANAGER'=> $link_start.'site_manager',
'U_HISTORY_STAT'=> $link_start.'stats&amp;year='.date('Y').'&amp;month='.date('n'),
'U_FAQ'=> $link_start.'help',
'U_SITES'=> $link_start.'remote_site',
'U_MAINTENANCE'=> $link_start.'maintenance',
'U_NOTIFICATION_BY_MAIL'=> $link_start.'notification_by_mail',
'U_CONFIG_GENERAL'=> $link_start.'configuration',
'U_CONFIG_DISPLAY'=> $conf_link.'default',
'U_CONFIG_EXTENTS'=> $link_start.'extend_for_templates',
'U_CONFIG_MENUBAR'=> $link_start.'menubar',
'U_CONFIG_LANGUAGES' => $link_start.'languages',
'U_CONFIG_THEMES'=> $link_start.'themes',
'U_CATEGORIES'=> $link_start.'cat_list',
'U_ALBUMS'=> $link_start.'albums',
'U_CAT_OPTIONS'=> $link_start.'cat_options',
'U_CAT_SEARCH'=> $link_start.'cat_search',
'U_CAT_UPDATE'=> $link_start.'site_update&amp;site=1',
'U_RATING'=> $link_start.'rating',
'U_RECENT_SET'=> $link_start.'batch_manager&amp;filter=prefilter-last_import',
'U_BATCH'=> $link_start.'batch_manager',
'U_TAGS'=> $link_start.'tags',
'U_USERS'=> $link_start.'user_list',
'U_GROUPS'=> $link_start.'group_list',
'U_RETURN'=> get_gallery_home_url(),
'U_ADMIN'=> PHPWG_ROOT_PATH.'admin.php',
'U_LOGOUT'=> PHPWG_ROOT_PATH.'index.php?act=logout',
'U_PLUGINS'=> $link_start.'plugins',
'U_ADD_PHOTOS' => $link_start.'photos_add',
'U_CHANGE_THEME' => $change_theme_url,
'ADMIN_PAGE_TITLE' => 'Piwigo Administration Page',
'ADMIN_PAGE_OBJECT_ID' => '',
'U_SHOW_TEMPLATE_TAB' => $conf['show_template_in_side_menu'],
'SHOW_RATING' => $conf['rate'],
)
);
if ($conf['enable_core_update'])
{
$template->assign('U_UPDATES', $link_start.'updates');
}
if ($conf['activate_comments'])
{
$template->assign('U_COMMENTS', $link_start.'comments');
// pending comments
$query = '
SELECT COUNT(*)
FROM '.COMMENTS_TABLE.'
WHERE validated=\'false\'
;';
list($nb_comments) = pwg_db_fetch_row(pwg_query($query));
if ($nb_comments > 0)
{
$template->assign('NB_PENDING_COMMENTS', $nb_comments);
$page['nb_pending_comments'] = $nb_comments;
}
}
// any photo in the caddie?
$query = '
SELECT COUNT(*)
FROM '.CADDIE_TABLE.'
WHERE user_id = '.$user['id'].'
;';
list($nb_photos_in_caddie) = pwg_db_fetch_row(pwg_query($query));
if ($nb_photos_in_caddie > 0)
{
$template->assign(
array(
'NB_PHOTOS_IN_CADDIE' => $nb_photos_in_caddie,
'U_CADDIE' => $link_start.'batch_manager&amp;filter=prefilter-caddie',
)
);
} else {
$template->assign(
array(
'NB_PHOTOS_IN_CADDIE' => 0,
'U_CADDIE' => '',
)
);
}
// any photos with no md5sum ?
if (in_array($page['page'], array('site_update', 'batch_manager')))
{
$nb_no_md5sum = count(get_photos_no_md5sum());
if ($nb_no_md5sum > 0)
{
$page['no_md5sum_number'] = $nb_no_md5sum;
}
}
// only calculate number of orphans on all pages if the number of images is "not huge"
$page['nb_orphans'] = 0;
list($page['nb_photos_total']) = pwg_db_fetch_row(pwg_query('SELECT COUNT(*) FROM '.IMAGES_TABLE));
if ($page['nb_photos_total'] < 100000) // 100k is already a big gallery
{
$page['nb_orphans'] = count_orphans();
}
$template->assign(
array(
'NB_ORPHANS' => $page['nb_orphans'],
'U_ORPHANS' => $link_start.'batch_manager&amp;filter=prefilter-no_album',
)
);
// +-----------------------------------------------------------------------+
// | Refresh permissions |
// +-----------------------------------------------------------------------+
// Only for pages witch change permissions
if (
in_array($page['page'],
array(
'site_manager', // delete site
'site_update', // ?only POST
)
)
or ( !empty($_POST) and in_array($page['page'],
array(
'album', // public/private; lock/unlock, permissions
'albums',
'cat_options', // public/private; lock/unlock
'user_list', // group assoc; user level
'user_perm',
)
)
)
)
{
invalidate_user_cache();
}
$show_whats_new = false;
$whats_new_major_version = get_branch_from_version(PHPWG_VERSION);
if (userprefs_get_param('show_whats_new_'.$whats_new_major_version, true) and pwg_is_dbconf_writeable())
{
if ($user['registration_date'] > $conf['last_major_update'])
{
userprefs_update_param('show_whats_new_'.$whats_new_major_version, false);
}
else
{
// purge old whats_new_*
if (isset($user['preferences']))
{
$userprefs_params_to_delete = array();
foreach (array_keys($user['preferences']) as $pref_param)
{
if (preg_match('/^whats_new_/', $pref_param))
{
$userprefs_params_to_delete[] = $pref_param;
}
}
if (count($userprefs_params_to_delete) > 0)
{
userprefs_delete_param($userprefs_params_to_delete);
}
}
$show_whats_new = true;
}
}
$release_note_url = PHPWG_URL.'/releases/'.$whats_new_major_version.'.0.0';
$whats_new_imgs = array(
'1' =>'https://ressources.piwigo.com/uploads/c/v/7/cv7jpz6hf8//2025/11/12/20251112112645-7e309b67.png',
'2' =>'https://ressources.piwigo.com/uploads/c/v/7/cv7jpz6hf8//2025/11/12/20251112112645-61f2fcd0.png',
'3' =>'https://ressources.piwigo.com/uploads/c/v/7/cv7jpz6hf8//2025/11/12/20251112112646-b322153b.png',
// '4' =>'https://ressources.piwigo.com/uploads/c/v/7/cv7jpz6hf8//2024/11/07/20241107171642-1109101f.png',
);
//If last major update conf is less than a month old then display bell for whats new popin
$display_bell = false;
if (strtotime($conf['last_major_update']) > strtotime('1 month ago'))
{
$display_bell = true;
}
$template->assign(
array(
'SHOW_WHATS_NEW' => $show_whats_new,
'WHATS_NEW_MAJOR_VERSION' => $whats_new_major_version,
'RELEASE_NOTE_URL' => $release_note_url,
'WHATS_NEW_IMGS' => $whats_new_imgs,
'DISPLAY_BELL' => $display_bell,
)
);
// +-----------------------------------------------------------------------+
// | Include specific page |
// +-----------------------------------------------------------------------+
trigger_notify('loc_begin_admin_page');
include(PHPWG_ROOT_PATH.'admin/'.$page['page'].'.php');
$template->assign('ACTIVE_MENU', get_active_menu($page['page']));
// +-----------------------------------------------------------------------+
// | Sending html code |
// +-----------------------------------------------------------------------+
// Add the Piwigo Official menu
$template->assign( 'pwgmenu', pwg_URL() );
include(PHPWG_ROOT_PATH.'include/page_header.php');
trigger_notify('loc_end_admin');
flush_page_messages();
$template->pparse('admin');
include(PHPWG_ROOT_PATH.'include/page_tail.php');
?>
@@ -0,0 +1,85 @@
<?php
// +-----------------------------------------------------------------------+
// | This file is part of Piwigo. |
// | |
// | For copyright and license information, please view the COPYING.txt |
// | file that was distributed with this source code. |
// +-----------------------------------------------------------------------+
if( !defined("PHPWG_ROOT_PATH") )
{
die ("Hacking attempt!");
}
// +-----------------------------------------------------------------------+
// | Basic checks |
// +-----------------------------------------------------------------------+
check_status(ACCESS_ADMINISTRATOR);
check_input_parameter('cat_id', $_GET, false, PATTERN_ID);
$admin_album_base_url = get_root_url().'admin.php?page=album-'.$_GET['cat_id'];
$query = '
SELECT *
FROM '.CATEGORIES_TABLE.'
WHERE id = '.$_GET['cat_id'].'
;';
$category = pwg_db_fetch_assoc(pwg_query($query));
if (!isset($category['id']))
{
die("unknown album");
}
// +-----------------------------------------------------------------------+
// | Tabs |
// +-----------------------------------------------------------------------+
include_once(PHPWG_ROOT_PATH.'admin/include/tabsheet.class.php');
$page['tab'] = 'properties';
if (isset($_GET['tab']))
{
$page['tab'] = $_GET['tab'];
}
$tabsheet = new tabsheet();
$tabsheet->set_id('album');
$tabsheet->select($page['tab']);
$tabsheet->assign();
// +-----------------------------------------------------------------------+
// | Load the tab |
// +-----------------------------------------------------------------------+
$category_name = trigger_change(
'render_category_name',
$category['name'],
'get_cat_display_name_cache'
);
$template->assign(array(
'ADMIN_PAGE_TITLE' => l10n('Edit album').' <strong>'.$category_name.'</strong>',
'ADMIN_PAGE_OBJECT_ID' => '#'.$category['id'],
));
if ('properties' == $page['tab'])
{
include(PHPWG_ROOT_PATH.'admin/cat_modify.php');
}
elseif ('sort_order' == $page['tab'])
{
include(PHPWG_ROOT_PATH.'admin/element_set_ranks.php');
}
elseif ('permissions' == $page['tab'])
{
$_GET['cat'] = $_GET['cat_id'];
include(PHPWG_ROOT_PATH.'admin/cat_perm.php');
}
else
{
include(PHPWG_ROOT_PATH.'admin/album_'.$page['tab'].'.php');
}
?>
@@ -0,0 +1,331 @@
<?php
// +-----------------------------------------------------------------------+
// | This file is part of Piwigo. |
// | |
// | For copyright and license information, please view the COPYING.txt |
// | file that was distributed with this source code. |
// +-----------------------------------------------------------------------+
if (!defined('PHPWG_ROOT_PATH'))
{
die ("Hacking attempt!");
}
include_once(PHPWG_ROOT_PATH.'include/functions_mail.inc.php');
include_once(PHPWG_ROOT_PATH.'admin/include/functions.php');
// +-----------------------------------------------------------------------+
// | Check Access and exit when user status is not ok |
// +-----------------------------------------------------------------------+
check_status(ACCESS_ADMINISTRATOR);
// +-----------------------------------------------------------------------+
// | variable initialization |
// +-----------------------------------------------------------------------+
$page['cat'] = $category['id'];
// +-----------------------------------------------------------------------+
// | form submission |
// +-----------------------------------------------------------------------+
// info by email to an access granted group of category informations
if (isset($_POST['submitEmail']))
{
check_pwg_token();
set_make_full_url();
$img = array();
/* TODO: if $category['representative_picture_id']
is empty find child representative_picture_id */
if (!empty($category['representative_picture_id']))
{
$query = '
SELECT id, file, path, representative_ext
FROM '.IMAGES_TABLE.'
WHERE id = '.$category['representative_picture_id'].'
;';
$result = pwg_query($query);
if (pwg_db_num_rows($result) > 0)
{
$element = pwg_db_fetch_assoc($result);
$img = array(
'link' => make_picture_url(
array(
'image_id' => $element['id'],
'image_file' => $element['file'],
'category' => $category
)
),
'src' => DerivativeImage::url(IMG_THUMB, $element),
);
}
}
$args = array(
'subject' => l10n('[%s] Visit album %s', $conf['gallery_title'], trigger_change('render_category_name', $category['name'], 'admin_cat_list')),
// TODO : change this language variable to 'Visit album %s'
// TODO : 'language_selected' => ....
);
$tpl = array(
'filename' => 'cat_group_info',
'assign' => array(
'IMG' => $img,
'CAT_NAME' => trigger_change('render_category_name', $category['name'], 'admin_cat_list'),
'LINK' => make_index_url(
array(
'category' => array(
'id' => $category['id'],
'name' => trigger_change('render_category_name', $category['name'], 'admin_cat_list'),
'permalink' => $category['permalink']
)
)
),
'CPL_CONTENT' => empty($_POST['mail_content']) ? '' : stripslashes($_POST['mail_content']),
)
);
if ('users' == $_POST['who'] and isset($_POST['users']) and count($_POST['users']) > 0)
{
check_input_parameter('users', $_POST, true, PATTERN_ID);
// TODO code very similar to function pwg_mail_group. We'd better create
// a function pwg_mail_users that could be called from here and from
// pwg_mail_group
// TODO to make checks even better, we should check that theses users
// have access to this album. No real privacy issue here, even if we
// send the email to a user without permission.
$query = '
SELECT
ui.user_id,
ui.status,
ui.language,
u.'.$conf['user_fields']['email'].' AS email,
u.'.$conf['user_fields']['username'].' AS username
FROM '.USER_INFOS_TABLE.' AS ui
JOIN '.USERS_TABLE.' AS u ON u.'.$conf['user_fields']['id'].' = ui.user_id
WHERE ui.user_id IN ('.implode(',', $_POST['users']).')
;';
$users = query2array($query);
$usernames = array();
foreach ($users as $u)
{
$usernames[] = $u['username'];
$authkey = create_user_auth_key($u['user_id'], $u['status']);
$user_tpl = $tpl;
if ($authkey !== false)
{
$user_tpl['assign']['LINK'] = add_url_params($tpl['assign']['LINK'], array('auth' => $authkey['auth_key']));
if (isset($user_tpl['assign']['IMG']['link']))
{
$user_tpl['assign']['IMG']['link'] = add_url_params(
$user_tpl['assign']['IMG']['link'],
array('auth' => $authkey['auth_key'])
);
}
}
$user_args = $args;
if (isset($authkey['auth_key']))
{
$user_args['auth_key'] = $authkey['auth_key'];
}
switch_lang_to($u['language']);
pwg_mail($u['email'], $user_args, $user_tpl);
switch_lang_back();
}
$message = l10n_dec('%d mail was sent.', '%d mails were sent.', count($users));
$message.= ' ('.implode(', ', $usernames).')';
$template->assign(
array(
'save_success' =>$message,
)
);
}
elseif ('group' == $_POST['who'] and !empty($_POST['group']))
{
check_input_parameter('group', $_POST, false, PATTERN_ID);
pwg_mail_group($_POST['group'], $args, $tpl);
$query = '
SELECT
name
FROM `'.GROUPS_TABLE.'`
WHERE id = '.$_POST['group'].'
;';
list($group_name) = pwg_db_fetch_row(pwg_query($query));
$template->assign(
array(
'save_success' =>l10n('An information email was sent to group "%s"', $group_name),
)
);
}
unset_make_full_url();
}
// +-----------------------------------------------------------------------+
// | template initialization |
// +-----------------------------------------------------------------------+
$template->set_filename('album_notification', 'album_notification.tpl');
$template->assign(
array(
'CATEGORIES_NAV' =>
trim(
get_cat_display_name_from_id(
$page['cat'],
'admin.php?page=album-'
)
),
'F_ACTION' => $admin_album_base_url.'-notification',
'PWG_TOKEN' => get_pwg_token(),
)
);
if ($conf['auth_key_duration'] > 0)
{
$template->assign(
'auth_key_duration',
time_since(
strtotime('now -'.$conf['auth_key_duration'].' second'),
'second',
null,
false
)
);
}
// +-----------------------------------------------------------------------+
// | form construction |
// +-----------------------------------------------------------------------+
$query = '
SELECT
id AS group_id
FROM `'.GROUPS_TABLE.'`
;';
$all_group_ids = array_from_query($query, 'group_id');
if (count($all_group_ids) == 0)
{
$template->assign('no_group_in_gallery', true);
}
else
{
if ('private' == $category['status'])
{
$template->assign('permission_url', $admin_album_base_url.'-permissions');
$query = '
SELECT
group_id
FROM '.GROUP_ACCESS_TABLE.'
WHERE cat_id = '.$category['id'].'
;';
$group_ids = array_from_query($query, 'group_id');
}
else
{
$group_ids = $all_group_ids;
}
if (count($group_ids) > 0)
{
$query = '
SELECT
id,
name
FROM `'.GROUPS_TABLE.'`
WHERE id IN ('.implode(',', $group_ids).')
ORDER BY name ASC
;';
$template->assign(
'group_mail_options',
simple_hash_from_query($query, 'id', 'name')
);
}
}
// all users with status != guest and permitted to this this album (for a
// perfect search, we should also check that album is not only filled with
// private photos)
$query = '
SELECT
user_id
FROM '.USER_INFOS_TABLE.'
WHERE status != \'guest\'
;';
$all_user_ids = query2array($query, null, 'user_id');
if ('private' == $category['status'])
{
$user_ids_access_indirect = array();
if (isset($group_ids) and count($group_ids) > 0)
{
$query = '
SELECT
user_id
FROM '.USER_GROUP_TABLE.'
WHERE group_id IN ('.implode(',', $group_ids).')
';
$user_ids_access_indirect = query2array($query, null, 'user_id');
}
$query = '
SELECT
user_id
FROM '.USER_ACCESS_TABLE.'
WHERE cat_id = '.$category['id'].'
;';
$user_ids_access_direct = query2array($query, null, 'user_id');
$user_ids_access = array_unique(array_merge($user_ids_access_direct, $user_ids_access_indirect));
$user_ids = array_intersect($user_ids_access, $all_user_ids);
}
else
{
$user_ids = $all_user_ids;
}
if (count($user_ids) > 0)
{
$query = '
SELECT
'.$conf['user_fields']['id'].' AS id,
'.$conf['user_fields']['username'].' AS username
FROM '.USERS_TABLE.'
WHERE id IN ('.implode(',', $user_ids).')
;';
$users = query2array($query, 'id', 'username');
$template->assign('user_options', $users);
}
// +-----------------------------------------------------------------------+
// | sending html code |
// +-----------------------------------------------------------------------+
$template->assign_var_from_handle('ADMIN_CONTENT', 'album_notification');
?>
+356
View File
@@ -0,0 +1,356 @@
<?php
// +-----------------------------------------------------------------------+
// | This file is part of Piwigo. |
// | |
// | For copyright and license information, please view the COPYING.txt |
// | file that was distributed with this source code. |
// +-----------------------------------------------------------------------+
if (!defined('PHPWG_ROOT_PATH'))
{
die('Hacking attempt!');
}
include_once(PHPWG_ROOT_PATH.'admin/include/functions.php');
$query = '
SELECT
COUNT(*)
FROM '.CATEGORIES_TABLE.'
;';
list($albums_counter) = pwg_db_fetch_row(pwg_query($query));
// +-----------------------------------------------------------------------+
// | Check Access and exit when user status is not ok |
// +-----------------------------------------------------------------------+
check_status(ACCESS_ADMINISTRATOR);
check_input_parameter('parent_id', $_GET, false, PATTERN_ID);
// +-----------------------------------------------------------------------+
// | tabs |
// +-----------------------------------------------------------------------+
$page['tab'] = 'list';
include(PHPWG_ROOT_PATH.'admin/include/albums_tab.inc.php');
// +-----------------------------------------------------------------------+
// | categories auto order |
// +-----------------------------------------------------------------------+
$open_cat = $_GET['parent_id'] ?? -1;
$sort_orders = array(
'name ASC',
'name DESC',
'date_creation DESC',
'date_creation ASC',
'date_available DESC',
'date_available ASC',
'natural_order DESC',
'natural_order ASC'
);
if (isset($_POST['simpleAutoOrder']) || isset($_POST['recursiveAutoOrder']) )
{
if (!in_array($_POST['order'],$sort_orders))
{
die('Invalid sort order');
}
check_input_parameter('id', $_POST, false, '/^-?\d+$/');
$query = '
SELECT id
FROM '.CATEGORIES_TABLE.'
WHERE id_uppercat '.
(($_POST['id'] === '-1') ? 'IS NULL' : '= '.$_POST['id']).'
;';
$category_ids = array_from_query($query, 'id');
if (isset($_POST['recursiveAutoOrder']))
{
$category_ids = get_subcat_ids($category_ids);
}
$categories = array();
$sort = array();
list($order_by_field, $order_by_asc) = explode(' ', $_POST['order']);
$order_by_date = false;
if (strpos($order_by_field, 'date_') === 0)
{
$order_by_date = true;
$ref_dates = get_categories_ref_date(
$category_ids,
$order_by_field,
'ASC' == $order_by_asc ? 'min' : 'max'
);
}
$query = '
SELECT id, name, id_uppercat
FROM '.CATEGORIES_TABLE.'
WHERE id IN ('.implode(',', $category_ids).')
;';
$result = pwg_query($query);
while ($row = pwg_db_fetch_assoc($result))
{
$row['name'] = trigger_change('render_category_name', $row['name'], 'admin_cat_list');
if ($order_by_date)
{
$sort[] = $ref_dates[ $row['id'] ];
}
else
{
$sort[] = remove_accents($row['name']);
}
$categories[] = array(
'id' => $row['id'],
'id_uppercat' => $row['id_uppercat'],
);
}
array_multisort(
$sort,
$order_by_field === "natural_order" ? SORT_NATURAL : SORT_REGULAR,
'ASC' == $order_by_asc ? SORT_ASC : SORT_DESC,
$categories
);
save_categories_order($categories);
$open_cat = $_POST['id'];
}
$template->assign('open_cat', $open_cat);
// +-----------------------------------------------------------------------+
// | template initialization |
// +-----------------------------------------------------------------------+
$template->set_filename('albums', 'albums.tpl');
$template->assign(
array(
'F_ACTION' => get_root_url().'admin.php?page=albums',
)
);
$template->assign('delay_before_autoOpen', $conf['album_move_delay_before_auto_opening']);
$template->assign("POS_PREF", $conf['newcat_default_position']); //TODO use user pref if it exists
// +-----------------------------------------------------------------------+
// | Album display |
// +-----------------------------------------------------------------------+
//Get all albums
$query = '
SELECT id,name,`rank`,status, visible, uppercats, lastmodified
FROM '.CATEGORIES_TABLE.'
;';
$allAlbum = query2array($query);
//Make an id tree
$associatedTree = array();
foreach ($allAlbum as $album)
{
$album['name'] = trigger_change('render_category_name', $album['name'], 'admin_cat_list');
$album['lastmodified'] = time_since($album['lastmodified'], 'year');
$parents = explode(',',$album['uppercats']);
$the_place = &$associatedTree[strval($parents[0])];
for ($i=1; $i < count($parents); $i++)
{
$the_place = &$the_place['children'][strval($parents[$i])];
}
$the_place['cat'] = $album;
}
// WARNING $user['forbidden_categories'] is 100% reliable only on gallery side because
// it's a cache variable. On administration side, if you modify public/private status
// of an album or change permissions, this variable is reset and not recalculated until
// you open the gallery. As this situation doesn't occur each time you use the
// administration, it's quite reliable but not as much as on gallery side.
$is_forbidden = array_fill_keys(@explode(',', $user['forbidden_categories']), 1);
//Make an ordered tree
function cmpCat($a, $b)
{
if ($a['rank'] == $b['rank'])
{
return 0;
}
return ($a['rank'] < $b['rank']) ? -1 : 1;
}
function assocToOrderedTree($assocT)
{
global $nb_photos_in, $nb_sub_photos, $is_forbidden;
$orderedTree = array();
foreach($assocT as $cat)
{
$orderedCat = array();
$orderedCat['rank'] = $cat['cat']['rank'];
$orderedCat['name'] = $cat['cat']['name'];
$orderedCat['status'] = $cat['cat']['status'];
$orderedCat['id'] = $cat['cat']['id'];
$orderedCat['visible'] = $cat['cat']['visible'];
$orderedCat['uppercats'] = $cat['cat']['uppercats'];
$orderedCat['nb_images'] = isset($nb_photos_in[$cat['cat']['id']]) ? $nb_photos_in[$cat['cat']['id']] : 0;
$orderedCat['last_updates'] = $cat['cat']['lastmodified'];
$orderedCat['has_not_access'] = isset($is_forbidden[$cat['cat']['id']]);
$orderedCat['nb_sub_photos'] = isset($nb_sub_photos[$cat['cat']['id']]) ? $nb_sub_photos[$cat['cat']['id']] : 0;
if (isset($cat['children']))
{
//Does not update when moving a node
$orderedCat['nb_subcats'] = count($cat['children']);
$orderedCat['children'] = assocToOrderedTree($cat['children']);
}
array_push($orderedTree, $orderedCat);
}
usort($orderedTree, 'cmpCat');
return $orderedTree;
}
$query = '
SELECT
category_id,
COUNT(*) AS nb_photos
FROM '.IMAGE_CATEGORY_TABLE.'
GROUP BY category_id
;';
$nb_photos_in = query2array($query, 'category_id', 'nb_photos');
$query = '
SELECT
id,
uppercats
FROM '.CATEGORIES_TABLE.'
;';
$all_categories = query2array($query, 'id', 'uppercats');
$subcats_of = array();
foreach ($all_categories as $id => $uppercats)
{
foreach (array_slice(explode(',', $uppercats), 0, -1) as $uppercat_id)
{
@$subcats_of[$uppercat_id][] = $id;
}
}
$nb_sub_photos = array();
foreach ($subcats_of as $cat_id => $subcat_ids)
{
$nb_photos = 0;
foreach ($subcat_ids as $id)
{
if (isset($nb_photos_in[$id]))
{
$nb_photos+= $nb_photos_in[$id];
}
}
$nb_sub_photos[$cat_id] = $nb_photos;
}
$template->assign(
array(
'album_data' => assocToOrderedTree($associatedTree),
'PWG_TOKEN' => get_pwg_token(),
'nb_albums' => count($allAlbum),
'ADMIN_PAGE_TITLE' => l10n('Albums'),
'light_album_manager' => ($albums_counter > $conf['light_album_manager_threshold']) ? 1 : 0,
)
);
// +-----------------------------------------------------------------------+
// | sending html code |
// +-----------------------------------------------------------------------+
$template->assign_var_from_handle('ADMIN_CONTENT', 'albums');
// +-----------------------------------------------------------------------+
// | functions |
// +-----------------------------------------------------------------------+
function get_categories_ref_date($ids, $field='date_available', $minmax='max')
{
// we need to work on the whole tree under each category, even if we don't
// want to sort sub categories
$category_ids = get_subcat_ids($ids);
// search for the reference date of each album
$query = '
SELECT
category_id,
'.$minmax.'('.$field.') as ref_date
FROM '.IMAGE_CATEGORY_TABLE.'
JOIN '.IMAGES_TABLE.' ON image_id = id
WHERE category_id IN ('.implode(',', $category_ids).')
GROUP BY category_id
;';
$ref_dates = query2array($query, 'category_id', 'ref_date');
// the iterate on all albums (having a ref_date or not) to find the
// reference_date, with a search on sub-albums
$query = '
SELECT
id,
uppercats
FROM '.CATEGORIES_TABLE.'
WHERE id IN ('.implode(',', $category_ids).')
;';
$uppercats_of = query2array($query, 'id', 'uppercats');
foreach (array_keys($uppercats_of) as $cat_id)
{
// find the subcats
$subcat_ids = array();
foreach ($uppercats_of as $id => $uppercats)
{
if (preg_match('/(^|,)'.$cat_id.'(,|$)/', $uppercats))
{
$subcat_ids[] = $id;
}
}
$to_compare = array();
foreach ($subcat_ids as $id)
{
if (isset($ref_dates[$id]))
{
$to_compare[] = $ref_dates[$id];
}
}
if (count($to_compare) > 0)
{
$ref_dates[$cat_id] = 'max' == $minmax ? max($to_compare) : min($to_compare);
}
else
{
$ref_dates[$cat_id] = null;
}
}
// only return the list of $ids, not the sub-categories
$return = array();
foreach ($ids as $id)
{
$return[$id] = $ref_dates[$id];
}
return $return;
}
?>
@@ -0,0 +1,813 @@
<?php
// +-----------------------------------------------------------------------+
// | This file is part of Piwigo. |
// | |
// | For copyright and license information, please view the COPYING.txt |
// | file that was distributed with this source code. |
// +-----------------------------------------------------------------------+
/**
* Management of elements set. Elements can belong to a category or to the
* user caddie.
*
*/
if (!defined('PHPWG_ROOT_PATH'))
{
die('Hacking attempt!');
}
include_once(PHPWG_ROOT_PATH.'admin/include/functions.php');
include_once(PHPWG_ROOT_PATH.'admin/include/tabsheet.class.php');
// +-----------------------------------------------------------------------+
// | Check Access and exit when user status is not ok |
// +-----------------------------------------------------------------------+
check_status(ACCESS_ADMINISTRATOR);
check_input_parameter('selection', $_POST, true, PATTERN_ID);
check_input_parameter('display', $_REQUEST, false, '/^(\d+|all)$/');
// +-----------------------------------------------------------------------+
// | specific actions |
// +-----------------------------------------------------------------------+
if (isset($_GET['action']))
{
if ('empty_caddie' == $_GET['action'])
{
$query = '
DELETE FROM '.CADDIE_TABLE.'
WHERE user_id = '.$user['id'].'
;';
pwg_query($query);
$_SESSION['page_infos'] = array(
l10n('Information data registered in database')
);
redirect(get_root_url().'admin.php?page='.$_GET['page']);
}
if ('delete_orphans' == $_GET['action'] and isset($_GET['nb_orphans_deleted']))
{
check_input_parameter('nb_orphans_deleted', $_GET, false, '/^\d+$/');
if ($_GET['nb_orphans_deleted'] > 0)
{
$_SESSION['page_infos'][] = l10n_dec(
'%d photo was deleted', '%d photos were deleted',
$_GET['nb_orphans_deleted']
);
redirect(get_root_url().'admin.php?page='.$_GET['page']);
}
}
if ('sync_md5sum' == $_GET['action'] and isset($_GET['nb_md5sum_added']))
{
check_input_parameter('nb_md5sum_added', $_GET, false, '/^\d+$/');
if ($_GET['nb_md5sum_added'] > 0)
{
$_SESSION['page_infos'][] = l10n_dec(
'%d checksums were added', '%d checksums were added',
$_GET['nb_md5sum_added']
);
redirect(get_root_url().'admin.php?page='.$_GET['page']);
}
}
}
// +-----------------------------------------------------------------------+
// | initialize current set |
// +-----------------------------------------------------------------------+
// filters from form
if (isset($_POST['submitFilter']))
{
// echo '<pre>'; print_r($_POST); echo '</pre>';
unset($_REQUEST['start']); // new photo set must reset the page
$_SESSION['bulk_manager_filter'] = array();
if (isset($_POST['filter_prefilter_use']))
{
$_SESSION['bulk_manager_filter']['prefilter'] = $_POST['filter_prefilter'];
if ('duplicates' == $_POST['filter_prefilter'])
{
$has_options = false;
if (isset($_POST['filter_duplicates_checksum']))
{
$_SESSION['bulk_manager_filter']['duplicates_checksum'] = true;
$has_options = true;
}
if (isset($_POST['filter_duplicates_date']))
{
$_SESSION['bulk_manager_filter']['duplicates_date'] = true;
$has_options = true;
}
if (isset($_POST['filter_duplicates_dimensions']))
{
$_SESSION['bulk_manager_filter']['duplicates_dimensions'] = true;
$has_options = true;
}
if (!$has_options or isset($_POST['filter_duplicates_filename']))
{
$_SESSION['bulk_manager_filter']['duplicates_filename'] = true;
}
}
}
if (isset($_POST['filter_category_use']))
{
check_input_parameter('filter_category', $_POST, false, PATTERN_ID);
$_SESSION['bulk_manager_filter']['category'] = $_POST['filter_category'];
if (isset($_POST['filter_category_recursive']))
{
$_SESSION['bulk_manager_filter']['category_recursive'] = true;
}
}
if (isset($_POST['filter_tags_use']))
{
$_SESSION['bulk_manager_filter']['tags'] = get_tag_ids($_POST['filter_tags'], false);
if (isset($_POST['tag_mode']) and in_array($_POST['tag_mode'], array('AND', 'OR')))
{
$_SESSION['bulk_manager_filter']['tag_mode'] = $_POST['tag_mode'];
}
}
if (isset($_POST['filter_level_use']))
{
check_input_parameter('filter_level', $_POST, false, '/^\d+$/');
if (in_array($_POST['filter_level'], $conf['available_permission_levels']))
{
$_SESSION['bulk_manager_filter']['level'] = $_POST['filter_level'];
if (isset($_POST['filter_level_include_lower']))
{
$_SESSION['bulk_manager_filter']['level_include_lower'] = true;
}
}
}
if (isset($_POST['filter_dimension_use']))
{
foreach (array('min_width','max_width','min_height','max_height') as $type)
{
if (filter_var($_POST['filter_dimension_'.$type], FILTER_VALIDATE_INT) !== false)
{
$_SESSION['bulk_manager_filter']['dimension'][$type] = $_POST['filter_dimension_'. $type ];
}
}
foreach (array('min_ratio','max_ratio') as $type)
{
if (filter_var($_POST['filter_dimension_'.$type], FILTER_VALIDATE_FLOAT) !== false)
{
$_SESSION['bulk_manager_filter']['dimension'][$type] = $_POST['filter_dimension_'. $type ];
}
}
}
if (isset($_POST['filter_filesize_use']))
{
foreach (array('min','max') as $type)
{
if (filter_var($_POST['filter_filesize_'.$type], FILTER_VALIDATE_FLOAT) !== false)
{
$_SESSION['bulk_manager_filter']['filesize'][$type] = $_POST['filter_filesize_'. $type ];
}
}
}
if (isset($_POST['filter_search_use']))
{
$_SESSION['bulk_manager_filter']['search']['q'] = $_POST['q'];
}
$_SESSION['bulk_manager_filter'] = trigger_change('batch_manager_register_filters', $_SESSION['bulk_manager_filter']);
}
// filters from url
elseif (isset($_GET['filter']))
{
if (!is_array($_GET['filter']))
{
$_GET['filter'] = explode(',', $_GET['filter']);
}
$_SESSION['bulk_manager_filter'] = array();
foreach ($_GET['filter'] as $filter)
{
list($type, $value) = explode('-', $filter, 2);
switch ($type)
{
case 'prefilter':
if (preg_match('/^duplicates-?/', $value))
{
list(, $duplicate_field) = explode('-', $value, 2);
$_SESSION['bulk_manager_filter']['prefilter'] = 'duplicates';
if (in_array($duplicate_field, array('filename', 'checksum', 'date', 'dimensions')))
{
$_SESSION['bulk_manager_filter']['duplicates_'.$duplicate_field] = true;
}
}
else
{
$_SESSION['bulk_manager_filter']['prefilter'] = $value;
}
break;
case 'album': case 'category': case 'cat':
if (is_numeric($value))
{
$_SESSION['bulk_manager_filter']['category'] = $value;
}
break;
case 'tag':
if (is_numeric($value))
{
$_SESSION['bulk_manager_filter']['tags'] = array($value);
$_SESSION['bulk_manager_filter']['tag_mode'] = 'AND';
}
break;
case 'level':
if (is_numeric($value) && in_array($value, $conf['available_permission_levels']))
{
$_SESSION['bulk_manager_filter']['level'] = $value;
}
break;
case 'search':
$_SESSION['bulk_manager_filter']['search']['q'] = $value;
break;
case 'dimension':
$dim_map = array('w'=>'width','h'=>'height','r'=>'ratio');
foreach (explode('-', $value) as $part)
{
$values = explode('..', substr($part, 1));
if (isset($dim_map[$part[0]]))
{
$type = $dim_map[$part[0]];
list(
$_SESSION['bulk_manager_filter']['dimension']['min_'.$type],
$_SESSION['bulk_manager_filter']['dimension']['max_'.$type]
) = $values;
}
}
break;
case 'filesize':
list(
$_SESSION['bulk_manager_filter']['filesize']['min'],
$_SESSION['bulk_manager_filter']['filesize']['max']
) = explode('..', $value);
break;
default:
$_SESSION['bulk_manager_filter'] = trigger_change('batch_manager_url_filter', $_SESSION['bulk_manager_filter'], $filter);
break;
}
}
}
if (empty($_SESSION['bulk_manager_filter']))
{
$_SESSION['bulk_manager_filter'] = array(
'prefilter' => 'caddie'
);
}
// echo '<pre>'; print_r($_SESSION['bulk_manager_filter']); echo '</pre>';
// depending on the current filter (in session), we find the appropriate photos
$filter_sets = array();
if (isset($_SESSION['bulk_manager_filter']['prefilter']))
{
switch ($_SESSION['bulk_manager_filter']['prefilter'])
{
case 'caddie':
$query = '
SELECT element_id
FROM '.CADDIE_TABLE.'
WHERE user_id = '.$user['id'].'
;';
$filter_sets[] = query2array($query, null, 'element_id');
break;
case 'favorites':
$query = '
SELECT image_id
FROM '.FAVORITES_TABLE.'
WHERE user_id = '.$user['id'].'
;';
$filter_sets[] = query2array($query, null, 'image_id');
break;
case 'last_import':
$query = '
SELECT MAX(date_available) AS date
FROM '.IMAGES_TABLE.'
;';
$row = pwg_db_fetch_assoc(pwg_query($query));
if (!empty($row['date']))
{
$query = '
SELECT id
FROM '.IMAGES_TABLE.'
WHERE date_available BETWEEN '.pwg_db_get_recent_period_expression(1, $row['date']).' AND \''.$row['date'].'\'
;';
$filter_sets[] = query2array($query, null, 'id');
}
break;
case 'no_virtual_album':
// we are searching elements not linked to any virtual category
$query = '
SELECT id
FROM '.IMAGES_TABLE.'
;';
$all_elements = query2array($query, null, 'id');
$linked_to_virtual = array();
$query = '
SELECT id
FROM '.CATEGORIES_TABLE.'
WHERE dir IS NULL
;';
$virtual_categories = query2array($query, null, 'id');
if (!empty($virtual_categories))
{
$query = '
SELECT DISTINCT(image_id)
FROM '.IMAGE_CATEGORY_TABLE.'
WHERE category_id IN ('.implode(',', $virtual_categories).')
;';
$linked_to_virtual = query2array($query, null, 'image_id');
}
$filter_sets[] = array_diff($all_elements, $linked_to_virtual);
break;
case 'no_album':
$filter_sets[] = get_orphans();
break;
case 'no_sync_md5sum':
$filter_sets[] = get_photos_no_md5sum();
break;
case 'no_tag':
$query = '
SELECT
id
FROM '.IMAGES_TABLE.'
LEFT JOIN '.IMAGE_TAG_TABLE.' ON id = image_id
WHERE tag_id is null
;';
$filter_sets[] = query2array($query, null, 'id');
break;
case 'duplicates':
$duplicates_on_fields = array();
if (isset($_SESSION['bulk_manager_filter']['duplicates_filename']))
{
$duplicates_on_fields[] = 'file';
}
if (isset($_SESSION['bulk_manager_filter']['duplicates_checksum']))
{
$duplicates_on_fields[] = 'md5sum';
}
if (isset($_SESSION['bulk_manager_filter']['duplicates_date']))
{
$duplicates_on_fields[] = 'date_creation';
}
if (isset($_SESSION['bulk_manager_filter']['duplicates_dimensions']))
{
$duplicates_on_fields[] = 'width';
$duplicates_on_fields[] = 'height';
}
// TODO improve this algorithm, because GROUP_CONCAT is truncated at
// 1024 chars. So if you have more than ~250 duplicates for a given
// combination of "duplicates_on_fields" you won't get all the
// duplicates.
$query = '
SELECT
GROUP_CONCAT(id) AS ids
FROM '.IMAGES_TABLE;
if (in_array('md5sum', $duplicates_on_fields))
{
$query.= '
WHERE md5sum IS NOT NULL
';
}
$query.= '
GROUP BY '.implode(',', $duplicates_on_fields).'
HAVING COUNT(*) > 1
;';
$array_of_ids_string = query2array($query, null, 'ids');
$ids = array();
foreach ($array_of_ids_string as $ids_string)
{
$ids_string = rtrim($ids_string,',');
$ids = array_merge($ids, explode(',', $ids_string));
}
$filter_sets[] = $ids;
break;
case 'all_photos':
if ( count($_SESSION['bulk_manager_filter']) == 1 )
{// make the query only if this is the only filter
$query = '
SELECT id
FROM '.IMAGES_TABLE.'
'.$conf['order_by'];
$filter_sets[] = query2array($query, null, 'id');
}
break;
default:
$filter_sets = trigger_change('perform_batch_manager_prefilters', $filter_sets, $_SESSION['bulk_manager_filter']['prefilter']);
break;
}
}
if (isset($_SESSION['bulk_manager_filter']['category']))
{
$categories = array();
// we need to check the category still exists (it may have been deleted since it was added in the session)
$query = '
SELECT COUNT(*)
FROM '.CATEGORIES_TABLE.'
WHERE id = '.$_SESSION['bulk_manager_filter']['category'].'
;';
list($counter) = pwg_db_fetch_row(pwg_query($query));
if (0 == $counter)
{
unset($_SESSION['bulk_manager_filter']);
redirect(get_root_url().'admin.php?page='.$_GET['page']);
}
if (isset($_SESSION['bulk_manager_filter']['category_recursive']))
{
$categories = get_subcat_ids(array($_SESSION['bulk_manager_filter']['category']));
}
else
{
$categories = array($_SESSION['bulk_manager_filter']['category']);
}
$query = '
SELECT DISTINCT(image_id)
FROM '.IMAGE_CATEGORY_TABLE.'
WHERE category_id IN ('.implode(',', $categories).')
;';
$filter_sets[] = query2array($query, null, 'image_id');
}
if (isset($_SESSION['bulk_manager_filter']['level']))
{
$operator = '=';
if (isset($_SESSION['bulk_manager_filter']['level_include_lower']))
{
$operator = '<=';
}
$query = '
SELECT id
FROM '.IMAGES_TABLE.'
WHERE level '.$operator.' '.$_SESSION['bulk_manager_filter']['level'].'
'.$conf['order_by'];
$filter_sets[] = query2array($query, null, 'id');
}
if (!empty($_SESSION['bulk_manager_filter']['tags']))
{
$filter_sets[] = get_image_ids_for_tags(
$_SESSION['bulk_manager_filter']['tags'],
$_SESSION['bulk_manager_filter']['tag_mode'],
null,
null,
false // we don't apply permissions in administration screens
);
}
if (isset($_SESSION['bulk_manager_filter']['dimension']))
{
$where_clauses = array();
if (isset($_SESSION['bulk_manager_filter']['dimension']['min_width']))
{
$where_clause[] = 'width >= '.$_SESSION['bulk_manager_filter']['dimension']['min_width'];
}
if (isset($_SESSION['bulk_manager_filter']['dimension']['max_width']))
{
$where_clause[] = 'width <= '.$_SESSION['bulk_manager_filter']['dimension']['max_width'];
}
if (isset($_SESSION['bulk_manager_filter']['dimension']['min_height']))
{
$where_clause[] = 'height >= '.$_SESSION['bulk_manager_filter']['dimension']['min_height'];
}
if (isset($_SESSION['bulk_manager_filter']['dimension']['max_height']))
{
$where_clause[] = 'height <= '.$_SESSION['bulk_manager_filter']['dimension']['max_height'];
}
if (isset($_SESSION['bulk_manager_filter']['dimension']['min_ratio']))
{
$where_clause[] = 'width/height >= '.$_SESSION['bulk_manager_filter']['dimension']['min_ratio'];
}
if (isset($_SESSION['bulk_manager_filter']['dimension']['max_ratio']))
{
// max_ratio is a floor value, so must be a bit increased
$where_clause[] = 'width/height < '.($_SESSION['bulk_manager_filter']['dimension']['max_ratio']+0.01);
}
$query = '
SELECT id
FROM '.IMAGES_TABLE.'
WHERE '.implode(' AND ',$where_clause).'
'.$conf['order_by'];
$filter_sets[] = query2array($query, null, 'id');
}
if (isset($_SESSION['bulk_manager_filter']['filesize']))
{
$where_clauses = array();
if (isset($_SESSION['bulk_manager_filter']['filesize']['min']))
{
// to counter the effect of converting kB to mB and rounding, we need to go slightly lower for the minimum value
$where_clause[] = 'filesize >= '.($_SESSION['bulk_manager_filter']['filesize']['min'] - 0.1)*1024;
}
if (isset($_SESSION['bulk_manager_filter']['filesize']['max']))
{
// to counter the effect of converting kB to mB and rounding, we need to go slightly higher for the maximum value
$where_clause[] = 'filesize <= '.($_SESSION['bulk_manager_filter']['filesize']['max'] + 0.1)*1024;
}
$query = '
SELECT id
FROM '.IMAGES_TABLE.'
WHERE '.implode(' AND ',$where_clause).'
'.$conf['order_by'];
$filter_sets[] = query2array($query, null, 'id');
}
if (isset($_SESSION['bulk_manager_filter']['search']) &&
strlen($_SESSION['bulk_manager_filter']['search']['q']))
{
include_once( PHPWG_ROOT_PATH .'include/functions_search.inc.php' );
$res = get_quick_search_results_no_cache($_SESSION['bulk_manager_filter']['search']['q'], array('permissions'=>false));
if (!empty($res['items']) && !empty($res['qs']['unmatched_terms']))
{
$template->assign('no_search_results', array_map('htmlspecialchars', $res['qs']['unmatched_terms']) );
}
$filter_sets[] = $res['items'];
}
$filter_sets = trigger_change('batch_manager_perform_filters', $filter_sets, $_SESSION['bulk_manager_filter']);
$current_set = array_shift($filter_sets);
foreach ($filter_sets as $set)
{
$current_set = array_intersect($current_set, $set);
}
$page['cat_elements_id'] = empty($current_set) ? array() : $current_set;
// +-----------------------------------------------------------------------+
// | first element to display |
// +-----------------------------------------------------------------------+
// $page['start'] contains the number of the first element in its
// category. For exampe, $page['start'] = 12 means we must show elements #12
// and $page['nb_images'] next elements
if (!isset($_REQUEST['start'])
or !is_numeric($_REQUEST['start'])
or $_REQUEST['start'] < 0
or (isset($_REQUEST['display']) and 'all' == $_REQUEST['display']))
{
$page['start'] = 0;
}
else
{
$page['start'] = $_REQUEST['start'];
}
// +-----------------------------------------------------------------------+
// | Tabs |
// +-----------------------------------------------------------------------+
$manager_link = get_root_url().'admin.php?page=batch_manager&amp;mode=';
if (isset($_GET['mode']))
{
check_input_parameter('mode', $_GET, false, '/^(global|unit)$/');
$page['tab'] = $_GET['mode'];
}
else
{
$page['tab'] = 'global';
}
$tabsheet = new tabsheet();
$tabsheet->set_id('batch_manager');
$tabsheet->select($page['tab']);
$tabsheet->assign();
// +-----------------------------------------------------------------------+
// | dimensions |
// +-----------------------------------------------------------------------+
$widths = array();
$heights = array();
$ratios = array();
$dimensions = array();
// get all width, height and ratios
$query = '
SELECT
DISTINCT width, height
FROM '.IMAGES_TABLE.'
WHERE width IS NOT NULL
AND height IS NOT NULL
;';
$result = pwg_query($query);
if (pwg_db_num_rows($result))
{
while ($row = pwg_db_fetch_assoc($result))
{
if ($row['width']>0 && $row['height']>0)
{
$widths[] = $row['width'];
$heights[] = $row['height'];
$ratios[] = floor($row['width'] / $row['height'] * 100) / 100;
}
}
}
if (empty($widths))
{ // arbitrary values, only used when no photos on the gallery
$widths = array(600, 1920, 3500);
$heights = array(480, 1080, 2300);
$ratios = array(1.25, 1.52, 1.78);
}
foreach (array('widths','heights','ratios') as $type)
{
${$type} = array_unique(${$type});
sort(${$type});
$dimensions[$type] = implode(',', ${$type});
}
$dimensions['bounds'] = array(
'min_width' => $widths[0],
'max_width' => end($widths),
'min_height' => $heights[0],
'max_height' => end($heights),
'min_ratio' => $ratios[0],
'max_ratio' => end($ratios),
);
// find ratio categories
$ratio_categories = array(
'portrait' => array(),
'square' => array(),
'landscape' => array(),
'panorama' => array(),
);
foreach ($ratios as $ratio)
{
if ($ratio < 0.95)
{
$ratio_categories['portrait'][] = $ratio;
}
else if ($ratio >= 0.95 and $ratio <= 1.05)
{
$ratio_categories['square'][] = $ratio;
}
else if ($ratio > 1.05 and $ratio < 2)
{
$ratio_categories['landscape'][] = $ratio;
}
else if ($ratio >= 2)
{
$ratio_categories['panorama'][] = $ratio;
}
}
foreach (array_keys($ratio_categories) as $type)
{
if (count($ratio_categories[$type]) > 0)
{
$dimensions['ratio_'.$type] = array(
'min' => $ratio_categories[$type][0],
'max' => end($ratio_categories[$type]),
);
}
}
// selected=bound if nothing selected
foreach (array_keys($dimensions['bounds']) as $type)
{
$dimensions['selected'][$type] = isset($_SESSION['bulk_manager_filter']['dimension'][$type])
? $_SESSION['bulk_manager_filter']['dimension'][$type]
: $dimensions['bounds'][$type]
;
}
$template->assign('dimensions', $dimensions);
// +-----------------------------------------------------------------------+
// | filesize |
// +-----------------------------------------------------------------------+
$filesizes = array();
$filesize = array();
$query = '
SELECT
filesize
FROM '.IMAGES_TABLE.'
WHERE filesize IS NOT NULL
GROUP BY filesize
;';
$result = pwg_query($query);
while ($row = pwg_db_fetch_assoc($result))
{
$filesizes[] = sprintf('%.1f', $row['filesize']/1024);
}
if (empty($filesizes))
{ // arbitrary values, only used when no photos on the gallery
$filesizes = array(0, 1, 2, 5, 8, 15);
}
$filesizes = array_unique($filesizes);
sort($filesizes);
$filesize['list'] = implode(',', $filesizes);
$filesize['bounds'] = array(
'min' => $filesizes[0],
'max' => end($filesizes),
);
// selected=bound if nothing selected
foreach (array_keys($filesize['bounds']) as $type)
{
$filesize['selected'][$type] = isset($_SESSION['bulk_manager_filter']['filesize'][$type])
? $_SESSION['bulk_manager_filter']['filesize'][$type]
: $filesize['bounds'][$type]
;
}
$template->assign('filesize', $filesize);
// +-----------------------------------------------------------------------+
// | open specific mode |
// +-----------------------------------------------------------------------+
include(PHPWG_ROOT_PATH.'admin/batch_manager_'.$page['tab'].'.php');
?>
@@ -0,0 +1,621 @@
<?php
// +-----------------------------------------------------------------------+
// | This file is part of Piwigo. |
// | |
// | For copyright and license information, please view the COPYING.txt |
// | file that was distributed with this source code. |
// +-----------------------------------------------------------------------+
/**
* Management of elements set. Elements can belong to a category or to the
* user caddie.
*
*/
if (!defined('PHPWG_ROOT_PATH'))
{
die('Hacking attempt!');
}
include_once(PHPWG_ROOT_PATH.'admin/include/functions.php');
// +-----------------------------------------------------------------------+
// | Check Access and exit when user status is not ok |
// +-----------------------------------------------------------------------+
check_status(ACCESS_ADMINISTRATOR);
if (!empty($_POST))
{
check_pwg_token();
}
trigger_notify('loc_begin_element_set_global');
check_input_parameter('del_tags', $_POST, true, PATTERN_ID);
check_input_parameter('associate', $_POST, true, PATTERN_ID);
check_input_parameter('move', $_POST, false, PATTERN_ID);
check_input_parameter('dissociate', $_POST, false, PATTERN_ID);
// +-----------------------------------------------------------------------+
// | current selection |
// +-----------------------------------------------------------------------+
$collection = array();
if (isset($_POST['nb_photos_deleted']))
{
check_input_parameter('nb_photos_deleted', $_POST, false, '/^\d+$/');
// let's fake a collection (we don't know the image_ids so we use "null", we only
// care about the number of items here)
$collection = array_fill(0, $_POST['nb_photos_deleted'], null);
}
else if (isset($_POST['setSelected']))
{
// Here we don't use check_input_parameter because preg_match has a limit in
// the repetitive pattern. Found a limit to 3276 but may depend on memory.
//
// check_input_parameter('whole_set', $_POST, false, '/^\d+(,\d+)*$/');
//
// Instead, let's break the input parameter into pieces and check pieces one by one.
$collection = explode(',', $_POST['whole_set']);
foreach ($collection as $id)
{
if (!preg_match('/^\d+$/', $id))
{
fatal_error('[Hacking attempt] the input parameter "whole_set" is not valid');
}
}
}
else if (isset($_POST['selection']))
{
$collection = $_POST['selection'];
}
// +-----------------------------------------------------------------------+
// | global mode form submission |
// +-----------------------------------------------------------------------+
// $page['prefilter'] is a shortcut to test if the current filter contains a
// given prefilter. The idea is to make conditions simpler to write in the
// code.
$page['prefilter'] = 'none';
if (isset($_SESSION['bulk_manager_filter']['prefilter']))
{
$page['prefilter'] = $_SESSION['bulk_manager_filter']['prefilter'];
}
$redirect_url = get_root_url().'admin.php?page='.$_GET['page'];
if (isset($_POST['submit']))
{
// if the user tries to apply an action, it means that there is at least 1
// photo in the selection
if (count($collection) == 0)
{
$page['errors'][] = l10n('Select at least one photo');
}
$action = $_POST['selectAction'];
$redirect = false;
if ('remove_from_caddie' == $action)
{
$query = '
DELETE
FROM '.CADDIE_TABLE.'
WHERE element_id IN ('.implode(',', $collection).')
AND user_id = '.$user['id'].'
;';
pwg_query($query);
// remove from caddie action available only in caddie so reload content
$redirect = true;
}
else if ('add_tags' == $action)
{
if (empty($_POST['add_tags']))
{
$page['errors'][] = l10n('Select at least one tag');
}
else
{
$tag_ids = get_tag_ids($_POST['add_tags']);
add_tags($tag_ids, $collection);
if ('no_tag' == $page['prefilter'])
{
$redirect = true;
}
}
}
else if ('del_tags' == $action)
{
if (isset($_POST['del_tags']) and count($_POST['del_tags']) > 0)
{
$taglist_before = get_image_tag_ids($collection);
$query = '
DELETE
FROM '.IMAGE_TAG_TABLE.'
WHERE image_id IN ('.implode(',', $collection).')
AND tag_id IN ('.implode(',', $_POST['del_tags']).')
;';
pwg_query($query);
$taglist_after = get_image_tag_ids($collection);
$images_to_update = compare_image_tag_lists($taglist_before, $taglist_after);
update_images_lastmodified($images_to_update);
if (isset($_SESSION['bulk_manager_filter']['tags']) &&
count(array_intersect($_SESSION['bulk_manager_filter']['tags'], $_POST['del_tags'])))
{
$redirect = true;
}
}
else
{
$page['errors'][] = l10n('Select at least one tag');
}
}
if ('associate' == $action)
{
if (empty($_POST['associate']))
{
$page['errors'][] = l10n('Select at least one album');
} else {
associate_images_to_categories(
$collection,
$_POST['associate']
);
$_SESSION['page_infos'] = array(
l10n('Information data registered in database')
);
// let's refresh the page because we the current set might be modified
if ('no_album' == $page['prefilter'])
{
$redirect = true;
}
else if ('no_virtual_album' == $page['prefilter'])
{
$category_info = get_cat_info($_POST['associate']);
if (empty($category_info['dir']))
{
$redirect = true;
}
}
}
}
else if ('move' == $action)
{
move_images_to_categories($collection, array($_POST['move']));
$_SESSION['page_infos'] = array(
l10n('Information data registered in database')
);
// let's refresh the page because we the current set might be modified
if ('no_album' == $page['prefilter'])
{
$redirect = true;
}
else if ('no_virtual_album' == $page['prefilter'])
{
$category_info = get_cat_info($_POST['move']);
if (empty($category_info['dir']))
{
$redirect = true;
}
}
else if (isset($_SESSION['bulk_manager_filter']['category'])
and $_POST['move'] != $_SESSION['bulk_manager_filter']['category'])
{
$redirect = true;
}
}
else if ('dissociate' == $action)
{
$nb_dissociated = dissociate_images_from_category($collection, $_POST['dissociate']);
if ($nb_dissociated > 0)
{
$_SESSION['page_infos'] = array(
l10n('Information data registered in database')
);
// let's refresh the page because the current set might be modified
$redirect = true;
}
}
// author
else if ('author' == $action)
{
if (isset($_POST['remove_author']))
{
$_POST['author'] = null;
}
$datas = array();
foreach ($collection as $image_id)
{
$datas[] = array(
'id' => $image_id,
'author' => $_POST['author']
);
}
mass_updates(
IMAGES_TABLE,
array('primary' => array('id'), 'update' => array('author')),
$datas
);
pwg_activity('photo', $collection, 'edit', array('action'=>'author'));
}
// title
else if ('title' == $action)
{
if (isset($_POST['remove_title']))
{
$_POST['title'] = null;
}
$datas = array();
foreach ($collection as $image_id)
{
$datas[] = array(
'id' => $image_id,
'name' => $_POST['title']
);
}
mass_updates(
IMAGES_TABLE,
array('primary' => array('id'), 'update' => array('name')),
$datas
);
pwg_activity('photo', $collection, 'edit', array('action'=>'title'));
}
// date_creation
else if ('date_creation' == $action)
{
if (isset($_POST['remove_date_creation']) || empty($_POST['date_creation']))
{
$date_creation = null;
}
else
{
$date_creation = $_POST['date_creation'];
}
$datas = array();
foreach ($collection as $image_id)
{
$datas[] = array(
'id' => $image_id,
'date_creation' => $date_creation
);
}
mass_updates(
IMAGES_TABLE,
array('primary' => array('id'), 'update' => array('date_creation')),
$datas
);
pwg_activity('photo', $collection, 'edit', array('action'=>'date_creation'));
}
// privacy_level
else if ('level' == $action)
{
$datas = array();
foreach ($collection as $image_id)
{
$datas[] = array(
'id' => $image_id,
'level' => $_POST['level']
);
}
mass_updates(
IMAGES_TABLE,
array('primary' => array('id'), 'update' => array('level')),
$datas
);
pwg_activity('photo', $collection, 'edit', array('action'=>'privacy_level'));
if (isset($_SESSION['bulk_manager_filter']['level']))
{
if ($_POST['level'] < $_SESSION['bulk_manager_filter']['level'])
{
$redirect = true;
}
}
}
// add_to_caddie
else if ('add_to_caddie' == $action)
{
fill_caddie($collection);
}
// delete
else if ('delete' == $action)
{
if (isset($_POST['confirm_deletion']) and 1 == $_POST['confirm_deletion'])
{
// now done with ajax calls, with blocks
// $deleted_count = delete_elements($collection, true);
if (count($collection) > 0)
{
$_SESSION['page_infos'][] = l10n_dec(
'%d photo was deleted', '%d photos were deleted',
count($collection)
);
$redirect_url = get_root_url().'admin.php?page='.$_GET['page'];
$redirect = true;
}
else
{
$page['errors'][] = l10n('No photo can be deleted');
}
}
else
{
$page['errors'][] = l10n('You need to confirm deletion');
}
}
// synchronize metadata
else if ('metadata' == $action)
{
$page['infos'][] = l10n('Metadata synchronized from file').' <span class="badge">'.count($collection).'</span>';
}
else if ('delete_derivatives' == $action && !empty($_POST['del_derivatives_type']))
{
$query='SELECT path,representative_ext FROM '.IMAGES_TABLE.'
WHERE id IN ('.implode(',', $collection).')';
$result = pwg_query($query);
while ($info = pwg_db_fetch_assoc($result))
{
foreach( $_POST['del_derivatives_type'] as $type)
{
delete_element_derivatives($info, $type);
}
}
}
else if ('generate_derivatives' == $action)
{
if ($_POST['regenerateSuccess'] != '0')
{
$page['infos'][] = l10n('%s photos have been regenerated', $_POST['regenerateSuccess']);
}
if ($_POST['regenerateError'] != '0')
{
$page['warnings'][] = l10n('%s photos can not be regenerated', $_POST['regenerateError']);
}
}
if (!in_array($action, array('remove_from_caddie','add_to_caddie','delete_derivatives','generate_derivatives')))
{
invalidate_user_cache();
}
trigger_notify('element_set_global_action', $action, $collection);
if ($redirect)
{
redirect($redirect_url);
}
}
// +-----------------------------------------------------------------------+
// | template init |
// +-----------------------------------------------------------------------+
$template->set_filenames(array('batch_manager_global' => 'batch_manager_global.tpl'));
$base_url = get_root_url().'admin.php';
include(PHPWG_ROOT_PATH.'admin/include/batch_manager_filters.inc.php');
// +-----------------------------------------------------------------------+
// | caddie options |
// +-----------------------------------------------------------------------+
$template->assign('IN_CADDIE', 'caddie' == $page['prefilter']);
// +-----------------------------------------------------------------------+
// | global mode form |
// +-----------------------------------------------------------------------+
if (count($page['cat_elements_id']) > 0)
{
// remove tags
$template->assign('associated_tags', get_common_tags($page['cat_elements_id'], -1));
}
// creation date
$template->assign('DATE_CREATION',
empty($_POST['date_creation']) ? date('Y-m-d').' 00:00:00' : $_POST['date_creation']
);
// image level options
$template->assign(
array(
'level_options'=> get_privacy_level_options(),
'level_options_selected' => 0,
)
);
// metadata
include_once( PHPWG_ROOT_PATH.'admin/site_reader_local.php');
$site_reader = new LocalSiteReader('./');
$used_metadata = implode( ', ', $site_reader->get_metadata_attributes());
$template->assign(
array(
'used_metadata' => $used_metadata,
)
);
//derivatives
$del_deriv_map = array();
foreach(ImageStdParams::get_defined_type_map() as $params)
{
$del_deriv_map[$params->type] = l10n($params->type);
}
$gen_deriv_map = $del_deriv_map;
$del_deriv_map[IMG_CUSTOM] = l10n(IMG_CUSTOM);
$template->assign(
array(
'del_derivatives_types' => $del_deriv_map,
'generate_derivatives_types' => $gen_deriv_map,
)
);
// +-----------------------------------------------------------------------+
// | global mode thumbnails |
// +-----------------------------------------------------------------------+
// how many items to display on this page
if (!empty($_GET['display']))
{
if ('all' == $_GET['display'])
{
$page['nb_images'] = count($page['cat_elements_id']);
}
else
{
$page['nb_images'] = intval($_GET['display']);
}
}
elseif (in_array($conf['batch_manager_images_per_page_global'], array(20, 50, 100)))
{
$page['nb_images'] = $conf['batch_manager_images_per_page_global'];
}
else
{
$page['nb_images'] = 20;
}
$nb_thumbs_page = 0;
if (count($page['cat_elements_id']) > 0)
{
$nav_bar = create_navigation_bar(
$base_url.get_query_string_diff(array('start')),
count($page['cat_elements_id']),
$page['start'],
$page['nb_images']
);
$template->assign('navbar', $nav_bar);
$is_category = false;
if (isset($_SESSION['bulk_manager_filter']['category'])
and !isset($_SESSION['bulk_manager_filter']['category_recursive']))
{
$is_category = true;
}
// If using the 'duplicates' filter,
// order by the fields that are used to find duplicates.
if (isset($_SESSION['bulk_manager_filter']['prefilter'])
and 'duplicates' === $_SESSION['bulk_manager_filter']['prefilter']
and isset($duplicates_on_fields))
{
// The $duplicates_on_fields variable is defined in ./batch_manager.php
$order_by_fields = array_merge( $duplicates_on_fields, array( 'id' ) );
$conf['order_by'] = ' ORDER BY '.join(', ', $order_by_fields);
}
$query = '
SELECT id,path,representative_ext,file,filesize,level,name,width,height,rotation
FROM '.IMAGES_TABLE;
if ($is_category)
{
$category_info = get_cat_info($_SESSION['bulk_manager_filter']['category']);
$conf['order_by'] = $conf['order_by_inside_category'];
if (!empty($category_info['image_order']))
{
$conf['order_by'] = ' ORDER BY '.$category_info['image_order'];
}
$query.= '
JOIN '.IMAGE_CATEGORY_TABLE.' ON id = image_id';
}
$query.= '
WHERE id IN ('.implode(',', $page['cat_elements_id']).')';
if ($is_category)
{
$query.= '
AND category_id = '.$_SESSION['bulk_manager_filter']['category'];
}
$query.= '
'.$conf['order_by'].'
LIMIT '.$page['nb_images'].' OFFSET '.$page['start'].'
;';
$result = pwg_query($query);
$thumb_params = ImageStdParams::get_by_type(IMG_SQUARE);
// template thumbnail initialization
while ($row = pwg_db_fetch_assoc($result))
{
$nb_thumbs_page++;
$src_image = new SrcImage($row);
$ttitle = render_element_name($row);
if ($ttitle != get_name_from_file($row['file']))
{
$ttitle.= ' ('.$row['file'].')';
}
$ttitle.= '<br>'.$row['width'].'&times;'.$row['height'].' pixels, '.sprintf('%.2f', $row['filesize']/1024).'MB';
$template->append(
'thumbnails', array_merge($row,
array(
'thumb' => new DerivativeImage($thumb_params, $src_image),
'TITLE' => $ttitle,
'FILE_SRC' => DerivativeImage::url(IMG_LARGE, $src_image),
'U_EDIT' => get_root_url().'admin.php?page=photo-'.$row['id'],
)
));
}
$template->assign('thumb_params', $thumb_params);
}
$template->assign(array(
'nb_thumbs_page' => $nb_thumbs_page,
'nb_thumbs_set' => count($page['cat_elements_id']),
'CACHE_KEYS' => get_admin_client_cache_keys(array('tags', 'categories')),
));
trigger_notify('loc_end_element_set_global');
//----------------------------------------------------------- sending html code
$template->assign_var_from_handle('ADMIN_CONTENT', 'batch_manager_global');
?>
@@ -0,0 +1,424 @@
<?php
// +-----------------------------------------------------------------------+
// | This file is part of Piwigo. |
// | |
// | For copyright and license information, please view the COPYING.txt |
// | file that was distributed with this source code. |
// +-----------------------------------------------------------------------+
/**
* Management of elements set. Elements can belong to a category or to the
* user caddie.
*
*/
if (!defined('PHPWG_ROOT_PATH'))
{
die('Hacking attempt!');
}
include_once(PHPWG_ROOT_PATH.'admin/include/functions.php');
// +-----------------------------------------------------------------------+
// | Check Access and exit when user status is not ok |
// +-----------------------------------------------------------------------+
check_status(ACCESS_ADMINISTRATOR);
trigger_notify('loc_begin_element_set_unit');
// +-----------------------------------------------------------------------+
// | unit mode form submission |
// +-----------------------------------------------------------------------+
if (isset($_POST['submit']))
{
check_pwg_token();
check_input_parameter('element_ids', $_POST, false, '/^\d+(,\d+)*$/');
$collection = explode(',', $_POST['element_ids']);
$datas = array();
$query = '
SELECT id, date_creation
FROM '.IMAGES_TABLE.'
WHERE id IN ('.implode(',', $collection).')
;';
$result = pwg_query($query);
while ($row = pwg_db_fetch_assoc($result))
{
$data = array();
$data['id'] = $row['id'];
$data['name'] = $_POST['name-'.$row['id']];
$data['author'] = $_POST['author-'.$row['id']];
$data['level'] = $_POST['level-'.$row['id']];
if ($conf['allow_html_descriptions'])
{
$data['comment'] = @$_POST['description-'.$row['id']];
}
else
{
$data['comment'] = strip_tags(@$_POST['description-'.$row['id']]);
}
if (!empty($_POST['date_creation-'.$row['id']]))
{
$data['date_creation'] = $_POST['date_creation-'.$row['id']];
}
else
{
$data['date_creation'] = null;
}
$datas[] = $data;
// tags management
$tag_ids = array();
if (!empty($_POST[ 'tags-'.$row['id'] ]))
{
$tag_ids = get_tag_ids($_POST[ 'tags-'.$row['id'] ]);
}
set_tags($tag_ids, $row['id']);
}
mass_updates(
IMAGES_TABLE,
array(
'primary' => array('id'),
'update' => array('name','author','level','comment','date_creation')
),
$datas
);
$page['infos'][] = l10n('Photo informations updated');
invalidate_user_cache();
}
//collection
$collection = array();
if (isset($_POST['nb_photos_deleted']))
{
check_input_parameter('nb_photos_deleted', $_POST, false, '/^\d+$/');
// let's fake a collection (we don't know the image_ids so we use "null", we only
// care about the number of items here)
$collection = array_fill(0, $_POST['nb_photos_deleted'], null);
}
else if (isset($_POST['setSelected']))
{
// Here we don't use check_input_parameter because preg_match has a limit in
// the repetitive pattern. Found a limit to 3276 but may depend on memory.
//
// check_input_parameter('whole_set', $_POST, false, '/^\d+(,\d+)*$/');
//
// Instead, let's break the input parameter into pieces and check pieces one by one.
$collection = explode(',', $_POST['whole_set']);
foreach ($collection as $id)
{
if (!preg_match('/^\d+$/', $id))
{
fatal_error('[Hacking attempt] the input parameter "whole_set" is not valid');
}
}
}
else if (isset($_POST['selection']))
{
$collection = $_POST['selection'];
}
// +-----------------------------------------------------------------------+
// | template init |
// +-----------------------------------------------------------------------+
$template->set_filenames(
array('batch_manager_unit' => 'batch_manager_unit.tpl'));
$base_url = PHPWG_ROOT_PATH.'admin.php';
$template->assign(
array(
'U_ELEMENTS_PAGE' => $base_url.get_query_string_diff(array('display','start')),
'level_options' => get_privacy_level_options(),
'ADMIN_PAGE_TITLE' => l10n('Batch Manager'),
'PWG_TOKEN' => get_pwg_token(),
)
);
include(PHPWG_ROOT_PATH.'admin/include/batch_manager_filters.inc.php');
// +-----------------------------------------------------------------------+
// | global mode thumbnails |
// +-----------------------------------------------------------------------+
$template->assign('ACTIVE_PLUGINS', array_keys($pwg_loaded_plugins));
// how many items to display on this page
if (!empty($_GET['display']))
{
// conf_update_param('batch_manager_images_per_page_unit' , intval($_GET['display']));
// $page['nb_images'] = $conf['batch_manager_images_per_page_unit'];
$page['nb_images'] = intval($_GET['display']);
}
elseif (in_array($conf['batch_manager_images_per_page_unit'], array(5, 10, 50)))
{
$page['nb_images'] = $conf['batch_manager_images_per_page_unit'];
}
else
{
$page['nb_images'] = 5;
}
$template->assign('per_page', $page['nb_images']);
if (count($page['cat_elements_id']) > 0)
{
$nav_bar = create_navigation_bar(
$base_url.get_query_string_diff(array('start')),
count($page['cat_elements_id']),
$page['start'],
$page['nb_images']
);
$template->assign(array('navbar' => $nav_bar));
$element_ids = array();
$is_category = false;
if (isset($_SESSION['bulk_manager_filter']['category'])
and !isset($_SESSION['bulk_manager_filter']['category_recursive']))
{
$is_category = true;
}
if (isset($_SESSION['bulk_manager_filter']['prefilter'])
and 'duplicates' == $_SESSION['bulk_manager_filter']['prefilter'])
{
$conf['order_by'] = ' ORDER BY file, id';
}
$query = '
SELECT *
FROM '.IMAGES_TABLE;
if ($is_category)
{
$category_info = get_cat_info($_SESSION['bulk_manager_filter']['category']);
$conf['order_by'] = $conf['order_by_inside_category'];
if (!empty($category_info['image_order']))
{
$conf['order_by'] = ' ORDER BY '.$category_info['image_order'];
}
$query.= '
JOIN '.IMAGE_CATEGORY_TABLE.' ON id = image_id';
}
$query.= '
WHERE id IN ('.implode(',', $page['cat_elements_id']).')';
if ($is_category)
{
$query.= '
AND category_id = '.$_SESSION['bulk_manager_filter']['category'];
}
$query.= '
'.$conf['order_by'].'
LIMIT '.$page['nb_images'].' OFFSET '.$page['start'].'
;';
// $result = pwg_query($query);
$images = query2array($query);
$added_by_ids = array_unique(array_column($images, 'added_by'));
if (count($added_by_ids) > 0)
{
$query = '
SELECT
'.$conf['user_fields']['username'].' AS username,
'.$conf['user_fields']['id'].' AS id
FROM '.USERS_TABLE.'
WHERE '.$conf['user_fields']['id'].' IN ( '.implode(',', $added_by_ids).' )
;';
$added_by_username_of = query2array($query, 'id', 'username');
}
$storage_category_id = null;
if (!empty($row['storage_category_id']))
{
$storage_category_id = $row['storage_category_id'];
}
foreach ($images as $row)
{
$element_ids[] = $row['id'];
$src_image = new SrcImage($row);
$image_file = $row['file'];
$query = '
SELECT
id,
name
FROM '.IMAGE_TAG_TABLE.' AS it
JOIN '.TAGS_TABLE.' AS t ON t.id = it.tag_id
WHERE image_id = '.$row['id'].'
;';
$tag_selection = get_taglist($query);
$legend = render_element_name($row);
if ($legend != get_name_from_file($row['file']))
{
$legend.= ' ('.$row['file'].')';
}
$extTab = explode('.',$row['path']);
// represent
// categories
$query = '
SELECT category_id, uppercats, dir
FROM '.IMAGE_CATEGORY_TABLE.' AS ic
INNER JOIN '.CATEGORIES_TABLE.' AS c
ON c.id = ic.category_id
WHERE image_id = '.$row['id'].'
;';
$sub_result = pwg_query($query);
$related_categories = array();
$related_category_ids = array();
$media['image'] = get_image_infos($row['id'], true);
while ($item = pwg_db_fetch_assoc($sub_result))
{
$name =
get_cat_display_name_cache(
$item['uppercats'],
get_root_url().'admin.php?page=album-'
);
if ($item['category_id'] == $storage_category_id)
{
$template->assign('STORAGE_CATEGORY', $name);
}
$related_categories[$item['category_id']] = array('name' => $name, 'unlinkable' => $item['category_id'] != $storage_category_id);
$related_category_ids[] = $item['category_id'];
}
// jump to link
$image_file = $row['file'];
$query = '
SELECT category_id
FROM '.IMAGE_CATEGORY_TABLE.'
WHERE image_id = '.$row['id'].'
;';
$authorizeds = array_diff(
array_from_query($query, 'category_id'),
explode(
',',
calculate_permissions($user['id'], $user['status'])
)
);
if (isset($row['cat_id'])
and in_array($row['cat_id'], $authorizeds))
{
$url_img = make_picture_url(
array(
'image_id' => $row['id'],
'image_file' => $image_file,
'category' => $cache['cat_names'][ $row['cat_id'] ],
)
);
}
else
{
foreach ($authorizeds as $category)
{
$url_img = make_picture_url(
array(
'image_id' => $row['id'], //utile ?
'image_file' => $image_file,
'category' => $cache['cat_names'][ $category ],
)
);
break;
}
}
$admin_photo_base_url = get_root_url().'admin.php?page=photo-'.$row['id'];
$admin_url_start = $admin_photo_base_url.'-properties';
$admin_url_start.= isset($row['cat_id']) ? '&amp;cat_id='.$row['cat_id'] : '';
$selected_level = isset($row['level']) ? $row['level'] : $row['level'];
$template->append(
'elements', array_merge($row,
array(
'ID' => $row['id'],
'TN_SRC' => DerivativeImage::url(IMG_MEDIUM, $src_image),
'FILE_SRC' => DerivativeImage::url(IMG_LARGE, $src_image),
'LEGEND' => $legend,
'U_EDIT' => get_root_url().'admin.php?page=photo-'.$row['id'],
'NAME' => htmlspecialchars(isset($row['name']) ? $row['name'] : ""),
'AUTHOR' => htmlspecialchars(isset($row['author']) ? $row['author'] : ""),
'LEVEL' => !empty($row['level'])?$row['level']:'0',
'DESCRIPTION' => htmlspecialchars(isset($row['comment']) ? $row['comment'] : ""),
'DATE_CREATION' => $row['date_creation'],
'TAGS' => $tag_selection,
'is_svg' => (strtoupper(end($extTab)) == 'SVG'),
'TITLE' => render_element_name($row),
'DIMENSIONS' => @$row['width'].'x'.@$row['height'].' px',
'FORMAT' => ($row['width'] >= $row['height'])? 1:0,//0:horizontal, 1:vertical
'FILESIZE' => l10n('%.2f MB',$row['filesize']/1024),
'REGISTRATION_DATE' => format_date($row['date_available']),
'EXT' => l10n('%s file type',end($extTab)),
'POST_DATE' => l10n('Added on %s', format_date($row['date_available'], array('day', 'month', 'year'))),
'AGE' => l10n(ucfirst(time_since($row['date_available'], 'year'))),
'ADDED_BY' => l10n('Added by %s', $added_by_username_of[ $row['added_by'] ] ?? l10n('N/A')),
'STATS' => l10n('Visited %d times', $row['hit']),
'FILE' => l10n('%s', $row['file']),
'related_categories' => $related_categories,
'related_category_ids' => json_encode($related_category_ids),
'U_JUMPTO' => (isset($url_img) and $user['level'] >= $media['image']['level']) ? $url_img : null,
'tag_selection' => $tag_selection,
'U_DOWNLOAD' => 'action.php?id='.$row['id'].'&amp;part=e&amp;pwg_token='.get_pwg_token().'&amp;download',
'U_HISTORY' => get_root_url().'admin.php?page=history&amp;filter_image_id='.$row['id'],
'U_ACTIVITY' => get_root_url().'admin.php?page=user_activity&photo='.$row['id'],
'U_DELETE' => $admin_url_start.'&amp;delete=1&amp;pwg_token='.get_pwg_token(),
'U_SYNC' => $admin_url_start.'&amp;sync_metadata=1',
'PATH'=>$row['path'],
'level_options_selected' => array($selected_level)
)
));
}
$template->assign(array(
'ELEMENT_IDS' => implode(',', $element_ids),
));
}
$template->assign(array(
'CACHE_KEYS' => get_admin_client_cache_keys(array('tags', 'categories')),
));
trigger_notify('loc_end_element_set_unit');
// +-----------------------------------------------------------------------+
// | sending html code |
// +-----------------------------------------------------------------------+
$template->assign_var_from_handle('ADMIN_CONTENT', 'batch_manager_unit');
?>
@@ -0,0 +1,355 @@
<?php
// +-----------------------------------------------------------------------+
// | This file is part of Piwigo. |
// | |
// | For copyright and license information, please view the COPYING.txt |
// | file that was distributed with this source code. |
// +-----------------------------------------------------------------------+
if (!defined('PHPWG_ROOT_PATH'))
{
die('Hacking attempt!');
}
include_once(PHPWG_ROOT_PATH.'admin/include/functions.php');
// +-----------------------------------------------------------------------+
// | Check Access and exit when user status is not ok |
// +-----------------------------------------------------------------------+
check_status(ACCESS_ADMINISTRATOR);
trigger_notify('loc_begin_cat_list');
if (!empty($_POST) or isset($_GET['delete']))
{
check_pwg_token();
}
$sort_orders = array(
'name ASC' => l10n('Album name, A &rarr; Z'),
'name DESC' => l10n('Album name, Z &rarr; A'),
'date_creation DESC' => l10n('Date created, new &rarr; old').' '.l10n('(determined from photos)'),
'date_creation ASC' => l10n('Date created, old &rarr; new').' '.l10n('(determined from photos)'),
'date_available DESC' => l10n('Date posted, new &rarr; old').' '.l10n('(determined from photos)'),
'date_available ASC' => l10n('Date posted, old &rarr; new').' '.l10n('(determined from photos)'),
);
// +-----------------------------------------------------------------------+
// | functions |
// +-----------------------------------------------------------------------+
function get_categories_ref_date($ids, $field='date_available', $minmax='max')
{
// we need to work on the whole tree under each category, even if we don't
// want to sort sub categories
$category_ids = get_subcat_ids($ids);
// search for the reference date of each album
$query = '
SELECT
category_id,
'.$minmax.'('.$field.') as ref_date
FROM '.IMAGE_CATEGORY_TABLE.'
JOIN '.IMAGES_TABLE.' ON image_id = id
WHERE category_id IN ('.implode(',', $category_ids).')
GROUP BY category_id
;';
$ref_dates = query2array($query, 'category_id', 'ref_date');
// the iterate on all albums (having a ref_date or not) to find the
// reference_date, with a search on sub-albums
$query = '
SELECT
id,
uppercats
FROM '.CATEGORIES_TABLE.'
WHERE id IN ('.implode(',', $category_ids).')
;';
$uppercats_of = query2array($query, 'id', 'uppercats');
foreach (array_keys($uppercats_of) as $cat_id)
{
// find the subcats
$subcat_ids = array();
foreach ($uppercats_of as $id => $uppercats)
{
if (preg_match('/(^|,)'.$cat_id.'(,|$)/', $uppercats))
{
$subcat_ids[] = $id;
}
}
$to_compare = array();
foreach ($subcat_ids as $id)
{
if (isset($ref_dates[$id]))
{
$to_compare[] = $ref_dates[$id];
}
}
if (count($to_compare) > 0)
{
$ref_dates[$cat_id] = 'max' == $minmax ? max($to_compare) : min($to_compare);
}
else
{
$ref_dates[$cat_id] = null;
}
}
// only return the list of $ids, not the sub-categories
$return = array();
foreach ($ids as $id)
{
$return[$id] = $ref_dates[$id];
}
return $return;
}
// +-----------------------------------------------------------------------+
// | initialization |
// +-----------------------------------------------------------------------+
check_input_parameter('parent_id', $_GET, false, PATTERN_ID);
$categories = array();
$base_url = get_root_url().'admin.php?page=cat_list';
$navigation = '<a href="'.$base_url.'">';
$navigation.= l10n('Home');
$navigation.= '</a>';
// +-----------------------------------------------------------------------+
// | tabs |
// +-----------------------------------------------------------------------+
$page['tab'] = 'list';
include(PHPWG_ROOT_PATH.'admin/include/albums_tab.inc.php');
// +-----------------------------------------------------------------------+
// | virtual categories management |
// +-----------------------------------------------------------------------+
// request to delete a virtual category
if (isset($_GET['delete']) and is_numeric($_GET['delete']))
{
$photo_deletion_mode = 'no_delete';
if (isset($_GET['photo_deletion_mode']))
{
$photo_deletion_mode = $_GET['photo_deletion_mode'];
}
delete_categories(array($_GET['delete']), $photo_deletion_mode);
$_SESSION['page_infos'] = array(l10n('Virtual album deleted'));
update_global_rank();
invalidate_user_cache();
$redirect_url = get_root_url().'admin.php?page=cat_list';
if (isset($_GET['parent_id']))
{
$redirect_url.= '&parent_id='.$_GET['parent_id'];
}
redirect($redirect_url);
}
// request to add a virtual category
elseif (isset($_POST['submitAdd']))
{
$output_create = create_virtual_category(
$_POST['virtual_name'],
@$_GET['parent_id']
);
invalidate_user_cache();
if (isset($output_create['error']))
{
$page['errors'][] = $output_create['error'];
}
else
{
$edit_url = get_root_url().'admin.php?page=album-'.$output_create['id'];
$page['infos'][] = $output_create['info'].' <a class="icon-pencil" href="'.$edit_url.'">'.l10n('Edit album').'</a>';
}
}
// +-----------------------------------------------------------------------+
// | Navigation path |
// +-----------------------------------------------------------------------+
if (isset($_GET['parent_id']))
{
$navigation.= $conf['level_separator'];
$navigation.= get_cat_display_name_from_id(
$_GET['parent_id'],
$base_url.'&amp;parent_id='
);
}
// +-----------------------------------------------------------------------+
// | template initialization |
// +-----------------------------------------------------------------------+
$template->set_filename('categories', 'cat_list.tpl');
$form_action = PHPWG_ROOT_PATH.'admin.php?page=cat_list';
if (isset($_GET['parent_id']))
{
$form_action.= '&amp;parent_id='.$_GET['parent_id'];
}
$sort_orders_checked = array_keys($sort_orders);
$template->assign(array(
'ADMIN_PAGE_TITLE' => l10n('Album list management'),
'CATEGORIES_NAV'=> preg_replace("# {2,}#"," ",preg_replace("#(\r\n|\n\r|\n|\r)#"," ",$navigation)),
'F_ACTION'=>$form_action,
'PWG_TOKEN' => get_pwg_token(),
'sort_orders' => $sort_orders,
'sort_order_checked' => array_shift($sort_orders_checked),
));
// +-----------------------------------------------------------------------+
// | Categories display |
// +-----------------------------------------------------------------------+
$categories = array();
$query = '
SELECT id, name, permalink, dir, `rank`, status
FROM '.CATEGORIES_TABLE;
if (!isset($_GET['parent_id']))
{
$query.= '
WHERE id_uppercat IS NULL';
}
else
{
$query.= '
WHERE id_uppercat = '.$_GET['parent_id'];
}
$query.= '
ORDER BY `rank` ASC
;';
$categories = hash_from_query($query, 'id');
// get the categories containing images directly
$categories_with_images = array();
if (count($categories))
{
$query = '
SELECT
category_id,
COUNT(*) AS nb_photos
FROM '.IMAGE_CATEGORY_TABLE.'
GROUP BY category_id
;';
// WHERE category_id IN ('.implode(',', array_keys($categories)).')
$nb_photos_in = query2array($query, 'category_id', 'nb_photos');
$query = '
SELECT
id,
uppercats
FROM '.CATEGORIES_TABLE.'
;';
$all_categories = query2array($query, 'id', 'uppercats');
$subcats_of = array();
foreach ($all_categories as $id => $uppercats)
{
foreach (array_slice(explode(',', $uppercats), 0, -1) as $uppercat_id)
{
@$subcats_of[$uppercat_id][] = $id;
}
}
$nb_sub_photos = array();
foreach ($subcats_of as $cat_id => $subcat_ids)
{
$nb_photos = 0;
foreach ($subcat_ids as $id)
{
if (isset($nb_photos_in[$id]))
{
$nb_photos+= $nb_photos_in[$id];
}
}
$nb_sub_photos[$cat_id] = $nb_photos;
}
}
$template->assign('categories', array());
$base_url = get_root_url().'admin.php?page=';
if (isset($_GET['parent_id']))
{
$template->assign(
'PARENT_EDIT',
$base_url.'album-'.$_GET['parent_id']
);
}
foreach ($categories as $category)
{
$cat_list_url = $base_url.'cat_list';
$self_url = $cat_list_url;
if (isset($_GET['parent_id']))
{
$self_url.= '&amp;parent_id='.$_GET['parent_id'];
}
$tpl_cat =
array(
'NAME' =>
trigger_change(
'render_category_name',
$category['name'],
'admin_cat_list'
),
'NB_PHOTOS' => isset($nb_photos_in[$category['id']]) ? $nb_photos_in[$category['id']] : 0,
'NB_SUB_PHOTOS' => isset($nb_sub_photos[$category['id']]) ? $nb_sub_photos[$category['id']] : 0,
'NB_SUB_ALBUMS' => isset($subcats_of[$category['id']]) ? count($subcats_of[$category['id']]) : 0,
'ID' => $category['id'],
'RANK' => $category['rank']*10,
'U_JUMPTO' => make_index_url(
array(
'category' => $category
)
),
'U_CHILDREN' => $cat_list_url.'&amp;parent_id='.$category['id'],
'U_EDIT' => $base_url.'album-'.$category['id'],
'U_ADD_PHOTOS_ALBUM' => $base_url.'photos_add&amp;album='.$category['id'],
'U_MOVE' => $base_url.'albums#cat-'.$category['id'],
'IS_VIRTUAL' => empty($category['dir']),
'CAT_ADMIN_ACCESS' => cat_admin_access($category['id']),
);
if (empty($category['dir']))
{
$tpl_cat['U_DELETE'] = $self_url.'&amp;delete='.$category['id'];
$tpl_cat['U_DELETE'].= '&amp;pwg_token='.get_pwg_token();
}
else
{
if ($conf['enable_synchronization'])
{
$tpl_cat['U_SYNC'] = $base_url.'site_update&amp;site=1&amp;cat_id='.$category['id'];
}
}
$template->append('categories', $tpl_cat);
}
trigger_notify('loc_end_cat_list');
// +-----------------------------------------------------------------------+
// | sending html code |
// +-----------------------------------------------------------------------+
$template->assign_var_from_handle('ADMIN_CONTENT', 'categories');
?>
@@ -0,0 +1,394 @@
<?php
// +-----------------------------------------------------------------------+
// | This file is part of Piwigo. |
// | |
// | For copyright and license information, please view the COPYING.txt |
// | file that was distributed with this source code. |
// +-----------------------------------------------------------------------+
if (!defined('PHPWG_ROOT_PATH'))
{
die('Hacking attempt!');
}
include_once(PHPWG_ROOT_PATH.'include/functions_mail.inc.php');
// get_complete_dir returns the concatenation of get_site_url and
// get_local_dir
// Example : "pets > rex > 1_year_old" is on the the same site as the
// Piwigo files and this category has 22 for identifier
// get_complete_dir(22) returns "./galleries/pets/rex/1_year_old/"
function get_complete_dir( $category_id )
{
return get_site_url($category_id).get_local_dir($category_id);
}
// get_local_dir returns an array with complete path without the site url
// Example : "pets > rex > 1_year_old" is on the the same site as the
// Piwigo files and this category has 22 for identifier
// get_local_dir(22) returns "pets/rex/1_year_old/"
function get_local_dir( $category_id )
{
global $page;
$uppercats = '';
$local_dir = '';
if ( isset( $page['plain_structure'][$category_id]['uppercats'] ) )
{
$uppercats = $page['plain_structure'][$category_id]['uppercats'];
}
else
{
$query = 'SELECT uppercats';
$query.= ' FROM '.CATEGORIES_TABLE.' WHERE id = '.$category_id;
$query.= ';';
$row = pwg_db_fetch_assoc( pwg_query( $query ) );
$uppercats = $row['uppercats'];
}
$upper_array = explode( ',', $uppercats );
$database_dirs = array();
$query = 'SELECT id,dir';
$query.= ' FROM '.CATEGORIES_TABLE.' WHERE id IN ('.$uppercats.')';
$query.= ';';
$result = pwg_query( $query );
while( $row = pwg_db_fetch_assoc( $result ) )
{
$database_dirs[$row['id']] = $row['dir'];
}
foreach ($upper_array as $id)
{
$local_dir.= $database_dirs[$id].'/';
}
return $local_dir;
}
// retrieving the site url : "http://domain.com/gallery/" or
// simply "./galleries/"
function get_site_url($category_id)
{
global $page;
$query = '
SELECT galleries_url
FROM '.SITES_TABLE.' AS s,'.CATEGORIES_TABLE.' AS c
WHERE s.id = c.site_id
AND c.id = '.$category_id.'
;';
$row = pwg_db_fetch_assoc(pwg_query($query));
return $row['galleries_url'];
}
function get_min_local_dir($local_dir)
{
$full_dir = explode('/', $local_dir);
if (count($full_dir) <= 3)
{
return $local_dir;
}
else
{
$start = $full_dir[0] . '/' . $full_dir[1];
$end = end($full_dir);
$concat = $start . '/&hellip;/' . $end;
return $concat;
}
}
// +-----------------------------------------------------------------------+
// | Check Access and exit when user status is not ok |
// +-----------------------------------------------------------------------+
check_status(ACCESS_ADMINISTRATOR);
trigger_notify('loc_begin_cat_modify');
//---------------------------------------------------------------- verification
if ( !isset( $_GET['cat_id'] ) || !is_numeric( $_GET['cat_id'] ) )
{
trigger_error( 'missing cat_id param', E_USER_ERROR);
}
//--------------------------------------------------------- form criteria check
if (isset($redirect))
{
redirect($admin_album_base_url.'-properties');
}
// nullable fields
foreach (array('comment','dir','site_id', 'id_uppercat') as $nullable)
{
if (!isset($category[$nullable]))
{
$category[$nullable] = '';
}
}
$category['is_virtual'] = empty($category['dir']) ? true : false;
$query = 'SELECT DISTINCT category_id
FROM '.IMAGE_CATEGORY_TABLE.'
WHERE category_id = '.$_GET['cat_id'].'
LIMIT 1';
$result = pwg_query($query);
$category['has_images'] = pwg_db_num_rows($result)>0 ? true : false;
// number of sub-categories
$subcat_ids = get_subcat_ids(array($category['id']));
$category['nb_subcats'] = count($subcat_ids) - 1;
// Navigation path
$navigation = get_cat_display_name_cache(
$category['uppercats'],
get_root_url().'admin.php?page=album-'
);
// Parent navigation path
$uppercats_array = explode(',', $category['uppercats']);
if (count($uppercats_array) > 1)
{
array_pop($uppercats_array);
$parent_navigation = get_cat_display_name_cache(
implode(',', $uppercats_array),
get_root_url().'admin.php?page=album-'
);
}
else
{
$parent_navigation = l10n('Root');
}
//----------------------------------------------------- template initialization
$template->set_filename( 'album_properties', 'cat_modify.tpl');
$base_url = get_root_url().'admin.php?page=';
$cat_list_url = $base_url.'albums';
$self_url = $cat_list_url;
if (!empty($category['id_uppercat']))
{
$self_url.= '&amp;parent_id='.$category['id_uppercat'];
}
// We show or hide this warning in JS
$page['warnings'][] = l10n('This album is currently locked, visible only to administrators.').'<span class="icon-cone unlock-album">'.l10n('Unlock it').'</span>';
$template->assign(
array(
'CATEGORIES_NAV' => preg_replace("# {2,}#"," ",preg_replace("#(\r\n|\n\r|\n|\r)#"," ",$navigation)),
'CATEGORIES_PARENT_NAV' => preg_replace("# {2,}#"," ",preg_replace("#(\r\n|\n\r|\n|\r)#"," ",$parent_navigation)),
'PARENT_CAT_ID' => !empty($category['id_uppercat']) ? $category['id_uppercat'] : 0,
'CAT_ID' => $category['id'],
'CAT_NAME' => @htmlspecialchars($category['name']),
'CAT_COMMENT' => @htmlspecialchars($category['comment']),
'IS_VISIBLE' => boolean_to_string($category['visible']),
'CAT_ADMIN_ACCESS' => cat_admin_access($category['id']),
'U_DELETE' => $base_url.'albums',
'U_JUMPTO' => make_index_url(
array(
'category' => $category
)
),
'U_ADD_PHOTOS_ALBUM' => $base_url.'photos_add&amp;album='.$category['id'],
'U_CHILDREN' => $cat_list_url.'&amp;parent_id='.$category['id'],
'U_MOVE' => $base_url.'albums&amp;parent_id='.$category['id'],
'U_ACTIVITY' => get_root_url().'admin.php?page=user_activity&album='.$category['id'],
)
);
if ($conf['activate_comments'])
{
$template->assign('CAT_COMMENTABLE', boolean_to_string($category['commentable']));
}
// manage album elements link
$image_count = 0;
$info_title = "";
if ($category['has_images'])
{
$template->assign(
'U_MANAGE_ELEMENTS',
$base_url.'batch_manager&amp;filter=album-'.$category['id']
);
$query = '
SELECT
COUNT(image_id),
MIN(DATE(date_available)),
MAX(DATE(date_available))
FROM '.IMAGES_TABLE.'
JOIN '.IMAGE_CATEGORY_TABLE.' ON image_id = id
WHERE category_id = '.$category['id'].'
;';
list($image_count, $min_date, $max_date) = pwg_db_fetch_row(pwg_query($query));
if ($min_date == $max_date)
{
$info_title = l10n(
'This album contains %d photos, added on %s.',
$image_count,
format_date($min_date)
);
}
else
{
$info_title = l10n(
'This album contains %d photos, added between %s and %s.',
$image_count,
format_date($min_date),
format_date($max_date)
);
}
}
$info_photos = l10n('%d photos', $image_count);
$template->assign(
array(
'INFO_PHOTO' => $info_photos,
'INFO_TITLE' => $info_title
)
);
// total number of images under this category (including sub-categories)
$query = '
SELECT DISTINCT
(image_id)
FROM
'.IMAGE_CATEGORY_TABLE.'
WHERE
category_id IN ('.implode(',', $subcat_ids).')
;';
$image_ids_recursive = query2array($query, null, 'image_id');
$category['nb_images_recursive'] = count($image_ids_recursive);
// date creation
$query = '
SELECT occured_on
FROM `'.ACTIVITY_TABLE.'`
WHERE object_id = '.$category['id'].'
AND object = "album"
AND action = "add"
';
$result = query2array($query);
if (count($result) > 0) {
$template->assign(
array(
'INFO_CREATION_SINCE' => time_since($result[0]['occured_on'], 'day', $format=null, $with_text=true, $with_week=true, $only_last_unit=true),
'INFO_CREATION' => format_date($result[0]['occured_on'], array('day', 'month','year'))
)
);
}
// Sub Albums
$query = '
SELECT COUNT(*)
FROM `'.CATEGORIES_TABLE.'`
WHERE id_uppercat = '.$category['id'].'
';
$result = query2array($query);
$template->assign(
array(
'INFO_DIRECT_SUB' => l10n(
'%d sub-albums',
$result[0]['COUNT(*)']
),
)
);
$template->assign(array(
'INFO_ID' => l10n('Numeric identifier : %d',$category['id']),
'INFO_LAST_MODIFIED_SINCE' => time_since($category['lastmodified'], 'minute', $format=null, $with_text=true, $with_week=true, $only_last_unit=true),
'INFO_LAST_MODIFIED'=> format_date($category['lastmodified'], array('day', 'month','year')),
'INFO_IMAGES_RECURSIVE' => l10n(
'%d including sub-albums',
$category['nb_images_recursive']
),
'INFO_SUBCATS' => l10n(
'%d in whole branch',
$category['nb_subcats']
),
'NB_SUBCATS' => $category['nb_subcats'],
)
);
$template->assign(array(
'U_MANAGE_RANKS' => $base_url.'element_set_ranks&amp;cat_id='.$category['id'],
'CACHE_KEYS' => get_admin_client_cache_keys(array('categories')),
));
if (!$category['is_virtual'])
{
$category['cat_full_dir'] = get_complete_dir($_GET['cat_id']);
$category_full_dir = preg_replace('/\/$/', '', $category['cat_full_dir']);
$template->assign(
array(
'CAT_FULL_DIR' => $category_full_dir
)
);
$template->assign('CAT_DIR_NAME', basename($category_full_dir));
$template->assign('CAT_MIN_DIR', get_min_local_dir($category_full_dir));
if ($conf['enable_synchronization'])
{
$template->assign(
'U_SYNC',
$base_url.'site_update&amp;site='.$category['site_id'].'&amp;cat_id='.$category['id']
);
}
}
// representant management
if ($category['has_images'] or !empty($category['representative_picture_id']))
{
$tpl_representant = array();
// picture to display : the identified representant or the generic random
// representant ?
if (!empty($category['representative_picture_id']))
{
$tpl_representant['picture'] = get_category_representant_properties($category['representative_picture_id'], IMG_MEDIUM);
}
// can the admin choose to set a new random representant ?
$tpl_representant['ALLOW_SET_RANDOM'] = ($category['has_images'] ? true : false);
// can the admin delete the current representant ?
if (
($category['has_images']
and $conf['allow_random_representative'])
or
(!$category['has_images']
and !empty($category['representative_picture_id'])))
{
$tpl_representant['ALLOW_DELETE'] = true;
}
$template->assign('representant', $tpl_representant);
}
if ($category['is_virtual'])
{
$template->assign('parent_category', empty($category['id_uppercat']) ? array() : array($category['id_uppercat']));
}
$template->assign('PWG_TOKEN', get_pwg_token());
trigger_notify('loc_end_cat_modify');
//----------------------------------------------------------- sending html code
$template->assign_var_from_handle('ADMIN_CONTENT', 'album_properties');
?>
@@ -0,0 +1,253 @@
<?php
// +-----------------------------------------------------------------------+
// | This file is part of Piwigo. |
// | |
// | For copyright and license information, please view the COPYING.txt |
// | file that was distributed with this source code. |
// +-----------------------------------------------------------------------+
if (!defined('PHPWG_ROOT_PATH'))
{
die ("Hacking attempt!");
}
include_once(PHPWG_ROOT_PATH.'admin/include/functions.php');
include_once(PHPWG_ROOT_PATH.'admin/include/tabsheet.class.php');
// +-----------------------------------------------------------------------+
// | Check Access and exit when user status is not ok |
// +-----------------------------------------------------------------------+
check_status(ACCESS_ADMINISTRATOR);
if (!empty($_POST))
{
check_pwg_token();
check_input_parameter('cat_true', $_POST, true, PATTERN_ID);
check_input_parameter('cat_false', $_POST, true, PATTERN_ID);
check_input_parameter('section', $_GET, false, '/^[a-z0-9_-]+$/i');
}
// +-----------------------------------------------------------------------+
// | modification registration |
// +-----------------------------------------------------------------------+
if (isset($_POST['falsify'])
and isset($_POST['cat_true'])
and count($_POST['cat_true']) > 0)
{
switch ($_GET['section'])
{
case 'comments' :
{
$query = '
UPDATE '.CATEGORIES_TABLE.'
SET commentable = \'false\'
WHERE id IN ('.implode(',', $_POST['cat_true']).')
;';
pwg_query($query);
break;
}
case 'visible' :
{
set_cat_visible($_POST['cat_true'], 'false');
break;
}
case 'status' :
{
set_cat_status($_POST['cat_true'], 'private');
break;
}
case 'representative' :
{
$query = '
UPDATE '.CATEGORIES_TABLE.'
SET representative_picture_id = NULL
WHERE id IN ('.implode(',', $_POST['cat_true']).')
;';
pwg_query($query);
break;
}
}
pwg_activity('album', $_POST['cat_true'], 'edit', array('section'=>$_GET['section'], 'action'=>'falsify'));
}
else if (isset($_POST['trueify'])
and isset($_POST['cat_false'])
and count($_POST['cat_false']) > 0)
{
switch ($_GET['section'])
{
case 'comments' :
{
$query = '
UPDATE '.CATEGORIES_TABLE.'
SET commentable = \'true\'
WHERE id IN ('.implode(',', $_POST['cat_false']).')
;';
pwg_query($query);
break;
}
case 'visible' :
{
set_cat_visible($_POST['cat_false'], 'true');
break;
}
case 'status' :
{
set_cat_status($_POST['cat_false'], 'public');
break;
}
case 'representative' :
{
// theoretically, all categories in $_POST['cat_false'] contain at
// least one element, so Piwigo can find a representant.
set_random_representant($_POST['cat_false']);
break;
}
}
pwg_activity('album', $_POST['cat_false'], 'edit', array('section'=>$_GET['section'], 'action'=>'trueify'));
}
// +-----------------------------------------------------------------------+
// | template init |
// +-----------------------------------------------------------------------+
$template->set_filenames(
array(
'cat_options' => 'cat_options.tpl',
'double_select' => 'double_select.tpl'
)
);
$page['section'] = isset($_GET['section']) ? $_GET['section'] : 'status';
$base_url = PHPWG_ROOT_PATH.'admin.php?page=cat_options&amp;section=';
$template->assign(
array(
'U_HELP' => get_root_url().'admin/popuphelp.php?page=cat_options',
'F_ACTION'=>$base_url.$page['section']
)
);
// TabSheet
$tabsheet = new tabsheet();
$tabsheet->set_id('cat_options');
$tabsheet->select($page['section']);
$tabsheet->assign();
// +-----------------------------------------------------------------------+
// | form display |
// +-----------------------------------------------------------------------+
// for each section, categories in the multiselect field can be :
//
// - true : commentable for comment section
// - false : un-commentable for comment section
// - NA : (not applicable) for virtual categories
//
// for true and false status, we associates an array of category ids,
// function display_select_categories will use the given CSS class for each
// option
$cats_true = array();
$cats_false = array();
switch ($page['section'])
{
case 'comments' :
{
$query_true = '
SELECT id,name,uppercats,global_rank
FROM '.CATEGORIES_TABLE.'
WHERE commentable = \'true\'
;';
$query_false = '
SELECT id,name,uppercats,global_rank
FROM '.CATEGORIES_TABLE.'
WHERE commentable = \'false\'
;';
$template->assign(
array(
'L_SECTION' => l10n('Authorize users to add comments on selected albums'),
'L_CAT_OPTIONS_TRUE' => l10n('Authorized'),
'L_CAT_OPTIONS_FALSE' => l10n('Forbidden'),
)
);
break;
}
case 'visible' :
{
$query_true = '
SELECT id,name,uppercats,global_rank
FROM '.CATEGORIES_TABLE.'
WHERE visible = \'true\'
;';
$query_false = '
SELECT id,name,uppercats,global_rank
FROM '.CATEGORIES_TABLE.'
WHERE visible = \'false\'
;';
$template->assign(
array(
'L_SECTION' => l10n('Lock albums'),
'L_CAT_OPTIONS_TRUE' => l10n('Unlocked'),
'L_CAT_OPTIONS_FALSE' => l10n('Locked'),
)
);
break;
}
case 'status' :
{
$query_true = '
SELECT id,name,uppercats,global_rank
FROM '.CATEGORIES_TABLE.'
WHERE status = \'public\'
;';
$query_false = '
SELECT id,name,uppercats,global_rank
FROM '.CATEGORIES_TABLE.'
WHERE status = \'private\'
;';
$template->assign(
array(
'L_SECTION' => l10n('Manage authorizations for selected albums'),
'L_CAT_OPTIONS_TRUE' => l10n('Public'),
'L_CAT_OPTIONS_FALSE' => l10n('Private'),
)
);
break;
}
case 'representative' :
{
$query_true = '
SELECT id,name,uppercats,global_rank
FROM '.CATEGORIES_TABLE.'
WHERE representative_picture_id IS NOT NULL
;';
$query_false = '
SELECT DISTINCT id,name,uppercats,global_rank
FROM '.CATEGORIES_TABLE.' INNER JOIN '.IMAGE_CATEGORY_TABLE.' ON id=category_id
WHERE representative_picture_id IS NULL
;';
$template->assign(
array(
'L_SECTION' => l10n('Representative'),
'L_CAT_OPTIONS_TRUE' => l10n('singly represented'),
'L_CAT_OPTIONS_FALSE' => l10n('randomly represented')
)
);
break;
}
}
display_select_cat_wrapper($query_true,array(),'category_option_true');
display_select_cat_wrapper($query_false,array(),'category_option_false');
$template->assign('PWG_TOKEN',get_pwg_token());
$template->assign('ADMIN_PAGE_TITLE', l10n('Properties of abums'));
// +-----------------------------------------------------------------------+
// | sending html code |
// +-----------------------------------------------------------------------+
$template->assign_var_from_handle('DOUBLE_SELECT', 'double_select');
$template->assign_var_from_handle('ADMIN_CONTENT', 'cat_options');
?>
@@ -0,0 +1,303 @@
<?php
// +-----------------------------------------------------------------------+
// | This file is part of Piwigo. |
// | |
// | For copyright and license information, please view the COPYING.txt |
// | file that was distributed with this source code. |
// +-----------------------------------------------------------------------+
if (!defined('PHPWG_ROOT_PATH'))
{
die ("Hacking attempt!");
}
include_once(PHPWG_ROOT_PATH.'admin/include/functions.php');
// +-----------------------------------------------------------------------+
// | Check Access and exit when user status is not ok |
// +-----------------------------------------------------------------------+
check_status(ACCESS_ADMINISTRATOR);
// +-----------------------------------------------------------------------+
// | variable initialization |
// +-----------------------------------------------------------------------+
$page['cat'] = $category['id'];
// +-----------------------------------------------------------------------+
// | form submission |
// +-----------------------------------------------------------------------+
if (!empty($_POST))
{
check_pwg_token();
if ($category['status'] != $_POST['status'] or ($category['status'] != 'public' and isset($_POST['apply_on_sub'])))
{
$cat_ids = array($page['cat']);
if (isset($_POST['apply_on_sub']))
{
$cat_ids = array_merge($cat_ids, get_subcat_ids(array($page['cat'])));
}
set_cat_status($cat_ids, $_POST['status']);
$category['status'] = $_POST['status'];
}
if ('private' == $_POST['status'])
{
//
// manage groups
//
$query = '
SELECT group_id
FROM '.GROUP_ACCESS_TABLE.'
WHERE cat_id = '.$page['cat'].'
;';
$groups_granted = array_from_query($query, 'group_id');
if (!isset($_POST['groups']))
{
$_POST['groups'] = array();
}
//
// remove permissions to groups
//
$deny_groups = array_diff($groups_granted, $_POST['groups']);
if (count($deny_groups) > 0)
{
// if you forbid access to an album, all sub-albums become
// automatically forbidden
$query = '
DELETE
FROM '.GROUP_ACCESS_TABLE.'
WHERE group_id IN ('.implode(',', $deny_groups).')
AND cat_id IN ('.implode(',', get_subcat_ids(array($page['cat']))).')
;';
pwg_query($query);
}
//
// add permissions to groups
//
$grant_groups = $_POST['groups'];
if (count($grant_groups) > 0)
{
$cat_ids = get_uppercat_ids(array($page['cat']));
if (isset($_POST['apply_on_sub']))
{
$cat_ids = array_merge($cat_ids, get_subcat_ids(array($page['cat'])));
}
$query = '
SELECT id
FROM '.CATEGORIES_TABLE.'
WHERE id IN ('.implode(',', $cat_ids).')
AND status = \'private\'
;';
$private_cats = array_from_query($query, 'id');
$inserts = array();
foreach ($private_cats as $cat_id)
{
foreach ($grant_groups as $group_id)
{
$inserts[] = array(
'group_id' => $group_id,
'cat_id' => $cat_id
);
}
}
mass_inserts(
GROUP_ACCESS_TABLE,
array('group_id','cat_id'),
$inserts,
array('ignore'=>true)
);
}
//
// users
//
$query = '
SELECT user_id
FROM '.USER_ACCESS_TABLE.'
WHERE cat_id = '.$page['cat'].'
;';
$users_granted = array_from_query($query, 'user_id');
if (!isset($_POST['users']))
{
$_POST['users'] = array();
}
//
// remove permissions to users
//
$deny_users = array_diff($users_granted, $_POST['users']);
if (count($deny_users) > 0)
{
// if you forbid access to an album, all sub-album become automatically
// forbidden
$query = '
DELETE
FROM '.USER_ACCESS_TABLE.'
WHERE user_id IN ('.implode(',', $deny_users).')
AND cat_id IN ('.implode(',', get_subcat_ids(array($page['cat']))).')
;';
pwg_query($query);
}
//
// add permissions to users
//
$grant_users = $_POST['users'];
if (count($grant_users) > 0)
{
add_permission_on_category($page['cat'], $grant_users);
}
}
$template->assign(
array(
'save_success' =>l10n('Album updated successfully'),
)
);
}
// +-----------------------------------------------------------------------+
// | template initialization |
// +-----------------------------------------------------------------------+
$template->set_filename('cat_perm', 'cat_perm.tpl');
$template->assign(
array(
'CATEGORIES_NAV' =>
get_cat_display_name_from_id(
$page['cat'],
'admin.php?page=album-'
),
'U_HELP' => get_root_url().'admin/popuphelp.php?page=cat_perm',
'F_ACTION' => $admin_album_base_url.'-permissions',
'private' => ('private' == $category['status']),
)
);
// +-----------------------------------------------------------------------+
// | form construction |
// +-----------------------------------------------------------------------+
// groups denied are the groups not granted. So we need to find all groups
// minus groups granted to find groups denied.
$groups = array();
$query = '
SELECT id, name
FROM `'.GROUPS_TABLE.'`
ORDER BY name ASC
;';
$groups = simple_hash_from_query($query, 'id', 'name');
$template->assign('groups', $groups);
// groups granted to access the category
$query = '
SELECT group_id
FROM '.GROUP_ACCESS_TABLE.'
WHERE cat_id = '.$page['cat'].'
;';
$group_granted_ids = array_from_query($query, 'group_id');
$template->assign('groups_selected', $group_granted_ids);
// users...
$users = array();
$query = '
SELECT '.$conf['user_fields']['id'].' AS id,
'.$conf['user_fields']['username'].' AS username
FROM '.USERS_TABLE.'
;';
$users = simple_hash_from_query($query, 'id', 'username');
$template->assign('users', $users);
$query = '
SELECT user_id
FROM '.USER_ACCESS_TABLE.'
WHERE cat_id = '.$page['cat'].'
;';
$user_granted_direct_ids = array_from_query($query, 'user_id');
$template->assign('users_selected', $user_granted_direct_ids);
$user_granted_indirect_ids = array();
if (count($group_granted_ids) > 0)
{
$granted_groups = array();
$query = '
SELECT user_id, group_id
FROM '.USER_GROUP_TABLE.'
WHERE group_id IN ('.implode(',', $group_granted_ids).')
';
$result = pwg_query($query);
while ($row = pwg_db_fetch_assoc($result))
{
if (!isset($granted_groups[ $row['group_id'] ]))
{
$granted_groups[ $row['group_id'] ] = array();
}
$granted_groups[ $row['group_id'] ][] = $row['user_id'];
}
$user_granted_by_group_ids = array();
foreach ($granted_groups as $group_users)
{
$user_granted_by_group_ids = array_merge($user_granted_by_group_ids, $group_users);
}
$user_granted_by_group_ids = array_unique($user_granted_by_group_ids);
$user_granted_indirect_ids = array_diff(
$user_granted_by_group_ids,
$user_granted_direct_ids
);
$template->assign('nb_users_granted_indirect', count($user_granted_indirect_ids));
foreach ($granted_groups as $group_id => $group_users)
{
$group_usernames = array();
foreach ($group_users as $user_id)
{
if (in_array($user_id, $user_granted_indirect_ids))
{
$group_usernames[] = $users[$user_id];
}
}
$template->append(
'user_granted_indirect_groups',
array(
'group_name' => $groups[$group_id],
'group_users' => implode(', ', $group_usernames),
)
);
}
}
// +-----------------------------------------------------------------------+
// | sending html code |
// +-----------------------------------------------------------------------+
$template->assign(array(
'PWG_TOKEN' => get_pwg_token(),
'INHERIT' => $conf['inheritance_by_default'],
'CACHE_KEYS' => get_admin_client_cache_keys(array('groups', 'users')),
));
$template->assign_var_from_handle('ADMIN_CONTENT', 'cat_perm');
?>
@@ -0,0 +1,56 @@
<?php
// +-----------------------------------------------------------------------+
// | This file is part of Piwigo. |
// | |
// | For copyright and license information, please view the COPYING.txt |
// | file that was distributed with this source code. |
// +-----------------------------------------------------------------------+
if (!defined('PHPWG_ROOT_PATH'))
{
die ("Hacking attempt!");
}
include_once(PHPWG_ROOT_PATH.'admin/include/functions.php');
// +-----------------------------------------------------------------------+
// | Check Access and exit when user status is not ok |
// +-----------------------------------------------------------------------+
check_status(ACCESS_ADMINISTRATOR);
// +-----------------------------------------------------------------------+
// | template init |
// +-----------------------------------------------------------------------+
$template->set_filenames(array('comments'=>'comments.tpl'));
$template->assign(
array(
'F_ACTION' => get_root_url().'admin.php?page=comments',
'PWG_TOKEN' => get_pwg_token(),
)
);
// +-----------------------------------------------------------------------+
// | Tabs |
// +-----------------------------------------------------------------------+
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('comments');
$tabsheet->select('');
$tabsheet->assign();
$template->assign('ADMIN_PAGE_TITLE', l10n('User comments'));
// +-----------------------------------------------------------------------+
// | sending html code |
// +-----------------------------------------------------------------------+
$template->assign_var_from_handle('ADMIN_CONTENT', 'comments');
?>
@@ -0,0 +1,707 @@
<?php
// +-----------------------------------------------------------------------+
// | This file is part of Piwigo. |
// | |
// | For copyright and license information, please view the COPYING.txt |
// | file that was distributed with this source code. |
// +-----------------------------------------------------------------------+
if( !defined("PHPWG_ROOT_PATH") )
{
die ("Hacking attempt!");
}
if (!is_webmaster())
{
$page['warnings'][] = str_replace('%s', l10n('user_status_webmaster'), l10n('%s status is required to edit parameters.'));
}
include_once(PHPWG_ROOT_PATH.'admin/include/functions.php');
include_once(PHPWG_ROOT_PATH.'admin/include/functions_upload.inc.php');
include_once(PHPWG_ROOT_PATH.'admin/include/tabsheet.class.php');
// +-----------------------------------------------------------------------+
// | Check Access and exit when user status is not ok |
// +-----------------------------------------------------------------------+
check_status(ACCESS_ADMINISTRATOR);
//-------------------------------------------------------- sections definitions
check_input_parameter('section', $_GET, false, '/^[a-z]+$/i');
if (!isset($_GET['section']))
{
$page['section'] = 'main';
}
else
{
$page['section'] = $_GET['section'];
}
$main_checkboxes = array(
'allow_user_registration',
'obligatory_user_mail_address',
'rate',
'rate_anonymous',
'allow_user_customization',
'log',
'history_admin',
'history_guest',
'show_mobile_app_banner_in_gallery',
'show_mobile_app_banner_in_admin',
'upload_detect_duplicate',
'use_standard_pages',
);
$sizes_checkboxes = array(
'original_resize',
);
$comments_checkboxes = array(
'activate_comments',
'comments_forall',
'comments_validation',
'email_admin_on_comment',
'email_admin_on_comment_validation',
'user_can_delete_comment',
'user_can_edit_comment',
'email_admin_on_comment_edition',
'email_admin_on_comment_deletion',
'comments_author_mandatory',
'comments_email_mandatory',
'comments_enable_website',
);
$display_checkboxes = array(
'menubar_filter_icon',
'index_search_in_set_button',
'index_search_in_set_action',
'index_sort_order_input',
'index_flat_icon',
'index_posted_date_icon',
'index_created_date_icon',
'index_slideshow_icon',
'index_sizes_icon',
'index_new_icon',
'index_edit_icon',
'index_caddie_icon',
'display_fromto',
'picture_metadata_icon',
'picture_slideshow_icon',
'picture_favorite_icon',
'picture_sizes_icon',
'picture_download_icon',
'picture_edit_icon',
'picture_caddie_icon',
'picture_representative_icon',
'picture_navigation_icons',
'picture_navigation_thumb',
'picture_menu',
);
$display_info_checkboxes = array(
'author',
'created_on',
'posted_on',
'dimensions',
'file',
'filesize',
'tags',
'categories',
'visits',
'rating_score',
);
if (!isset($conf['filters_views']))
{
conf_update_param('filters_views', $conf['default_filters_views'], true);
}
$filters_names_checkboxes = array_values(array_diff(array_keys(safe_unserialize($conf['filters_views'])), array('last_filters_conf')));
// image order management
$sort_fields = array(
'' => '',
'file ASC' => l10n('File name, A &rarr; Z'),
'file DESC' => l10n('File name, Z &rarr; A'),
'name ASC' => l10n('Photo title, A &rarr; Z'),
'name DESC' => l10n('Photo title, Z &rarr; A'),
'date_creation DESC' => l10n('Date created, new &rarr; old'),
'date_creation ASC' => l10n('Date created, old &rarr; new'),
'date_available DESC' => l10n('Date posted, new &rarr; old'),
'date_available ASC' => l10n('Date posted, old &rarr; new'),
'rating_score DESC' => l10n('Rating score, high &rarr; low'),
'rating_score ASC' => l10n('Rating score, low &rarr; high'),
'hit DESC' => l10n('Visits, high &rarr; low'),
'hit ASC' => l10n('Visits, low &rarr; high'),
'id ASC' => l10n('Numeric identifier, 1 &rarr; 9'),
'id DESC' => l10n('Numeric identifier, 9 &rarr; 1'),
'`rank` ASC' => l10n('Manual sort order'),
);
$comments_order = array(
'ASC' => l10n('Show oldest comments first'),
'DESC' => l10n('Show latest comments first'),
);
$mail_themes = array(
'clear' => 'Clear',
'dark' => 'Dark',
);
//------------------------------ verification and registration of modifications
if (isset($_POST['submit']))
{
check_pwg_token();
$int_pattern = '/^\d+$/';
switch ($page['section'])
{
case 'main' :
{
if ( !isset($conf['order_by_custom']) and !isset($conf['order_by_inside_category_custom']) )
{
if ( !empty($_POST['order_by']) )
{
check_input_parameter('order_by', $_POST, true, '/^('.implode('|', array_keys($sort_fields)).')$/');
$used = array();
foreach ($_POST['order_by'] as $i => $val)
{
if (empty($val) or isset($used[$val]))
{
unset($_POST['order_by'][$i]);
}
else
{
$used[$val] = true;
}
}
if ( !count($_POST['order_by']) )
{
$page['errors'][] = l10n('No order field selected');
}
else
{
// limit to the number of available parameters
$order_by = $order_by_inside_category = array_slice($_POST['order_by'], 0, ceil(count($sort_fields)/2));
// there is no rank outside categories
if ( ($i = array_search('`rank` ASC', $order_by)) !== false)
{
unset($order_by[$i]);
}
// must define a default order_by if user want to order by rank only
if ( count($order_by) == 0 )
{
$order_by = array('id ASC');
}
$_POST['order_by'] = 'ORDER BY '.implode(', ', $order_by);
$_POST['order_by_inside_category'] = 'ORDER BY '.implode(', ', $order_by_inside_category);
}
}
else
{
$page['errors'][] = l10n('No order field selected');
}
}
if (empty($_POST['email_admin_on_new_user']))
{
$_POST['email_admin_on_new_user'] = 'none';
}
elseif ('all' == $_POST['email_admin_on_new_user_filter'])
{
$_POST['email_admin_on_new_user'] = 'all';
}
else
{
if (empty($_POST['email_admin_on_new_user_filter_group']))
{
$_POST['email_admin_on_new_user'] = 'all';
}
else
{
$_POST['email_admin_on_new_user'] = 'group:'.$_POST['email_admin_on_new_user_filter_group'];
}
}
foreach( $main_checkboxes as $checkbox)
{
$_POST[$checkbox] = empty($_POST[$checkbox])?'false':'true';
}
break;
}
case 'watermark' :
{
include(PHPWG_ROOT_PATH.'admin/include/configuration_watermark_process.inc.php');
break;
}
case 'sizes' :
{
include(PHPWG_ROOT_PATH.'admin/include/configuration_sizes_process.inc.php');
break;
}
case 'comments' :
{
// the number of comments per page must be an integer between 5 and 50
// included
if (!preg_match($int_pattern, $_POST['nb_comment_page'])
or $_POST['nb_comment_page'] < 5
or $_POST['nb_comment_page'] > 50)
{
$page['errors'][] = l10n('The number of comments a page must be between 5 and 50 included.');
}
foreach( $comments_checkboxes as $checkbox)
{
$_POST[$checkbox] = empty($_POST[$checkbox])?'false':'true';
}
break;
}
case 'default' :
{
// Never go here
break;
}
case 'display' :
{
if (!preg_match($int_pattern, $_POST['nb_categories_page'])
or $_POST['nb_categories_page'] < 4)
{
$page['errors'][] = l10n('The number of albums a page must be above 4.');
}
foreach( $display_checkboxes as $checkbox)
{
$_POST[$checkbox] = empty($_POST[$checkbox])?'false':'true';
}
foreach( $display_info_checkboxes as $checkbox)
{
$_POST['picture_informations'][$checkbox] =
empty($_POST['picture_informations'][$checkbox])? false : true;
}
$_POST['picture_informations'] = addslashes(serialize($_POST['picture_informations']));
break;
}
case 'search' :
{
foreach( $filters_names_checkboxes as $checkbox)
{
if (empty($_POST['filters_views_box'][$checkbox])){
$_POST['filters_views'][$checkbox]['access'] = 'nobody';
$_POST['filters_views'][$checkbox]['default'] = false;
}
else{
$_POST['filters_views'][$checkbox]['default'] =
empty($_POST['filters_views'][$checkbox]['default'])? false : true;
}
}
$_POST['filters_views']['last_filters_conf'] =
empty($_POST['filters_views']['last_filters_conf'])? false : true;
$_POST['filters_views'] = addslashes(serialize($_POST['filters_views']));
}
}
// updating configuration if no error found
if (!in_array($page['section'], array('sizes', 'watermark')) and count($page['errors']) == 0 and is_webmaster())
{
//echo '<pre>'; print_r($_POST); echo '</pre>';
$result = pwg_query('SELECT param FROM '.CONFIG_TABLE);
while ($row = pwg_db_fetch_assoc($result))
{
if (isset($_POST[$row['param']]))
{
$value = $_POST[$row['param']];
if ('gallery_title' == $row['param'])
{
if (!$conf['allow_html_descriptions'])
{
$value = strip_tags($value);
}
}
$query = '
UPDATE '.CONFIG_TABLE.'
SET value = \''. str_replace("\'", "''", $value).'\'
WHERE param = \''.$row['param'].'\'
;';
pwg_query($query);
}
}
$template->assign(
array(
'save_success' => l10n('Your configuration settings are saved'),
)
);
pwg_activity('system', ACTIVITY_SYSTEM_CORE, 'config', array('config_section'=>$page['section']));
}
//------------------------------------------------------ $conf reinitialization
load_conf_from_db();
}
// restore default derivatives settings
if ('sizes' == $page['section'] and isset($_GET['action']) and 'restore_settings' == $_GET['action'])
{
ImageStdParams::restore_default();
clear_derivative_cache();
// reset conf
load_conf_from_db();
$template->assign(
array(
'save_success' => l10n('Your configuration settings are saved'),
)
);
pwg_activity('system', ACTIVITY_SYSTEM_CORE, 'config', array('config_section'=>$page['section'],'config_action'=>$_GET['action']));
}
//----------------------------------------------------- template initialization
$template->set_filename('config', 'configuration_' . $page['section'] . '.tpl');
// TabSheet
$tabsheet = new tabsheet();
$tabsheet->set_id('configuration');
$tabsheet->select($page['section']);
$tabsheet->assign();
$action = get_root_url().'admin.php?page=configuration';
$action.= '&amp;section='.$page['section'];
$template->assign(
array(
'U_HELP' => get_root_url().'admin/popuphelp.php?page=configuration',
'PWG_TOKEN' => get_pwg_token(),
'F_ACTION'=>$action
));
switch ($page['section'])
{
case 'main' :
{
function order_by_is_local()
{
$conf = array();
include(PHPWG_ROOT_PATH . 'include/config_default.inc.php');
@include(PHPWG_ROOT_PATH. 'local/config/config.inc.php');
if (isset($conf['local_dir_site']))
{
@include(PHPWG_ROOT_PATH.PWG_LOCAL_DIR. 'config/config.inc.php');
}
return isset($conf['order_by']) or isset($conf['order_by_inside_category']);
}
if (order_by_is_local())
{
$page['warnings'][] = l10n('You have specified <i>$conf[\'order_by\']</i> in your local configuration file, this parameter in deprecated, please remove it or rename it into <i>$conf[\'order_by_custom\']</i> !');
}
if ( isset($conf['order_by_custom']) or isset($conf['order_by_inside_category_custom']) )
{
$order_by = array('');
$template->assign('ORDER_BY_IS_CUSTOM', true);
}
else
{
$out = array();
$order_by = trim($conf['order_by_inside_category']);
$order_by = str_replace('ORDER BY ', false, $order_by);
$order_by = explode(', ', $order_by);
}
$template->assign(
'main',
array(
'CONF_GALLERY_TITLE' => htmlspecialchars($conf['gallery_title']),
'CONF_PAGE_BANNER' => htmlspecialchars($conf['page_banner']),
'week_starts_on_options' => array(
'sunday' => $lang['day'][0],
'monday' => $lang['day'][1],
),
'week_starts_on_options_selected' => $conf['week_starts_on'],
'mail_theme' => $conf['mail_theme'],
'mail_theme_options' => $mail_themes,
'order_by' => $order_by,
'order_by_options' => $sort_fields,
'email_admin_on_new_user' => 'none' != $conf['email_admin_on_new_user'],
'email_admin_on_new_user_filter' => in_array($conf['email_admin_on_new_user'], array('none', 'all')) ? 'all' : 'group',
'email_admin_on_new_user_filter_group' => preg_match('/^group:(\d+)$/', $conf['email_admin_on_new_user'], $matches) ? $matches[1] : -1,
)
);
// list of groups
$query = '
SELECT
id,
name
FROM `'.GROUPS_TABLE.'`
;';
$groups = query2array($query, 'id', 'name');
natcasesort($groups);
$template->assign(
array(
'group_options' => $groups,
)
);
foreach ($main_checkboxes as $checkbox)
{
$template->append(
'main',
array(
$checkbox => $conf[$checkbox]
),
true
);
}
break;
}
case 'comments' :
{
$template->assign(
'comments',
array(
'NB_COMMENTS_PAGE'=>$conf['nb_comment_page'],
'comments_order'=>$conf['comments_order'],
'comments_order_options'=> $comments_order
)
);
foreach ($comments_checkboxes as $checkbox)
{
$template->append(
'comments',
array(
$checkbox => $conf[$checkbox]
),
true
);
}
break;
}
case 'default' :
{
$edit_user = build_user($conf['guest_id'], false);
include_once(PHPWG_ROOT_PATH.'profile.php');
$errors = array();
if (save_profile_from_post($edit_user, $errors))
{
// Reload user
$edit_user = build_user($conf['guest_id'], false);
$page['infos'][] = l10n('Information data registered in database');
}
$page['errors'] = array_merge($page['errors'], $errors);
load_profile_in_template(
$action,
'',
$edit_user,
'GUEST_'
);
$template->assign('default', array());
break;
}
case 'display' :
{
foreach ($display_checkboxes as $checkbox)
{
$template->append(
'display',
array(
$checkbox => $conf[$checkbox]
),
true
);
}
$template->append(
'display',
array(
'picture_informations' => unserialize($conf['picture_informations']),
'NB_CATEGORIES_PAGE' => $conf['nb_categories_page'],
),
true
);
break;
}
case 'sizes' :
{
// we only load the derivatives if it was not already loaded: it occurs
// when submitting the form and an error remains
if (!isset($page['sizes_loaded_in_tpl']))
{
$is_gd = (pwg_image::get_library()=='gd')? true : false;
$template->assign('is_gd', $is_gd);
$template->assign(
'sizes',
array(
'original_resize_maxwidth' => $conf['original_resize_maxwidth'],
'original_resize_maxheight' => $conf['original_resize_maxheight'],
'original_resize_quality' => $conf['original_resize_quality'],
)
);
foreach ($sizes_checkboxes as $checkbox)
{
$template->append(
'sizes',
array(
$checkbox => $conf[$checkbox]
),
true
);
}
// derivatives = multiple size
$enabled = ImageStdParams::get_defined_type_map();
$disabled = safe_unserialize(ImageStdParams::get_disabled_type_map());
if ($disabled === false)
{
$disabled = array();
}
$tpl_vars = array();
foreach(ImageStdParams::get_all_types() as $type)
{
$tpl_var = array();
$tpl_var['must_square'] = ($type==IMG_SQUARE ? true : false);
$tpl_var['must_enable'] = ($type==IMG_SQUARE || $type==IMG_THUMB || $type==$conf['derivative_default_size'])? true : false;
if ($params = @$enabled[$type])
{
$tpl_var['enabled'] = true;
}
else
{
$tpl_var['enabled']=false;
$params=@$disabled[$type];
}
if ($params)
{
list($tpl_var['w'],$tpl_var['h']) = $params->sizing->ideal_size;
if ( ($tpl_var['crop'] = round(100*$params->sizing->max_crop)) > 0)
{
list($tpl_var['minw'],$tpl_var['minh']) = $params->sizing->min_size;
}
else
{
$tpl_var['minw'] = $tpl_var['minh'] = "";
}
$tpl_var['sharpen'] = $params->sharpen;
}
$tpl_vars[$type]=$tpl_var;
}
$template->assign('derivatives', $tpl_vars);
$template->assign('resize_quality', ImageStdParams::$quality);
$tpl_vars = array();
$now = time();
foreach(ImageStdParams::$custom as $custom=>$time)
{
$tpl_vars[$custom] = ($now-$time<=24*3600) ? l10n('today') : time_since($time, 'day');
}
$template->assign('custom_derivatives', $tpl_vars);
}
break;
}
case 'watermark' :
{
$watermark_files = array();
foreach (glob(PHPWG_ROOT_PATH.'themes/default/watermarks/*.png') as $file)
{
$watermark_files[] = substr($file, strlen(PHPWG_ROOT_PATH));
}
if ( ($glob=glob(PHPWG_ROOT_PATH.PWG_LOCAL_DIR.'watermarks/*.png')) !== false)
{
foreach ($glob as $file)
{
$watermark_files[] = substr($file, strlen(PHPWG_ROOT_PATH));
}
}
$watermark_filemap = array( '' => '---' );
foreach( $watermark_files as $file)
{
$display = basename($file);
$watermark_filemap[$file] = $display;
}
$template->assign('watermark_files', $watermark_filemap);
if ($template->get_template_vars('watermark') === null)
{
$wm = ImageStdParams::get_watermark();
$position = 'custom';
if ($wm->xpos == 0 and $wm->ypos == 0)
{
$position = 'topleft';
}
if ($wm->xpos == 100 and $wm->ypos == 0)
{
$position = 'topright';
}
if ($wm->xpos == 50 and $wm->ypos == 50)
{
$position = 'middle';
}
if ($wm->xpos == 0 and $wm->ypos == 100)
{
$position = 'bottomleft';
}
if ($wm->xpos == 100 and $wm->ypos == 100)
{
$position = 'bottomright';
}
if ($wm->xrepeat != 0 || $wm->yrepeat != 0)
{
$position = 'custom';
}
$template->assign(
'watermark',
array(
'file' => $wm->file,
'minw' => $wm->min_size[0],
'minh' => $wm->min_size[1],
'xpos' => $wm->xpos,
'ypos' => $wm->ypos,
'xrepeat' => $wm->xrepeat,
'yrepeat' => $wm->yrepeat,
'opacity' => $wm->opacity,
'position' => $position,
)
);
}
break;
}
case 'search':
{
$template->assign(
'search',
array(
'filters_views' => safe_unserialize($conf['filters_views']),
'filters_names' => $filters_names_checkboxes,
),
);
$template->assign('SHOW_FILTER_RATINGS', $conf['rate']);
}
}
$template->assign('isWebmaster', (is_webmaster()) ? 1 : 0);
$template->assign('ADMIN_PAGE_TITLE', l10n('Configuration'));
//----------------------------------------------------------- sending html code
$template->assign_var_from_handle('ADMIN_CONTENT', 'config');
?>
@@ -0,0 +1,234 @@
<?php
// +-----------------------------------------------------------------------+
// | This file is part of Piwigo. |
// | |
// | For copyright and license information, please view the COPYING.txt |
// | file that was distributed with this source code. |
// +-----------------------------------------------------------------------+
/**
* Change rank of images inside a category
*
*/
if (!defined('PHPWG_ROOT_PATH'))
{
die('Hacking attempt!');
}
include_once(PHPWG_ROOT_PATH.'admin/include/functions.php');
// +-----------------------------------------------------------------------+
// | Check Access and exit when user status is not ok |
// +-----------------------------------------------------------------------+
check_status(ACCESS_ADMINISTRATOR);
if (!isset($_GET['cat_id']) or !is_numeric($_GET['cat_id']))
{
trigger_error('missing cat_id param', E_USER_ERROR);
}
$page['category_id'] = $_GET['cat_id'];
// +-----------------------------------------------------------------------+
// | global mode form submission |
// +-----------------------------------------------------------------------+
$image_order_choices = array('default', 'rank', 'user_define');
$image_order_choice = 'default';
if (isset($_POST['submit']))
{
if (isset($_POST['rank_of_image']))
{
asort($_POST['rank_of_image'], SORT_NUMERIC);
save_images_order(
$page['category_id'],
array_keys($_POST['rank_of_image'])
);
}
if (!empty($_POST['image_order_choice'])
&& in_array($_POST['image_order_choice'], $image_order_choices))
{
$image_order_choice = $_POST['image_order_choice'];
}
$message = l10n('Album updated successfully');
$image_order = null;
if ($image_order_choice=='user_define')
{
for ($i=0; $i<3; $i++)
{
if (!empty($_POST['image_order'][$i]))
{
if (!empty($image_order)) $image_order.= ',';
$image_order.= $_POST['image_order'][$i];
}
}
}
elseif ($image_order_choice=='rank')
{
$image_order = '`rank` ASC';
$message = l10n('Images manual order was saved');
}
$query = '
UPDATE '.CATEGORIES_TABLE.'
SET image_order = '.(isset($image_order) ? '\''.$image_order.'\'' : 'NULL').'
WHERE id='.$page['category_id'];
pwg_query($query);
if (isset($_POST['image_order_subcats']))
{
$cat_info = get_cat_info($page['category_id']);
$query = '
UPDATE '.CATEGORIES_TABLE.'
SET image_order = '.(isset($image_order) ? '\''.$image_order.'\'' : 'NULL').'
WHERE uppercats LIKE \''.$cat_info['uppercats'].',%\'';
pwg_query($query);
}
$template->assign(
array(
'save_success' => $message,
)
);
}
// +-----------------------------------------------------------------------+
// | template init |
// +-----------------------------------------------------------------------+
$template->set_filenames(
array('element_set_ranks' => 'element_set_ranks.tpl')
);
$base_url = get_root_url().'admin.php';
$query = '
SELECT *
FROM '.CATEGORIES_TABLE.'
WHERE id = '.$page['category_id'].'
;';
$category = pwg_db_fetch_assoc(pwg_query($query));
if ($category['image_order']=='rank ASC' or $category['image_order']=='`rank` ASC')
{
$image_order_choice = 'rank';
}
elseif ($category['image_order']!='')
{
$image_order_choice = 'user_define';
}
// Navigation path
$navigation = get_cat_display_name_cache(
$category['uppercats'],
get_root_url().'admin.php?page=album-'
);
$template->assign(
array(
'CATEGORIES_NAV' => preg_replace("# {2,}#"," ",preg_replace("#(\r\n|\n\r|\n|\r)#"," ",$navigation)),
'F_ACTION' => $base_url.get_query_string_diff(array()),
)
);
// +-----------------------------------------------------------------------+
// | thumbnails |
// +-----------------------------------------------------------------------+
$query = '
SELECT
id,
file,
path,
representative_ext,
width, height, rotation,
name,
`rank`
FROM '.IMAGES_TABLE.'
JOIN '.IMAGE_CATEGORY_TABLE.' ON image_id = id
WHERE category_id = '.$page['category_id'].'
ORDER BY `rank`
;';
$result = pwg_query($query);
if (pwg_db_num_rows($result) > 0)
{
// template thumbnail initialization
$current_rank = 1;
$derivativeParams = ImageStdParams::get_by_type(IMG_SQUARE);
while ($row = pwg_db_fetch_assoc($result))
{
$derivative = new DerivativeImage($derivativeParams, new SrcImage($row));
if ( !empty( $row['name'] ) )
{
$thumbnail_name = $row['name'];
}
else
{
$file_wo_ext = get_filename_wo_extension($row['file']);
$thumbnail_name = str_replace('_', ' ', $file_wo_ext);
}
$current_rank++;
$template->append(
'thumbnails',
array(
'ID' => $row['id'],
'NAME' => $thumbnail_name,
'TN_SRC' => $derivative->get_url(),
'RANK' => $current_rank * 10,
'SIZE' => $derivative->get_size(),
)
);
}
}
// image order management
$sort_fields = array(
'' => '',
'file ASC' => l10n('File name, A &rarr; Z'),
'file DESC' => l10n('File name, Z &rarr; A'),
'name ASC' => l10n('Photo title, A &rarr; Z'),
'name DESC' => l10n('Photo title, Z &rarr; A'),
'date_creation DESC' => l10n('Date created, new &rarr; old'),
'date_creation ASC' => l10n('Date created, old &rarr; new'),
'date_available DESC' => l10n('Date posted, new &rarr; old'),
'date_available ASC' => l10n('Date posted, old &rarr; new'),
'rating_score DESC' => l10n('Rating score, high &rarr; low'),
'rating_score ASC' => l10n('Rating score, low &rarr; high'),
'hit DESC' => l10n('Visits, high &rarr; low'),
'hit ASC' => l10n('Visits, low &rarr; high'),
'id ASC' => l10n('Numeric identifier, 1 &rarr; 9'),
'id DESC' => l10n('Numeric identifier, 9 &rarr; 1'),
'rank ASC' => l10n('Manual sort order'),
);
$template->assign('image_order_options', $sort_fields);
$image_order = explode(',', isset($category['image_order']) ? $category['image_order'] : "");
for ($i=0; $i<3; $i++) // 3 fields
{
if ( isset($image_order[$i]) )
{
$template->append('image_order', $image_order[$i]);
}
else
{
$template->append('image_order', '');
}
}
$template->assign('image_order_choice', $image_order_choice);
// +-----------------------------------------------------------------------+
// | sending html code |
// +-----------------------------------------------------------------------+
$template->assign_var_from_handle('ADMIN_CONTENT', 'element_set_ranks');
?>
@@ -0,0 +1,189 @@
<?php
// +-----------------------------------------------------------------------+
// | This file is part of Piwigo. |
// | |
// | For copyright and license information, please view the COPYING.txt |
// | file that was distributed with this source code. |
// +-----------------------------------------------------------------------+
/**
* Define replacement conditions for each template from template-extension
* (template called "replacer").
*
* "original template" from ./template/yoga (or any other than yoga)
* will be replaced by a "replacer" if the replacer is linked to this "original template"
* (and optionally, when the requested URL contains an "optional URL keyword").
*
* "Optional URL keywords" are those you can find after the module name in URLs.
*
* Therefore "Optional URL keywords" can be an active "permalink"
* (see permalinks in our documentation for further explanation).
*/
// +-----------------------------------------------------------------------+
// initialization |
// +-----------------------------------------------------------------------+
if (!defined('PHPWG_ROOT_PATH')) { die('Hacking attempt!'); }
include_once(PHPWG_ROOT_PATH.'admin/include/functions.php');
check_status(ACCESS_ADMINISTRATOR);
$tpl_extension = isset($conf['extents_for_templates']) ?
unserialize($conf['extents_for_templates']) : array();
$new_extensions = get_extents();
/* Selective URLs keyword */
$relevant_parameters = array(
'----------',
'category',
'favorites',
'most_visited',
'best_rated',
'recent_pics',
'recent_cats',
'created-monthly-calendar',
'posted-monthly-calendar',
'search',
'flat',
'list', /* <=> Random */
'tags',
);
$query = '
SELECT permalink
FROM '.CATEGORIES_TABLE.'
WHERE permalink IS NOT NULL
';
/* Add active permalinks */
$permalinks = array_from_query($query, 'permalink');
$relevant_parameters = array_merge($relevant_parameters, $permalinks);
/* Link all supported templates to their respective handle */
$eligible_templates = array(
'----------' => 'N/A',
'about.tpl' => 'about',
'comments.tpl' => 'comments',
'comment_list.tpl' => 'comment_list',
'footer.tpl' => 'tail',
'header.tpl' => 'header',
'identification.tpl' => 'identification',
'index.tpl' => 'index',
'mainpage_categories.tpl' => 'index_category_thumbnails',
'menubar.tpl' => 'menubar',
'menubar_categories.tpl' => 'mbCategories',
'menubar_identification.tpl' => 'mbIdentification',
'menubar_links.tpl' => 'mbLinks',
'menubar_menu.tpl' => 'mbMenu',
'menubar_specials.tpl' => 'mbSpecials',
'menubar_tags.tpl' => 'mbTags',
'month_calendar.tpl' => 'month_calendar',
'navigation_bar.tpl' => 'navbar',
'nbm.tpl' => 'nbm',
'notification.tpl' => 'notification',
'password.tpl' => 'password',
'picture.tpl' => 'picture',
'picture_content.tpl' => 'default_content',
'picture_nav_buttons.tpl' => 'picture_nav_buttons',
'popuphelp.tpl' => 'popuphelp',
'profile.tpl' => 'profile',
'profile_content.tpl' => 'profile_content',
'redirect.tpl' => 'redirect',
'register.tpl' => 'register',
'search.tpl' => 'search',
'slideshow.tpl' => 'slideshow',
'tags.tpl' => 'tags',
'thumbnails.tpl' => 'index_thumbnails',
);
$flip_templates = array_flip($eligible_templates);
$available_templates = array_merge(
array('N/A' => '----------'),
get_dirs(PHPWG_ROOT_PATH.'themes'));
// +-----------------------------------------------------------------------+
// | selected templates |
// +-----------------------------------------------------------------------+
if (isset($_POST['submit']))
{
$replacements = array();
$i = 0;
while (isset($_POST['reptpl'][$i]))
{
$newtpl = $_POST['reptpl'][$i];
$original = $_POST['original'][$i];
$handle = $eligible_templates[$original];
$url_keyword = $_POST['url'][$i];
if ($url_keyword == '----------') $url_keyword = 'N/A';
$bound_tpl = $_POST['bound'][$i];
if ($bound_tpl == '----------') $bound_tpl = 'N/A';
if ($handle != 'N/A')
{
$replacements[$newtpl] = array($handle, $url_keyword, $bound_tpl);
}
$i++;
}
$conf['extents_for_templates'] = serialize($replacements);
$tpl_extension = $replacements;
/* ecrire la nouvelle conf */
$query = '
UPDATE '.CONFIG_TABLE.'
SET value = \''. $conf['extents_for_templates'] .'\'
WHERE param = \'extents_for_templates\';';
if (pwg_query($query))
{
$page['infos'][] = l10n('Templates configuration has been recorded.');
}
}
// +-----------------------------------------------------------------------+
// | template init |
// +-----------------------------------------------------------------------+
/* Clearing (remove old extents, add new ones) */
foreach ($tpl_extension as $file => $conditions)
{
if ( !in_array($file,$new_extensions) ) unset($tpl_extension[$file]);
else $new_extensions = array_diff($new_extensions,array($file));
}
foreach ($new_extensions as $file)
{
$tpl_extension[$file] = array('N/A', 'N/A', 'N/A');
}
$template->set_filenames(array('extend_for_templates'
=> 'extend_for_templates.tpl'));
$base_url = PHPWG_ROOT_PATH.'admin.php?page=extend_for_templates';
$template->assign(
array(
'U_HELP' => get_root_url().'admin/popuphelp.php?page=extend_for_templates',
));
ksort($tpl_extension);
foreach ($tpl_extension as $file => $conditions)
{
$handle = $conditions[0];
$url_keyword = $conditions[1];
$bound_tpl = $conditions[2];
{
$template->append('extents',
array(
'replacer' => $file,
'url_parameter' => $relevant_parameters,
'original_tpl' => array_keys($eligible_templates),
'bound_tpl' => $available_templates,
'selected_tpl' => $flip_templates[$handle],
'selected_url' => $url_keyword,
'selected_bound' => $bound_tpl,)
);
}
}
// +-----------------------------------------------------------------------+
// | html code display |
// +-----------------------------------------------------------------------+
$template->assign('ADMIN_PAGE_TITLE', l10n('Extend for templates'));
$template->assign_var_from_handle('ADMIN_CONTENT', 'extend_for_templates');
?>
@@ -0,0 +1,116 @@
<?php
// +-----------------------------------------------------------------------+
// | This file is part of Piwigo. |
// | |
// | For copyright and license information, please view the COPYING.txt |
// | file that was distributed with this source code. |
// +-----------------------------------------------------------------------+
if( !defined("PHPWG_ROOT_PATH") )
{
die ("Hacking attempt!");
}
include_once(PHPWG_ROOT_PATH.'admin/include/functions.php');
// +-----------------------------------------------------------------------+
// | tabs |
// +-----------------------------------------------------------------------+
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('groups');
$tabsheet->select('group_list');
$tabsheet->assign();
// +-----------------------------------------------------------------------+
// | Check Access and exit when user status is not ok |
// +-----------------------------------------------------------------------+
check_status(ACCESS_ADMINISTRATOR);
if (!empty($_POST) or isset($_GET['delete']) or isset($_GET['toggle_is_default']))
{
check_pwg_token();
}
// +-----------------------------------------------------------------------+
// | template init |
// +-----------------------------------------------------------------------+
$template->set_filenames(array('group_list' => 'group_list.tpl'));
$template->assign(
array(
'F_ADD_ACTION' => get_root_url().'admin.php?page=group_list',
// 'U_HELP' => get_root_url().'admin/popuphelp.php?page=group_list',
'PWG_TOKEN' => get_pwg_token(),
'CACHE_KEYS' => get_admin_client_cache_keys(array('groups', 'users')),
)
);
// +-----------------------------------------------------------------------+
// | group list |
// +-----------------------------------------------------------------------+
$query = '
SELECT id, name, is_default
FROM `'.GROUPS_TABLE.'`
ORDER BY name ASC
;';
$result = pwg_query($query);
$admin_url = get_root_url().'admin.php?page=';
$perm_url = $admin_url.'group_perm&amp;group_id=';
$users_url = $admin_url.'user_list&amp;group=';
$del_url = $admin_url.'group_list&amp;delete=';
$toggle_is_default_url = $admin_url.'group_list&amp;toggle_is_default=';
$group_counter = 0;
while ($row = pwg_db_fetch_assoc($result))
{
$query = '
SELECT u.'. $conf['user_fields']['username'].' AS username
FROM '.USERS_TABLE.' AS u
INNER JOIN '.USER_GROUP_TABLE.' AS ug
ON u.'.$conf['user_fields']['id'].' = ug.user_id
WHERE ug.group_id = '.$row['id'].'
;';
$members=array();
$res=pwg_query($query);
while ($us= pwg_db_fetch_assoc($res))
{
$members[]=$us['username'];
}
$template->append(
'groups',
array(
'NAME' => $row['name'],
'ID' => $row['id'],
'IS_DEFAULT' => (get_boolean($row['is_default']) ? ' ['.l10n('default').']' : ''),
'NB_MEMBERS' => count($members),
'L_MEMBERS' => implode(' <span class="userSeparator">&middot;</span> ', $members),
'MEMBERS' => l10n_dec('%d member', '%d members', count($members)),
'U_DELETE' => $del_url.$row['id'].'&amp;pwg_token='.get_pwg_token(),
'U_PERM' => $perm_url.$row['id'],
'U_USERS' => $users_url.$row['id'],
'U_ISDEFAULT' => $toggle_is_default_url.$row['id'].'&amp;pwg_token='.get_pwg_token(),
)
);
$group_counter++;
}
$template->assign('ADMIN_PAGE_TITLE', l10n('Groups').' <span class="badge-number">'.$group_counter.'</span>');
// +-----------------------------------------------------------------------+
// | sending html code |
// +-----------------------------------------------------------------------+
$template->assign_var_from_handle('ADMIN_CONTENT', 'group_list');
?>
@@ -0,0 +1,176 @@
<?php
// +-----------------------------------------------------------------------+
// | This file is part of Piwigo. |
// | |
// | For copyright and license information, please view the COPYING.txt |
// | file that was distributed with this source code. |
// +-----------------------------------------------------------------------+
if( !defined("PHPWG_ROOT_PATH") )
{
die ("Hacking attempt!");
}
include_once(PHPWG_ROOT_PATH.'admin/include/functions.php');
// +-----------------------------------------------------------------------+
// | Check Access and exit when user status is not ok |
// +-----------------------------------------------------------------------+
check_status(ACCESS_ADMINISTRATOR);
if (!empty($_POST))
{
check_pwg_token();
check_input_parameter('cat_true', $_POST, true, PATTERN_ID);
check_input_parameter('cat_false', $_POST, true, PATTERN_ID);
}
// +-----------------------------------------------------------------------+
// | variables init |
// +-----------------------------------------------------------------------+
if (!isset($_GET['group_id']))
{
fatal_error('group_id URL parameter is missing');
}
check_input_parameter('group_id', $_GET, false, PATTERN_ID);
$page['group'] = $_GET['group_id'];
// +-----------------------------------------------------------------------+
// | updates |
// +-----------------------------------------------------------------------+
if (isset($_POST['falsify'])
and isset($_POST['cat_true'])
and count($_POST['cat_true']) > 0)
{
// if you forbid access to a category, all sub-categories become
// automatically forbidden
$subcats = get_subcat_ids($_POST['cat_true']);
$query = '
DELETE
FROM '.GROUP_ACCESS_TABLE.'
WHERE group_id = '.$page['group'].'
AND cat_id IN ('.implode(',', $subcats).')
;';
pwg_query($query);
}
else if (isset($_POST['trueify'])
and isset($_POST['cat_false'])
and count($_POST['cat_false']) > 0)
{
$uppercats = get_uppercat_ids($_POST['cat_false']);
$private_uppercats = array();
$query = '
SELECT id
FROM '.CATEGORIES_TABLE.'
WHERE id IN ('.implode(',', $uppercats).')
AND status = \'private\'
;';
$result = pwg_query($query);
while ($row = pwg_db_fetch_assoc($result))
{
$private_uppercats[] = $row['id'];
}
// retrying to authorize a category which is already authorized may cause
// an error (in SQL statement), so we need to know which categories are
// accesible
$authorized_ids = array();
$query = '
SELECT cat_id
FROM '.GROUP_ACCESS_TABLE.'
WHERE group_id = '.$page['group'].'
;';
$result = pwg_query($query);
while ($row = pwg_db_fetch_assoc($result))
{
$authorized_ids[] = $row['cat_id'];
}
$inserts = array();
$to_autorize_ids = array_diff($private_uppercats, $authorized_ids);
foreach ($to_autorize_ids as $to_autorize_id)
{
$inserts[] = array(
'group_id' => $page['group'],
'cat_id' => $to_autorize_id
);
}
mass_inserts(GROUP_ACCESS_TABLE, array('group_id','cat_id'), $inserts);
invalidate_user_cache();
}
// +-----------------------------------------------------------------------+
// | template init |
// +-----------------------------------------------------------------------+
$template->set_filenames(
array(
'group_perm' => 'group_perm.tpl',
'double_select' => 'double_select.tpl'
)
);
$template->assign(
array(
'TITLE' =>
l10n(
'Manage permissions for group "%s"',
get_groupname($page['group'])
),
'L_CAT_OPTIONS_TRUE'=>l10n('Authorized'),
'L_CAT_OPTIONS_FALSE'=>l10n('Forbidden'),
'F_ACTION' =>
get_root_url().
'admin.php?page=group_perm&amp;group_id='.
$page['group']
)
);
// only private categories are listed
$query_true = '
SELECT id,name,uppercats,global_rank
FROM '.CATEGORIES_TABLE.' INNER JOIN '.GROUP_ACCESS_TABLE.' ON cat_id = id
WHERE status = \'private\'
AND group_id = '.$page['group'].'
;';
display_select_cat_wrapper($query_true,array(),'category_option_true');
$result = pwg_query($query_true);
$authorized_ids = array();
while ($row = pwg_db_fetch_assoc($result))
{
$authorized_ids[] = $row['id'];
}
$query_false = '
SELECT id,name,uppercats,global_rank
FROM '.CATEGORIES_TABLE.'
WHERE status = \'private\'';
if (count($authorized_ids) > 0)
{
$query_false.= '
AND id NOT IN ('.implode(',', $authorized_ids).')';
}
$query_false.= '
;';
display_select_cat_wrapper($query_false,array(),'category_option_false');
$template->assign('PWG_TOKEN', get_pwg_token());
// +-----------------------------------------------------------------------+
// | html code display |
// +-----------------------------------------------------------------------+
$template->assign_var_from_handle('DOUBLE_SELECT', 'double_select');
$template->assign_var_from_handle('ADMIN_CONTENT', 'group_perm');
?>
+70
View File
@@ -0,0 +1,70 @@
<?php
// +-----------------------------------------------------------------------+
// | This file is part of Piwigo. |
// | |
// | For copyright and license information, please view the COPYING.txt |
// | file that was distributed with this source code. |
// +-----------------------------------------------------------------------+
include_once(PHPWG_ROOT_PATH.'admin/include/functions.php');
include_once(PHPWG_ROOT_PATH.'admin/include/tabsheet.class.php');
// +-----------------------------------------------------------------------+
// | Check Access and exit when user status is not ok |
// +-----------------------------------------------------------------------+
check_status(ACCESS_ADMINISTRATOR);
$help_link = get_root_url().'admin.php?page=help&section=';
$selected = null;
if (!isset($_GET['section']))
{
$selected = 'add_photos';
}
else
{
$selected = $_GET['section'];
}
$tabsheet = new tabsheet();
$tabsheet->set_id('help');
$tabsheet->select($selected);
$tabsheet->assign();
trigger_notify('loc_end_help');
$template->set_filenames(array('help' => 'help.tpl'));
$template->assign(
array(
'HELP_CONTENT' => load_language(
'help/help_'.$tabsheet->selected.'.html',
'',
array('return'=>true)
),
'HELP_SECTION_TITLE' => $tabsheet->sheets[ $tabsheet->selected ]['caption'],
)
);
$language_prefix = substr($user['language'], 0, 3);
if ('en_' == $language_prefix)
{
$page['messages'][] = sprintf(
'Need help to use Piwigo? <a href="%s" target="_blank">Check the online documentation</a> !',
'https://doc.piwigo.org/'
);
}
elseif ('fr_' == $language_prefix)
{
$page['messages'][] = sprintf(
'Besoin d\'aide pour utiliser Piwigo ? Consultez la <a href="%s" target="_blank">documentation en ligne</a> !',
'https://doc-fr.piwigo.org/'
);
}
// +-----------------------------------------------------------------------+
// | sending html code |
// +-----------------------------------------------------------------------+
$template->assign_var_from_handle('ADMIN_CONTENT', 'help');
?>
@@ -0,0 +1,150 @@
<?php
// +-----------------------------------------------------------------------+
// | This file is part of Piwigo. |
// | |
// | For copyright and license information, please view the COPYING.txt |
// | file that was distributed with this source code. |
// +-----------------------------------------------------------------------+
/**
* Display filtered history lines
*/
// +-----------------------------------------------------------------------+
// | functions |
// +-----------------------------------------------------------------------+
// +-----------------------------------------------------------------------+
// | initialization |
// +-----------------------------------------------------------------------+
if (!defined('PHPWG_ROOT_PATH'))
{
die('Hacking attempt!');
}
include_once(PHPWG_ROOT_PATH.'admin/include/functions.php');
include_once(PHPWG_ROOT_PATH.'admin/include/functions_history.inc.php');
$types = array_merge(array('none'), get_enums(HISTORY_TABLE, 'image_type'));
$display_thumbnails = array('no_display_thumbnail' => l10n('No display'),
'display_thumbnail_classic' => l10n('Classic display'),
'display_thumbnail_hoverbox' => l10n('Hoverbox display')
);
// +-----------------------------------------------------------------------+
// | Check Access and exit when user status is not ok |
// +-----------------------------------------------------------------------+
check_status(ACCESS_ADMINISTRATOR);
check_input_parameter('filter_ip', $_GET, false, '/^[0-9.]+$/');
check_input_parameter('filter_image_id', $_GET, false, '/^\d+$/');
check_input_parameter('filter_user_id', $_GET, false, '/^\d+$/');
// +-----------------------------------------------------------------------+
// | template init |
// +-----------------------------------------------------------------------+
$template->set_filename('history', 'history.tpl');
// TabSheet initialization
history_tabsheet();
$template->assign(
array(
'F_ACTION' => get_root_url().'admin.php?page=history',
'API_METHOD' => 'ws.php?format=json&method=pwg.history.search'
)
);
// +-----------------------------------------------------------------------+
// | navigation bar |
// +-----------------------------------------------------------------------+
if (isset($page['search_id']))
{
$navbar = create_navigation_bar(
get_root_url().'admin.php'.get_query_string_diff(array('start')),
$page['nb_lines'],
$page['start'],
$conf['nb_logs_page']
);
$template->assign('navbar', $navbar);
}
// +-----------------------------------------------------------------------+
// | filter form |
// +-----------------------------------------------------------------------+
$form = array();
if (isset($page['search']))
{
if (isset($page['search']['fields']['date-after']))
{
$form['start'] = $page['search']['fields']['date-after'];
}
if (isset($page['search']['fields']['date-before']))
{
$form['end'] = $page['search']['fields']['date-before'];
}
}
else
{
// by default, at page load, we want the selected date to be the current
// date
$form['start'] = $form['end'] = date('Y-m-d');
$form['types'] = $types;
// Hoverbox by default
$form['display_thumbnail'] =
pwg_get_cookie_var('display_thumbnail', 'no_display_thumbnail');
}
$form_param['ip'] = isset($_GET['filter_ip']) ? $_GET['filter_ip'] : @$form['ip'];
$form_param['image_id'] = isset($_GET['filter_image_id']) ? $_GET['filter_image_id'] : @$form['image_id'];
$form_param['user_id'] = isset($_GET['filter_user_id']) ? $_GET['filter_user_id'] : "-1";
if (isset($_GET['filter_ip']) or isset($_GET['filter_image_id']) or isset($_GET['filter_user_id']))
{
$form['start'] = '';
}
if ($form_param['user_id'] != "-1") {
$query = '
SELECT
username
FROM '.USERS_TABLE.'
WHERE id = '.$form_param['user_id'].'
;';
list($form_param['user_name']) = pwg_db_fetch_row(pwg_query($query));
$form_param['user_id'] = empty(pwg_db_fetch_row(pwg_query($query))) ? "-1" : $form_param['user_id'];
}
$template->assign(
array(
'USER_ID' => $form_param['user_id'],
'USER_NAME' => @$form_param['user_name'],
'IMAGE_ID' => $form_param['image_id'],
'FILENAME' => @$form['filename'],
'IP' => $form_param['ip'],
'START' => @$form['start'],
'END' => @$form['end'],
)
);
$template->assign('display_thumbnails', $display_thumbnails);
$template->assign('display_thumbnail_selected', $form['display_thumbnail']);
$template->assign('guest_id', $conf['guest_id']);
$template->assign('ADMIN_PAGE_TITLE', l10n('History'));
// +-----------------------------------------------------------------------+
// | html code display |
// +-----------------------------------------------------------------------+
$template->assign_var_from_handle('ADMIN_CONTENT', 'history');
?>
@@ -0,0 +1,197 @@
<?php
// +-----------------------------------------------------------------------+
// | This file is part of Piwigo. |
// | |
// | For copyright and license information, please view the COPYING.txt |
// | file that was distributed with this source code. |
// +-----------------------------------------------------------------------+
add_event_handler('tabsheet_before_select', 'add_core_tabs', 0);
function add_core_tabs($sheets, $tab_id)
{
global $conf;
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-menu"></span>'.l10n('List'), '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.'albums');
$sheets['permalinks'] = array('caption' => '<span class="icon-link-1"></span>'.l10n('Permalinks'), 'url' => $my_base_url.'permalinks');
break;
case 'users':
global $my_base_url;
$sheets['user_list'] = array('caption' => '<span class="icon-menu"></span>'.l10n('List'), 'url' => $my_base_url.'user_list');
$sheets['user_activity'] = array('caption' => '<span class="icon-pulse"></span>'.l10n('Activity'), 'url' => $my_base_url.'user_activity');
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;
$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' => '<span class="icon-menu"></span>'.l10n('List'), '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-menu"> </span>'.l10n('List'), 'url' => $my_base_url.'group_list');
break;
case 'configuration':
global $conf_link;
$sheets['main'] = array('caption' => '<span class="icon-cog"></span>'.l10n('General'), 'url' => $conf_link.'main');
$sheets['sizes'] = array('caption' => '<span class="icon-zoom-square"></span>'.l10n('Photo sizes'), 'url' => $conf_link.'sizes');
$sheets['watermark'] = array('caption' => '<span class="icon-file-image"></span>'.l10n('Watermark'), 'url' => $conf_link.'watermark');
$sheets['display'] = array('caption' => '<span class="icon-television"></span>'.l10n('Display'), 'url' => $conf_link.'display');
$sheets['comments'] = array('caption' => '<span class="icon-chat"></span>'.l10n('Comments'), 'url' => $conf_link.'comments');
$sheets['search'] = array('caption' => '<span class="icon-search"></span>'.l10n('Search'), 'url' => $conf_link.'search');
// $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-menu"></span>'.l10n('List'), 'url' => $my_base_url.'&amp;tab=installed');
if ($conf['enable_extensions_install'])
{
$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('List'), '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, $conf;
$sheets['properties'] = array('caption' => '<span class="icon-file-image"></span>'.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');
if ($conf['enable_formats'])
{
$sheets['formats'] = array('caption' => '<span class="icon-docs"></span>'.l10n('Formats'), 'url' => $admin_photo_base_url.'-formats');
}
break;
case 'photos_add':
$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-menu"></span>'.l10n('List'), 'url' => $my_base_url.'&amp;tab=installed');
if ($conf['enable_extensions_install'])
{
$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 Plugin'), '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-menu"></span>'.l10n('List'), 'url' => $my_base_url.'&amp;tab=installed');
if ($conf['enable_extensions_install'])
{
$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');
}
$sheets['standard_pages'] = array('caption' => '<span class="icon-cog-alt"></span>'.l10n('Standard pages'), 'url' => $my_base_url.'&amp;tab=standard_pages');
break;
case 'updates':
global $my_base_url;
if ($conf['enable_core_update'])
{
$sheets['pwg'] = array('caption' => l10n('Piwigo core'), 'url' => $my_base_url);
}
if ($conf['enable_extensions_install'])
{
$sheets['ext'] = array('caption' => l10n('Extensions'), 'url' => $my_base_url.'&amp;tab=ext');
}
break;
case 'site_update':
global $my_base_url;
$sheets['synchronization'] = array('caption' => '<span class="icon-exchange"></span>'.l10n('Synchronization'), 'url' => $my_base_url.'site_update&site=1');
$sheets['site_maager'] = array('caption' => '<span class="icon-flow-branch"></span>'.l10n('Site manager'), 'url' => $my_base_url.'site_manager');
break;
case 'maintenance':
global $my_base_url;
$sheets['actions'] = array('caption' => '<span class="icon-tools"></span>'.l10n('Actions'), 'url' => $my_base_url.'maintenance&tab=actions');
$sheets['env'] = array('caption' => '<span class="icon-television"></span>'.l10n('Environment'), 'url' => $my_base_url.'maintenance&tab=env');
$sheets['sys'] = array('caption' => '<span class="icon-pulse"></span>'.l10n('System Activities'), 'url' => $my_base_url.'maintenance&tab=sys');
break;
}
return $sheets;
}
?>
@@ -0,0 +1,30 @@
<?php
// +-----------------------------------------------------------------------+
// | This file is part of Piwigo. |
// | |
// | For copyright and license information, please view the COPYING.txt |
// | file that was distributed with this source code. |
// +-----------------------------------------------------------------------+
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();
$query = '
SELECT COUNT(*)
FROM '.CATEGORIES_TABLE.'
;';
list($nb_cats) = pwg_db_fetch_row(pwg_query($query));
$template->assign(
array(
'nb_cats' => $nb_cats,
)
);
?>
@@ -0,0 +1,141 @@
<?php
// +-----------------------------------------------------------------------+
// | This file is part of Piwigo. |
// | |
// | For copyright and license information, please view the COPYING.txt |
// | file that was distributed with this source code. |
// +-----------------------------------------------------------------------+
if (!defined('PHPWG_ROOT_PATH'))
{
die ("Hacking attempt!");
}
$prefilters = array(
array('ID' => 'caddie', 'NAME' => l10n('Caddie')),
array('ID' => 'favorites', 'NAME' => l10n('Your favorites')),
array('ID' => 'last_import', 'NAME' => l10n('Last import')),
array('ID' => 'no_album', 'NAME' => l10n('With no album') . ' (' . l10n('Orphans') . ')'),
array('ID' => 'no_tag', 'NAME' => l10n('With no tag')),
array('ID' => 'duplicates', 'NAME' => l10n('Duplicates')),
array('ID' => 'all_photos', 'NAME' => l10n('All'))
);
if ($conf['enable_synchronization'])
{
$prefilters[] = array('ID' => 'no_virtual_album', 'NAME' => l10n('With no virtual album'));
$prefilters[] = array('ID' => 'no_sync_md5sum', 'NAME' => l10n('With no checksum'));
}
function UC_name_compare($a, $b)
{
return strcmp(strtolower($a['NAME']), strtolower($b['NAME']));
}
$prefilters = trigger_change('get_batch_manager_prefilters', $prefilters);
// Sort prefilters by localized name.
usort($prefilters, function ($a, $b) {
return strcmp(strtolower($a['NAME']), strtolower($b['NAME']));
});
$template->assign(
array(
'conf_checksum_compute_blocksize' => $conf['checksum_compute_blocksize'],
'prefilters' => $prefilters,
'filter' => $_SESSION['bulk_manager_filter'],
'selection' => $collection,
'all_elements' => $page['cat_elements_id'],
'START' => $page['start'],
'PWG_TOKEN' => get_pwg_token(),
'U_DISPLAY' => $base_url . get_query_string_diff(array('display')),
'F_ACTION' => $base_url . get_query_string_diff(array('cat', 'start', 'tag', 'filter')),
'ADMIN_PAGE_TITLE' => l10n('Batch Manager'),
)
);
if (isset($page['no_md5sum_number']))
{
$template->assign(
array(
'NB_NO_MD5SUM' => $page['no_md5sum_number'],
)
);
} else {
$template->assign('NB_NO_MD5SUM', '');
}
// privacy level
foreach ($conf['available_permission_levels'] as $level)
{
$level_options[$level] = l10n(sprintf('Level %d', $level));
if (0 == $level) {
$level_options[$level] = l10n('Everybody');
}
}
$template->assign(
array(
'filter_level_options' => $level_options,
'filter_level_options_selected' => isset($_SESSION['bulk_manager_filter']['level'])
? $_SESSION['bulk_manager_filter']['level']
: 0,
)
);
// tags
$filter_tags = array();
if (!empty($_SESSION['bulk_manager_filter']['tags']))
{
$query = '
SELECT
id,
name
FROM ' . TAGS_TABLE . '
WHERE id IN (' . implode(',', $_SESSION['bulk_manager_filter']['tags']) . ')
;';
$filter_tags = get_taglist($query);
}
$template->assign('filter_tags', $filter_tags);
// in the filter box, which category to select by default
$selected_category = null;
$selected_category_name = '';
if (isset($_SESSION['bulk_manager_filter']['category']))
{
$selected_category = intval($_SESSION['bulk_manager_filter']['category']);
$selected_category_name = get_cat_display_name_from_id($selected_category);
}
$template->assign('filter_category_selected_name', strip_tags($selected_category_name));
$template->assign('filter_category_selected', $selected_category);
// Dissociate from a category : categories listed for dissociation can only
// represent virtual links. We can't create orphans. Links to physical
// categories can't be broken.
$associated_categories = array();
if (count($page['cat_elements_id']) > 0)
{
$query = '
SELECT
DISTINCT(category_id) AS id
FROM ' . IMAGE_CATEGORY_TABLE . ' AS ic
JOIN ' . IMAGES_TABLE . ' AS i ON i.id = ic.image_id
WHERE ic.image_id IN (' . implode(',', $page['cat_elements_id']) . ')
AND (
ic.category_id != i.storage_category_id
OR i.storage_category_id IS NULL
)
;';
$associated_categories = query2array($query, 'id', 'id');
}
$template->assign('associated_categories', $associated_categories);
load_language('help_quick_search.lang');
@@ -0,0 +1,243 @@
<?php
// +-----------------------------------------------------------------------+
// | This file is part of Piwigo. |
// | |
// | For copyright and license information, please view the COPYING.txt |
// | file that was distributed with this source code. |
// +-----------------------------------------------------------------------+
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('exif_read_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;
}
}
?>
@@ -0,0 +1,331 @@
<?php
// +-----------------------------------------------------------------------+
// | This file is part of Piwigo. |
// | |
// | For copyright and license information, please view the COPYING.txt |
// | file that was distributed with this source code. |
// +-----------------------------------------------------------------------+
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'))
);
}
}
?>
@@ -0,0 +1,267 @@
<?php
// +-----------------------------------------------------------------------+
// | This file is part of Piwigo. |
// | |
// | For copyright and license information, please view the COPYING.txt |
// | file that was distributed with this source code. |
// +-----------------------------------------------------------------------+
if( !defined("PHPWG_ROOT_PATH") )
{
die ("Hacking attempt!");
}
if (!is_webmaster())
{
return;
}
$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 = safe_unserialize(ImageStdParams::get_disabled_type_map());
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);
ImageStdParams::set_and_save_disabled($disabled);
if (count($changed_types))
{
clear_derivative_cache($changed_types);
}
$template->assign(
array(
'save_success' => l10n('Your configuration settings are saved'),
)
);
pwg_activity('system', ACTIVITY_SYSTEM_CORE, 'config', array('config_section'=>'sizes'));
}
else
{
foreach ($original_fields as $field)
{
if (isset($_POST[$field]))
{
$template->append(
'sizes',
array(
$field => strip_tags($_POST[$field]) // strip_tags prevents from XSS attempt
),
true
);
}
}
$template->assign('derivatives', $pderivatives);
$template->assign('ferrors', $errors);
$template->assign('resize_quality', $_POST['resize_quality']);
$page['sizes_loaded_in_tpl'] = true;
}
?>
@@ -0,0 +1,211 @@
<?php
// +-----------------------------------------------------------------------+
// | This file is part of Piwigo. |
// | |
// | For copyright and license information, please view the COPYING.txt |
// | file that was distributed with this source code. |
// +-----------------------------------------------------------------------+
if( !defined("PHPWG_ROOT_PATH") )
{
die ("Hacking attempt!");
}
if (!is_webmaster())
{
return;
}
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);
}
$template->assign(
array(
'save_success' => l10n('Your configuration settings are saved'),
)
);
pwg_activity('system', ACTIVITY_SYSTEM_CORE, 'config', array('config_section'=>'watermark'));
}
else
{
$template->assign('watermark', $pwatermark);
$template->assign('ferrors', $errors);
}
?>
File diff suppressed because it is too large Load Diff
@@ -0,0 +1,506 @@
<?php
// +-----------------------------------------------------------------------+
// | This file is part of Piwigo. |
// | |
// | For copyright and license information, please view the COPYING.txt |
// | file that was distributed with this source code. |
// +-----------------------------------------------------------------------+
/**
* @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,
search_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'])
{
history_remove_summarized_column();
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);
history_remove_summarized_column();
}
function history_remove_summarized_column()
{
global $conf;
if (isset($conf['history_summarized_dropped']) and $conf['history_summarized_dropped'])
{
return;
}
$query = '
SELECT
COUNT(*)
FROM '.HISTORY_TABLE.'
;';
list($count) = pwg_db_fetch_row(pwg_query($query));
if ($count > $conf['history_autopurge_keep_lines']+$conf['history_autopurge_blocksize'])
{
// it's not yet time to remove history.summarized
return;
}
$result = pwg_query('SHOW COLUMNS FROM `'.HISTORY_TABLE.'` LIKE "summarized";');
if (pwg_db_num_rows($result))
{
pwg_query('ALTER TABLE `'.HISTORY_TABLE.'` DROP COLUMN `summarized`;');
}
conf_update_param('history_summarized_dropped', true);
}
add_event_handler('get_history', 'get_history');
trigger_notify('functions_history_included');
?>
@@ -0,0 +1,113 @@
<?php
// +-----------------------------------------------------------------------+
// | This file is part of Piwigo. |
// | |
// | For copyright and license information, please view the COPYING.txt |
// | file that was distributed with this source code. |
// +-----------------------------------------------------------------------+
/**
* @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('modus')))
{
$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()))
{
$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());
}
}
?>
@@ -0,0 +1,437 @@
<?php
// +-----------------------------------------------------------------------+
// | This file is part of Piwigo. |
// | |
// | For copyright and license information, please view the COPYING.txt |
// | file that was distributed with this source code. |
// +-----------------------------------------------------------------------+
/**
* @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]);
}
if (empty($exif[$pwg_key]))
{
unset($exif[$pwg_key]);
continue;
}
$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 (function_exists('mime_content_type'))
{
$mime_type = mime_content_type($file);
if (str_starts_with($mime_type, 'image/'))
{
if (in_array($mime_type, array('image/svg+xml', 'image/svg')))
{
$xml = file_get_contents($file);
$xmlget = simplexml_load_string($xml);
$xmlattributes = $xmlget->attributes();
$width = $xmlattributes->width;
$height = $xmlattributes->height;
$vb = (string) $xmlattributes->viewBox;
if (isset($width) and $width != "")
{
$infos['width'] = (int) $width;
} elseif (isset($vb))
{
$infos['width'] = round(explode(" ", $vb)[2]);
}
if (isset($height) and $height != "")
{
$infos['height'] = (int) $height;
} elseif (isset($vb))
{
$infos['height'] = round(explode(" ", $vb)[3]);
}
}
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);
}
foreach (array('name', 'author') as $single_line_field)
{
if (isset($infos[$single_line_field]))
{
foreach (array("\r\n", "\n", "\r") as $to_replace_string)
{
$infos[$single_line_field] = str_replace($to_replace_string, ' ', $infos[$single_line_field]);
}
}
}
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;
}
// print_r($data);
$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);
// new lines are always considered as keyword separators
$keywords_string = str_replace(array("\r\n", "\n", "\r"), ',', $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;
}
?>
@@ -0,0 +1,531 @@
<?php
// +-----------------------------------------------------------------------+
// | This file is part of Piwigo. |
// | |
// | For copyright and license information, please view the COPYING.txt |
// | file that was distributed with this source code. |
// +-----------------------------------------------------------------------+
/* 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(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);
}
?>
@@ -0,0 +1,189 @@
<?php
// +-----------------------------------------------------------------------+
// | This file is part of Piwigo. |
// | |
// | For copyright and license information, please view the COPYING.txt |
// | file that was distributed with this source code. |
// +-----------------------------------------------------------------------+
/** 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'][] = '{'.$permalink.'} '.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;
}
?>
@@ -0,0 +1,31 @@
<?php
// +-----------------------------------------------------------------------+
// | This file is part of Piwigo. |
// | |
// | For copyright and license information, please view the COPYING.txt |
// | file that was distributed with this source code. |
// +-----------------------------------------------------------------------+
/**
* 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;
}
?>
@@ -0,0 +1,322 @@
<?php
// +-----------------------------------------------------------------------+
// | This file is part of Piwigo. |
// | |
// | For copyright and license information, please view the COPYING.txt |
// | file that was distributed with this source code. |
// +-----------------------------------------------------------------------+
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(
'modus',
'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))
{
// make sure default Piwigo theme is active
$query = '
SELECT
COUNT(*)
FROM '.PREFIX_TABLE.'themes
WHERE id = \''.PHPWG_DEFAULT_TEMPLATE.'\'
;';
list($counter) = pwg_db_fetch_row(pwg_query($query));
if ($counter < 1)
{
// we need to activate theme first
include_once(PHPWG_ROOT_PATH.'admin/include/themes.class.php');
$themes = new themes();
$themes->perform_action('activate', PHPWG_DEFAULT_TEMPLATE);
}
// then associate it to default user
$query = '
UPDATE '.PREFIX_TABLE.'user_infos
SET theme = \''.PHPWG_DEFAULT_TEMPLATE.'\'
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(function_exists('get_magic_quotes_gpc') && !@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);
}
}
?>
File diff suppressed because it is too large Load Diff
@@ -0,0 +1,926 @@
<?php
// +-----------------------------------------------------------------------+
// | This file is part of Piwigo. |
// | |
// | For copyright and license information, please view the COPYING.txt |
// | file that was distributed with this source code. |
// +-----------------------------------------------------------------------+
// +-----------------------------------------------------------------------+
// | 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)
{
global $conf;
$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, $conf['picture_ext']))
{
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 webp_info($source_filepath)
{
// function based on https://stackoverflow.com/questions/61221874/detect-if-a-webp-image-is-transparent-in-php
//
// https://github.com/webmproject/libwebp/blob/master/src/dec/webp_dec.c
// https://developers.google.com/speed/webp/docs/riff_container
// https://developers.google.com/speed/webp/docs/webp_lossless_bitstream_specification
// https://stackoverflow.com/questions/61221874/detect-if-a-webp-image-is-transparent-in-php
$fp = fopen($source_filepath, 'rb');
if (!$fp) {
throw new Exception("webp_info(): fopen($f): Failed");
}
$buf = fread($fp, 25);
fclose($fp);
switch (true) {
case!is_string($buf):
case strlen($buf) < 25:
case substr($buf, 0, 4) != 'RIFF':
case substr($buf, 8, 4) != 'WEBP':
case substr($buf, 12, 3) != 'VP8':
throw new Exception("webp_info(): not a valid webp image");
case $buf[15] == ' ':
// Simple File Format (Lossy)
return array(
'type' => 'VP8',
'has-animation' => false,
'has-transparent' => false,
);
case $buf[15] == 'L':
// Simple File Format (Lossless)
return array(
'type' => 'VP8L',
'has-animation' => false,
'has-transparent' => (bool) (!!(ord($buf[24]) & 0x00000010)),
);
case $buf[15] == 'X':
// Extended File Format
return array(
'type' => 'VP8X',
'has-animation' => (bool) (!!(ord($buf[20]) & 0x00000002)),
'has-transparent' => (bool) (!!(ord($buf[20]) & 0x00000010)),
);
default:
throw new Exception("webp_info(): could not detect webp type");
}
}
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;
}
protected 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 get_ext_imagick_command()
{
global $page, $conf;
if (!isset($page['ext_imagick_command']))
{
$retval=null;
$cmd_out=null;
// check if magick is in path
exec('command -v '.$conf['ext_imagick_dir'].'magick', $cmd_out , $retval );
if (0 == $retval)
{
$page['ext_imagick_command'] = 'magick';
}
else
{
$page['ext_imagick_command'] = 'convert';
}
}
return $page['ext_imagick_command'];
}
static function is_ext_imagick()
{
global $conf;
if (!function_exists('exec'))
{
return false;
}
@exec($conf['ext_imagick_dir'].pwg_image::get_ext_imagick_command().' -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 'ext_imagick':
if ($extension != 'gif' and self::is_ext_imagick())
{
return 'ext_imagick';
}
case 'imagick':
if ($extension != 'gif' and self::is_imagick())
{
return '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 $is_animated_webp = false;
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');
}
if ('webp' == strtolower(get_extension($source_filepath)))
{
$webp_info = pwg_image::webp_info($source_filepath);
if ($webp_info['has-animation'])
{
$this->is_animated_webp = true;
// ImageMagick "identify" returns the list of width x height for each
// frame, such as "400x300400x300400x300" (3 frames of 400x300), as a big
// string, impossible to parse :-/ So let's use the PHP embedded function
// getimagesize here.
list($this->width, $this->height) = getimagesize($source_filepath);
return;
}
}
$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;
// the final "!" is added to crop the canva too, for animated picture (with WebP in mind)
$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)
{
global $conf;
if ($this->is_animated_webp)
{
// in cas of animated WebP, we need to maximize quality to 70 to avoid
// heavy thumbnails (or square or whatever is displayed on the thumbnails
// page)
$quality = min($quality, $conf['animated_webp_compression_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.pwg_image::get_ext_imagick_command();
$exec .= ' "'.realpath($this->source_filepath).'"';
// If the image is animated webp add a filter to avoid breaking the animation
if ($this->is_animated_webp)
{
$exec .= ' -layers coalesce ';
}
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);
}
}
?>
@@ -0,0 +1,15 @@
<?php
// +-----------------------------------------------------------------------+
// | This file is part of Piwigo. |
// | |
// | For copyright and license information, please view the COPYING.txt |
// | file that was distributed with this source code. |
// +-----------------------------------------------------------------------+
// Recursive call
$url = '../';
header( 'Request-URI: '.$url );
header( 'Content-Location: '.$url );
header( 'Location: '.$url );
exit();
?>
@@ -0,0 +1,431 @@
<?php
// +-----------------------------------------------------------------------+
// | This file is part of Piwigo. |
// | |
// | For copyright and license information, please view the COPYING.txt |
// | file that was distributed with this source code. |
// +-----------------------------------------------------------------------+
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 (!$conf['enable_extensions_install'] and 'delete' == $action)
{
die('Piwigo extensions install/update/delete system is disabled');
}
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']));
}
}
?>
File diff suppressed because it is too large Load Diff
@@ -0,0 +1,221 @@
<?php
// +-----------------------------------------------------------------------+
// | This file is part of Piwigo. |
// | |
// | For copyright and license information, please view the COPYING.txt |
// | file that was distributed with this source code. |
// +-----------------------------------------------------------------------+
// +-----------------------------------------------------------------------+
// | Photo selection |
// +-----------------------------------------------------------------------+
$template->assign(
array(
'F_ADD_ACTION'=> PHOTOS_ADD_BASE_URL,
'chunk_size' => $conf['upload_form_chunk_size'],
'max_file_size' => $conf['upload_form_max_file_size'],
'ADMIN_PAGE_TITLE' => l10n('Upload Photos'),
)
);
// 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, uppercats
FROM '.CATEGORIES_TABLE.'
WHERE id = '.$_GET['album'].'
;';
$result = pwg_query($query);
if (pwg_db_num_rows($result) == 1)
{
$selected_category = array($_GET['album']);
$cat = pwg_db_fetch_assoc($result);
$template->assign('ADD_TO_ALBUM', get_cat_display_name_cache($cat['uppercats'], null));
}
else
{
fatal_error('[Hacking attempt] the album id = "'.$_GET['album'].'" is not valid');
}
}
else
{
// we need to know the category in which the last photo was added
$query = '
SELECT category_id, c.uppercats
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']);
$selected_category_name = get_cat_display_name_cache($row['uppercats'], null);
$template->assign('selected_category_name', $selected_category_name);
}
}
// existing album
$template->assign('selected_category', $selected_category);
// how many existing albums?
$query = '
SELECT
COUNT(*)
FROM '.CATEGORIES_TABLE.'
;';
list($nb_albums) = pwg_db_fetch_row(pwg_query($query));
// $nb_albums = 0;
$template->assign('NB_ALBUMS', $nb_albums);
// 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('exif_read_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'
)
);
}
?>
@@ -0,0 +1,843 @@
<?php
// +-----------------------------------------------------------------------+
// | This file is part of Piwigo. |
// | |
// | For copyright and license information, please view the COPYING.txt |
// | file that was distributed with this source code. |
// +-----------------------------------------------------------------------+
/**
* 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';
// piwigo-videojs and piwigo-openstreetmap unfortunately have a "-" in their folder
// name (=plugin_id) and a class name can't have a "-". So we have to replace with a "_"
$classname = str_replace('-', '_', $classname);
// 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())
{
global $conf;
if (!$conf['enable_extensions_install'] and 'delete' == $action)
{
die('Piwigo extensions install/update/delete system is disabled');
}
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);
}
$activity_details = array('plugin_id'=>$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);
$activity_details['version'] = $this->fs_plugins[$plugin_id]['version'];
if (empty($errors))
{
$query = '
INSERT INTO '. PLUGINS_TABLE .' (id,version)
VALUES (\''. $plugin_id .'\', \''. $this->fs_plugins[$plugin_id]['version'] .'\')
;';
pwg_query($query);
}
else
{
$activity_details['result'] = 'error';
}
break;
case 'update':
$previous_version = $this->fs_plugins[$plugin_id]['version'];
$activity_details['from_version'] = $previous_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'];
$activity_details['to_version'] = $new_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);
}
}
else
{
$activity_details['result'] = 'error';
}
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);
$activity_details['version'] = $crt_db_plugin['version'];
}
if (empty($errors))
{
$query = '
UPDATE '. PLUGINS_TABLE .'
SET state=\'active\'
WHERE id=\''. $plugin_id .'\'
;';
pwg_query($query);
}
else
{
$activity_details['result'] = 'error';
}
break;
case 'deactivate':
if (!isset($crt_db_plugin) or $crt_db_plugin['state'] != 'active')
{
$activity_details['result'] = 'error';
break;
}
$query = '
UPDATE '. PLUGINS_TABLE .'
SET state=\'inactive\'
WHERE id=\''. $plugin_id .'\'
;';
pwg_query($query);
$plugin_maintain->deactivate();
if (isset($crt_db_plugin['version']))
{
$activity_details['version'] = $crt_db_plugin['version'];
}
break;
case 'uninstall':
if (!isset($crt_db_plugin))
{
$activity_details['result'] = 'error';
$activity_details['error'] = 'plugin not installed';
break;
}
if (isset($crt_db_plugin['version']))
{
$activity_details['version'] = $crt_db_plugin['version'];
}
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))
{
if (isset($crt_db_plugin['version']))
{
$activity_details['db_version'] = $crt_db_plugin['version'];
}
$this->perform_action('uninstall', $plugin_id);
}
if (!isset($this->fs_plugins[$plugin_id]))
{
break;
}
else
{
$activity_details['fs_version'] = $this->fs_plugins[$plugin_id]['version'];
}
include_once(PHPWG_ROOT_PATH.'admin/include/functions.php');
deltree(PHPWG_PLUGINS_PATH . $plugin_id, PHPWG_PLUGINS_PATH . 'trash');
break;
}
pwg_activity('system', ACTIVITY_SYSTEM_PLUGIN, $action, $activity_details);
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'=>'',
'hasSettings'=>false,
);
$plg_data = file_get_contents($path.'/main.inc.php', false, 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 (preg_match("/Has Settings:\\s*([Tt]rue|[Ww]ebmaster)/", $plg_data, $val))
{
if (strtolower($val[1]) == 'webmaster')
{
global $user;
if (isset($user) and 'webmaster' == $user['status'])
{
$plugin['hasSettings'] = true;
}
}
else
{
$plugin['hasSettings'] = true;
}
}
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
// Beta test : return last version on PEM if the current version isn't known or else return the current and the last version
function get_versions_to_check($beta_test=false, $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))
{
$i = 0;
// If the actual version exist, put the PEM id in $versions_to_check
while ($i < count($pem_versions) && count($versions_to_check) == 0)
{
if (get_branch_from_version($pem_versions[$i]['name']) == get_branch_from_version($version))
{
$versions_to_check[] = $pem_versions[$i]['id'];
}
$i++;
}
// If $beta_test is true, search the previous version
if ($beta_test)
{
// If the actual version is not in PEM, put the latest PEM version
if (count($versions_to_check) == 0)
{
$versions_to_check[] = $pem_versions[0]['id'];
}
else // Else search the next version in PEM
{
$has_found_previous_version = false;
while ($i < count($pem_versions) && !$has_found_previous_version)
{
if ($pem_versions[$i]['id'] != $versions_to_check[0])
{
$versions_to_check[] = $pem_versions[$i]['id'];
$has_found_previous_version = true;
}
$i++;
}
}
}
// 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
* $beta_test parameter add plugins compatible with the previous version
*/
function get_server_plugins($new=false, $beta_test=false)
{
global $user, $conf;
$versions_to_check = $this->get_versions_to_check($beta_test);
if (empty($versions_to_check))
{
return true;
}
// 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-next.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;
}
}
?>
@@ -0,0 +1,144 @@
<?php
// +-----------------------------------------------------------------------+
// | This file is part of Piwigo. |
// | |
// | For copyright and license information, please view the COPYING.txt |
// | file that was distributed with this source code. |
// +-----------------------------------------------------------------------+
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');
}
}
?>
@@ -0,0 +1,770 @@
<?php
// +-----------------------------------------------------------------------+
// | This file is part of Piwigo. |
// | |
// | For copyright and license information, please view the COPYING.txt |
// | file that was distributed with this source code. |
// +-----------------------------------------------------------------------+
/**
* 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 (!$conf['enable_extensions_install'] and 'delete' == $action)
{
die('Piwigo extensions install/update/delete system is disabled');
}
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();
$activity_details = array('theme_id'=>$theme_id);
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);
$activity_details['version'] = $this->fs_themes[$theme_id]['version'];
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;
}
pwg_activity('system', ACTIVITY_SYSTEM_THEME, $action, $activity_details);
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]);
}
if (preg_match('/["\']use_standard_pages["\'].*?(true|false)/i', $theme_data, $val))
{
$theme['use_standard_pages'] = 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/'
.userprefs_get_param('admin_theme', 'clear')
.'/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-next.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, &$theme_id=null)
{
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')
{
$theme_id = $dest;
}
else
{
$theme_id = ($root == '.' ? 'extension_' . $dest : basename($root));
}
$extract_path = PHPWG_THEMES_PATH . $theme_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_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;
}
}
?>
@@ -0,0 +1,668 @@
<?php
// +-----------------------------------------------------------------------+
// | This file is part of Piwigo. |
// | |
// | For copyright and license information, please view the COPYING.txt |
// | file that was distributed with this source code. |
// +-----------------------------------------------------------------------+
if (!defined('PHPWG_ROOT_PATH')) die('Hacking attempt!');
include_once(PHPWG_ROOT_PATH.'include/functions.inc.php');
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('modus', '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()
{
global $conf;
$new_versions = array(
'piwigo.org-checked' => false,
'is_dev' => true,
);
list($env, $build_version) = get_container_info();
if (preg_match('/^(\d+\.\d+)\.(\d+)$/', PHPWG_VERSION))
{
$new_versions['is_dev'] = false;
$actual_branch = get_branch_from_version(('Official' === $env)
? substr($build_version, 0, -1)
: PHPWG_VERSION
);
$url = PHPWG_URL.'/download/all_versions.php';
$url.= '?rand='.md5(uniqid(rand(), true)); // Avoid server cache
$url .= ('Official' === $env) ? '&docker' : '&show_requirements'; // Check docker version if in container
$url.= '&origin_hash='.sha1($conf['secret_key'].get_absolute_root_url());
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 ('Official' === $env)
{
if ($this->container_version_compare($build_version, $last_version))
{
$last_branch = get_branch_from_version(substr($last_version, 0, -1));
if ($last_branch == $actual_branch)
{
$new_versions['minor'] = $last_version;
}
else
{
$new_versions['major'] = $last_version;
foreach ($all_versions as $version)
{
$branch = get_branch_from_version(substr($version, 0, -1));
if ($branch == $actual_branch)
{
if ($this->container_version_compare($build_version, $version))
{
$new_versions['minor'] = $version;
}
break;
}
}
}
}
}
else
{
list($last_version_number, $last_version_php) = explode('/', trim($all_versions[0]));
if (version_compare(PHPWG_VERSION, $last_version_number, '<'))
{
$last_branch = get_branch_from_version($last_version_number);
if ($last_branch == $actual_branch)
{
$new_versions['minor'] = $last_version_number;
$new_versions['minor_php'] = $last_version_php;
}
else
{
$new_versions['major'] = $last_version_number;
$new_versions['major_php'] = $last_version_php;
// Check if new version exists in same branch
foreach ($all_versions as $version)
{
list($version_number, $version_php) = explode('/', trim($version));
$branch = get_branch_from_version($version_number);
if ($branch == $actual_branch)
{
if (version_compare(PHPWG_VERSION, $version_number, '<'))
{
$new_versions['minor'] = $version_number;
$new_versions['minor_php'] = $version_php;
}
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;
if (!pwg_is_dbconf_writeable())
{
return;
}
$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 upgrade_to($upgrade_to, &$step, $check_current_version=true)
{
global $page, $conf, $template;
if ($check_current_version and !version_compare($upgrade_to, PHPWG_VERSION, '>'))
{
// TODO why redirect to a plugin page? maybe a remaining code from when
// the update system was provided as a plugin?
redirect(get_root_url().'admin.php?page=plugin-'.basename(dirname(__FILE__)));
}
$obsolete_list = null;
if ($step == 2)
{
$code = get_branch_from_version(PHPWG_VERSION).'.x_to_'.$upgrade_to;
$dl_code = str_replace(array('.', '_'), '', $code);
$remove_path = $code;
// no longer try to delete files on a minor upgrade
// $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))
{
if (!empty($obsolete_list))
{
self::process_obsolete_list($obsolete_list);
}
deltree(PHPWG_ROOT_PATH.$conf['data_location'].'update');
invalidate_user_cache(true);
conf_update_param('piwigo_installed_version', $upgrade_to);
pwg_activity('system', ACTIVITY_SYSTEM_CORE, 'update', array('from_version'=>PHPWG_VERSION, 'to_version'=>$upgrade_to));
if ($step == 2)
{
// only delete compiled templates on minor update. Doing this on
// a major update might even encounter fatal error if Smarty
// changes. Anyway, a compiled template purge will be performed
// by upgrade.php
$template->delete_compiled_templates();
conf_delete_param('fs_quick_check_last_check');
$page['infos'][] = l10n('Update Complete');
$page['infos'][] = $upgrade_to;
$page['updated_version'] = $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');
}
}
}
// Compare version number with a letter suffix
// Similar to version_compare with "<" sign
function container_version_compare($v1,$v2)
{
// Split 16.2.0d into "16.2.0" as semantic_ver and "d" as sub_ver
$v1_semantic_ver = substr($v1, 0, -1);
$v1_sub_ver = substr($v1, -1);
$v2_semantic_ver = substr($v2, 0, -1);
$v2_sub_ver = substr($v2, -1);
$res = version_compare($v1_semantic_ver, $v2_semantic_ver);
// Return for any
if ($res === 0)
{
return strcmp($v1_sub_ver, $v2_sub_ver) < 0;
}
return $res;
}
}
?>
@@ -0,0 +1,18 @@
<?php
// +-----------------------------------------------------------------------+
// | This file is part of Piwigo. |
// | |
// | For copyright and license information, please view the COPYING.txt |
// | file that was distributed with this source code. |
// +-----------------------------------------------------------------------+
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('users');
$tabsheet->select($page['tab']);
$tabsheet->assign();
?>
@@ -0,0 +1,15 @@
<?php
// +-----------------------------------------------------------------------+
// | This file is part of Piwigo. |
// | |
// | For copyright and license information, please view the COPYING.txt |
// | file that was distributed with this source code. |
// +-----------------------------------------------------------------------+
// Recursive call
$url = '../';
header( 'Request-URI: '.$url );
header( 'Content-Location: '.$url );
header( 'Location: '.$url );
exit();
?>
+472
View File
@@ -0,0 +1,472 @@
<?php
// +-----------------------------------------------------------------------+
// | This file is part of Piwigo. |
// | |
// | For copyright and license information, please view the COPYING.txt |
// | file that was distributed with this source code. |
// +-----------------------------------------------------------------------+
if (!defined('PHPWG_ROOT_PATH'))
{
die ("Hacking attempt!");
}
include_once(PHPWG_ROOT_PATH.'admin/include/functions.php');
include_once(PHPWG_ROOT_PATH.'admin/include/check_integrity.class.php');
include_once(PHPWG_ROOT_PATH.'admin/include/c13y_internal.class.php');
// +-----------------------------------------------------------------------+
// | Check Access and exit when user status is not ok |
// +-----------------------------------------------------------------------+
check_status(ACCESS_ADMINISTRATOR);
// +-----------------------------------------------------------------------+
// | tabs |
// +-----------------------------------------------------------------------+
if (isset($_GET['action']) and 'hide_newsletter_subscription' == $_GET['action'])
{
userprefs_update_param('show_newsletter_subscription', 'false');
exit();
}
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('admin_home');
$tabsheet->select('');
$tabsheet->assign();
// +-----------------------------------------------------------------------+
// | actions |
// +-----------------------------------------------------------------------+
if (isset($page['nb_pending_comments']))
{
$message = l10n('User comments').' <i class="icon-chat"></i> ';
$message.= '<a href="'.$link_start.'comments">';
$message.= l10n('%d waiting for validation', $page['nb_pending_comments']);
$message.= ' <i class="icon-right"></i></a>';
$page['messages'][] = $message;
}
// any orphan photo?
$nb_orphans = $page['nb_orphans']; // already calculated in admin.php
if ($page['nb_photos_total'] >= 100000) // but has not been calculated on a big gallery, so force it now
{
$nb_orphans = count_orphans();
}
if ($nb_orphans > 0)
{
$orphans_url = PHPWG_ROOT_PATH.'admin.php?page=batch_manager&amp;filter=prefilter-no_album';
$message = '<a href="'.$orphans_url.'"><i class="icon-heart-broken"></i>';
$message.= l10n('Orphans').'</a>';
$message.= '<span class="adminMenubarCounter">'.$nb_orphans.'</span>';
$page['warnings'][] = $message;
}
// locked album ?
$query = '
SELECT COUNT(*)
FROM '.CATEGORIES_TABLE.'
WHERE visible =\'false\'
;';
list($locked_album) = pwg_db_fetch_row(pwg_query($query));
if ($locked_album > 0)
{
$locked_album_url = PHPWG_ROOT_PATH.'admin.php?page=cat_options&section=visible';
$message = '<a href="'.$locked_album_url.'"><i class="icon-cone"></i>';
$message.= l10n('Locked album').'</a>';
$message.= '<span class="adminMenubarCounter">'.$locked_album.'</span>';
$page['warnings'][] = $message;
}
fs_quick_check();
// +-----------------------------------------------------------------------+
// | template init |
// +-----------------------------------------------------------------------+
$template->set_filenames(array('intro' => 'intro.tpl'));
if ($conf['show_newsletter_subscription'] and userprefs_get_param('show_newsletter_subscription', true)) {
$query = '
SELECT registration_date
FROM '.USER_INFOS_TABLE.'
WHERE registration_date IS NOT NULL
ORDER BY user_id ASC
LIMIT 1
;';
list($register_date) = pwg_db_fetch_row(pwg_query($query));
$query = '
SELECT COUNT(*)
FROM '.CATEGORIES_TABLE.'
;';
list($nb_cats) = pwg_db_fetch_row(pwg_query($query));
$query = '
SELECT COUNT(*)
FROM '.IMAGES_TABLE.'
;';
list($nb_images) = pwg_db_fetch_row(pwg_query($query));
include_once(PHPWG_ROOT_PATH.'include/mdetect.php');
$uagent_obj = new uagent_info();
// To see the newsletter promote, the account must have 2 weeks ancient, 3 albums created and 30 photos uploaded
if (!$uagent_obj->DetectIos() and strtotime($register_date) < strtotime('2 weeks ago') and $nb_cats >= 3 and $nb_images >= 30){
$template->assign(
array(
'EMAIL' => $user['email'],
'SUBSCRIBE_BASE_URL' => get_newsletter_subscribe_base_url($user['language']),
'OLD_NEWSLETTERS_URL' => get_old_newsletters_base_url($user['language']),
)
);
}
}
$stats = get_pwg_general_statitics();
$du_decimals = 1;
$du_gb = $stats['disk_usage']/(1024*1024);
if ($du_gb > 100)
{
$du_decimals = 0;
}
$template->assign(
array(
'NB_PHOTOS' => $stats['nb_photos'],
'NB_ALBUMS' => $stats['nb_categories'],
'NB_TAGS' => $stats['nb_tags'],
'NB_IMAGE_TAG' => $stats['nb_image_tag'],
'NB_USERS' => $stats['nb_users'],
'NB_GROUPS' => $stats['nb_groups'],
'NB_RATES' => $stats['nb_rates'],
'NB_VIEWS' => number_format_human_readable($stats['nb_views']),
'NB_PLUGINS' => count($pwg_loaded_plugins),
'STORAGE_USED' => str_replace(' ', '&nbsp;', l10n('%sGB', number_format($du_gb, $du_decimals))),
'U_QUICK_SYNC' => PHPWG_ROOT_PATH.'admin.php?page=site_update&amp;site=1&amp;quick_sync=1&amp;pwg_token='.get_pwg_token(),
'CHECK_FOR_UPDATES' => $conf['dashboard_check_for_updates'],
)
);
if ($conf['activate_comments'])
{
$query = '
SELECT COUNT(*)
FROM '.COMMENTS_TABLE.'
;';
list($nb_comments) = pwg_db_fetch_row(pwg_query($query));
$template->assign('NB_COMMENTS', $nb_comments);
} else {
$template->assign('NB_COMMENTS', 0);
}
if ($conf['show_piwigo_latest_news'])
{
$latest_news = get_piwigo_news();
if (isset($latest_news['id']) and $latest_news['posted_on'] > time()-60*60*24*30)
{
$page['messages'][] = sprintf(
'%s <a href="%s" title="%s" target="_blank"><i class="icon-bell"></i> %s</a>',
l10n('Latest Piwigo news'),
$latest_news['url'],
time_since($latest_news['posted_on'], 'year').' ('.$latest_news['posted'].')',
$latest_news['subject']
);
}
}
trigger_notify('loc_end_intro');
// +-----------------------------------------------------------------------+
// | get activity data |
// +-----------------------------------------------------------------------+
$nb_weeks = $conf['dashboard_activity_nb_weeks'];
//Count mondays
$mondays = 0;
//Get mondays number for the chart legend
$week_number = array();
//Array for sorting days in circle size
$temp_data = array();
$activity_last_weeks = array();
$date = new DateTime();
//Get data from $nb_weeks last weeks
while ($mondays < $nb_weeks)
{
if ($date->format('D') == 'Mon')
{
$week_number[] = $date->format('W');
$mondays += 1;
}
$date->sub(new DateInterval('P1D'));
}
$week_number = array_reverse($week_number);
$date_string = $date->format('Y-m-d');
if (!isset($_SESSION['cache_activity_last_weeks']) or $_SESSION['cache_activity_last_weeks']['calculated_on'] < strtotime('5 minutes ago'))
{
$start_time = get_moment();
$query = '
SELECT
DATE_FORMAT(occured_on , \'%Y-%m-%d\') AS activity_day,
object,
action,
COUNT(*) AS activity_counter
FROM `'.ACTIVITY_TABLE.'`
WHERE occured_on >= \''.$date_string.'\'
GROUP BY activity_day, object, action
;';
$activity_actions = query2array($query);
foreach ($activity_actions as $action)
{
// set the time to 12:00 (midday) so that it doesn't goes to previous/next day due to timezone offset
$day_date = new DateTime($action['activity_day'].' 12:00:00');
$week = 0;
for ($i=0; $i < $nb_weeks; $i++)
{
if ($week_number[$i] == $day_date->format('W'))
{
$week = $i;
}
}
$day_nb = $day_date->format('N');
@$activity_last_weeks[$week][$day_nb]['details'][ucfirst($action['object'])][ucfirst($action['action'])] = $action['activity_counter'];
@$activity_last_weeks[$week][$day_nb]['number'] += $action['activity_counter'];
@$activity_last_weeks[$week][$day_nb]['date'] = format_date($day_date->getTimestamp());
}
$logger->debug('[admin/intro::'.__LINE__.'] recent activity calculated in '.get_elapsed_time($start_time, get_moment()));
$_SESSION['cache_activity_last_weeks'] = array(
'calculated_on' => time(),
'data' => $activity_last_weeks,
);
}
$activity_last_weeks = $_SESSION['cache_activity_last_weeks']['data'];
foreach($activity_last_weeks as $week => $i)
{
foreach($i as $day => $j)
{
$details = $j['details'];
ksort($details);
$activity_last_weeks[$week][$day]['details'] = $details;
if ($j['number'] > 0)
{
$temp_data[] = array('x' => $j['number'], 'd'=>$day, 'w'=>$week);
}
}
}
// Algorithm to sort days in circle size :
// * Get the difference between sorted numbers of activity per day (only not null numbers)
// * Split days max $circle_sizes time on the biggest difference (but not below 120%)
// * Set the sizes according to the groups created
//Function to sort days by number of activity
function cmp_day($a, $b)
{
if ($a['x'] == $b['x'])
{
return 0;
}
return ($a['x'] < $b['x']) ? -1 : 1;
}
usort($temp_data, 'cmp_day');
//Get the percent difference
$diff_x = array();
for ($i=1; $i < count($temp_data); $i++)
{
$diff_x[] = $temp_data[$i]['x']/$temp_data[$i-1]['x']*100;
}
$split = 0;
//Split (split represented by -1)
if (count($diff_x) > 0)
{
while (max($diff_x) > 120)
{
$diff_x[array_search(max($diff_x), $diff_x)] = -1;
$split++;
}
}
//Fill empty chart data for the template
$chart_data = array();
for ($i=0; $i < $nb_weeks; $i++)
{
for ($j=1; $j <= 7; $j++)
{
$chart_data[$i][$j] = 0;
}
}
$size = 1;
if (isset($temp_data[0]))
{
$chart_data[$temp_data[0]['w']][$temp_data[0]['d']] = $size;
}
//Set sizes in chart data
for ($i=1; $i < count($temp_data); $i++)
{
if ($diff_x[$i-1] == -1)
{
$size++;
}
$chart_data[$temp_data[$i]['w']][$temp_data[$i]['d']] = $size;
}
//Assign data for the template
$template->assign('ACTIVITY_WEEK_NUMBER',$week_number);
$template->assign('ACTIVITY_LAST_WEEKS', $activity_last_weeks);
$template->assign('ACTIVITY_CHART_DATA',$chart_data);
$template->assign('ACTIVITY_CHART_NUMBER_SIZES',$size);
$day_labels = array();
for ($i=0; $i<=6; $i++)
{
// first 3 letters of day name
$day_labels[] = mb_substr($lang['day'][($i+1)%7], 0, 3);
}
$template->assign('DAY_LABELS', $day_labels);
// +-----------------------------------------------------------------------+
// | get storage data |
// +-----------------------------------------------------------------------+
$video_format = array('webm','webmv','ogg','ogv','mp4','m4v', 'mov');
$data_storage = array();
//Select files in Image_Table
$query = '
SELECT
COUNT(*) AS ext_counter,
SUBSTRING_INDEX(path,".",-1) AS ext,
SUM(filesize) AS filesize
FROM `'.IMAGES_TABLE.'`
GROUP BY ext
;';
$file_extensions = query2array($query, 'ext');
foreach ($file_extensions as $ext => $ext_details)
{
$type = null;
if (in_array(strtolower($ext), $conf['picture_ext']))
{
$type = 'Photos';
}
elseif (in_array(strtolower($ext), $video_format))
{
$type = 'Videos';
}
else
{
$type = 'Other';
}
@$data_storage[$type]['total']['filesize'] += $ext_details['filesize'];
@$data_storage[$type]['total']['nb_files'] += $ext_details['ext_counter'];
@$data_storage[$type]['details'][strtoupper($ext)] = array(
'filesize' => $ext_details['filesize'],
'nb_files' => $ext_details['ext_counter'],
);
}
//Select files from format table
$query = '
SELECT
COUNT(*) AS ext_counter,
ext,
SUM(filesize) AS filesize
FROM `'.IMAGE_FORMAT_TABLE.'`
GROUP BY ext
;';
$file_extensions = query2array($query, 'ext');
foreach ($file_extensions as $ext => $ext_details)
{
$type = 'Formats';
@$data_storage[$type]['total']['filesize'] += $ext_details['filesize'];
@$data_storage[$type]['total']['nb_files'] += $ext_details['ext_counter'];
@$data_storage[$type]['details'][strtoupper($ext)] = array(
'filesize' => $ext_details['filesize'],
'nb_files' => $ext_details['ext_counter'],
);
}
// Add cache size if requested and known.
if ($conf['add_cache_to_storage_chart'] && isset($conf['cache_sizes']))
{
$cache_sizes = unserialize($conf['cache_sizes']);
if (isset($cache_sizes))
{
if (isset($cache_sizes[0]) && isset($cache_sizes[0]['value']))
{
@$data_storage['Cache']['total']['filesize'] = $cache_sizes[0]['value']/1024;
}
}
}
//Calculate total storage
$total_storage = 0;
foreach ($data_storage as $value)
{
$total_storage += $value['total']['filesize'];
}
//Pass data to HTML
$template->assign('STORAGE_TOTAL',$total_storage);
$template->assign('STORAGE_CHART_DATA',$data_storage);
// +-----------------------------------------------------------------------+
// | sending html code |
// +-----------------------------------------------------------------------+
$template->assign_var_from_handle('ADMIN_CONTENT', 'intro');
// Check integrity
$c13y = new check_integrity();
// add internal checks
new c13y_internal();
// check and display
$c13y->check();
$c13y->display();
?>
@@ -0,0 +1,41 @@
<?php
// +-----------------------------------------------------------------------+
// | This file is part of Piwigo. |
// | |
// | For copyright and license information, please view the COPYING.txt |
// | file that was distributed with this source code. |
// +-----------------------------------------------------------------------+
if( !defined("PHPWG_ROOT_PATH") )
{
die ("Hacking attempt!");
}
include_once(PHPWG_ROOT_PATH.'admin/include/tabsheet.class.php');
$my_base_url = get_root_url().'admin.php?page=languages';
if (isset($_GET['tab']))
{
check_input_parameter('tab', $_GET, false, '/^(installed|update|new)$/');
$page['tab'] = $_GET['tab'];
}
else
{
$page['tab'] = 'installed';
}
$tabsheet = new tabsheet();
$tabsheet->set_id('languages');
$tabsheet->select($page['tab']);
$tabsheet->assign();
if ($page['tab'] == 'update') {
include(PHPWG_ROOT_PATH.'admin/updates_ext.php');
$template->assign('ADMIN_PAGE_TITLE', l10n('Languages'));
}
else
{
include(PHPWG_ROOT_PATH.'admin/languages_'.$page['tab'].'.php');
}
?>
@@ -0,0 +1,123 @@
<?php
// +-----------------------------------------------------------------------+
// | This file is part of Piwigo. |
// | |
// | For copyright and license information, please view the COPYING.txt |
// | file that was distributed with this source code. |
// +-----------------------------------------------------------------------+
if( !defined("PHPWG_ROOT_PATH") )
{
die ("Hacking attempt!");
}
if (!is_webmaster())
{
$page['warnings'][] = str_replace('%s', l10n('user_status_webmaster'), l10n('%s status is required to edit parameters.'));
}
include_once(PHPWG_ROOT_PATH.'admin/include/languages.class.php');
$template->set_filenames(array('languages' => 'languages_installed.tpl'));
$base_url = get_root_url().'admin.php?page='.$page['page'];
$languages = new languages();
$languages->get_db_languages();
//--------------------------------------------------perform requested actions
check_input_parameter('action', $_GET, false, '/^(activate|deactivate|set_default|delete)$/');
check_input_parameter('language', $_GET, false, '/^('.join('|', array_keys($languages->fs_languages)).')$/');
if (isset($_GET['action']) and isset($_GET['language']) and is_webmaster())
{
$page['errors'] = $languages->perform_action($_GET['action'], $_GET['language']);
if (empty($page['errors']))
{
redirect($base_url);
}
}
// +-----------------------------------------------------------------------+
// | start template output |
// +-----------------------------------------------------------------------+
$default_language = get_default_language();
$tpl_languages = array();
foreach($languages->fs_languages as $language_id => $language)
{
$language['u_action'] = add_url_params($base_url, array('language' => $language_id));
if (in_array($language_id, array_keys($languages->db_languages)))
{
$language['state'] = 'active';
$language['deactivable'] = true;
if (count($languages->db_languages) <= 1)
{
$language['deactivable'] = false;
$language['deactivate_tooltip'] = l10n('Impossible to deactivate this language, you need at least one language.');
}
if ($language_id == $default_language)
{
$language['deactivable'] = false;
$language['deactivate_tooltip'] = l10n('Impossible to deactivate this language, first set another language as default.');
}
}
else
{
$language['state'] = 'inactive';
}
if ($language_id == $default_language)
{
$language['is_default'] = true;
array_unshift($tpl_languages, $language);
}
else
{
$language['is_default'] = false;
$tpl_languages[] = $language;
}
}
$template->assign(
array(
'languages' => $tpl_languages,
)
);
$template->append('language_states', 'active');
$template->append('language_states', 'inactive');
$missing_language_ids = array_diff(
array_keys($languages->db_languages),
array_keys($languages->fs_languages)
);
foreach($missing_language_ids as $language_id)
{
$query = '
UPDATE '.USER_INFOS_TABLE.'
SET language = \''.get_default_language().'\'
WHERE language = \''.$language_id.'\'
;';
pwg_query($query);
$query = '
DELETE
FROM '.LANGUAGES_TABLE.'
WHERE id= \''.$language_id.'\'
;';
pwg_query($query);
}
$template->assign('isWebmaster', (is_webmaster()) ? 1 : 0);
$template->assign('ADMIN_PAGE_TITLE', l10n('Languages'));
$template->assign('CONF_ENABLE_EXTENSIONS_INSTALL', $conf['enable_extensions_install']);
$template->assign_var_from_handle('ADMIN_CONTENT', 'languages');
?>
@@ -0,0 +1,120 @@
<?php
// +-----------------------------------------------------------------------+
// | This file is part of Piwigo. |
// | |
// | For copyright and license information, please view the COPYING.txt |
// | file that was distributed with this source code. |
// +-----------------------------------------------------------------------+
if( !defined("PHPWG_ROOT_PATH") )
{
die ("Hacking attempt!");
}
if (!$conf['enable_extensions_install'])
{
die('Piwigo extensions install/update system is disabled');
}
include_once(PHPWG_ROOT_PATH.'admin/include/languages.class.php');
$template->set_filenames(array('languages' => 'languages_new.tpl'));
$base_url = get_root_url().'admin.php?page='.$page['page'].'&tab='.$page['tab'];
$languages = new languages();
$languages->get_db_languages();
// +-----------------------------------------------------------------------+
// | setup check |
// +-----------------------------------------------------------------------+
$languages_dir = PHPWG_ROOT_PATH.'language';
if (!is_writable($languages_dir))
{
$page['errors'][] = l10n('Add write access to the "%s" directory', 'language');
}
// +-----------------------------------------------------------------------+
// | perform installation |
// +-----------------------------------------------------------------------+
if (isset($_GET['revision']))
{
if (!is_webmaster())
{
$page['errors'][] = l10n('Webmaster status is required.');
}
else
{
check_pwg_token();
$install_status = $languages->extract_language_files('install', $_GET['revision']);
redirect($base_url.'&installstatus='.$install_status);
}
}
// +-----------------------------------------------------------------------+
// | installation result |
// +-----------------------------------------------------------------------+
if (isset($_GET['installstatus']))
{
switch ($_GET['installstatus'])
{
case 'ok':
$page['infos'][] = l10n('Language has been successfully installed');
break;
case 'temp_path_error':
$page['errors'][] = l10n('Can\'t create temporary file.');
break;
case 'dl_archive_error':
$page['errors'][] = l10n('Can\'t download archive.');
break;
case 'archive_error':
$page['errors'][] = l10n('Can\'t read or extract archive.');
break;
default:
$page['errors'][] = l10n('An error occured during extraction (%s).', htmlspecialchars($_GET['installstatus']));
}
}
// +-----------------------------------------------------------------------+
// | start template output |
// +-----------------------------------------------------------------------+
if ($languages->get_server_languages(true))
{
foreach($languages->server_languages as $language)
{
list($date, ) = explode(' ', $language['revision_date']);
$url_auto_install = htmlentities($base_url)
. '&amp;revision=' . $language['revision_id']
. '&amp;pwg_token='.get_pwg_token()
;
$template->append('languages', array(
'EXT_NAME' => $language['extension_name'],
'EXT_DESC' => $language['extension_description'],
'EXT_URL' => PEM_URL.'/extension_view.php?eid='.$language['extension_id'],
'VERSION' => $language['revision_name'],
'VER_DESC' => $language['revision_description'],
'DATE' => $date,
'AUTHOR' => $language['author_name'],
'URL_INSTALL' => $url_auto_install,
'URL_DOWNLOAD' => $language['download_url'] . '&amp;origin=piwigo_download'));
}
}
else
{
$page['errors'][] = l10n('Can\'t connect to server.');
}
$template->assign('ADMIN_PAGE_TITLE', l10n('Languages'));
$template->assign('isWebmaster', (is_webmaster()) ? 1 : 0);
$template->assign_var_from_handle('ADMIN_CONTENT', 'languages');
?>
@@ -0,0 +1,125 @@
<?php
// +-----------------------------------------------------------------------+
// | This file is part of Piwigo. |
// | |
// | For copyright and license information, please view the COPYING.txt |
// | file that was distributed with this source code. |
// +-----------------------------------------------------------------------+
if (!defined('PHPWG_ROOT_PATH'))
{
die ("Hacking attempt!");
}
include_once(PHPWG_ROOT_PATH.'admin/include/functions.php');
include_once(PHPWG_ROOT_PATH.'admin/include/image.class.php');
// +-----------------------------------------------------------------------+
// | Check Access and exit when user status is not ok |
// +-----------------------------------------------------------------------+
check_status(ACCESS_ADMINISTRATOR);
if (isset($_GET['action']))
{
check_pwg_token();
}
// +-----------------------------------------------------------------------+
// | Commons parameters |
// +-----------------------------------------------------------------------+
$maint_actions = array(
'derivatives' => array(
'icon' => 'icon-trash-1',
'label' => l10n('Delete multiple size images'),
),
'lock_gallery' => array(
'icon' => 'icon-lock',
'label' => l10n('Lock gallery'),
),
'unlock_gallery' => array(
'icon' => 'icon-lock',
'label' => l10n('Unlock gallery'),
),
'categories' => array(
'icon' => 'icon-folder-open',
'label' => l10n('Update albums informations'),
),
'images' => array(
'icon' => 'icon-info-circled-1',
'label' => l10n('Update photos information'),
),
'empty_lounge' => array(
'icon' => 'icon-thumbs-up',
'label' => l10n('Empty lounge'),
),
'delete_orphan_tags' => array(
'icon' => 'icon-tags',
'label' => l10n('Delete orphan tags'),
),
'user_cache' => array(
'icon' => 'icon-user-1',
'label' => l10n('Purge user cache'),
),
'history_detail' => array(
'icon' => 'icon-back-in-time',
'label' => l10n('Purge history detail'),
),
'history_summary' => array(
'icon' => 'icon-back-in-time',
'label' => l10n('Purge history summary'),
),
'sessions' => array(
'icon' => 'icon-th-list',
'label' => l10n('Purge sessions'),
),
'feeds' => array(
'icon' => 'icon-bell',
'label' => l10n('Purge never used notification feeds'),
),
'database' => array(
'icon' => 'icon-database',
'label' => l10n('Repair and optimize database'),
),
'c13y' => array(
'icon' => 'icon-ok',
'label' => l10n('Reinitialize check integrity'),
),
'search' => array(
'icon' => 'icon-search',
'label' => l10n('Purge search history'),
),
'compiled-templates' => array(
'icon' => 'icon-file-code',
'label' => l10n('Purge compiled templates'),
),
);
// +-----------------------------------------------------------------------+
// | tabs |
// +-----------------------------------------------------------------------+
include_once(PHPWG_ROOT_PATH.'admin/include/tabsheet.class.php');
$my_base_url = get_root_url().'admin.php?page=';
if (isset($_GET['tab']))
{
check_input_parameter('tab', $_GET, false, '/^(actions|env|sys)$/');
$page['tab'] = $_GET['tab'];
}
else
{
$page['tab'] = 'actions';
}
$tabsheet = new tabsheet();
$tabsheet->set_id('maintenance');
$tabsheet->select($page['tab']);
$tabsheet->assign();
include(PHPWG_ROOT_PATH.'admin/maintenance_'.$page['tab'].'.php');
$template->assign(
array('ADMIN_PAGE_TITLE' => l10n('Maintenance'))
);
@@ -0,0 +1,409 @@
<?php
// +-----------------------------------------------------------------------+
// | This file is part of Piwigo. |
// | |
// | For copyright and license information, please view the COPYING.txt |
// | file that was distributed with this source code. |
// +-----------------------------------------------------------------------+
fs_quick_check();
// +-----------------------------------------------------------------------+
// | actions |
// +-----------------------------------------------------------------------+
$action = isset($_GET['action']) ? $_GET['action'] : '';
$register_activity = true;
switch ($action)
{
case 'phpinfo' :
{
phpinfo();
exit();
}
case 'lock_gallery' :
{
conf_update_param('gallery_locked', 'true');
pwg_activity('system', ACTIVITY_SYSTEM_CORE, 'maintenance', array('maintenance_action'=>$action));
redirect(get_root_url().'admin.php?page=maintenance');
break;
}
case 'unlock_gallery' :
{
conf_update_param('gallery_locked', 'false');
$_SESSION['page_infos'] = array(l10n('Gallery unlocked'));
pwg_activity('system', ACTIVITY_SYSTEM_CORE, 'maintenance', array('maintenance_action'=>$action));
redirect(get_root_url().'admin.php?page=maintenance');
break;
}
case 'categories' :
{
images_integrity();
categories_integrity();
update_uppercats();
update_category('all');
update_global_rank();
invalidate_user_cache(true);
$page['infos'][] = sprintf('%s : %s', l10n('Update albums informations'), l10n('action successfully performed.'));
break;
}
case 'images' :
{
images_integrity();
update_path();
include_once(PHPWG_ROOT_PATH.'include/functions_rate.inc.php');
update_rating_score();
invalidate_user_cache();
$page['infos'][] = sprintf('%s : %s', l10n('Update photos information'), l10n('action successfully performed.'));
break;
}
case 'delete_orphan_tags' :
{
delete_orphan_tags();
$page['infos'][] = sprintf('%s : %s', l10n('Delete orphan tags'), l10n('action successfully performed.'));
break;
}
case 'user_cache' :
{
invalidate_user_cache();
$page['infos'][] = sprintf('%s : %s', l10n('Purge user cache'), l10n('action successfully performed.'));
break;
}
case 'history_detail' :
{
$query = '
DELETE
FROM '.HISTORY_TABLE.'
;';
pwg_query($query);
$page['infos'][] = sprintf('%s : %s', l10n('Purge history detail'), l10n('action successfully performed.'));
break;
}
case 'history_summary' :
{
$query = '
DELETE
FROM '.HISTORY_SUMMARY_TABLE.'
;';
pwg_query($query);
$page['infos'][] = sprintf('%s : %s', l10n('Purge history summary'), l10n('action successfully performed.'));
break;
}
case 'sessions' :
{
pwg_session_gc();
// delete all sessions associated to invalid user ids (it should never happen)
$query = '
SELECT
id,
data
FROM '.SESSIONS_TABLE.'
;';
$sessions = query2array($query);
$query = '
SELECT
'.$conf['user_fields']['id'].' AS id
FROM '.USERS_TABLE.'
;';
$all_user_ids = query2array($query, 'id', null);
$sessions_to_delete = array();
foreach ($sessions as $session)
{
if (preg_match('/pwg_uid\|i:(\d+);/', $session['data'], $matches))
{
if (!isset($all_user_ids[ $matches[1] ]))
{
$sessions_to_delete[] = $session['id'];
}
}
}
if (count($sessions_to_delete) > 0)
{
$query = '
DELETE
FROM '.SESSIONS_TABLE.'
WHERE id IN (\''.implode("','", $sessions_to_delete).'\')
;';
pwg_query($query);
}
$page['infos'][] = sprintf('%s : %s', l10n('Purge sessions'), l10n('action successfully performed.'));
break;
}
case 'feeds' :
{
$query = '
DELETE
FROM '.USER_FEED_TABLE.'
WHERE last_check IS NULL
;';
pwg_query($query);
$page['infos'][] = sprintf('%s : %s', l10n('Purge never used notification feeds'), l10n('action successfully performed.'));
break;
}
case 'database' :
{
do_maintenance_all_tables();
break;
}
case 'c13y' :
{
include_once(PHPWG_ROOT_PATH.'admin/include/check_integrity.class.php');
$c13y = new check_integrity();
$c13y->maintenance();
$page['infos'][] = sprintf('%s : %s', l10n('Reinitialize check integrity'), l10n('action successfully performed.'));
break;
}
case 'empty_lounge':
{
$rows = empty_lounge();
$page['infos'][] = sprintf('%d photos were moved from the upload lounge to their albums', count($rows));
break;
}
case 'search' :
{
$query = '
DELETE
FROM '.SEARCH_TABLE.'
;';
pwg_query($query);
sprintf('%s : %s', l10n('Reinitialize check integrity'), l10n('action successfully performed.'));
break;
}
case 'compiled-templates':
{
$template->delete_compiled_templates();
FileCombiner::clear_combined_files();
$persistent_cache->purge(true);
$page['infos'][] = sprintf('%s : %s', l10n('Purge compiled templates'), l10n('action successfully performed.'));
break;
}
case 'derivatives':
{
$types_str = $_GET['type'];
if ($types_str == "all") {
clear_derivative_cache($_GET['type']);
} else {
$types = explode('_', $types_str);
foreach ($types as $type_to_clear) {
clear_derivative_cache($type_to_clear);
}
}
$page['infos'][] = l10n('action successfully performed.');
break;
}
case 'check_upgrade':
{
if (!fetchRemote(PHPWG_URL.'/download/latest_version', $result))
{
$page['errors'][] = l10n('Unable to check for upgrade.');
}
else
{
$versions = array('current' => PHPWG_VERSION);
$lines = @explode("\r\n", $result);
// if the current version is a BSF (development branch) build, we check
// the first line, for stable versions, we check the second line
if (preg_match('/^BSF/', $versions['current']))
{
$versions['latest'] = trim($lines[0]);
// because integer are limited to 4,294,967,296 we need to split BSF
// versions in date.time
foreach ($versions as $key => $value)
{
$versions[$key] =
preg_replace('/BSF_(\d{8})(\d{4})/', '$1.$2', $value);
}
}
else
{
$versions['latest'] = trim($lines[1]);
}
if ('' == $versions['latest'])
{
$page['errors'][] = l10n('Check for upgrade failed for unknown reasons.');
}
// concatenation needed to avoid automatic transformation by release
// script generator
else if ('%'.'PWGVERSION'.'%' == $versions['current'])
{
$page['infos'][] = l10n('You are running on development sources, no check possible.');
}
else if (version_compare($versions['current'], $versions['latest']) < 0)
{
$page['infos'][] = l10n('A new version of Piwigo is available.');
}
else
{
$page['infos'][] = l10n('You are running the latest version of Piwigo.');
}
}
$page['infos'][] = l10n('action successfully performed.');
}
default :
{
$register_activity = false;
break;
}
}
if ($register_activity)
{
pwg_activity('system', ACTIVITY_SYSTEM_CORE, 'maintenance', array('maintenance_action'=>$action));
}
// +-----------------------------------------------------------------------+
// | template init |
// +-----------------------------------------------------------------------+
$template->set_filenames(array('maintenance'=>'maintenance_actions.tpl'));
$pwg_token = get_pwg_token();
$url_format = get_root_url().'admin.php?page=maintenance&amp;action=%s&amp;pwg_token='.get_pwg_token();
if (!is_webmaster())
{
$page['warnings'][] = str_replace('%s', l10n('user_status_webmaster'), l10n('%s status is required to edit parameters.'));
}
$purge_urls[l10n('All')] = 'all';
foreach(ImageStdParams::get_defined_type_map() as $params)
{
$purge_urls[ l10n($params->type) ] = $params->type;
}
$purge_urls[ l10n(IMG_CUSTOM) ] = IMG_CUSTOM;
$php_current_timestamp = date("Y-m-d H:i:s");
$db_version = pwg_get_db_version();
list($db_current_date) = pwg_db_fetch_row(pwg_query('SELECT now();'));
$template->assign(
array(
'maint_actions' => $maint_actions,
'U_MAINT_CATEGORIES' => sprintf($url_format, 'categories'),
'U_MAINT_IMAGES' => sprintf($url_format, 'images'),
'U_MAINT_ORPHAN_TAGS' => sprintf($url_format, 'delete_orphan_tags'),
'U_MAINT_USER_CACHE' => sprintf($url_format, 'user_cache'),
'U_MAINT_HISTORY_DETAIL' => sprintf($url_format, 'history_detail'),
'U_MAINT_HISTORY_SUMMARY' => sprintf($url_format, 'history_summary'),
'U_MAINT_SESSIONS' => sprintf($url_format, 'sessions'),
'U_MAINT_FEEDS' => sprintf($url_format, 'feeds'),
'U_MAINT_DATABASE' => sprintf($url_format, 'database'),
'U_MAINT_C13Y' => sprintf($url_format, 'c13y'),
'U_MAINT_SEARCH' => sprintf($url_format, 'search'),
'U_MAINT_COMPILED_TEMPLATES' => sprintf($url_format, 'compiled-templates'),
'U_MAINT_DERIVATIVES' => sprintf($url_format, 'derivatives'),
'purge_derivatives' => $purge_urls,
'U_HELP' => get_root_url().'admin/popuphelp.php?page=maintenance',
'PHPWG_URL' => PHPWG_URL,
'PWG_VERSION' => PHPWG_VERSION,
'U_CHECK_UPGRADE' => sprintf($url_format, 'check_upgrade'),
'OS' => PHP_OS,
'PHP_VERSION' => phpversion(),
'DB_ENGINE' => 'MySQL',
'DB_VERSION' => $db_version,
'U_PHPINFO' => sprintf($url_format, 'phpinfo'),
'PHP_DATATIME' => $php_current_timestamp,
'DB_DATATIME' => $db_current_date,
'pwg_token' => $pwg_token,
'cache_sizes' => (isset($conf['cache_sizes'])) ? unserialize($conf['cache_sizes']) : null,
'time_elapsed_since_last_calc' => (isset($conf['cache_sizes'])) ? time_since(unserialize($conf['cache_sizes'])[3]['value'], 'year') : null,
)
);
// graphics library
switch (pwg_image::get_library())
{
case 'ext_imagick':
$library = 'External ImageMagick';
exec($conf['ext_imagick_dir'].pwg_image::get_ext_imagick_command().' -version', $returnarray);
if (preg_match('/Version: ImageMagick (\d+\.\d+\.\d+-?\d*)/', $returnarray[0], $match))
{
$library .= ' ' . $match[1];
}
$template->assign('GRAPHICS_LIBRARY', $library);
break;
case 'imagick':
$library = 'ImageMagick';
$img = new Imagick();
$version = $img->getVersion();
if (preg_match('/ImageMagick \d+\.\d+\.\d+-?\d*/', $version['versionString'], $match))
{
$library = $match[0];
}
$template->assign('GRAPHICS_LIBRARY', $library);
break;
case 'gd':
$gd_info = gd_info();
$template->assign('GRAPHICS_LIBRARY', 'GD '.@$gd_info['GD Version']);
break;
}
if ($conf['gallery_locked'])
{
$template->assign(
array(
'U_MAINT_UNLOCK_GALLERY' => sprintf($url_format, 'unlock_gallery'),
)
);
}
else
{
$template->assign(
array(
'U_MAINT_LOCK_GALLERY' => sprintf($url_format, 'lock_gallery'),
)
);
}
$query = '
SELECT
COUNT(*)
FROM '.LOUNGE_TABLE.'
;';
list($nb_lounge) = pwg_db_fetch_row(pwg_query($query));
if ($nb_lounge > 0)
{
$template->assign(
array(
'U_EMPTY_LOUNGE' => sprintf($url_format, 'empty_lounge'),
'LOUNGE_COUNTER' => $nb_lounge,
)
);
}
$template->assign('isWebmaster', (is_webmaster()) ? 1 : 0);
// +-----------------------------------------------------------------------+
// | Define advanced features |
// +-----------------------------------------------------------------------+
$advanced_features = array();
//$advanced_features is array of array composed of CAPTION & URL
$advanced_features = trigger_change(
'get_admin_advanced_features_links',
$advanced_features
);
$template->assign('advanced_features', $advanced_features);
// +-----------------------------------------------------------------------+
// | sending html code |
// +-----------------------------------------------------------------------+
$template->assign_var_from_handle('ADMIN_CONTENT', 'maintenance');
?>
@@ -0,0 +1,365 @@
<?php
// +-----------------------------------------------------------------------+
// | This file is part of Piwigo. |
// | |
// | For copyright and license information, please view the COPYING.txt |
// | file that was distributed with this source code. |
// +-----------------------------------------------------------------------+
if (!defined('PHPWG_ROOT_PATH'))
{
die ("Hacking attempt!");
}
include_once(PHPWG_ROOT_PATH.'admin/include/functions.php');
include_once(PHPWG_ROOT_PATH.'admin/include/image.class.php');
// +-----------------------------------------------------------------------+
// | Check Access and exit when user status is not ok |
// +-----------------------------------------------------------------------+
check_status(ACCESS_ADMINISTRATOR);
if (isset($_GET['action']))
{
check_pwg_token();
}
// +-----------------------------------------------------------------------+
// | actions |
// +-----------------------------------------------------------------------+
$action = isset($_GET['action']) ? $_GET['action'] : '';
switch ($action)
{
case 'phpinfo' :
{
phpinfo();
exit();
}
case 'lock_gallery' :
{
conf_update_param('gallery_locked', 'true');
redirect(get_root_url().'admin.php?page=maintenance');
break;
}
case 'unlock_gallery' :
{
conf_update_param('gallery_locked', 'false');
$_SESSION['page_infos'] = array(l10n('Gallery unlocked'));
redirect(get_root_url().'admin.php?page=maintenance');
break;
}
case 'categories' :
{
images_integrity();
categories_integrity();
update_uppercats();
update_category('all');
update_global_rank();
invalidate_user_cache(true);
break;
}
case 'images' :
{
images_integrity();
update_path();
include_once(PHPWG_ROOT_PATH.'include/functions_rate.inc.php');
update_rating_score();
invalidate_user_cache();
break;
}
case 'delete_orphan_tags' :
{
delete_orphan_tags();
break;
}
case 'user_cache' :
{
invalidate_user_cache();
break;
}
case 'history_detail' :
{
$query = '
DELETE
FROM '.HISTORY_TABLE.'
;';
pwg_query($query);
break;
}
case 'history_summary' :
{
$query = '
DELETE
FROM '.HISTORY_SUMMARY_TABLE.'
;';
pwg_query($query);
break;
}
case 'sessions' :
{
pwg_session_gc();
// delete all sessions associated to invalid user ids (it should never happen)
$query = '
SELECT
id,
data
FROM '.SESSIONS_TABLE.'
;';
$sessions = query2array($query);
$query = '
SELECT
'.$conf['user_fields']['id'].' AS id
FROM '.USERS_TABLE.'
;';
$all_user_ids = query2array($query, 'id', null);
$sessions_to_delete = array();
foreach ($sessions as $session)
{
if (preg_match('/pwg_uid\|i:(\d+);/', $session['data'], $matches))
{
if (!isset($all_user_ids[ $matches[1] ]))
{
$sessions_to_delete[] = $session['id'];
}
}
}
if (count($sessions_to_delete) > 0)
{
$query = '
DELETE
FROM '.SESSIONS_TABLE.'
WHERE id IN (\''.implode("','", $sessions_to_delete).'\')
;';
pwg_query($query);
}
break;
}
case 'feeds' :
{
$query = '
DELETE
FROM '.USER_FEED_TABLE.'
WHERE last_check IS NULL
;';
pwg_query($query);
break;
}
case 'database' :
{
do_maintenance_all_tables();
break;
}
case 'c13y' :
{
include_once(PHPWG_ROOT_PATH.'admin/include/check_integrity.class.php');
$c13y = new check_integrity();
$c13y->maintenance();
break;
}
case 'search' :
{
$query = '
DELETE
FROM '.SEARCH_TABLE.'
;';
pwg_query($query);
break;
}
case 'compiled-templates':
{
$template->delete_compiled_templates();
FileCombiner::clear_combined_files();
$persistent_cache->purge(true);
break;
}
case 'derivatives':
{
clear_derivative_cache($_GET['type']);
break;
}
case 'check_upgrade':
{
if (!fetchRemote(PHPWG_URL.'/download/latest_version', $result))
{
$page['errors'][] = l10n('Unable to check for upgrade.');
}
else
{
$versions = array('current' => PHPWG_VERSION);
$lines = @explode("\r\n", $result);
// if the current version is a BSF (development branch) build, we check
// the first line, for stable versions, we check the second line
if (preg_match('/^BSF/', $versions['current']))
{
$versions['latest'] = trim($lines[0]);
// because integer are limited to 4,294,967,296 we need to split BSF
// versions in date.time
foreach ($versions as $key => $value)
{
$versions[$key] =
preg_replace('/BSF_(\d{8})(\d{4})/', '$1.$2', $value);
}
}
else
{
$versions['latest'] = trim($lines[1]);
}
if ('' == $versions['latest'])
{
$page['errors'][] = l10n('Check for upgrade failed for unknown reasons.');
}
// concatenation needed to avoid automatic transformation by release
// script generator
else if ('%'.'PWGVERSION'.'%' == $versions['current'])
{
$page['infos'][] = l10n('You are running on development sources, no check possible.');
}
else if (version_compare($versions['current'], $versions['latest']) < 0)
{
$page['infos'][] = l10n('A new version of Piwigo is available.');
$update_url = PHPWG_ROOT_PATH.'admin.php?page=updates';
$page['infos'][] = '<a href="'. $update_url . '">' . l10n('Update to Piwigo %s', $versions['latest']) . '</a>';
}
else
{
$page['infos'][] = l10n('You are running the latest version of Piwigo.');
}
}
}
default :
{
break;
}
}
// +-----------------------------------------------------------------------+
// | template init |
// +-----------------------------------------------------------------------+
$template->set_filenames(array('maintenance'=>'maintenance_env.tpl'));
$url_format = get_root_url().'admin.php?page=maintenance&amp;action=%s&amp;pwg_token='.get_pwg_token();
$purge_urls[l10n('All')] = sprintf($url_format, 'derivatives').'&amp;type=all';
foreach(ImageStdParams::get_defined_type_map() as $params)
{
$purge_urls[ l10n($params->type) ] = sprintf($url_format, 'derivatives').'&amp;type='.$params->type;
}
$purge_urls[ l10n(IMG_CUSTOM) ] = sprintf($url_format, 'derivatives').'&amp;type='.IMG_CUSTOM;
$php_current_timestamp = date("Y-m-d H:i:s");
$db_version = pwg_get_db_version();
list($db_current_date) = pwg_db_fetch_row(pwg_query('SELECT now();'));
list($container_name,$container_version) = get_container_info();
if (!in_array($container_name, ['Official','none']))
{
$container_name = '(unofficial) '.$container_name;
}
$template->assign(
array(
'U_MAINT_CATEGORIES' => sprintf($url_format, 'categories'),
'U_MAINT_IMAGES' => sprintf($url_format, 'images'),
'U_MAINT_ORPHAN_TAGS' => sprintf($url_format, 'delete_orphan_tags'),
'U_MAINT_USER_CACHE' => sprintf($url_format, 'user_cache'),
'U_MAINT_HISTORY_DETAIL' => sprintf($url_format, 'history_detail'),
'U_MAINT_HISTORY_SUMMARY' => sprintf($url_format, 'history_summary'),
'U_MAINT_SESSIONS' => sprintf($url_format, 'sessions'),
'U_MAINT_FEEDS' => sprintf($url_format, 'feeds'),
'U_MAINT_DATABASE' => sprintf($url_format, 'database'),
'U_MAINT_C13Y' => sprintf($url_format, 'c13y'),
'U_MAINT_SEARCH' => sprintf($url_format, 'search'),
'U_MAINT_COMPILED_TEMPLATES' => sprintf($url_format, 'compiled-templates'),
'U_MAINT_DERIVATIVES' => sprintf($url_format, 'derivatives'),
'purge_derivatives' => $purge_urls,
'U_HELP' => get_root_url().'admin/popuphelp.php?page=maintenance',
'PHPWG_URL' => PHPWG_URL,
'PWG_VERSION' => PHPWG_VERSION,
'U_CHECK_UPGRADE' => sprintf($url_format, 'check_upgrade'),
'OS' => PHP_OS,
'CONTAINER_INFO' => $container_name.(!empty($container_version) ? ' '.$container_version : ''),
'PHP_VERSION' => phpversion(),
'DB_ENGINE' => 'MySQL',
'DB_VERSION' => $db_version,
'U_PHPINFO' => sprintf($url_format, 'phpinfo'),
'PHP_DATATIME' => $php_current_timestamp,
'DB_DATATIME' => $db_current_date,
'cache_sizes' => (isset($conf['cache_sizes'])) ? unserialize($conf['cache_sizes']) : null,
'time_elapsed_since_last_calc' => (isset($conf['cache_sizes'])) ? time_since(unserialize($conf['cache_sizes'])[3]['value'], 'year') : null,
)
);
// graphics library
$graphics_library = get_graphics_library_label();
if (!empty($graphics_library))
{
$template->assign('GRAPHICS_LIBRARY', $graphics_library);
}
if ($conf['gallery_locked'])
{
$template->assign(
array(
'U_MAINT_UNLOCK_GALLERY' => sprintf($url_format, 'unlock_gallery'),
)
);
}
else
{
$template->assign(
array(
'U_MAINT_LOCK_GALLERY' => sprintf($url_format, 'lock_gallery'),
)
);
}
$installed_on = get_installation_date();
if (!empty($installed_on))
{
$template->assign(
array(
'INSTALLED_ON' => format_date($installed_on, array('day', 'month', 'year')),
'INSTALLED_SINCE' => time_since($installed_on, 'day'),
)
);
}
// +-----------------------------------------------------------------------+
// | Define advanced features |
// +-----------------------------------------------------------------------+
$advanced_features = array();
//$advanced_features is array of array composed of CAPTION & URL
$advanced_features = trigger_change(
'get_admin_advanced_features_links',
$advanced_features
);
$template->assign('advanced_features', $advanced_features);
// +-----------------------------------------------------------------------+
// | sending html code |
// +-----------------------------------------------------------------------+
$template->assign_var_from_handle('ADMIN_CONTENT', 'maintenance');
?>
@@ -0,0 +1,382 @@
<?php
// +-----------------------------------------------------------------------+
// | This file is part of Piwigo. |
// | |
// | For copyright and license information, please view the COPYING.txt |
// | file that was distributed with this source code. |
// +-----------------------------------------------------------------------+
if (!defined('PHPWG_ROOT_PATH'))
{
die ("Hacking attempt!");
}
// +-----------------------------------------------------------------------+
// | Only Webmaster can see this tab |
// +-----------------------------------------------------------------------+
if (is_webmaster())
{
// Get system activities data
if (isset($_GET['method']) && 'pwg.activity_sys.getList' == $_GET['method'])
{
$response = array();
$data = array();
$query = '
SELECT
activity_id,
object,
object_id,
action,
performed_by,
occured_on,
details,
IF(performed_by = 0, \'System\', '.$conf['user_fields']['username'].') AS username
FROM '.ACTIVITY_TABLE.'
LEFT JOIN '.USERS_TABLE.' ON performed_by = '.$conf['user_fields']['id'].'
WHERE object = \'system\'
ORDER BY activity_id DESC';
// Format our data for frontend
$result = pwg_query($query);
while ($rows = pwg_db_fetch_assoc($result))
{
$major_infos = false;
$object = '';
$object_icon = '';
$action_icon = '';
$action_color = '';
$action = $rows['action'];
$date = '';
$hour = '';
$details = unserialize($rows['details']);
$detail = array(
'type' => 'empty',
);
// For each categories (Core, Plugin and Theme) we need to format theirs actions
switch ($rows['object_id'])
{
case ACTIVITY_SYSTEM_CORE:
$object_icon = 'icon-piwigo';
$object = l10n('Core');
switch ($rows['action'])
{
case 'install':
$action_icon = 'icon-download';
$action_color = 'icon-green';
$action = l10n('Install');
break;
case 'config':
$action_icon = 'icon-cog-alt';
$action_color = 'icon-yellow';
$action = l10n('Configuration');
// for config we need to specific format details
if (isset($details['config_section']))
{
$c_icon = '';
$c_text = '';
switch ($details['config_section'])
{
case 'main':
$c_icon = 'icon-cog';
$c_text = l10n('General');
break;
case 'watermark':
$c_icon = 'icon-file-image';
$c_text = l10n('Watermark');
break;
case 'sizes':
$c_icon = 'icon-zoom-square';
$c_text = l10n('Photo sizes');
// sizes have 2 params always Photo sizes and sometimes config_action
if (isset($details['config_action']) && 'restore_settings' == $details['config_action'])
{
$detail[] = array(
'icon' => 'icon-back-in-time',
'text' => l10n('Set as default')
);
}
break;
case 'comments':
$c_icon = 'icon-chat';
$c_text = l10n('Comments');
break;
case 'display':
$c_icon = 'icon-television';
$c_text = l10n('Display');
break;
default:
$c_icon = 'icon-cog-alt';
$c_text = $details['config_section'];
break;
}
$detail['type'] = 'config_section';
$detail[] = array(
'icon' => $c_icon,
'text' => $c_text
);
}
break;
case 'maintenance':
$action_icon = 'icon-cone';
$action_color = 'icon-yellow';
$action = l10n('Maintenance');
// for maintenance we need to specific format details
if (isset($details['maintenance_action']))
{
$action_detail = $details['maintenance_action'];
$detail = array(
'type' => 'maintenance_action',
'icon' => $maint_actions[$action_detail]['icon'] ?? 'icon-cone',
'text' => $maint_actions[$action_detail]['label'] ?? $action_detail,
);
}
break;
case 'update':
$action_icon = 'icon-arrows-cw';
$action_color = 'icon-blue';
$action = l10n('Update');
$major_infos = true;
break;
case 'autoupdate':
$action_icon = 'icon-arrows-cw';
$action_color = 'icon-blue';
$action = l10n('Auto-update');
$major_infos = true;
break;
default:
$action_icon = 'icon-download';
$action_color = 'icon-yellow';
break;
}
break;
case ACTIVITY_SYSTEM_PLUGIN:
$object_icon = 'icon-puzzle';
$object = 'plugin';
if (isset($details['plugin_id']))
{
$object = str_replace(['_', '-'], ' ', $details['plugin_id']);
}
switch ($rows['action'])
{
case 'install':
$action_icon = 'icon-download';
$action_color = 'icon-green';
$action = l10n('Install');
break;
case 'update':
$action_icon = 'icon-arrows-cw';
$action_color = 'icon-blue';
$action = l10n('Update');
break;
case 'activate':
$action_icon = 'icon-check';
$action_color = 'icon-green';
$action = l10n('Activate');
break;
case 'deactivate':
$action_icon = 'icon-block';
$action_color = 'icon-purple';
$action = l10n('Deactivate');
break;
case 'uninstall':
$action_icon = 'icon-trash-1';
$action_color = 'icon-red';
$action = l10n('Uninstall');
break;
case 'restore':
$action_icon = 'icon-back-in-time';
$action_color = 'icon-blue';
$action = l10n('Restore');
break;
case 'delete':
$action_icon = 'icon-trash-1';
$action_color = 'icon-red';
$action = l10n('Delete');
// for delete we need to specific format details
if (isset($details['db_version']))
{
$detail['type'] = 'db_fs_version';
$detail[] = array(
'icon' => 'icon-flow-branch',
'text' => 'database : ' . $details['db_version']
);
}
if (isset($details['fs_version']))
{
$detail['type'] = 'db_fs_version';
$detail[] = array(
'icon' => 'icon-flow-branch',
'text' => 'filesystem : ' . $details['fs_version']
);
}
break;
case 'autoupdate':
$action_icon = 'icon-arrows-cw';
$action_color = 'icon-blue';
$action = l10n('Auto-update');
break;
default:
$action_icon = 'icon-puzzle';
$action_color = 'icon-yellow';
break;
}
break;
case ACTIVITY_SYSTEM_THEME:
$object_icon = 'icon-brush';
$object = 'theme';
if (isset($details['theme_id']))
{
$object = str_replace(['_', '-'], ' ', $details['theme_id']);
}
switch ($rows['action'])
{
case 'install':
$action_icon = 'icon-download';
$action_color = 'icon-green';
$action = l10n('Install');
break;
case 'activate':
$action_icon = 'icon-check';
$action_color = 'icon-green';
$action = l10n('Activate');
break;
case 'deactivate':
$action_icon = 'icon-block';
$action_color = 'icon-purple';
$action = l10n('Deactivate');
break;
case 'delete':
$action_icon = 'icon-trash-1';
$action_color = 'icon-red';
$action = l10n('Delete');
break;
case 'set_default':
$action_icon = 'icon-star';
$action_color = 'icon-yellow';
$action = l10n('Set as default');
break;
case 'update':
$action_icon = 'icon-arrows-cw';
$action_color = 'icon-blue';
$action = l10n('Update');
break;
default:
$action_icon = 'icon-brush';
$action_color = 'icon-yellow';
break;
}
break;
default:
break;
}
// For each lines we need to format theirs details (general details)
if (isset($details['from_version']))
{
$detail = array(
'type' => 'from_to',
array(
'icon' => 'icon-flow-branch',
'text' => $details['from_version'],
),
array(
'icon' => isset($details['to_version']) ? 'icon-flow-branch' : 'icon-block',
'text' => isset($details['to_version']) ? $details['to_version'] : ($details['result'] ?? ''),
),
);
}
else if (isset($details['version']))
{
$detail = array(
'type' => 'version',
'icon' => 'icon-flow-branch',
'text' => $details['version']
);
}
else if (isset($details['result']))
{
$detail = array(
'type' => 'error',
'icon' => 'icon-block',
'text' => $details['result']
);
}
// Format our data before send
// This data will be manipulate by maintenance_sys.js
list($date, $hour) = explode(' ', $rows['occured_on']);
$data[] = array(
'major_infos' => $major_infos,
'id' => $rows['activity_id'],
'object_icon' => $object_icon,
'object' => ucwords($object),
'action_icon' => $action_icon,
'action_color' => $action_color,
'action' => $action,
'user_id' => $rows['performed_by'],
'username' => $rows['username'],
'date' => format_date($date),
'hour' => $hour,
'detail' => $detail
);
}
// Now we good to send our response data
$response = array(
'data' => $data,
);
echo json_encode($response);
exit;
}
}
else
{
$page['warnings'][] = str_replace('%s', l10n('user_status_webmaster'), l10n('%s status is required to edit parameters.'));
}
// +-----------------------------------------------------------------------+
// | template init |
// +-----------------------------------------------------------------------+
$template->assign('isWebmaster', (is_webmaster()) ? 1 : 0);
$template->set_filenames(array('maintenance'=>'maintenance_sys.tpl'));
// +-----------------------------------------------------------------------+
// | sending html code |
// +-----------------------------------------------------------------------+
$template->assign_var_from_handle('ADMIN_CONTENT', 'maintenance');
?>
@@ -0,0 +1,167 @@
<?php
// +-----------------------------------------------------------------------+
// | This file is part of Piwigo. |
// | |
// | For copyright and license information, please view the COPYING.txt |
// | file that was distributed with this source code. |
// +-----------------------------------------------------------------------+
if (!defined('PHPWG_ROOT_PATH'))
{
die ("Hacking attempt!");
}
if (!is_webmaster())
{
$page['warnings'][] = str_replace('%s', l10n('user_status_webmaster'), l10n('%s status is required to edit parameters.'));
}
function abs_fn_cmp($a, $b)
{
return abs($a)-abs($b);
}
function make_consecutive( &$orders, $step=50 )
{
uasort( $orders, 'abs_fn_cmp' );
$crt = 1;
foreach( $orders as $id=>$pos)
{
$orders[$id] = $step * ($pos<0 ? -$crt : $crt);
$crt++;
}
}
include_once(PHPWG_ROOT_PATH.'include/block.class.php');
// +-----------------------------------------------------------------------+
// | tabs |
// +-----------------------------------------------------------------------+
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('menus');
$tabsheet->select('');
$tabsheet->assign();
$menu = new BlockManager('menubar');
$menu->load_registered_blocks();
$reg_blocks = $menu->get_registered_blocks();
$mb_conf = @$conf[ 'blk_'.$menu->get_id() ];
if ( is_string($mb_conf) )
$mb_conf = unserialize( $mb_conf );
if ( !is_array($mb_conf) )
$mb_conf=array();
foreach ($mb_conf as $id => $pos)
{
if (!isset($reg_blocks[$id]))
unset($mb_conf[$id]);
}
$idx=1;
foreach ($reg_blocks as $id => $block)
{
if ( !isset($mb_conf[$id]) )
$mb_conf[$id] = $idx*50;
$idx++;
}
if ( isset($_POST['submit']) and is_webmaster())
{
foreach ( $mb_conf as $id => $pos )
{
$hide = isset($_POST['hide_'.$id]);
$mb_conf[$id] = ($hide ? -1 : +1)*abs($pos);
$pos = (int)@$_POST['pos_'.$id];
if ($pos>0)
$mb_conf[$id] = $mb_conf[$id] > 0 ? $pos : -$pos;
}
make_consecutive( $mb_conf );
// BEGIN OPTIM - DONT ASK ABOUT THIS ALGO - but optimizes the size of the array we save in DB
/* !!! OPTIM DISABLED UNTIL IT HAS BEEN FIXED !!!
$reg_keys = array_keys($reg_blocks);
$cnf_keys = array_keys($mb_conf);
$best_slice = array( 'len'=>0 );
for ($i=0; $i<count($reg_keys); $i++)
{
for ($j=0; $j<count($cnf_keys); $j++)
{
for ($k=0; max($i,$j)+$k<count($cnf_keys); $k++)
{
if ($cnf_keys[$j+$k] == $reg_keys[$i+$k] )
{
if ( 1+$k>$best_slice['len'])
{
$best_slice['len'] = 1+$k;
$best_slice['start_cnf'] = $j;
}
}
else
break;
}
}
}
*/
$mb_conf_db = $mb_conf;
/*
if ($best_slice['len'])
{
for ($j=0; $j<$best_slice['start_cnf']; $j++ )
{
$sign = $mb_conf_db[ $cnf_keys[$j] ] > 0 ? 1 : -1;
$mb_conf_db[ $cnf_keys[$j] ] = $sign * ( ($best_slice['start_cnf'])*50 - ($best_slice['start_cnf']-$j) );
}
for ($j=$best_slice['start_cnf']; $j<$best_slice['start_cnf']+$best_slice['len']; $j++ )
{
if ($mb_conf_db[ $cnf_keys[$j] ] > 0)
unset( $mb_conf_db[ $cnf_keys[$j] ] );
}
}
//var_export( $best_slice ); var_export($mb_conf); var_export($mb_conf_db);
// END OPTIM
*/
$query = '
UPDATE '.CONFIG_TABLE.'
SET value=\''.addslashes(serialize($mb_conf_db)).'\'
WHERE param=\'blk_'.addslashes($menu->get_id()).'\'
';
pwg_query($query);
$template->assign(
array(
'save_success' => l10n('Order of menubar items has been updated successfully.'),
)
);
}
make_consecutive( $mb_conf );
foreach ($mb_conf as $id => $pos )
{
$template->append( 'blocks',
array(
'pos' => $pos/5,
'reg' => $reg_blocks[$id]
)
);
}
$action = get_root_url().'admin.php?page=menubar';
$template->assign(array('F_ACTION'=>$action));
$template->assign('isWebmaster', (is_webmaster()) ? 1 : 0);
$template->assign('ADMIN_PAGE_TITLE', l10n('Menu Management'));
$template->set_filename( 'menubar_admin_content', 'menubar.tpl' );
$template->assign_var_from_handle( 'ADMIN_CONTENT', 'menubar_admin_content');
?>
@@ -0,0 +1,739 @@
<?php
// +-----------------------------------------------------------------------+
// | This file is part of Piwigo. |
// | |
// | For copyright and license information, please view the COPYING.txt |
// | file that was distributed with this source code. |
// +-----------------------------------------------------------------------+
// +-----------------------------------------------------------------------+
// | include |
// +-----------------------------------------------------------------------+
if (!defined('PHPWG_ROOT_PATH'))
{
die ("Hacking attempt!");
}
include_once(PHPWG_ROOT_PATH.'admin/include/functions.php');
include_once(PHPWG_ROOT_PATH.'admin/include/functions_notification_by_mail.inc.php');
include_once(PHPWG_ROOT_PATH.'admin/include/tabsheet.class.php');
include_once(PHPWG_ROOT_PATH.'include/common.inc.php');
include_once(PHPWG_ROOT_PATH.'include/functions_notification.inc.php');
include_once(PHPWG_ROOT_PATH.'include/functions_mail.inc.php');
// +-----------------------------------------------------------------------+
// | Check Access and exit when user status is not ok |
// +-----------------------------------------------------------------------+
check_status(ACCESS_ADMINISTRATOR);
check_input_parameter('mode', $_GET, false, '/^(param|subscribe|send)$/');
// +-----------------------------------------------------------------------+
// | Initialization |
// +-----------------------------------------------------------------------+
$base_url = get_root_url().'admin.php';
$must_repost = false;
// +-----------------------------------------------------------------------+
// | functions |
// +-----------------------------------------------------------------------+
/*
* Do timeout treatment in order to finish to send mails
*
* @param $post_keyname: key of check_key post array
* @param check_key_treated: array of check_key treated
* @return none
*/
function do_timeout_treatment($post_keyname, $check_key_treated = array())
{
global $env_nbm, $base_url, $page, $must_repost;
if ($env_nbm['is_sendmail_timeout'])
{
if (isset($_POST[$post_keyname]))
{
$post_count = count($_POST[$post_keyname]);
$treated_count = count($check_key_treated);
if ($treated_count != 0)
{
$time_refresh = ceil((get_moment() - $env_nbm['start_time']) * $post_count / $treated_count);
}
else
{
$time_refresh = 0;
}
$_POST[$post_keyname] = array_diff($_POST[$post_keyname], $check_key_treated);
$must_repost = true;
$page['errors'][] = l10n_dec(
'Execution time is out, treatment must be continue [Estimated time: %d second].',
'Execution time is out, treatment must be continue [Estimated time: %d seconds].',
$time_refresh
);
}
}
}
/*
* Get the authorized_status for each tab
* return corresponding status
*/
function get_tab_status($mode)
{
$result = ACCESS_WEBMASTER;
switch ($mode)
{
case 'param':
case 'subscribe':
$result = ACCESS_WEBMASTER;
break;
case 'send':
$result = ACCESS_ADMINISTRATOR;
break;
default:
$result = ACCESS_WEBMASTER;
break;
}
return $result;
}
/*
* Inserting News users
*/
function insert_new_data_user_mail_notification()
{
global $conf, $page, $env_nbm;
// Set null mail_address empty
$query = '
update
'.USERS_TABLE.'
set
'.$conf['user_fields']['email'].' = null
where
trim('.$conf['user_fields']['email'].') = \'\';';
pwg_query($query);
// null mail_address are not selected in the list
$query = '
select
u.'.$conf['user_fields']['id'].' as user_id,
u.'.$conf['user_fields']['username'].' as username,
u.'.$conf['user_fields']['email'].' as mail_address
from
'.USERS_TABLE.' as u left join '.USER_MAIL_NOTIFICATION_TABLE.' as m on u.'.$conf['user_fields']['id'].' = m.user_id
where
u.'.$conf['user_fields']['email'].' is not null and
m.user_id is null
order by
user_id;';
$result = pwg_query($query);
if (pwg_db_num_rows($result) > 0)
{
$inserts = array();
$check_key_list = array();
while ($nbm_user = pwg_db_fetch_assoc($result))
{
// Calculate key
$nbm_user['check_key'] = find_available_check_key();
// Save key
$check_key_list[] = $nbm_user['check_key'];
// Insert new nbm_users
$inserts[] = array(
'user_id' => $nbm_user['user_id'],
'check_key' => $nbm_user['check_key'],
'enabled' => 'false' // By default if false, set to true with specific functions
);
$page['infos'][] = l10n(
'User %s [%s] added.',
stripslashes($nbm_user['username']),
$nbm_user['mail_address']
);
}
// Insert new nbm_users
mass_inserts(USER_MAIL_NOTIFICATION_TABLE, array('user_id', 'check_key', 'enabled'), $inserts);
// Update field enabled with specific function
$check_key_treated = do_subscribe_unsubscribe_notification_by_mail
(
true,
$conf['nbm_default_value_user_enabled'],
$check_key_list
);
// On timeout simulate like tabsheet send
if ($env_nbm['is_sendmail_timeout'])
{
$quoted_check_key_list = quote_check_key_list(array_diff($check_key_list, $check_key_treated));
if (count($quoted_check_key_list) != 0 )
{
$query = 'delete from '.USER_MAIL_NOTIFICATION_TABLE.' where check_key in ('.implode(",", $quoted_check_key_list).');';
$result = pwg_query($query);
redirect($base_url.get_query_string_diff(array(), false), l10n('Operation in progress')."\n".l10n('Please wait...'));
}
}
}
}
/*
* Apply global functions to mail content
* return customize mail content rendered
*/
function render_global_customize_mail_content($customize_mail_content)
{
global $conf;
if ($conf['nbm_send_html_mail'] and !(strpos($customize_mail_content, '<') === 0))
{
// On HTML mail, detects if the content are HTML format.
// If it's plain text format, convert content to readable HTML
return nl2br(htmlspecialchars($customize_mail_content));
}
else
{
return $customize_mail_content;
}
}
/*
* Send mail for notification to all users
* Return list of "selected" users for 'list_to_send'
* Return list of "treated" check_key for 'send'
*/
function do_action_send_mail_notification($action = 'list_to_send', $check_key_list = array(), $customize_mail_content = '')
{
global $conf, $page, $user, $lang_info, $lang, $env_nbm;
$return_list = array();
if (in_array($action, array('list_to_send', 'send')))
{
list($dbnow) = pwg_db_fetch_row(pwg_query('SELECT NOW();'));
$is_action_send = ($action == 'send');
// disabled and null mail_address are not selected in the list
$data_users = get_user_notifications('send', $check_key_list);
// List all if it's define on options or on timeout
$is_list_all_without_test = ($env_nbm['is_sendmail_timeout'] or $conf['nbm_list_all_enabled_users_to_send']);
// Check if exist news to list user or send mails
if ((!$is_list_all_without_test) or ($is_action_send))
{
if (count($data_users) > 0)
{
$datas = array();
if (!isset($customize_mail_content))
{
$customize_mail_content = $conf['nbm_complementary_mail_content'];
}
$customize_mail_content =
trigger_change('nbm_render_global_customize_mail_content', $customize_mail_content);
// Prepare message after change language
if ($is_action_send)
{
$msg_break_timeout = l10n('Time to send mail is limited. Others mails are skipped.');
}
else
{
$msg_break_timeout = l10n('Prepared time for list of users to send mail is limited. Others users are not listed.');
}
// Begin nbm users environment
begin_users_env_nbm($is_action_send);
foreach ($data_users as $nbm_user)
{
if ((!$is_action_send) and check_sendmail_timeout())
{
// Stop fill list on 'list_to_send', if the quota is override
$page['infos'][] = $msg_break_timeout;
break;
}
if (($is_action_send) and check_sendmail_timeout())
{
// Stop fill list on 'send', if the quota is override
$page['errors'][] = $msg_break_timeout;
break;
}
// set env nbm user
set_user_on_env_nbm($nbm_user, $is_action_send);
if ($is_action_send)
{
$auth = null;
$add_url_params = array();
$auth_key = create_user_auth_key($nbm_user['user_id'], $nbm_user['status']);
if ($auth_key !== false)
{
$auth = $auth_key['auth_key'];
$add_url_params['auth'] = $auth;
}
set_make_full_url();
// Fill return list of "treated" check_key for 'send'
$return_list[] = $nbm_user['check_key'];
if ($conf['nbm_send_detailed_content'])
{
$news = news($nbm_user['last_send'], $dbnow, false, $conf['nbm_send_html_mail'], $auth);
$exist_data = count($news) > 0;
}
else
{
$exist_data = news_exists($nbm_user['last_send'], $dbnow);
}
if ($exist_data)
{
$subject = '['.$conf['gallery_title'].'] '.l10n('New photos added');
// Assign current var for nbm mail
assign_vars_nbm_mail_content($nbm_user);
if (!is_null($nbm_user['last_send']))
{
$env_nbm['mail_template']->assign
(
'content_new_elements_between',
array
(
'DATE_BETWEEN_1' => $nbm_user['last_send'],
'DATE_BETWEEN_2' => $dbnow,
)
);
}
else
{
$env_nbm['mail_template']->assign
(
'content_new_elements_single',
array
(
'DATE_SINGLE' => $dbnow,
)
);
}
if ($conf['nbm_send_detailed_content'])
{
$env_nbm['mail_template']->assign('global_new_lines', $news);
}
$nbm_user_customize_mail_content =
trigger_change('nbm_render_user_customize_mail_content',
$customize_mail_content, $nbm_user);
if (!empty($nbm_user_customize_mail_content))
{
$env_nbm['mail_template']->assign
(
'custom_mail_content', $nbm_user_customize_mail_content
);
}
if ($conf['nbm_send_html_mail'] and $conf['nbm_send_recent_post_dates'])
{
$recent_post_dates = get_recent_post_dates_array(
$conf['recent_post_dates']['NBM']);
foreach ($recent_post_dates as $date_detail)
{
$env_nbm['mail_template']->append
(
'recent_posts',
array
(
'TITLE' => get_title_recent_post_date($date_detail),
'HTML_DATA' => get_html_description_recent_post_date($date_detail, $auth)
)
);
}
}
$env_nbm['mail_template']->assign
(
array
(
'GOTO_GALLERY_TITLE' => $conf['gallery_title'],
'GOTO_GALLERY_URL' => add_url_params(get_gallery_home_url(), $add_url_params),
'SEND_AS_NAME' => $env_nbm['send_as_name'],
)
);
$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'],
'auth_key' => $auth,
)
);
if ($ret)
{
inc_mail_sent_success($nbm_user);
$datas[] = array(
'user_id' => $nbm_user['user_id'],
'last_send' => $dbnow
);
}
else
{
inc_mail_sent_failed($nbm_user);
}
unset_make_full_url();
}
}
else
{
if (news_exists($nbm_user['last_send'], $dbnow))
{
// Fill return list of "selected" users for 'list_to_send'
$return_list[] = $nbm_user;
}
}
// unset env nbm user
unset_user_on_env_nbm();
}
// Restore nbm environment
end_users_env_nbm();
if ($is_action_send)
{
mass_updates(
USER_MAIL_NOTIFICATION_TABLE,
array(
'primary' => array('user_id'),
'update' => array('last_send')
),
$datas
);
display_counter_info();
}
}
else
{
if ($is_action_send)
{
$page['errors'][] = l10n('No user to send notifications by mail.');
}
}
}
else
{
// Quick List, don't check news
// Fill return list of "selected" users for 'list_to_send'
$return_list = $data_users;
}
}
// Return list of "selected" users for 'list_to_send'
// Return list of "treated" check_key for 'send'
return $return_list;
}
// +-----------------------------------------------------------------------+
// | Main |
// +-----------------------------------------------------------------------+
if (!isset($_GET['mode']))
{
$page['mode'] = 'send';
}
else
{
$page['mode'] = $_GET['mode'];
}
// +-----------------------------------------------------------------------+
// | Check Access and exit when user status is not ok |
// +-----------------------------------------------------------------------+
check_status(get_tab_status($page['mode']));
// +-----------------------------------------------------------------------+
// | Add event handler |
// +-----------------------------------------------------------------------+
add_event_handler('nbm_render_global_customize_mail_content', 'render_global_customize_mail_content');
trigger_notify('nbm_event_handler_added');
// +-----------------------------------------------------------------------+
// | Insert new users with mails |
// +-----------------------------------------------------------------------+
if (!isset($_POST) or (count($_POST) ==0))
{
// No insert data in post mode
insert_new_data_user_mail_notification();
}
// +-----------------------------------------------------------------------+
// | Treatment of tab post |
// +-----------------------------------------------------------------------+
if (!empty($_POST))
{
check_pwg_token();
}
switch ($page['mode'])
{
case 'param' :
{
if (isset($_POST['param_submit']))
{
$_POST['nbm_send_mail_as'] = strip_tags($_POST['nbm_send_mail_as']);
check_input_parameter('nbm_send_html_mail', $_POST, false, '/^(true|false)$/');
check_input_parameter('nbm_send_detailed_content', $_POST, false, '/^(true|false)$/');
check_input_parameter('nbm_send_recent_post_dates', $_POST, false, '/^(true|false)$/');
$updated_param_count = 0;
// Update param
$result = pwg_query('select param, value from '.CONFIG_TABLE.' where param like \'nbm\\_%\'');
while ($nbm_user = pwg_db_fetch_assoc($result))
{
if (isset($_POST[$nbm_user['param']]))
{
conf_update_param($nbm_user['param'], $_POST[$nbm_user['param']], true);
$updated_param_count++;
}
}
$template->assign(
array(
'save_success' => l10n_dec(
'%d parameter was updated.', '%d parameters were updated.',
$updated_param_count
)
)
);
}
}
case 'subscribe' :
{
if (isset($_POST['falsify']) and isset($_POST['cat_true']))
{
$check_key_treated = unsubscribe_notification_by_mail(true, $_POST['cat_true']);
do_timeout_treatment('cat_true', $check_key_treated);
}
else
if (isset($_POST['trueify']) and isset($_POST['cat_false']))
{
$check_key_treated = subscribe_notification_by_mail(true, $_POST['cat_false']);
do_timeout_treatment('cat_false', $check_key_treated);
}
break;
}
case 'send' :
{
if (isset($_POST['send_submit']) and isset($_POST['send_selection']) and isset($_POST['send_customize_mail_content']))
{
$check_key_treated = do_action_send_mail_notification('send', $_POST['send_selection'], stripslashes($_POST['send_customize_mail_content']));
do_timeout_treatment('send_selection', $check_key_treated);
}
}
}
// +-----------------------------------------------------------------------+
// | template initialization |
// +-----------------------------------------------------------------------+
$template->set_filenames
(
array
(
'double_select' => 'double_select.tpl',
'notification_by_mail'=>'notification_by_mail.tpl'
)
);
$template->assign
(
array
(
'PWG_TOKEN' => get_pwg_token(),
'U_HELP' => get_root_url().'admin/popuphelp.php?page=notification_by_mail',
'F_ACTION'=> $base_url.get_query_string_diff(array())
)
);
if (is_autorize_status(ACCESS_WEBMASTER))
{
// TabSheet
$tabsheet = new tabsheet();
$tabsheet->set_id('nbm');
$tabsheet->select($page['mode']);
$tabsheet->assign();
}
if ($must_repost)
{
// Get name of submit button
$repost_submit_name = '';
if (isset($_POST['falsify']))
{
$repost_submit_name = 'falsify';
}
elseif (isset($_POST['trueify']))
{
$repost_submit_name = 'trueify';
}
elseif (isset($_POST['send_submit']))
{
$repost_submit_name = 'send_submit';
}
$template->assign('REPOST_SUBMIT_NAME', $repost_submit_name);
}
switch ($page['mode'])
{
case 'param' :
{
$template->assign(
$page['mode'],
array(
'SEND_HTML_MAIL' => $conf['nbm_send_html_mail'],
'SEND_MAIL_AS' => $conf['nbm_send_mail_as'],
'SEND_DETAILED_CONTENT' => $conf['nbm_send_detailed_content'],
'COMPLEMENTARY_MAIL_CONTENT' => $conf['nbm_complementary_mail_content'],
'SEND_RECENT_POST_DATES' => $conf['nbm_send_recent_post_dates'],
));
break;
}
case 'subscribe' :
{
$template->assign( $page['mode'], true );
$template->assign(
array(
'L_CAT_OPTIONS_TRUE' => l10n('Subscribed'),
'L_CAT_OPTIONS_FALSE' => l10n('Unsubscribed')
)
);
$data_users = get_user_notifications('subscribe');
$opt_true = array();
$opt_true_selected = array();
$opt_false = array();
$opt_false_selected = array();
foreach ($data_users as $nbm_user)
{
if (get_boolean($nbm_user['enabled']))
{
$opt_true[ $nbm_user['check_key'] ] = stripslashes($nbm_user['username']).'['.$nbm_user['mail_address'].']';
if ((isset($_POST['falsify']) and isset($_POST['cat_true']) and in_array($nbm_user['check_key'], $_POST['cat_true'])))
{
$opt_true_selected[] = $nbm_user['check_key'];
}
}
else
{
$opt_false[ $nbm_user['check_key'] ] = stripslashes($nbm_user['username']).'['.$nbm_user['mail_address'].']';
if (isset($_POST['trueify']) and isset($_POST['cat_false']) and in_array($nbm_user['check_key'], $_POST['cat_false']))
{
$opt_false_selected[] = $nbm_user['check_key'];
}
}
}
$template->assign( array(
'category_option_true' => $opt_true,
'category_option_true_selected' => $opt_true_selected,
'category_option_false' => $opt_false,
'category_option_false_selected' => $opt_false_selected,
)
);
$template->assign_var_from_handle('DOUBLE_SELECT', 'double_select');
break;
}
case 'send' :
{
$tpl_var = array('users'=> array() );
$data_users = do_action_send_mail_notification('list_to_send');
$tpl_var['CUSTOMIZE_MAIL_CONTENT'] =
isset($_POST['send_customize_mail_content'])
? stripslashes($_POST['send_customize_mail_content'])
: $conf['nbm_complementary_mail_content'];
if (count($data_users))
{
foreach ($data_users as $nbm_user)
{
if (
(!$must_repost) or // Not timeout, normal treatment
(($must_repost) and in_array($nbm_user['check_key'], $_POST['send_selection'])) // Must be repost, show only user to send
)
{
$tpl_var['users'][] =
array(
'ID' => $nbm_user['check_key'],
'CHECKED' => ( // not check if not selected, on init select<all
isset($_POST['send_selection']) and // not init
!in_array($nbm_user['check_key'], $_POST['send_selection']) // not selected
) ? '' : 'checked="checked"',
'USERNAME'=> stripslashes($nbm_user['username']),
'EMAIL' => $nbm_user['mail_address'],
'LAST_SEND'=> $nbm_user['last_send']
);
}
}
}
$template->assign($page['mode'], $tpl_var);
if ($conf['auth_key_duration'] > 0)
{
$template->assign(
'auth_key_duration',
time_since(
strtotime('now -'.$conf['auth_key_duration'].' second'),
'second',
null,
false
)
);
}
break;
}
}
$template->assign('ADMIN_PAGE_TITLE', l10n('Send mail to users'));
// +-----------------------------------------------------------------------+
// | Sending html code |
// +-----------------------------------------------------------------------+
$template->assign_var_from_handle('ADMIN_CONTENT', 'notification_by_mail');
?>
@@ -0,0 +1,190 @@
<?php
// +-----------------------------------------------------------------------+
// | This file is part of Piwigo. |
// | |
// | For copyright and license information, please view the COPYING.txt |
// | file that was distributed with this source code. |
// +-----------------------------------------------------------------------+
function parse_sort_variables(
$sortable_by, $default_field,
$get_param, $get_rejects,
$template_var,
$anchor = '' )
{
global $template;
$url_components = parse_url( $_SERVER['REQUEST_URI'] );
$base_url = $url_components['path'];
parse_str($url_components['query'], $vars);
$is_first = true;
foreach ($vars as $key => $value)
{
if (!in_array($key, $get_rejects) and $key!=$get_param)
{
$base_url .= $is_first ? '?' : '&amp;';
$is_first = false;
if (!in_array($key, array('page', 'psf', 'dpsf', 'pwg_token')))
{
fatal_error('unexpected URL get key');
}
$base_url .= urlencode($key).'='.urlencode($value);
}
}
$ret = array();
foreach( $sortable_by as $field)
{
$url = $base_url;
$disp = '↓'; // TODO: an small image is better
if ( $field !== @$_GET[$get_param] )
{
if ( !isset($default_field) or $default_field!=$field )
{ // the first should be the default
$url = add_url_params($url, array($get_param=>$field) );
}
elseif (isset($default_field) and !isset($_GET[$get_param]) )
{
$ret[] = $field;
$disp = '<em>'.$disp.'</em>';
}
}
else
{
$ret[] = $field;
$disp = '<em>'.$disp.'</em>';
}
if ( isset($template_var) )
{
$template->assign( $template_var.strtoupper($field),
'<a href="'.$url.$anchor.'" title="'.l10n('Sort order').'">'.$disp.'</a>'
);
}
}
return $ret;
}
if (!defined('PHPWG_ROOT_PATH')) die('Hacking attempt!');
include_once(PHPWG_ROOT_PATH.'admin/include/functions_permalinks.php');
check_input_parameter('cat_id', $_POST, false, PATTERN_ID);
$selected_cat = array();
if ( isset($_POST['set_permalink']) and $_POST['cat_id']>0 )
{
check_pwg_token();
$permalink = $_POST['permalink'];
if ( empty($permalink) )
delete_cat_permalink($_POST['cat_id'], isset($_POST['save']) );
else
set_cat_permalink($_POST['cat_id'], $permalink, isset($_POST['save']) );
$selected_cat = array( $_POST['cat_id'] );
}
elseif ( isset($_GET['delete_permanent']) )
{
check_pwg_token();
$query = '
DELETE FROM '.OLD_PERMALINKS_TABLE.'
WHERE permalink=\''.pwg_db_real_escape_string($_GET['delete_permanent']).'\'
LIMIT 1';
$result = pwg_query($query);
if (pwg_db_changes($result)==0)
{
$page['errors'][] = l10n('Cannot delete the old permalink !');
}
}
$template->set_filename('permalinks', 'permalinks.tpl' );
// +-----------------------------------------------------------------------+
// | tabs |
// +-----------------------------------------------------------------------+
$page['tab'] = 'permalinks';
include(PHPWG_ROOT_PATH.'admin/include/albums_tab.inc.php');
$query = '
SELECT
id, permalink,
CONCAT(id, " - ", name, IF(permalink IS NULL, "", " &radic;") ) AS name,
uppercats, global_rank
FROM '.CATEGORIES_TABLE;
display_select_cat_wrapper( $query, $selected_cat, 'categories', false );
$pwg_token = get_pwg_token();
// --- generate display of active permalinks -----------------------------------
$sort_by = parse_sort_variables(
array('id', 'name', 'permalink'), 'name',
'psf',
array('delete_permanent'),
'SORT_' );
$query = '
SELECT id, permalink, uppercats, global_rank
FROM '.CATEGORIES_TABLE.'
WHERE permalink IS NOT NULL
';
if ( $sort_by[0]=='id' or $sort_by[0]=='permalink' )
{
$query .= ' ORDER BY '.$sort_by[0];
}
$categories=array();
$result=pwg_query($query);
while ( $row = pwg_db_fetch_assoc($result) )
{
$row['name'] = get_cat_display_name_cache( $row['uppercats'] );
$categories[] = $row;
}
if ( $sort_by[0]=='name')
{
usort($categories, 'global_rank_compare');
}
$template->assign( 'permalinks', $categories );
// --- generate display of old permalinks --------------------------------------
$sort_by = parse_sort_variables(
array('cat_id','permalink','date_deleted','last_hit','hit'), null,
'dpsf',
array('delete_permanent'),
'SORT_OLD_', '#old_permalinks' );
$url_del_base = get_root_url().'admin.php?page=permalinks';
$query = 'SELECT * FROM '.OLD_PERMALINKS_TABLE;
if ( count($sort_by) )
{
$query .= ' ORDER BY '.$sort_by[0];
}
$result = pwg_query($query);
$deleted_permalinks=array();
while ( $row = pwg_db_fetch_assoc($result) )
{
$row['name'] = get_cat_display_name_cache($row['cat_id']);
$row['U_DELETE'] =
add_url_params(
$url_del_base,
array('delete_permanent'=> $row['permalink'],'pwg_token'=>$pwg_token)
);
$deleted_permalinks[] = $row;
}
$template->assign(array(
'PWG_TOKEN' => $pwg_token,
'U_HELP' => get_root_url().'admin/popuphelp.php?page=permalinks',
'deleted_permalinks' => $deleted_permalinks,
'ADMIN_PAGE_TITLE' => l10n('Albums'),
));
$template->assign_var_from_handle('ADMIN_CONTENT', 'permalinks');
?>
@@ -0,0 +1,82 @@
<?php
// +-----------------------------------------------------------------------+
// | This file is part of Piwigo. |
// | |
// | For copyright and license information, please view the COPYING.txt |
// | file that was distributed with this source code. |
// +-----------------------------------------------------------------------+
if( !defined("PHPWG_ROOT_PATH") )
{
die ("Hacking attempt!");
}
// +-----------------------------------------------------------------------+
// | Basic checks |
// +-----------------------------------------------------------------------+
check_status(ACCESS_ADMINISTRATOR);
check_input_parameter('cat_id', $_GET, false, PATTERN_ID);
check_input_parameter('image_id', $_GET, false, PATTERN_ID);
$admin_photo_base_url = get_root_url().'admin.php?page=photo-'.$_GET['image_id'];
// retrieving direct information about picture
$page['image'] = get_image_infos($_GET['image_id'], true);
if (isset($_GET['cat_id']))
{
$query = '
SELECT *
FROM '.CATEGORIES_TABLE.'
WHERE id = '.$_GET['cat_id'].'
;';
$category = pwg_db_fetch_assoc(pwg_query($query));
}
// +-----------------------------------------------------------------------+
// | Tabs |
// +-----------------------------------------------------------------------+
include_once(PHPWG_ROOT_PATH.'admin/include/tabsheet.class.php');
$page['tab'] = 'properties';
if (isset($_GET['tab']))
{
$page['tab'] = $_GET['tab'];
}
$tabsheet = new tabsheet();
$tabsheet->set_id('photo');
$tabsheet->select($page['tab']);
$tabsheet->assign();
$template->assign(
array(
'ADMIN_PAGE_TITLE' => l10n('Edit photo').' <span class="image-id">#'.$_GET['image_id'].'</span>',
)
);
// +-----------------------------------------------------------------------+
// | Load the tab |
// +-----------------------------------------------------------------------+
if ('properties' == $page['tab'])
{
include(PHPWG_ROOT_PATH.'admin/picture_modify.php');
}
elseif ('coi' == $page['tab'])
{
include(PHPWG_ROOT_PATH.'admin/picture_coi.php');
}
elseif ('formats' == $page['tab'] && $conf['enable_formats'])
{
include(PHPWG_ROOT_PATH.'admin/picture_formats.php');
}
else
{
include(PHPWG_ROOT_PATH.'admin/photo_'.$page['tab'].'.php');
}
?>
@@ -0,0 +1,74 @@
<?php
// +-----------------------------------------------------------------------+
// | This file is part of Piwigo. |
// | |
// | For copyright and license information, please view the COPYING.txt |
// | file that was distributed with this source code. |
// +-----------------------------------------------------------------------+
if( !defined("PHPWG_ROOT_PATH") )
{
die ("Hacking attempt!");
}
include_once(PHPWG_ROOT_PATH.'admin/include/functions.php');
include_once(PHPWG_ROOT_PATH.'admin/include/tabsheet.class.php');
include_once(PHPWG_ROOT_PATH.'admin/include/functions_upload.inc.php');
include_once(PHPWG_ROOT_PATH.'admin/include/image.class.php');
define(
'PHOTOS_ADD_BASE_URL',
get_root_url().'admin.php?page=photos_add'
);
// +-----------------------------------------------------------------------+
// | Check Access and exit when user status is not ok |
// +-----------------------------------------------------------------------+
check_status(ACCESS_ADMINISTRATOR);
// +-----------------------------------------------------------------------+
// | Load configuration |
// +-----------------------------------------------------------------------+
$upload_form_config = get_upload_form_config();
// +-----------------------------------------------------------------------+
// | Tabs |
// +-----------------------------------------------------------------------+
if (isset($_GET['section']))
{
$page['tab'] = $_GET['section'];
// backward compatibility
if ('ploader' == $page['tab'])
{
$page['tab'] = 'applications';
}
}
else
{
$page['tab'] = 'direct';
}
$tabsheet = new tabsheet();
$tabsheet->set_id('photos_add');
$tabsheet->select($page['tab']);
$tabsheet->assign();
// +-----------------------------------------------------------------------+
// | template init |
// +-----------------------------------------------------------------------+
$template->set_filenames(
array(
'photos_add' => 'photos_add_'.$page['tab'].'.tpl'
)
);
// +-----------------------------------------------------------------------+
// | Load the tab |
// +-----------------------------------------------------------------------+
include(PHPWG_ROOT_PATH.'admin/photos_add_'.$page['tab'].'.php');
?>
@@ -0,0 +1,25 @@
<?php
// +-----------------------------------------------------------------------+
// | This file is part of Piwigo. |
// | |
// | For copyright and license information, please view the COPYING.txt |
// | file that was distributed with this source code. |
// +-----------------------------------------------------------------------+
if (!defined('PHOTOS_ADD_BASE_URL'))
{
die ("Hacking attempt!");
}
// +-----------------------------------------------------------------------+
// | template init |
// +-----------------------------------------------------------------------+
// +-----------------------------------------------------------------------+
// | sending html code |
// +-----------------------------------------------------------------------+
$template->assign('ADMIN_PAGE_TITLE', l10n('Upload Photos'));
$template->assign_var_from_handle('ADMIN_CONTENT', 'photos_add');
?>
@@ -0,0 +1,164 @@
<?php
// +-----------------------------------------------------------------------+
// | This file is part of Piwigo. |
// | |
// | For copyright and license information, please view the COPYING.txt |
// | file that was distributed with this source code. |
// +-----------------------------------------------------------------------+
if (!defined('PHOTOS_ADD_BASE_URL'))
{
die ("Hacking attempt!");
}
// +-----------------------------------------------------------------------+
// | batch management request |
// +-----------------------------------------------------------------------+
if (isset($_GET['batch']))
{
check_input_parameter('batch', $_GET, false, '/^\d+(,\d+)*$/');
$query = '
DELETE FROM '.CADDIE_TABLE.'
WHERE user_id = '.$user['id'].'
;';
pwg_query($query);
$inserts = array();
foreach (array_unique(explode(',', $_GET['batch'])) as $image_id)
{
$inserts[] = array(
'user_id' => $user['id'],
'element_id' => $image_id,
);
}
mass_inserts(
CADDIE_TABLE,
array_keys($inserts[0]),
$inserts
);
redirect(get_root_url().'admin.php?page=batch_manager&filter=prefilter-caddie');
}
if (userprefs_get_param('promote-mobile-apps', true))
{
$query = '
SELECT registration_date
FROM '.USER_INFOS_TABLE.'
WHERE registration_date IS NOT NULL
ORDER BY user_id ASC
LIMIT 1
;';
list($register_date) = pwg_db_fetch_row(pwg_query($query));
$query = '
SELECT COUNT(*)
FROM '.CATEGORIES_TABLE.'
;';
list($nb_cats) = pwg_db_fetch_row(pwg_query($query));
$query = '
SELECT COUNT(*)
FROM '.IMAGES_TABLE.'
;';
list($nb_images) = pwg_db_fetch_row(pwg_query($query));
include_once(PHPWG_ROOT_PATH.'include/mdetect.php');
$uagent_obj = new uagent_info();
// To see the mobile app promote, the account must have 2 weeks ancient, 3 albums created and 30 photos uploaded
$template->assign("PROMOTE_MOBILE_APPS", (!$uagent_obj->DetectIos() and strtotime($register_date) < strtotime('2 weeks ago') and $nb_cats >= 3 and $nb_images >= 30));
}
else
{
$template->assign("PROMOTE_MOBILE_APPS", false);
}
$template->assign('PHPWG_URL', PHPWG_URL);
// +-----------------------------------------------------------------------+
// | Formats Mode |
// +-----------------------------------------------------------------------+
$display_formats = $conf['enable_formats'] && isset($_GET['formats']);
$have_formats_original = false;
$formats_original_info = array();
$formats_ext_info = null;
// If URL parameter isn't empty
if ($display_formats && $_GET['formats'])
{
check_input_parameter('formats', $_GET, false, PATTERN_ID, false);
$formats_original_info = get_image_infos($_GET['formats']);
if ($formats_original_info)
{
$src_image = new SrcImage($formats_original_info);
$formats_original_info['src'] = DerivativeImage::url(IMG_SQUARE, $src_image);
// Fetch actual formats
$query = '
SELECT *
FROM '.IMAGE_FORMAT_TABLE.'
WHERE image_id = '.$formats_original_info['id'].'
;';
$formats = query2array($query);
if (!empty($formats))
{
$format_strings = array();
$formats_exts = array();
foreach ($formats as $format)
{
$format_strings[] = sprintf('%s (%.2fMB)', $format['ext'], $format['filesize']/1024);
$formats_exts[] = strtolower($format['ext']);
}
$formats_original_info['formats'] = l10n('Formats: %s', implode(', ', $format_strings));
$formats_ext_info = json_encode($formats_exts);
}
$extTab = explode('.',$formats_original_info['file']);
$formats_original_info['ext'] = l10n('%s file type',strtoupper(end($extTab)));
$formats_original_info['u_edit'] = get_root_url().'admin.php?page=photo-'.$formats_original_info['id'];
$have_formats_original = true;
}
else
{
$page['errors'][] = l10n('The original picture selected dosen\'t exists.');
}
}
// +-----------------------------------------------------------------------+
// | prepare form |
// +-----------------------------------------------------------------------+
include_once(PHPWG_ROOT_PATH.'admin/include/photos_add_direct_prepare.inc.php');
// +-----------------------------------------------------------------------+
// | sending html code |
// +-----------------------------------------------------------------------+
trigger_notify('loc_end_photo_add_direct');
$template->assign(array(
'ENABLE_FORMATS' => $conf['enable_formats'],
'DISPLAY_FORMATS' => $display_formats,
'HAVE_FORMATS_ORIGINAL' => $have_formats_original,
'FORMATS_ORIGINAL_INFO' => $formats_original_info,
'FORMATS_EXT_INFO' => $formats_ext_info,
'SWITCH_FORMAT_MODE_URL' => get_root_url().'admin.php?page=photos_add'.($display_formats ? '':'&formats'),
'format_ext' => implode(',', $conf['format_ext']),
'str_format_ext' => implode(', ', $conf['format_ext']),
));
$template->assign_var_from_handle('ADMIN_CONTENT', 'photos_add');
?>
@@ -0,0 +1,33 @@
<?php
// +-----------------------------------------------------------------------+
// | This file is part of Piwigo. |
// | |
// | For copyright and license information, please view the COPYING.txt |
// | file that was distributed with this source code. |
// +-----------------------------------------------------------------------+
if (!defined('PHOTOS_ADD_BASE_URL'))
{
die ("Hacking attempt!");
}
// +-----------------------------------------------------------------------+
// | template init |
// +-----------------------------------------------------------------------+
$template->assign(
'FTP_HELP_CONTENT',
load_language(
'help/photos_add_ftp.html',
'',
array('return'=>true)
)
);
// +-----------------------------------------------------------------------+
// | sending html code |
// +-----------------------------------------------------------------------+
$template->assign('ADMIN_PAGE_TITLE', l10n('Upload Photos'));
$template->assign_var_from_handle('ADMIN_CONTENT', 'photos_add');
?>
@@ -0,0 +1,98 @@
<?php
// +-----------------------------------------------------------------------+
// | This file is part of Piwigo. |
// | |
// | For copyright and license information, please view the COPYING.txt |
// | file that was distributed with this source code. |
// +-----------------------------------------------------------------------+
if(!defined("PHPWG_ROOT_PATH"))
{
die('Hacking attempt!');
}
// +-----------------------------------------------------------------------+
// | Check Access and exit when user status is not ok |
// +-----------------------------------------------------------------------+
check_status(ACCESS_ADMINISTRATOR);
check_input_parameter('image_id', $_GET, false, PATTERN_ID);
if (isset($_POST['submit']))
{
$query = 'UPDATE '.IMAGES_TABLE;
if (strlen($_POST['l'])==0)
{
$query .= ' SET coi=NULL';
}
else
{
$coi = fraction_to_char($_POST['l'])
.fraction_to_char($_POST['t'])
.fraction_to_char($_POST['r'])
.fraction_to_char($_POST['b']);
$query .= ' SET coi=\''.$coi.'\'';
}
$query .= ' WHERE id='.$_GET['image_id'];
pwg_query($query);
}
$query = 'SELECT * FROM '.IMAGES_TABLE.' WHERE id='.$_GET['image_id'];
$row = pwg_db_fetch_assoc( pwg_query($query) );
if (isset($_POST['submit']))
{
foreach(ImageStdParams::get_defined_type_map() as $params)
{
if ($params->sizing->max_crop != 0)
{
delete_element_derivatives($row, $params->type);
}
}
delete_element_derivatives($row, IMG_CUSTOM);
$uid = '&b='.time();
$conf['question_mark_in_urls'] = $conf['php_extension_in_urls'] = true;
if ($conf['derivative_url_style']==1)
{
$conf['derivative_url_style']=0; //auto
}
}
else
{
$uid = '';
}
$tpl_var = array(
'TITLE' => render_element_name($row),
'ALT' => $row['file'],
'U_IMG' => DerivativeImage::url(IMG_LARGE, $row),
);
if (!empty($row['coi']))
{
$tpl_var['coi'] = array(
'l'=> char_to_fraction($row['coi'][0]),
't'=> char_to_fraction($row['coi'][1]),
'r'=> char_to_fraction($row['coi'][2]),
'b'=> char_to_fraction($row['coi'][3]),
);
}
foreach(ImageStdParams::get_defined_type_map() as $params)
{
if ($params->sizing->max_crop != 0)
{
$derivative = new DerivativeImage($params, new SrcImage($row) );
$template->append( 'cropped_derivatives', array(
'U_IMG' => $derivative->get_url().$uid,
'HTM_SIZE' => $derivative->get_size_htm(),
) );
}
}
$template->assign($tpl_var);
$template->set_filename('picture_coi', 'picture_coi.tpl');
$template->assign_var_from_handle('ADMIN_CONTENT', 'picture_coi');
?>
@@ -0,0 +1,63 @@
<?php
// +-----------------------------------------------------------------------+
// | This file is part of Piwigo. |
// | |
// | For copyright and license information, please view the COPYING.txt |
// | file that was distributed with this source code. |
// +-----------------------------------------------------------------------+
if(!defined("PHPWG_ROOT_PATH"))
{
die('Hacking attempt!');
}
// +-----------------------------------------------------------------------+
// | Check Access and exit when user status is not ok |
// +-----------------------------------------------------------------------+
check_status(ACCESS_ADMINISTRATOR);
check_input_parameter('image_id', $_GET, false, PATTERN_ID);
$query='
SELECT *
FROM '.IMAGES_TABLE.'
WHERE id = '. $_GET['image_id'] .'
;';
$images = query2array($query);
$image = $images[0];
$query = '
SELECT
*
FROM '.IMAGE_FORMAT_TABLE.'
WHERE image_id = '.$_GET['image_id'].'
;';
$formats = query2array($query);
foreach ($formats as &$format)
{
$format['download_url'] = 'action.php?format='.$format['format_id'].'&amp;download';
$format['label'] = strtoupper($format['ext']);
$lang_key = 'format '.strtoupper($format['ext']);
if (isset($lang[$lang_key]))
{
$format['label'] = $lang[$lang_key];
}
$format['filesize'] = round($format['filesize']/1024, 2);
}
$template->assign(array(
'ADD_FORMATS_URL' => get_root_url().'admin.php?page=photos_add&formats='.$_GET['image_id'],
'IMG_SQUARE_SRC' => DerivativeImage::url(ImageStdParams::get_by_type(IMG_SQUARE), $image),
'FORMATS' => $formats,
'PWG_TOKEN' => get_pwg_token(),
));
$template->set_filename('picture_formats', 'picture_formats.tpl');
$template->assign_var_from_handle('ADMIN_CONTENT', 'picture_formats');
?>
@@ -0,0 +1,430 @@
<?php
// +-----------------------------------------------------------------------+
// | This file is part of Piwigo. |
// | |
// | For copyright and license information, please view the COPYING.txt |
// | file that was distributed with this source code. |
// +-----------------------------------------------------------------------+
if(!defined("PHPWG_ROOT_PATH"))
{
die('Hacking attempt!');
}
include_once(PHPWG_ROOT_PATH.'admin/include/functions.php');
// +-----------------------------------------------------------------------+
// | Check Access and exit when user status is not ok |
// +-----------------------------------------------------------------------+
check_status(ACCESS_ADMINISTRATOR);
check_input_parameter('image_id', $_GET, false, PATTERN_ID);
check_input_parameter('level', $_POST, false, '/^\d+$/');
check_input_parameter('date_creation', $_POST, false, '/^\d\d\d\d-\d\d-\d\d( \d\d:\d\d:\d\d)?$/');
// retrieving direct information about picture. This may have been already
// done on admin/photo.php but this page can also be accessed without
// photo.php as proxy.
if (!isset($page['image']))
{
$page['image'] = get_image_infos($_GET['image_id'], true);
}
// represent
$query = '
SELECT id
FROM '.CATEGORIES_TABLE.'
WHERE representative_picture_id = '.$_GET['image_id'].'
;';
$represented_albums = query2array($query, null, 'id');
// +-----------------------------------------------------------------------+
// | delete photo |
// +-----------------------------------------------------------------------+
if (isset($_GET['delete']))
{
check_pwg_token();
delete_elements(array($_GET['image_id']), true);
invalidate_user_cache();
// where to redirect the user now?
//
// 1. if a category is available in the URL, use it
// 2. else use the first reachable linked category
// 3. redirect to gallery root
if ($custom_context = get_edit_context($_GET['image_id']))
{
// considering we have a context available, we fake one to build the url
// and we replace it with the context found in the session for this image_id
redirect(str_replace('list/1,2', $custom_context, make_index_url(array('list'=>array(1,2)))));
}
redirect(make_index_url());
}
// +-----------------------------------------------------------------------+
// | synchronize metadata |
// +-----------------------------------------------------------------------+
if (isset($_GET['sync_metadata']))
{
sync_metadata(array( intval($_GET['image_id'])));
$page['infos'][] = l10n('Metadata synchronized from file');
}
//--------------------------------------------------------- update informations
if (isset($_POST['submit']))
{
check_pwg_token();
$data = array();
$data['id'] = $_GET['image_id'];
$data['level'] = $_POST['level'];
$to_sanitize_fields = array('name', 'author', 'comment');
foreach ($to_sanitize_fields as $field)
{
$data[$field] = $conf['allow_html_descriptions'] ? @$_POST[$field] : strip_tags(@$_POST[$field]);
}
if (!empty($_POST['date_creation']))
{
$data['date_creation'] = $_POST['date_creation'];
}
else
{
$data['date_creation'] = null;
}
$data = trigger_change('picture_modify_before_update', $data);
single_update(
IMAGES_TABLE,
$data,
array('id' => $data['id'])
);
// time to deal with tags
$tag_ids = array();
if (!empty($_POST['tags']))
{
$tag_ids = get_tag_ids($_POST['tags']);
}
set_tags($tag_ids, $_GET['image_id']);
// association to albums
if (!isset($_POST['associate']))
{
$_POST['associate'] = array();
}
check_input_parameter('associate', $_POST, true, PATTERN_ID);
move_images_to_categories(array($_GET['image_id']), $_POST['associate']);
invalidate_user_cache();
// thumbnail for albums
if (!isset($_POST['represent']))
{
$_POST['represent'] = array();
}
check_input_parameter('represent', $_POST, true, PATTERN_ID);
$no_longer_thumbnail_for = array_diff($represented_albums, $_POST['represent']);
if (count($no_longer_thumbnail_for) > 0)
{
set_random_representant($no_longer_thumbnail_for);
}
$new_thumbnail_for = array_diff($_POST['represent'], $represented_albums);
if (count($new_thumbnail_for) > 0)
{
$query = '
UPDATE '.CATEGORIES_TABLE.'
SET representative_picture_id = '.$_GET['image_id'].'
WHERE id IN ('.implode(',', $new_thumbnail_for).')
;';
pwg_query($query);
}
$represented_albums = $_POST['represent'];
$template->assign(
array(
'save_success' => l10n('Photo informations updated'),
)
);
pwg_activity('photo', $_GET['image_id'], 'edit');
// refresh page cache
$page['image'] = get_image_infos($_GET['image_id'], true);
}
// tags
$query = '
SELECT
id,
name
FROM '.IMAGE_TAG_TABLE.' AS it
JOIN '.TAGS_TABLE.' AS t ON t.id = it.tag_id
WHERE image_id = '.$_GET['image_id'].'
;';
$tag_selection = get_taglist($query);
$row = $page['image'];
if (isset($data['date_creation']))
{
$row['date_creation'] = $data['date_creation'];
}
$storage_category_id = null;
if (!empty($row['storage_category_id']))
{
$storage_category_id = $row['storage_category_id'];
}
$image_file = $row['file'];
// +-----------------------------------------------------------------------+
// | template init |
// +-----------------------------------------------------------------------+
$template->set_filenames(
array(
'picture_modify' => 'picture_modify.tpl'
)
);
$admin_url_start = $admin_photo_base_url.'-properties';
$src_image = new SrcImage($row);
// in case the photo needs a rotation of 90 degrees (clockwise or counterclockwise), we switch width and height
if (in_array($row['rotation'], array(1, 3)))
{
list($row['width'], $row['height']) = array($row['height'], $row['width']);
}
$template->assign(
array(
'tag_selection' => $tag_selection,
'U_DOWNLOAD' => 'action.php?id='.$_GET['image_id'].'&amp;part=e&amp;pwg_token='.get_pwg_token().'&amp;download',
'U_SYNC' => $admin_url_start.'&amp;sync_metadata=1',
'U_DELETE' => $admin_url_start.'&amp;delete=1&amp;pwg_token='.get_pwg_token(),
'U_HISTORY' => get_root_url().'admin.php?page=history&amp;filter_image_id='.$_GET['image_id'],
'U_ACTIVITY' => get_root_url().'admin.php?page=user_activity&photo='.$_GET['image_id'],
'PATH'=>$row['path'],
'TN_SRC' => DerivativeImage::url(IMG_MEDIUM, $src_image),
'FILE_SRC' => DerivativeImage::url(IMG_LARGE, $src_image),
'NAME' =>
isset($_POST['name']) ?
stripslashes($_POST['name']) : @$row['name'],
'TITLE' => render_element_name($row),
'DIMENSIONS' => @$row['width'].' * '.@$row['height'],
'FORMAT' => ($row['width'] >= $row['height'])? 1:0,//0:horizontal, 1:vertical
'FILESIZE' => @$row['filesize'].' KB',
'REGISTRATION_DATE' => format_date($row['date_available']),
'AUTHOR' => htmlspecialchars(
isset($_POST['author'])
? stripslashes($_POST['author'])
: (empty($row['author']) ? '' : $row['author'])
),
'DATE_CREATION' => $row['date_creation'],
'DESCRIPTION' =>
htmlspecialchars( isset($_POST['comment']) ?
stripslashes($_POST['comment']) : (empty($row['comment']) ? '' : $row['comment'])),
'F_ACTION' =>
get_root_url().'admin.php'
.get_query_string_diff(array('sync_metadata'))
)
);
$added_by = 'N/A';
$query = '
SELECT '.$conf['user_fields']['username'].' AS username
FROM '.USERS_TABLE.'
WHERE '.$conf['user_fields']['id'].' = '.$row['added_by'].'
;';
$result = pwg_query($query);
while ($user_row = pwg_db_fetch_assoc($result))
{
$row['added_by'] = $user_row['username'];
}
$extTab = explode('.',$row['file']);
$intro_vars = array(
'file' => l10n('%s', $row['file']),
'date' => l10n('Posted the %s', format_date($row['date_available'], array('day', 'month', 'year'))),
'age' => l10n(ucfirst(time_since($row['date_available'], 'year'))),
'added_by' => l10n('Added by %s', $row['added_by']),
'size' => l10n('%s pixels, %.2f MB', $row['width'].'&times;'.$row['height'], $row['filesize']/1024),
'stats' => l10n('Visited %d times', $row['hit']),
'id' => l10n($row['id']),
'ext' => l10n('%s file type',strtoupper(end($extTab))),
'is_svg'=> (strtoupper(end($extTab)) == 'SVG'),
);
if ($conf['rate'] and !empty($row['rating_score']))
{
$query = '
SELECT
COUNT(*)
FROM '.RATE_TABLE.'
WHERE element_id = '.$_GET['image_id'].'
;';
list($row['nb_rates']) = pwg_db_fetch_row(pwg_query($query));
$intro_vars['stats'].= ', '.sprintf(l10n('Rated %d times, score : %.2f'), $row['nb_rates'], $row['rating_score']);
}
$query = '
SELECT *
FROM '.IMAGE_FORMAT_TABLE.'
WHERE image_id = '.$row['id'].'
;';
$formats = query2array($query);
if (!empty($formats))
{
$format_strings = array();
foreach ($formats as $format)
{
$format_strings[] = sprintf('%s (%.2fMB)', $format['ext'], $format['filesize']/1024);
}
$intro_vars['formats'] = l10n('Formats: %s', implode(', ', $format_strings));
}
$template->assign('INTRO', $intro_vars);
if (in_array(get_extension($row['path']),$conf['picture_ext']))
{
$template->assign('U_COI', get_root_url().'admin.php?page=picture_coi&amp;image_id='.$_GET['image_id']);
}
// image level options
$selected_level = isset($_POST['level']) ? $_POST['level'] : $row['level'];
$template->assign(
array(
'level_options'=> get_privacy_level_options(),
'level_options_selected' => array($selected_level)
)
);
// categories
$query = '
SELECT category_id, uppercats, dir
FROM '.IMAGE_CATEGORY_TABLE.' AS ic
INNER JOIN '.CATEGORIES_TABLE.' AS c
ON c.id = ic.category_id
WHERE image_id = '.$_GET['image_id'].'
;';
$result = pwg_query($query);
$related_categories = array();
$related_categories_ids = array();
while ($row = pwg_db_fetch_assoc($result))
{
$name =
get_cat_display_name_cache(
$row['uppercats'],
get_root_url().'admin.php?page=album-'
);
if ($row['category_id'] == $storage_category_id)
{
$template->assign('STORAGE_CATEGORY', $name);
}
$related_categories[$row['category_id']] = array('name' => $name, 'unlinkable' => $row['category_id'] != $storage_category_id);
$related_categories_ids[] = $row['category_id'];
}
$template->assign('related_categories', $related_categories);
$template->assign('related_categories_ids', $related_categories_ids);
// jump to link
//
// 1. if an edit_context is available, we use it (without checking permissions)
// 2. else if user level is higher than image level, randomly find an authorized category
// 3. else no jumpto link
if ($custom_context = get_edit_context($_GET['image_id']))
{
$template->assign('U_JUMPTO', make_picture_url(array('image_id' => $_GET['image_id'])).'/'.$custom_context);
}
elseif ($user['level'] >= $page['image']['level'])
{
$query = '
SELECT category_id
FROM '.IMAGE_CATEGORY_TABLE.'
WHERE image_id = '.$_GET['image_id'].'
;';
$authorizeds = array_diff(
array_from_query($query, 'category_id'),
explode(
',',
calculate_permissions($user['id'], $user['status'])
)
);
if (count($authorizeds) > 0)
{
$category = $authorizeds[array_rand($authorizeds)];
$url_img = make_picture_url(
array(
'image_id' => $_GET['image_id'],
'image_file' => $image_file,
'category' => $cache['cat_names'][ $category ],
)
);
$template->assign('U_JUMPTO', $url_img);
}
}
// associate to albums
$query = '
SELECT id
FROM '.CATEGORIES_TABLE.'
INNER JOIN '.IMAGE_CATEGORY_TABLE.' ON id = category_id
WHERE image_id = '.$_GET['image_id'].'
;';
$associated_albums = query2array($query, null, 'id');
$template->assign(array(
'associated_albums' => $associated_albums,
'represented_albums' => $represented_albums,
'STORAGE_ALBUM' => $storage_category_id,
'CACHE_KEYS' => get_admin_client_cache_keys(array('tags', 'categories')),
'PWG_TOKEN' => get_pwg_token(),
));
trigger_notify('loc_end_picture_modify');
//----------------------------------------------------------- sending html code
$template->assign_var_from_handle('ADMIN_CONTENT', 'picture_modify');
?>
@@ -0,0 +1,59 @@
<?php
// +-----------------------------------------------------------------------+
// | This file is part of Piwigo. |
// | |
// | For copyright and license information, please view the COPYING.txt |
// | file that was distributed with this source code. |
// +-----------------------------------------------------------------------+
if( !defined("PHPWG_ROOT_PATH") )
{
die ("Hacking attempt!");
}
include_once(PHPWG_ROOT_PATH.'admin/include/functions.php');
check_status(ACCESS_ADMINISTRATOR);
$sections = explode('/', $_GET['section'] ?? '');
for ($i=0; $i<count($sections); $i++)
{
if (empty($sections[$i]))
{
unset($sections[$i]);
$i--;
continue;
}
if ($sections[$i] == '..' or !preg_match('/^[a-zA-Z0-9_\.-]+$/', $sections[$i]))
{
die('invalid section token ['.htmlentities($sections[$i]).']');
}
}
if (count($sections)<2)
{
die('Invalid plugin URL');
}
$plugin_id = $sections[0];
if (!preg_match('/^[\w-]+$/', $plugin_id))
{
die('Invalid plugin identifier');
}
if ( !isset($pwg_loaded_plugins[$plugin_id]) )
{
die('Invalid URL - plugin '.$plugin_id.' not active');
}
$filename = PHPWG_PLUGINS_PATH.implode('/', $sections);
if (is_file($filename))
{
include_once($filename);
}
else
{
die('Missing file '.htmlentities($filename));
}
?>
@@ -0,0 +1,36 @@
<?php
// +-----------------------------------------------------------------------+
// | This file is part of Piwigo. |
// | |
// | For copyright and license information, please view the COPYING.txt |
// | file that was distributed with this source code. |
// +-----------------------------------------------------------------------+
if( !defined("PHPWG_ROOT_PATH") )
{
die ("Hacking attempt!");
}
include_once(PHPWG_ROOT_PATH.'admin/include/tabsheet.class.php');
$my_base_url = get_root_url().'admin.php?page=plugins';
if (isset($_GET['tab']))
$page['tab'] = $_GET['tab'];
else
$page['tab'] = 'installed';
$tabsheet = new tabsheet();
$tabsheet->set_id('plugins');
$tabsheet->select($page['tab']);
$tabsheet->assign();
if ($page['tab'] == 'update') {
include(PHPWG_ROOT_PATH.'admin/updates_ext.php');
$template->assign('ADMIN_PAGE_TITLE', l10n('Plugins'));
}
else
{
include(PHPWG_ROOT_PATH.'admin/plugins_'.$page['tab'].'.php');
}
?>
@@ -0,0 +1,219 @@
<?php
// +-----------------------------------------------------------------------+
// | This file is part of Piwigo. |
// | |
// | For copyright and license information, please view the COPYING.txt |
// | file that was distributed with this source code. |
// +-----------------------------------------------------------------------+
if( !defined("PHPWG_ROOT_PATH") )
{
die ("Hacking attempt!");
}
include_once(PHPWG_ROOT_PATH.'admin/include/plugins.class.php');
$template->set_filenames(array('plugins' => 'plugins_installed.tpl'));
// should we display details on plugins?
if (isset($_GET['show_details']))
{
if (1 == $_GET['show_details'])
{
$show_details = true;
}
else
{
$show_details = false;
}
pwg_set_session_var('plugins_show_details', $show_details);
}
elseif (null != pwg_get_session_var('plugins_show_details'))
{
$show_details = pwg_get_session_var('plugins_show_details');
}
else
{
$show_details = false;
}
$base_url = get_root_url().'admin.php?page='.$page['page'];
$pwg_token = get_pwg_token();
$action_url = $base_url.'&amp;plugin='.'%s'.'&amp;pwg_token='.$pwg_token;
$plugins = new plugins();
//--------------------------------------------------------Incompatible Plugins
if (isset($_GET['incompatible_plugins']))
{
$incompatible_plugins_raw = $plugins->get_incompatible_plugins();
if (false === $incompatible_plugins_raw)
{
echo json_encode(array());
exit;
}
$incompatible_plugins = array();
foreach ($incompatible_plugins_raw as $plugin => $version)
{
if ($plugin == '~~expire~~') continue;
$incompatible_plugins[] = $plugin;
}
echo json_encode($incompatible_plugins);
exit;
}
//--------------------------------------------------------Get the menu with the depreciated version
$plugin_menu_links_deprec = trigger_change('get_admin_plugin_menu_links', array());
$settings_url_for_plugin_deprec = array();
foreach ($plugin_menu_links_deprec as $value)
{
if (preg_match('/^admin\.php\?page=plugin-(.*)$/', $value["URL"], $matches)) {
$settings_url_for_plugin_deprec[$matches[1]] = $value["URL"];
} elseif (preg_match('/^.*section=(.*?)[\/&%].*$/', $value["URL"], $matches)) {
$settings_url_for_plugin_deprec[$matches[1]] = $value["URL"];
}
}
// +-----------------------------------------------------------------------+
// | start template output |
// +-----------------------------------------------------------------------+
$plugins->sort_fs_plugins('name');
$merged_extensions = $plugins->get_merged_extensions();
$merged_plugins = false;
$tpl_plugins = array();
$count_types_plugins = array("active"=>0, "inactive"=>0, "missing"=>0, "merged"=>0);
foreach($plugins->fs_plugins as $plugin_id => $fs_plugin)
{
if (isset($_SESSION['incompatible_plugins'][$plugin_id])
and $fs_plugin['version'] != $_SESSION['incompatible_plugins'][$plugin_id])
{
// Incompatible plugins must be reinitilized
unset($_SESSION['incompatible_plugins']);
}
$setting_url = '';
if (isset($settings_url_for_plugin_deprec[$plugin_id])) { //old version
$setting_url = $settings_url_for_plugin_deprec[$plugin_id];
} else if ($fs_plugin['hasSettings']) { // new version
$setting_url = "admin.php?page=plugin-".$plugin_id;
if (preg_match('/^piwigo-(videojs|openstreetmap)$/', $plugin_id))
{
$setting_url = str_replace('piwigo-', 'piwigo_', $setting_url);
}
}
$url_to_replace = array(
'http://piwigo.org/ext',
'https://piwigo.org/ext'
);
$visit_url = str_replace($url_to_replace, PEM_URL, $fs_plugin['uri']);
$tpl_plugin = array(
'ID' => $plugin_id,
'NAME' => $fs_plugin['name'],
'VISIT_URL' => $visit_url,
'VERSION' => $fs_plugin['version'],
'DESC' => $fs_plugin['description'],
'AUTHOR' => $fs_plugin['author'],
'AUTHOR_URL' => @$fs_plugin['author uri'],
'U_ACTION' => sprintf($action_url, $plugin_id),
'SETTINGS_URL' => $setting_url,
);
if (isset($plugins->db_plugins_by_id[$plugin_id]))
{
$tpl_plugin['STATE'] = $plugins->db_plugins_by_id[$plugin_id]['state'];
}
else
{
$tpl_plugin['STATE'] = 'inactive';
}
if (isset($fs_plugin['extension']) and isset($merged_extensions[$fs_plugin['extension']]))
{
// Deactivate manually plugin from database
$query = 'UPDATE '.PLUGINS_TABLE.' SET state=\'inactive\' WHERE id=\''.$plugin_id.'\'';
pwg_query($query);
$tpl_plugin['STATE'] = 'merged';
$tpl_plugin['DESC'] = l10n('THIS PLUGIN IS NOW PART OF PIWIGO CORE! DELETE IT NOW.');
$merged_plugins = true;
}
$count_types_plugins[$tpl_plugin['STATE']]++;
$tpl_plugins[] = $tpl_plugin;
}
$template->append('plugin_states', 'active');
$template->append('plugin_states', 'inactive');
if ($merged_plugins)
{
$template->append('plugin_states', 'merged');
}
$missing_plugin_ids = array_diff(
array_keys($plugins->db_plugins_by_id),
array_keys($plugins->fs_plugins)
);
if (count($missing_plugin_ids) > 0)
{
foreach ($missing_plugin_ids as $plugin_id)
{
$tpl_plugins[] = array(
'NAME' => $plugin_id,
'ID' => $plugin_id,
'VERSION' => $plugins->db_plugins_by_id[$plugin_id]['version'],
'DESC' => l10n('ERROR: THIS PLUGIN IS MISSING BUT IT IS INSTALLED! UNINSTALL IT NOW.'),
'U_ACTION' => sprintf($action_url, $plugin_id),
'STATE' => 'missing',
);
$count_types_plugins['missing']++;
}
$template->append('plugin_states', 'missing');
}
// sort plugins by state then by name
function cmp($a, $b)
{
$s = array('merged' => 0, 'missing' => 1, 'active' => 2, 'inactive' => 3);
if($a['STATE'] == $b['STATE'])
return strcasecmp($a['NAME'], $b['NAME']);
else
return $s[$a['STATE']] >= $s[$b['STATE']];
}
// Stoped plugin sorting for new plugin manager
// usort($tpl_plugins, 'cmp');
$template->assign(
array(
'plugins' => $tpl_plugins,
'count_types_plugins' => $count_types_plugins,
'PWG_TOKEN' => $pwg_token,
'base_url' => $base_url,
'show_details' => $show_details,
'max_inactive_before_hide' => isset($_GET['show_inactive']) ? 999 : 8,
'isWebmaster' => (is_webmaster()) ? 1 : 0,
'ADMIN_PAGE_TITLE' => l10n('Plugins'),
'view_selector' => userprefs_get_param('plugin-manager-view', 'classic'),
'CONF_ENABLE_EXTENSIONS_INSTALL' => $conf['enable_extensions_install'],
)
);
$template->assign_var_from_handle('ADMIN_CONTENT', 'plugins');
?>
@@ -0,0 +1,208 @@
<?php
// +-----------------------------------------------------------------------+
// | This file is part of Piwigo. |
// | |
// | For copyright and license information, please view the COPYING.txt |
// | file that was distributed with this source code. |
// +-----------------------------------------------------------------------+
if( !defined("PHPWG_ROOT_PATH") )
{
die ("Hacking attempt!");
}
if (!$conf['enable_extensions_install'])
{
die('Piwigo extensions install/update system is disabled');
}
include_once(PHPWG_ROOT_PATH.'admin/include/plugins.class.php');
$template->set_filenames(array('plugins' => 'plugins_new.tpl'));
$base_url = get_root_url().'admin.php?page='.$page['page'].'&tab='.$page['tab'];
$plugins = new plugins();
//------------------------------------------------------automatic installation
if (isset($_GET['revision']) and isset($_GET['extension']))
{
if (!is_webmaster())
{
$page['errors'][] = l10n('Webmaster status is required.');
}
else
{
check_pwg_token();
$install_status = $plugins->extract_plugin_files('install', $_GET['revision'], $_GET['extension'], $plugin_id);
redirect($base_url.'&installstatus='.$install_status.'&plugin_id='.$plugin_id);
}
}
//--------------------------------------------------------------install result
if (isset($_GET['installstatus']))
{
switch ($_GET['installstatus'])
{
case 'ok':
// since Piwigo 12, you need to be on the page of installed plugins to active a plugin with
// a JS action, no need to provide plugin_id in URL, just link to the page of installed
// plugins, filtered on deactivated plugins. The webmaster will have to find its newly
// installed plugin and click on the activation switch.
$activate_url = get_root_url().'admin.php?page=plugins&amp;filter=deactivated';
$page['infos'][] = l10n('Plugin has been successfully copied');
$page['infos'][] = '<a href="'. $activate_url . '">' . l10n('Activate it now') . '</a>';
if (isset($plugins->fs_plugins[$_GET['plugin_id']]))
{
pwg_activity(
'system',
ACTIVITY_SYSTEM_PLUGIN,
'install',
array(
'plugin_id' => $_GET['plugin_id'],
'version' => $plugins->fs_plugins[$_GET['plugin_id']]['version'],
)
);
}
break;
case 'temp_path_error':
$page['errors'][] = l10n('Can\'t create temporary file.');
break;
case 'dl_archive_error':
$page['errors'][] = l10n('Can\'t download archive.');
break;
case 'archive_error':
$page['errors'][] = l10n('Can\'t read or extract archive.');
break;
default:
$page['errors'][] = l10n('An error occured during extraction (%s).', htmlspecialchars($_GET['installstatus']));
$page['errors'][] = l10n('Please check "plugins" folder and sub-folders permissions (CHMOD).');
}
}
//---------------------------------------------------------------Order options
$template->assign('order_options',
array(
'date' => l10n('Post date'),
'revision' => l10n('Last revisions'),
'name' => l10n('Name'),
'author' => l10n('Author'),
'downloads' => l10n('Number of downloads')));
// +-----------------------------------------------------------------------+
// | start template output |
// +-----------------------------------------------------------------------+
// Beta test : show plugins of last version on PEM if the current version isn't present
// If the current version in known, give the current and last version's compatible plugins
$beta_test = false;
if(isset($_GET['beta-test']) && $_GET['beta-test'] == 'true')
{
$beta_test = true;
}
if ($plugins->get_server_plugins(true, $beta_test))
{
/* order plugins */
if (pwg_get_session_var('plugins_new_order') != null)
{
$order_selected = pwg_get_session_var('plugins_new_order');
$plugins->sort_server_plugins($order_selected);
$template->assign('order_selected', $order_selected);
}
else
{
$plugins->sort_server_plugins('date');
$template->assign('order_selected', 'date');
}
foreach($plugins->server_plugins as $plugin)
{
$ext_desc = trim($plugin['extension_description'], " \n\r");
list($small_desc) = explode("\n", wordwrap($ext_desc, 200));
$url_auto_install = htmlentities($base_url)
. '&amp;revision=' . $plugin['revision_id']
. '&amp;extension=' . $plugin['extension_id']
. '&amp;pwg_token='.get_pwg_token()
;
// get the age of the last revision in days
$last_revision_diff = date_diff(date_create($plugin['revision_date']), date_create());
$certification = 1;
$has_compatible_version = false;
// Check if the current version is in the compatible version (not necessary if we are in beta test)
if ($beta_test) {
foreach ($plugin['compatible_with_versions'] as $vers) {
if (get_branch_from_version($vers) == get_branch_from_version(PHPWG_VERSION))
{
$has_compatible_version = true;
}
}
} else {
$has_compatible_version = true;
}
if (!$has_compatible_version) {
$certification = -1;
}
elseif ($last_revision_diff->days < 90) // if the last revision is new of 3 month or less
{
$certification = 3;
}
elseif ($last_revision_diff->days < 180) // 6 month or less
{
$certification = 2;
}
elseif ($last_revision_diff->y > 3) // 3 years or less
{
$certification = 0;
}
// Between 6 month and 3 years : certification = 1
$template->append('plugins', array(
'ID' => $plugin['extension_id'],
'EXT_NAME' => $plugin['extension_name'],
'EXT_URL' => PEM_URL.'/extension_view.php?eid='.$plugin['extension_id'],
'SMALL_DESC' => trim($small_desc, " \r\n"),
'BIG_DESC' => $ext_desc,
'VERSION' => $plugin['revision_name'],
'REVISION_DATE' => preg_replace('/[^0-9]/', '', strtotime($plugin['revision_date'])),
'REVISION_FORMATED_DATE' => format_date($plugin['revision_date'], array('day','month','year')).", ".time_since($plugin['revision_date'], "day"),
'AUTHOR' => $plugin['author_name'],
'DOWNLOADS' => $plugin['extension_nb_downloads'],
'URL_INSTALL' => $url_auto_install,
'CERTIFICATION' => $certification,
'RATING' => $plugin['rating_score'],
'NB_RATINGS' => $plugin['nb_ratings'],
'SCREENSHOT' => (key_exists('screenshot_url', $plugin)) ? $plugin['screenshot_url']:'',
'TAGS' => $plugin["tags"],
));
}
}
else
{
$page['errors'][] = l10n('Can\'t connect to server.');
}
if (!$beta_test and preg_match('/(beta|RC)/', PHPWG_VERSION))
{
$template->assign('BETA_URL', $base_url.'&amp;beta-test=true');
}
$template->assign('ADMIN_PAGE_TITLE', l10n('Plugins'));
$template->assign('BETA_TEST', $beta_test);
$template->assign_var_from_handle('ADMIN_CONTENT', 'plugins');
?>
@@ -0,0 +1,94 @@
<?php
// +-----------------------------------------------------------------------+
// | This file is part of Piwigo. |
// | |
// | For copyright and license information, please view the COPYING.txt |
// | file that was distributed with this source code. |
// +-----------------------------------------------------------------------+
// +-----------------------------------------------------------------------+
// | initialization |
// +-----------------------------------------------------------------------+
define('PHPWG_ROOT_PATH', '../');
define('PWG_HELP', true);
define('IN_ADMIN', true);
include_once( PHPWG_ROOT_PATH.'include/common.inc.php' );
// +-----------------------------------------------------------------------+
// | Check Access and exit when user status is not ok |
// +-----------------------------------------------------------------------+
check_status(ACCESS_ADMINISTRATOR);
if (!isset($_GET['output']) or 'content_only' != $_GET['output'])
{
// Note on 2023-09-28 : calling popuphelp.php without output=content_only no longer occurs in Piwigo core.
$page['body_id'] = 'thePopuphelpPage';
$title = l10n('Piwigo Help');
$page['page_banner'] = '<h1>'.$title.'</h1>';
$page['meta_robots']=array('noindex'=>1, 'nofollow'=>1);
// set required template variables to avoid "Undefined array key" with PHP 8
$template->assign(
array(
'U_RETURN' => '',
'USERNAME' => '',
'U_FAQ'=> '',
'U_CHANGE_THEME' => '',
'U_LOGOUT' => '',
)
);
include(PHPWG_ROOT_PATH.'include/page_header.php');
}
if
(
isset($_GET['page'])
and preg_match('/^[a-z_]*$/', $_GET['page'])
)
{
$help_content = load_language(
'help/'.$_GET['page'].'.html',
'',
array(
'force_fallback' => 'en_UK',
'return' => true,
)
);
if ($help_content == false)
{
$help_content = '';
}
$help_content = trigger_change('get_popup_help_content', $help_content, $_GET['page']);
}
else
{
die('Hacking attempt!');
}
$template->set_filename('popuphelp','popuphelp.tpl');
$template->assign(
array
(
'HELP_CONTENT' => $help_content
));
if (isset($_GET['output']) and 'content_only' == $_GET['output'])
{
echo $help_content;
exit();
}
// +-----------------------------------------------------------------------+
// | html code display |
// +-----------------------------------------------------------------------+
$template->pparse('popuphelp');
include(PHPWG_ROOT_PATH.'include/page_tail.php');
?>
@@ -0,0 +1,34 @@
<?php
// +-----------------------------------------------------------------------+
// | This file is part of Piwigo. |
// | |
// | For copyright and license information, please view the COPYING.txt |
// | file that was distributed with this source code. |
// +-----------------------------------------------------------------------+
if( !defined("PHPWG_ROOT_PATH") ) die ("Hacking attempt!");
check_input_parameter('user_id', $_GET, false, PATTERN_ID);
$edit_user = build_user( $_GET['user_id'], false );
if (!empty($_POST))
{
check_pwg_token();
}
include_once(PHPWG_ROOT_PATH.'profile.php');
$errors = array();
save_profile_from_post($edit_user, $errors);
load_profile_in_template(
get_root_url().'admin.php?page=profile&amp;user_id='.$edit_user['id'],
get_root_url().'admin.php?page=user_list',
$edit_user
);
$page['errors'] = array_merge($page['errors'], $errors);
$template->set_filename('profile', 'profile.tpl');
$template->assign_var_from_handle('ADMIN_CONTENT', 'profile');
?>
+258
View File
@@ -0,0 +1,258 @@
<?php
// +-----------------------------------------------------------------------+
// | This file is part of Piwigo. |
// | |
// | For copyright and license information, please view the COPYING.txt |
// | file that was distributed with this source code. |
// +-----------------------------------------------------------------------+
if (!defined('PHPWG_ROOT_PATH'))
{
die ("Hacking attempt!");
}
include_once(PHPWG_ROOT_PATH.'admin/include/functions.php');
// +-----------------------------------------------------------------------+
// | Check Access and exit when user status is not ok |
// +-----------------------------------------------------------------------+
check_status(ACCESS_ADMINISTRATOR);
check_input_parameter('display', $_GET, false, PATTERN_ID);
include_once(PHPWG_ROOT_PATH.'admin/include/tabsheet.class.php');
$tabsheet = new tabsheet();
$tabsheet->set_id('rating');
$tabsheet->select('rating');
$tabsheet->assign();
// +-----------------------------------------------------------------------+
// | initialization |
// +-----------------------------------------------------------------------+
if (isset($_GET['start']) and is_numeric($_GET['start']))
{
$start = $_GET['start'];
}
else
{
$start = 0;
}
$elements_per_page=10;
if (isset($_GET['display']) and is_numeric($_GET['display']))
{
$elements_per_page = $_GET['display'];
}
$order_by_index=0;
if (isset($_GET['order_by']) and is_numeric($_GET['order_by']))
{
$order_by_index = $_GET['order_by'];
}
$page['user_filter'] = '';
if (isset($_GET['users']))
{
if ($_GET['users'] == 'user')
{
$page['user_filter'] = ' AND r.user_id <> '.$conf['guest_id'];
}
elseif ($_GET['users'] == 'guest')
{
$page['user_filter'] = ' AND r.user_id = '.$conf['guest_id'];
}
}
$page['cat_filter'] = '';
if (isset($_GET['cat']) and is_numeric($_GET['cat']))
{
$cat_ids = get_subcat_ids(array($_GET['cat']));
if (count($cat_ids) > 0)
{
$page['cat_filter'] = ' AND ic.category_id IN ('.implode(',', $cat_ids).')';
}
}
$users = array();
$query = '
SELECT '.$conf['user_fields']['username'].' as username, '.$conf['user_fields']['id'].' as id
FROM '.USERS_TABLE.'
;';
$result = pwg_query($query);
while ($row = pwg_db_fetch_assoc($result))
{
$users[$row['id']]=stripslashes($row['username']);
}
$query = '
SELECT
COUNT(DISTINCT(r.element_id))
FROM '.RATE_TABLE.' AS r';
if (!empty($page['cat_filter']))
{
$query.= '
JOIN '.IMAGES_TABLE.' AS i ON r.element_id = i.id
JOIN '.IMAGE_CATEGORY_TABLE.' AS ic ON ic.image_id = i.id';
}
$query.= '
WHERE 1=1'. $page['user_filter'];
list($nb_images) = pwg_db_fetch_row(pwg_query($query));
$query = '
SELECT
COUNT(*)
FROM '.RATE_TABLE.
';';
list($nb_elements) = pwg_db_fetch_row(pwg_query($query));
// +-----------------------------------------------------------------------+
// | template init |
// +-----------------------------------------------------------------------+
$template->set_filename('rating', 'rating.tpl');
$template->assign(
array(
'navbar' => create_navigation_bar(
PHPWG_ROOT_PATH.'admin.php'.get_query_string_diff(array('start','del')),
$nb_images,
$start,
$elements_per_page
),
'F_ACTION' => PHPWG_ROOT_PATH.'admin.php',
'DISPLAY' => $elements_per_page,
'NB_ELEMENTS' => $nb_elements,
'category' => (isset($_GET['cat']) ? array($_GET['cat']) : array()),
'CACHE_KEYS' => get_admin_client_cache_keys(array('categories')),
)
);
$available_order_by= array(
array(l10n('Rate date'), 'recently_rated DESC'),
array(l10n('Rating score'), 'score DESC'),
array(l10n('Average rate'), 'avg_rates DESC'),
array(l10n('Number of rates'), 'nb_rates DESC'),
array(l10n('Sum of rates'), 'sum_rates DESC'),
array(l10n('File name'), 'file DESC'),
array(l10n('Creation date'), 'date_creation DESC'),
array(l10n('Post date'), 'date_available DESC'),
);
for ($i=0; $i<count($available_order_by); $i++)
{
$template->append(
'order_by_options',
$available_order_by[$i][0]
);
}
$template->assign('order_by_options_selected', array($order_by_index) );
$user_options = array(
'all' => l10n('all'),
'user' => l10n('Users'),
'guest' => l10n('Guests'),
);
$template->assign('user_options', $user_options );
$template->assign('user_options_selected', array(@$_GET['users']) );
$template->assign('ADMIN_PAGE_TITLE', l10n('Rating'));
$query = '
SELECT i.id,
i.path,
i.file,
i.representative_ext,
i.rating_score AS score,
MAX(r.date) AS recently_rated,
ROUND(AVG(r.rate),2) AS avg_rates,
COUNT(r.rate) AS nb_rates,
SUM(r.rate) AS sum_rates
FROM '.RATE_TABLE.' AS r
LEFT JOIN '.IMAGES_TABLE.' AS i ON r.element_id = i.id';
if (!empty($page['cat_filter']))
{
$query.= '
JOIN '.IMAGE_CATEGORY_TABLE.' AS ic ON ic.image_id = i.id';
}
$query.= '
WHERE 1 = 1 ' . $page['user_filter'] . $page['cat_filter'] . '
GROUP BY i.id,
i.path,
i.file,
i.representative_ext,
i.rating_score,
r.element_id
ORDER BY ' . $available_order_by[$order_by_index][1] .'
LIMIT '.$elements_per_page.' OFFSET '.$start.'
;';
$images = array();
$result = pwg_query($query);
while ($row = pwg_db_fetch_assoc($result))
{
$images[] = $row;
}
$template->assign( 'images', array() );
foreach ($images as $image)
{
$thumbnail_src = DerivativeImage::thumb_url($image);
$image_url = get_root_url().'admin.php?page=photo-'.$image['id'];
$query = 'SELECT *
FROM '.RATE_TABLE.' AS r
WHERE r.element_id='.$image['id'] . '
ORDER BY date DESC;';
$result = pwg_query($query);
$nb_rates = pwg_db_num_rows($result);
$tpl_image =
array(
'id' => $image['id'],
'U_THUMB' => $thumbnail_src,
'U_URL' => $image_url,
'SCORE_RATE' => $image['score'],
'AVG_RATE' => $image['avg_rates'],
'SUM_RATE' => $image['sum_rates'],
'NB_RATES' => (int)$image['nb_rates'],
'NB_RATES_TOTAL' => (int)$nb_rates,
'FILE' => $image['file'],
'rates' => array()
);
while ($row = pwg_db_fetch_assoc($result))
{
if ( isset($users[$row['user_id']]) )
{
$user_rate = $users[$row['user_id']];
}
else
{
$user_rate = '? '. $row['user_id'];
}
if ( strlen($row['anonymous_id'])>0 )
{
$user_rate .= '('.$row['anonymous_id'].')';
}
$row['USER'] = $user_rate;
$tpl_image['rates'][] = $row;
}
$template->append( 'images', $tpl_image );
}
// +-----------------------------------------------------------------------+
// | sending html code |
// +-----------------------------------------------------------------------+
$template->assign_var_from_handle('ADMIN_CONTENT', 'rating');
?>
@@ -0,0 +1,253 @@
<?php
// +-----------------------------------------------------------------------+
// | This file is part of Piwigo. |
// | |
// | For copyright and license information, please view the COPYING.txt |
// | file that was distributed with this source code. |
// +-----------------------------------------------------------------------+
defined('PHPWG_ROOT_PATH') or die ("Hacking attempt!");
include_once(PHPWG_ROOT_PATH.'admin/include/tabsheet.class.php');
$tabsheet = new tabsheet();
$tabsheet->set_id('rating');
$tabsheet->select('rating_user');
$tabsheet->assign();
$filter_min_rates = 2;
if (isset($_GET['f_min_rates']))
{
$filter_min_rates = (int)$_GET['f_min_rates'];
}
$consensus_top_number = $conf['top_number'];
if (isset($_GET['consensus_top_number']))
{
$consensus_top_number = (int)$_GET['consensus_top_number'];
}
// build users
global $conf;
$query = 'SELECT DISTINCT
u.'.$conf['user_fields']['id'].' AS id,
u.'.$conf['user_fields']['username'].' AS name,
ui.status
FROM '.USERS_TABLE.' AS u INNER JOIN '.USER_INFOS_TABLE.' AS ui
ON u.'.$conf['user_fields']['id'].' = ui.user_id';
$users_by_id = array();
$result = pwg_query($query);
while ($row = pwg_db_fetch_assoc($result))
{
$users_by_id[(int)$row['id']] = array(
'name' => $row['name'],
'anon' => is_autorize_status(ACCESS_CLASSIC, $row['status']) ? false : true
);
}
$by_user_rating_model = array( 'rates' => array() );
foreach($conf['rate_items'] as $rate)
{
$by_user_rating_model['rates'][$rate] = array();
}
// by user aggregation
$image_ids = array();
$by_user_ratings = array();
$query = '
SELECT * FROM '.RATE_TABLE.' ORDER by date DESC';
$result = pwg_query($query);
while ($row = pwg_db_fetch_assoc($result))
{
if (!isset($users_by_id[$row['user_id']]))
{
$users_by_id[$row['user_id']] = array('name' => '???'.$row['user_id'], 'anon' => false);
}
$usr = $users_by_id[$row['user_id']];
if ($usr['anon'])
{
$user_key = $usr['name'].'('.$row['anonymous_id'].')';
}
else
{
$user_key = $usr['name'];
}
$rating = & $by_user_ratings[$user_key];
if ( is_null($rating) )
{
$rating = $by_user_rating_model;
$rating['uid'] = (int)$row['user_id'];
$rating['aid'] = $usr['anon'] ? $row['anonymous_id'] : '';
$rating['last_date'] = $rating['first_date'] = $row['date'];
}
else
$rating['first_date'] = $row['date'];
$rating['rates'][$row['rate']][] = array(
'id' => $row['element_id'],
'date' => $row['date'],
);
$image_ids[$row['element_id']] = 1;
unset($rating);
}
// get image tn urls
$image_urls = array();
if (count($image_ids) > 0 )
{
$query = 'SELECT id, name, file, path, representative_ext, level
FROM '.IMAGES_TABLE.'
WHERE id IN ('.implode(',', array_keys($image_ids)).')';
$result = pwg_query($query);
$params = ImageStdParams::get_by_type(IMG_SQUARE);
while ($row = pwg_db_fetch_assoc($result))
{
$image_urls[ $row['id'] ] = array(
'tn' => DerivativeImage::url($params, $row),
'page' => make_picture_url( array('image_id'=>$row['id'], 'image_file'=>$row['file']) ),
);
}
}
//all image averages
$query='SELECT element_id,
AVG(rate) AS avg
FROM '.RATE_TABLE.'
GROUP BY element_id';
$all_img_sum = array();
$result = pwg_query($query);
while ($row = pwg_db_fetch_assoc($result))
{
$all_img_sum[(int)$row['element_id']] = array( 'avg'=>(float)$row['avg'] );
}
$query='SELECT id
FROM '.IMAGES_TABLE.'
ORDER by rating_score DESC
LIMIT '.$consensus_top_number;
$best_rated = array_flip( array_from_query($query, 'id'));
// by user stats
foreach($by_user_ratings as $id => &$rating)
{
$c=0; $s=0; $ss=0; $consensus_dev=0; $consensus_dev_top=0; $consensus_dev_top_count=0;
foreach($rating['rates'] as $rate => $rates)
{
$ct = count($rates);
$c += $ct;
$s += $ct * $rate;
$ss += $ct * $rate * $rate;
foreach($rates as $id_date)
{
$dev = abs($rate - $all_img_sum[$id_date['id']]['avg']);
$consensus_dev += $dev;
if (isset($best_rated[$id_date['id']]))
{
$consensus_dev_top += $dev;
$consensus_dev_top_count++;
}
}
}
$consensus_dev /= $c;
if ($consensus_dev_top_count)
$consensus_dev_top /= $consensus_dev_top_count;
$var = ($ss - $s*$s/$c)/$c;
$rating += array(
'id' => $id,
'count' => $c,
'avg' => $s/$c,
'cv' => $s==0 ? -1 : sqrt($var)/($s/$c), // http://en.wikipedia.org/wiki/Coefficient_of_variation
'cd' => $consensus_dev,
'cdtop' => $consensus_dev_top_count ? $consensus_dev_top : '',
);
}
unset($rating);
// filter
foreach($by_user_ratings as $id => $rating)
{
if ($rating['count'] <= $filter_min_rates)
{
unset($by_user_ratings[$id]);
}
}
function avg_compare($a, $b)
{
$d = $a['avg'] - $b['avg'];
return ($d==0) ? 0 : ($d<0 ? -1 : 1);
}
function count_compare($a, $b)
{
$d = $a['count'] - $b['count'];
return ($d==0) ? 0 : ($d<0 ? -1 : 1);
}
function cv_compare($a, $b)
{
$d = $b['cv'] - $a['cv']; //desc
return ($d==0) ? 0 : ($d<0 ? -1 : 1);
}
function consensus_dev_compare($a, $b)
{
$d = $b['cd'] - $a['cd']; //desc
return ($d==0) ? 0 : ($d<0 ? -1 : 1);
}
function last_rate_compare($a, $b)
{
return -strcmp( $a['last_date'], $b['last_date']);
}
$order_by_index=4;
if (isset($_GET['order_by']) and is_numeric($_GET['order_by']))
{
$order_by_index = $_GET['order_by'];
}
$available_order_by= array(
array(l10n('Average rate'), 'avg_compare'),
array(l10n('Number of rates'), 'count_compare'),
array(l10n('Variation'), 'cv_compare'),
array(l10n('Consensus deviation'), 'consensus_dev_compare'),
array(l10n('Last'), 'last_rate_compare'),
);
for ($i=0; $i<count($available_order_by); $i++)
{
$template->append(
'order_by_options',
$available_order_by[$i][0]
);
}
$template->assign('order_by_options_selected', array($order_by_index) );
$x = uasort($by_user_ratings, $available_order_by[$order_by_index][1] );
$query = '
SELECT
COUNT(*)
FROM '.RATE_TABLE.
';';
list($nb_elements) = pwg_db_fetch_row(pwg_query($query));
$template->assign( array(
'F_ACTION' => get_root_url().'admin.php',
'F_MIN_RATES' => $filter_min_rates,
'CONSENSUS_TOP_NUMBER' => $consensus_top_number,
'available_rates' => $conf['rate_items'],
'ratings' => $by_user_ratings,
'image_urls' => $image_urls,
'TN_WIDTH' => ImageStdParams::get_by_type(IMG_SQUARE)->sizing->ideal_size[0],
'NB_ELEMENTS' => $nb_elements,
'ADMIN_PAGE_TITLE' => l10n('Rating'),
));
$template->set_filename('rating', 'rating_user.tpl');
$template->assign_var_from_handle('ADMIN_CONTENT', 'rating');
?>
@@ -0,0 +1,185 @@
<?php
// +-----------------------------------------------------------------------+
// | This file is part of Piwigo. |
// | |
// | For copyright and license information, please view the COPYING.txt |
// | file that was distributed with this source code. |
// +-----------------------------------------------------------------------+
if (!defined('PHPWG_ROOT_PATH'))
{
die ("Hacking attempt!");
}
include_once(PHPWG_ROOT_PATH.'admin/include/functions.php');
// +-----------------------------------------------------------------------+
// | Check Access and exit when user status is not ok |
// +-----------------------------------------------------------------------+
if (!$conf['enable_synchronization'])
{
die('synchronization is disabled');
}
check_status(ACCESS_ADMINISTRATOR);
if (!empty($_POST) or isset($_GET['action']))
{
check_pwg_token();
}
// +-----------------------------------------------------------------------+
// | template init |
// +-----------------------------------------------------------------------+
$template->set_filenames(array('site_manager'=>'site_manager.tpl'));
// +-----------------------------------------------------------------------+
// | tabs |
// +-----------------------------------------------------------------------+
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('site_update');
$tabsheet->select('site_maager');
$tabsheet->assign();
// +-----------------------------------------------------------------------+
// | new site creation form |
// +-----------------------------------------------------------------------+
if (isset($_POST['submit']) and !empty($_POST['galleries_url']))
{
$is_remote = url_is_remote( $_POST['galleries_url'] );
if ($is_remote)
{
fatal_error('remote sites not supported');
}
$url = preg_replace('/[\/]*$/', '', $_POST['galleries_url']);
$url.= '/';
if ( ! (strpos($url, '.') === 0 ) )
{
$url = './' . $url;
}
// site must not exists
$query = '
SELECT COUNT(id) AS count
FROM '.SITES_TABLE.'
WHERE galleries_url = \''.$url.'\'
;';
$row = pwg_db_fetch_assoc(pwg_query($query));
if ($row['count'] > 0)
{
$page['errors'][] = l10n('This site already exists').' ['.$url.']';
}
if (count($page['errors']) == 0)
{
if ( ! file_exists($url) )
{
$page['errors'][] = l10n('Directory does not exist').' ['.$url.']';
}
}
if (count($page['errors']) == 0)
{
$query = '
INSERT INTO '.SITES_TABLE.'
(galleries_url)
VALUES
(\''.$url.'\')
;';
pwg_query($query);
$page['infos'][] = $url.' '.l10n('created');
}
}
// +-----------------------------------------------------------------------+
// | actions on site |
// +-----------------------------------------------------------------------+
if (isset($_GET['site']) and is_numeric($_GET['site']))
{
$page['site'] = $_GET['site'];
}
if (isset($_GET['action']) and isset($page['site']))
{
$query = '
SELECT galleries_url
FROM '.SITES_TABLE.'
WHERE id = '.$page['site'].'
;';
list($galleries_url) = pwg_db_fetch_row(pwg_query($query));
switch($_GET['action'])
{
case 'delete' :
{
delete_site($page['site']);
$page['infos'][] = $galleries_url.' '.l10n('deleted');
break;
}
}
}
$template->assign(
array(
'F_ACTION' => get_root_url().'admin.php'.get_query_string_diff(array('action','site','pwg_token')),
'PWG_TOKEN' => get_pwg_token(),
'ADMIN_PAGE_TITLE' => l10n('Synchronize'),
)
);
$query = '
SELECT c.site_id, COUNT(DISTINCT c.id) AS nb_categories, COUNT(i.id) AS nb_images
FROM '.CATEGORIES_TABLE.' AS c LEFT JOIN '.IMAGES_TABLE.' AS i
ON c.id=i.storage_category_id
WHERE c.site_id IS NOT NULL
GROUP BY c.site_id
;';
$sites_detail = hash_from_query($query, 'site_id');
$query = '
SELECT *
FROM '.SITES_TABLE.'
;';
$result = pwg_query($query);
while ($row = pwg_db_fetch_assoc($result))
{
$is_remote = url_is_remote($row['galleries_url']);
$base_url = PHPWG_ROOT_PATH.'admin.php';
$base_url.= '?page=site_manager';
$base_url.= '&amp;site='.$row['id'];
$base_url.= '&amp;pwg_token='.get_pwg_token();
$base_url.= '&amp;action=';
$update_url = PHPWG_ROOT_PATH.'admin.php';
$update_url.= '?page=site_update';
$update_url.= '&amp;site='.$row['id'];
$tpl_var =
array(
'NAME' => $row['galleries_url'],
'TYPE' => l10n( $is_remote ? 'Remote' : 'Local' ),
'CATEGORIES' => (int)@$sites_detail[$row['id']]['nb_categories'],
'IMAGES' => (int)@$sites_detail[$row['id']]['nb_images'],
'U_SYNCHRONIZE' => $update_url
);
if ($row['id'] != 1)
{
$tpl_var['U_DELETE'] = $base_url.'delete';
}
$plugin_links = array();
//$plugin_links is array of array composed of U_HREF, U_HINT & U_CAPTION
$plugin_links =
trigger_change('get_admins_site_links',
$plugin_links, $row['id'], $is_remote);
$tpl_var['plugin_links'] = $plugin_links;
$template->append('sites', $tpl_var);
}
$template->assign_var_from_handle('ADMIN_CONTENT', 'site_manager');
?>
@@ -0,0 +1,197 @@
<?php
// +-----------------------------------------------------------------------+
// | This file is part of Piwigo. |
// | |
// | For copyright and license information, please view the COPYING.txt |
// | file that was distributed with this source code. |
// +-----------------------------------------------------------------------+
// provides data for site synchronization from the local file system
class LocalSiteReader
{
var $site_url;
function __construct($url)
{
$this->site_url = $url;
global $conf;
if (!isset($conf['flip_file_ext']))
{
$conf['flip_file_ext'] = array_flip($conf['file_ext']);
}
if (!isset($conf['flip_picture_ext']))
{
$conf['flip_picture_ext'] = array_flip($conf['picture_ext']);
}
}
/**
* Is this local site ok ?
*
* @return true on success, false otherwise
*/
function open()
{
global $errors;
if (!is_dir($this->site_url))
{
$errors[] = array(
'path' => $this->site_url,
'type' => 'PWG-ERROR-NO-FS'
);
return false;
}
return true;
}
// retrieve file system sub-directories fulldirs
function get_full_directories($basedir)
{
$fs_fulldirs = get_fs_directories($basedir);
return $fs_fulldirs;
}
/**
* Returns an array with all file system files according to $conf['file_ext']
* and $conf['picture_ext']
* @param string $path recurse in this directory
* @return array like "pic.jpg"=>array('representative_ext'=>'jpg' ... )
*/
function get_elements($path)
{
global $conf;
$subdirs = array();
$fs = array();
if (is_dir($path) && $contents = opendir($path) )
{
while (($node = readdir($contents)) !== false)
{
if ($node == '.' or $node == '..') continue;
if (is_file($path.'/'.$node))
{
$extension = strtolower(get_extension($node));
$filename_wo_ext = get_filename_wo_extension($node);
if ( isset($conf['flip_file_ext'][$extension]) )
{
$representative_ext = null;
if (! isset($conf['flip_picture_ext'][$extension]) )
{
$representative_ext = $this->get_representative_ext($path, $filename_wo_ext);
}
$fs[ $path.'/'.$node ] = array('representative_ext' => $representative_ext);
if ($conf['enable_formats'])
{
$fs[ $path.'/'.$node ]['formats'] = $this->get_formats($path, $filename_wo_ext);
}
}
}
else if (is_dir($path.'/'.$node)
and $node != 'pwg_high'
and $node != 'pwg_representative'
and $node != 'pwg_format'
and $node != 'thumbnail' )
{
$subdirs[] = $node;
}
} //end while readdir
closedir($contents);
foreach ($subdirs as $subdir)
{
$tmp_fs = $this->get_elements($path.'/'.$subdir);
$fs = array_merge($fs, $tmp_fs);
}
ksort($fs);
} //end if is_dir
return $fs;
}
// returns the name of the attributes that are supported for
// files update/synchronization
function get_update_attributes()
{
return array('representative_ext');
}
function get_element_update_attributes($file)
{
global $conf;
$data = array();
$filename = basename($file);
$extension = get_extension($filename);
$representative_ext = null;
if (! isset($conf['flip_picture_ext'][$extension]) )
{
$dirname = dirname($file);
$filename_wo_ext = get_filename_wo_extension($filename);
$representative_ext = $this->get_representative_ext($dirname, $filename_wo_ext);
}
$data['representative_ext'] = $representative_ext;
return $data;
}
// returns the name of the attributes that are supported for
// metadata update/synchronization according to configuration
function get_metadata_attributes()
{
return get_sync_metadata_attributes();
}
// returns a hash of attributes (metadata+filesize+width,...) for file
function get_element_metadata($infos)
{
return get_sync_metadata($infos);
}
//-------------------------------------------------- private functions --------
function get_representative_ext($path, $filename_wo_ext)
{
global $conf;
$base_test = $path.'/pwg_representative/'.$filename_wo_ext.'.';
foreach ($conf['picture_ext'] as $ext)
{
$test = $base_test.$ext;
if (is_file($test))
{
return $ext;
}
}
return null;
}
function get_formats($path, $filename_wo_ext)
{
global $conf;
$formats = array();
$base_test = $path.'/pwg_format/'.$filename_wo_ext.'.';
foreach ($conf['format_ext'] as $ext)
{
$test = $base_test.$ext;
if (is_file($test))
{
$formats[$ext] = floor(filesize($test) / 1024);
}
}
return $formats;
}
}
?>
File diff suppressed because it is too large Load Diff
+399
View File
@@ -0,0 +1,399 @@
<?php
// +-----------------------------------------------------------------------+
// | This file is part of Piwigo. |
// | |
// | For copyright and license information, please view the COPYING.txt |
// | file that was distributed with this source code. |
// +-----------------------------------------------------------------------+
if (!defined('PHPWG_ROOT_PATH'))
{
die ('Hacking attempt!');
}
include_once(PHPWG_ROOT_PATH.'admin/include/functions.php');
include_once(PHPWG_ROOT_PATH.'admin/include/functions_history.inc.php');
// +-----------------------------------------------------------------------+
// | Functions |
// +-----------------------------------------------------------------------+
//Get the last unit of time for years, months, days and hours
function get_last($last_number=60, $type='year')
{
$query = '
SELECT
year,
month,
day,
hour,
nb_pages
FROM '.HISTORY_SUMMARY_TABLE;
if ($type === 'hour')
{
$query.= '
WHERE year IS NOT NULL
AND month IS NOT NULL
AND day IS NOT NULL
AND hour IS NOT NULL
ORDER BY
year DESC,
month DESC,
day DESC,
hour DESC
LIMIT '.$last_number.'
;';
}
elseif ($type === 'day')
{
$query.= '
WHERE year IS NOT NULL
AND month IS NOT NULL
AND day IS NOT NULL
AND hour IS NULL
ORDER BY
year DESC,
month DESC,
day DESC
LIMIT '.$last_number.'
;';
}
elseif ($type === 'month')
{
$query.= '
WHERE year IS NOT NULL
AND month IS NOT NULL
AND day IS NULL
ORDER BY
year DESC,
month DESC
LIMIT '.$last_number.'
;';
}
else
{
$query.= '
WHERE year IS NOT NULL
AND month IS NULL
ORDER BY
year DESC
LIMIT '.$last_number.'
;';
}
$result = pwg_query($query);
$output = array();
while ($row = pwg_db_fetch_assoc($result))
{
$output[] = $row;
}
return $output;
}
function get_month_of_last_years ($last = 'all')
{
$query = '
SELECT
year,
month,
day,
hour,
nb_pages
FROM '.HISTORY_SUMMARY_TABLE.'
WHERE month IS NOT NULL
AND day IS NULL
ORDER BY
year DESC,
month DESC';
if ($last !== 'all')
{
$date = new DateTime();
$limit = ($last - 1)*12+$date->format('n') - 1;
$query .=
' LIMIT '.$limit;
$result = query2array($query.';');
$lastDate = $date->sub(new DateInterval('P'.($last - 1).'Y'.($date->format('n') - 1).'M'));
return set_missing_values('month', $result, $lastDate, new DateTime());
}
if (count(query2array($query.';')) > 1 )
{
return set_missing_values('month', query2array($query.';'));
} else {
$last_year_date = new DateTime();
return set_missing_values(
'month',
query2array($query.';'),
$last_year_date->sub(new DateInterval('P1Y')),
new DateTime()
);
}
}
function get_month_stats()
{
$result = array();
$date = new DateTime();
$date_last_month = clone $date;
$date_last_year = clone $date;
$months = array();
$date_last_month->sub(new DateInterval('P1M'));
$date_last_year->sub(new DateInterval('P1Y'));
$query = '
SELECT
year,
month,
day,
hour,
nb_pages
FROM '.HISTORY_SUMMARY_TABLE.'
WHERE
(
(year = '.$date->format('Y').' AND month = '.$date->format('n').')
OR (year = '.$date_last_month->format('Y').' AND month = '.$date_last_month->format('n').')
OR (year = '.$date_last_year->format('Y').' AND month = '.$date_last_year->format('n').')
)
AND day IS NOT NULL
AND hour IS NULL
ORDER BY
year DESC,
month DESC
;';
foreach (query2array($query) as $value)
{
$date = get_date_object($value);
@$months[$date->format('Y/m/1')][] = $value;
}
$actual_date = new DateTime();
if (!isset($months[$actual_date->format('Y/m/1')]))
{
@$months[$actual_date->format('Y/m/1')][] = array(
'year' => $actual_date->format('Y'),
'month'=> $actual_date->format('n'),
'day'=> null,
'hour'=> null,
'nb_pages' => 0
);
}
foreach ($months as $key => $val)
{
$lastDate = new DateTime($key);
$lastDate = $lastDate->add(new DateInterval('P1M'));
$lastDate = $lastDate->sub(new DateInterval('P1D'));
if ($lastDate > new DateTime())
{
$lastDate = new DateTime();
}
$result['month'][] = set_missing_values('day',$val, new DateTime($key), $lastDate);
}
$query = '
SELECT
AVG(nb_pages)
FROM '.HISTORY_SUMMARY_TABLE.'
WHERE
(
year = '.$date->format('Y').' OR
(year = '.($date->format('Y')-1).' and month > '.$date->format('n').')
)
AND day IS NOT NULL
AND hour IS NULL
ORDER BY
year DESC,
month DESC
;';
list($result['avg']) = pwg_db_fetch_row(pwg_query($query));
return $result;
}
// +-----------------------------------------------------------------------+
// | Check Access and exit when user status is not ok |
// +-----------------------------------------------------------------------+
check_status(ACCESS_ADMINISTRATOR);
// +-----------------------------------------------------------------------+
// | Refresh summary from details |
// +-----------------------------------------------------------------------+
history_summarize();
// +-----------------------------------------------------------------------+
// | Display statistics header |
// +-----------------------------------------------------------------------+
$template->set_filename('stats', 'stats.tpl');
// TabSheet initialization
history_tabsheet();
$base_url = get_root_url().'admin.php?page=history';
$template->assign(
array(
'U_HELP' => get_root_url().'admin/popuphelp.php?page=history',
'F_ACTION' => $base_url,
)
);
// +-----------------------------------------------------------------------+
// | Set missing rows to 0 |
// +-----------------------------------------------------------------------+
function set_missing_values($unit, $data, $firstDate = null, $lastDate = null)
{
$limit = count($data);
$result = array();
if ($firstDate == null)
{
$date = get_date_object($data[count($data) - 1]);
} else {
$date = $firstDate;
}
if ($lastDate == null)
{
$date_end = get_date_object($data[0]);
} else {
$date_end = $lastDate;
}
//Declare variable according the unit
if ($unit == 'year')
{
$date_format = 'Y';
$date_add = 'P1Y';
}
else if ($unit == 'month')
{
$date_format = 'Y-m';
$date_add = 'P1M';
}
else if ($unit == 'day')
{
$date_format = 'Y-m-d';
$date_add = 'P1D';
}
else if ($unit == 'hour')
{
$date_format = 'Y-m-d\TH:00';
$date_add = 'PT1H';
}
//Fill an empty array with all the dates
while ($date <= $date_end) {
$result[$date->format($date_format)] = 0;
$date->add(new DateInterval($date_add));
}
//Overload with database rows
foreach ($data as $value)
{
$str = get_date_object($value)->format($date_format);
if (isset($result[$str]))
{
$result[$str] += $value['nb_pages'];
}
}
return $result;
}
//Get a DateTime object for a database row
function get_date_object($row)
{
$date_string = $row['year'];
if ($row['month'] != null)
{
$date_string = $date_string.'-'.$row['month'] ;
if ($row['day'] != null)
{
$date_string = $date_string.'-'.$row['day'];
if ($row['hour'] != null)
{
$date_string = $date_string.' '.$row['hour'].':00';
}
}
}
else
{
$date_string .= '-1';
}
return new DateTime($date_string);
}
// +-----------------------------------------------------------------------+
// | Send data to template |
// +-----------------------------------------------------------------------+
$actual_date = new DateTime();
$actual_date->add(new DateInterval('PT1S'));
$first_date = new DateTime();
$last_hours = set_missing_values(
'hour',
get_last(72, 'hour'),
$first_date->sub(new DateInterval("P3D")),
$actual_date
);
$first_date = new DateTime();
$last_days = set_missing_values(
'day',
get_last(90, 'day'),
$first_date->sub(new DateInterval("P90D")),
$actual_date
);
$first_date = new DateTime();
$last_months = set_missing_values(
'month',
get_last(60, 'month'),
$first_date->sub(new DateInterval("P60M")),
$actual_date
);
if (count(get_last(60, 'year')) > 1 )
{
$last_years = set_missing_values(
'year',
get_last(60, 'year')
);
} else {
$last_year_date = new DateTime();
$last_years = set_missing_values(
'year',
get_last(60, 'year'),
$last_year_date->sub(new DateInterval('P1Y')),
new DateTime()
);
}
ksort($lang['month']);
$template->assign(array(
'compareYears' => get_month_of_last_years($conf['stat_compare_year_displayed']),
'monthStats' => get_month_stats(),
'lastHours' => $last_hours,
'lastDays' => $last_days,
'lastMonths' => $last_months,
'lastYears' => $last_years,
'langCode' => strval($user['language']),
'month_labels' => join('~', $lang['month']),
'ADMIN_PAGE_TITLE' => l10n('History'),
));
$template->assign_var_from_handle('ADMIN_CONTENT', 'stats');
?>
+165
View File
@@ -0,0 +1,165 @@
<?php
// +-----------------------------------------------------------------------+
// | This file is part of Piwigo. |
// | |
// | For copyright and license information, please view the COPYING.txt |
// | file that was distributed with this source code. |
// +-----------------------------------------------------------------------+
if( !defined("PHPWG_ROOT_PATH") )
{
die ("Hacking attempt!");
}
include_once(PHPWG_ROOT_PATH.'admin/include/functions.php');
check_status(ACCESS_ADMINISTRATOR);
// +-----------------------------------------------------------------------+
// | tabs |
// +-----------------------------------------------------------------------+
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('tags');
$tabsheet->select('');
$tabsheet->assign();
// +-----------------------------------------------------------------------+
// | delete orphan tags |
// +-----------------------------------------------------------------------+
if (isset($_GET['action']) and 'delete_orphans' == $_GET['action'])
{
check_pwg_token();
delete_orphan_tags();
$_SESSION['message_tags'] = l10n('Orphan tags deleted');
redirect(get_root_url().'admin.php?page=tags');
}
// +-----------------------------------------------------------------------+
// | template init |
// +-----------------------------------------------------------------------+
$template->set_filenames(array('tags' => 'tags.tpl'));
$template->assign(
array(
'F_ACTION' => PHPWG_ROOT_PATH.'admin.php?page=tags',
'PWG_TOKEN' => get_pwg_token(),
)
);
// +-----------------------------------------------------------------------+
// | orphan tags |
// +-----------------------------------------------------------------------+
$warning_tags = "";
$orphan_tags = get_orphan_tags();
$orphan_tag_names_array = '[]';
$orphan_tag_names = array();
foreach ($orphan_tags as $tag)
{
$orphan_tag_names[] = trigger_change('render_tag_name', $tag['name'], $tag);
}
if (count($orphan_tag_names) > 0)
{
$warning_tags = sprintf(
l10n('You have %d orphan tags %s'),
count($orphan_tag_names),
'<a
class="icon-eye"
data-url="'.get_root_url().'admin.php?page=tags&amp;action=delete_orphans&amp;pwg_token='.get_pwg_token().'">'
.l10n('Review').'</a>'
);
$orphan_tag_names_array = '["';
$orphan_tag_names_array.= implode(
'" ,"',
array_map(
'htmlentities',
$orphan_tag_names,
array_fill(0 , count($orphan_tag_names) , ENT_QUOTES)
)
);
$orphan_tag_names_array.= '"]';
}
$template->assign(
array(
'orphan_tag_names_array' => $orphan_tag_names_array,
'warning_tags' => $warning_tags,
)
);
$message_tags = '';
if (isset($_SESSION['message_tags']))
{
$message_tags = $_SESSION['message_tags'];
unset($_SESSION['message_tags']);
}
$template->assign('message_tags', $message_tags);
// +-----------------------------------------------------------------------+
// | form creation |
// +-----------------------------------------------------------------------+
$per_page = 100;
// tag counters
$query = '
SELECT tag_id, COUNT(image_id) AS counter
FROM '.IMAGE_TAG_TABLE.'
GROUP BY tag_id';
$tag_counters = simple_hash_from_query($query, 'tag_id', 'counter');
// all tags
$query = '
SELECT name, id, url_name
FROM '.TAGS_TABLE.'
;';
$result = pwg_query($query);
$all_tags = array();
while ($tag = pwg_db_fetch_assoc($result))
{
$raw_name = $tag['name'];
$tag['raw_name'] = $raw_name;
$tag['name'] = trigger_change('render_tag_name', $raw_name, $tag);
$counter = intval(@$tag_counters[ $tag['id'] ]);
if ($counter > 0)
{
$tag['counter'] = intval(@$tag_counters[ $tag['id'] ]);
}
$alt_names = trigger_change('get_tag_alt_names', array(), $raw_name);
$alt_names = array_diff( array_unique($alt_names), array($tag['name']) );
if (count($alt_names))
{
$tag['alt_names'] = implode(', ', $alt_names);
}
$all_tags[] = $tag;
}
usort($all_tags, 'tag_alpha_compare');
$template->assign(
array(
'first_tags' => array_slice($all_tags, 0, $per_page),
'data' => $all_tags,
'total' => count($all_tags),
'per_page' => $per_page,
'ADMIN_PAGE_TITLE' => l10n('Tags'),
)
);
// +-----------------------------------------------------------------------+
// | sending html code |
// +-----------------------------------------------------------------------+
$template->assign_var_from_handle('ADMIN_CONTENT', 'tags');
?>
@@ -0,0 +1,38 @@
<?php
// +-----------------------------------------------------------------------+
// | This file is part of Piwigo. |
// | |
// | For copyright and license information, please view the COPYING.txt |
// | file that was distributed with this source code. |
// +-----------------------------------------------------------------------+
if( !defined("PHPWG_ROOT_PATH") )
{
die ("Hacking attempt!");
}
include_once(PHPWG_ROOT_PATH.'admin/include/functions.php');
check_status(ACCESS_ADMINISTRATOR);
if (empty($_GET['theme']))
{
die('Invalid theme URL');
}
include_once(PHPWG_ROOT_PATH.'admin/include/themes.class.php');
$themes = new themes();
if (!in_array($_GET['theme'], array_keys($themes->fs_themes)))
{
die('Invalid theme');
}
$filename = PHPWG_THEMES_PATH.$_GET['theme'].'/admin/admin.inc.php';
if (is_file($filename))
{
include_once($filename);
}
else
{
die('Missing file '.$filename);
}
?>
@@ -0,0 +1,36 @@
<?php
// +-----------------------------------------------------------------------+
// | This file is part of Piwigo. |
// | |
// | For copyright and license information, please view the COPYING.txt |
// | file that was distributed with this source code. |
// +-----------------------------------------------------------------------+
if( !defined("PHPWG_ROOT_PATH") )
{
die ("Hacking attempt!");
}
include_once(PHPWG_ROOT_PATH.'admin/include/tabsheet.class.php');
$my_base_url = get_root_url().'admin.php?page=themes';
if (isset($_GET['tab']))
$page['tab'] = $_GET['tab'];
else
$page['tab'] = 'installed';
$tabsheet = new tabsheet();
$tabsheet->set_id('themes');
$tabsheet->select($page['tab']);
$tabsheet->assign();
if ($page['tab'] == 'update') {
include(PHPWG_ROOT_PATH.'admin/updates_ext.php');
$template->assign('ADMIN_PAGE_TITLE', l10n('Themes'));
}
else
{
include(PHPWG_ROOT_PATH.'admin/themes_'.$page['tab'].'.php');
}
?>
Binary file not shown.

After

Width:  |  Height:  |  Size: 249 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 367 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 965 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 585 B

Some files were not shown because too many files have changed in this diff Show More