diff --git a/.gitignore b/.gitignore new file mode 100644 index 000000000..85a9ffbca --- /dev/null +++ b/.gitignore @@ -0,0 +1,19 @@ +# Piwigo specific directories +/_data +/plugins/* +!/plugins/index.php +/upload +/galleries/* +!/galleries/index.php +/local/* +!/local/**/index.php + +# IntelliJ +.idea +*.iml +*.ipr +*.iws + +# Eclipse +.settings +.project \ No newline at end of file diff --git a/LICENSE.txt b/LICENSE.txt new file mode 100644 index 000000000..d159169d1 --- /dev/null +++ b/LICENSE.txt @@ -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. + + + Copyright (C) + + 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. + + , 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. diff --git a/README.md b/README.md new file mode 100644 index 000000000..673fc966a --- /dev/null +++ b/README.md @@ -0,0 +1,52 @@ +[![Piwigo](http://piwigo.org/screenshots/logos/piwigo@280.png)](http://piwigo.org) +--------- + +Piwigo is photo gallery software for the web, built by an active community of users and developers. + +Extensions make Piwigo easily customizable. Icing on the cake, Piwigo is free and open source. + +![screenshot](http://piwigo.org/screenshots/github-screenshot.jpg) + + * [piwigo.org](http://piwigo.org) + * [Demo](http://piwigo.org/demo) + * [Downloads](http://piwigo.org/basics/downloads) + * [User guide](http://piwigo.org/doc) + * [Plugins and themes](http://piwigo.org/ext) + * [Forum](http://piwigo.org/forum) + * [News](http://piwigo.org/news) + +## Requirements + + * A webserver (Apache or nginx recommended) + * PHP 5.2 or greater + * MySQL 5 or greater or MariaDB equivalent + * ImageMagick (recommended) or PHP GD + +## Quick start install + +### NetInstall + + * Download the [NetInstall script](http://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](http://piwigo.org/basics/installation_netinstall) + +### Manual + + * Download the [latest stable version](http://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](http://piwigo.org/basics/installation_manual) + +If you do not have your own server, consider the [piwigo.com](http://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. + +## License + +Piwigo is released under the GPL v2 license. + diff --git a/about.php b/about.php index 9f6318d16..6bd853a02 100644 --- a/about.php +++ b/about.php @@ -2,7 +2,7 @@ // +-----------------------------------------------------------------------+ // | Piwigo - a PHP based photo gallery | // +-----------------------------------------------------------------------+ -// | Copyright(C) 2008-2014 Piwigo Team http://piwigo.org | +// | Copyright(C) 2008-2016 Piwigo Team http://piwigo.org | // | Copyright(C) 2003-2008 PhpWebGallery Team http://phpwebgallery.net | // | Copyright(C) 2002-2003 Pierrick LE GALL http://le-gall.net/pierrick | // +-----------------------------------------------------------------------+ diff --git a/action.php b/action.php index 4b92e056c..33ae408ed 100644 --- a/action.php +++ b/action.php @@ -2,7 +2,7 @@ // +-----------------------------------------------------------------------+ // | Piwigo - a PHP based photo gallery | // +-----------------------------------------------------------------------+ -// | Copyright(C) 2008-2014 Piwigo Team http://piwigo.org | +// | Copyright(C) 2008-2016 Piwigo Team http://piwigo.org | // | Copyright(C) 2003-2008 PhpWebGallery Team http://phpwebgallery.net | // | Copyright(C) 2002-2003 Pierrick LE GALL http://le-gall.net/pierrick | // +-----------------------------------------------------------------------+ @@ -57,11 +57,34 @@ function do_error( $code, $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') ) ) + or !in_array($_GET['part'], array('e','r','f') ) ) { do_error(400, 'Invalid request - id/part'); } @@ -116,6 +139,10 @@ switch ($_GET['part']) 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) ) @@ -130,6 +157,10 @@ else if ($_GET['part'] == 'e') { pwg_log($_GET['id'], 'other'); } +else if ($_GET['part'] == 'f') +{ + pwg_log($_GET['id'], 'high', $format['format_id']); +} $http_headers = array(); @@ -155,7 +186,7 @@ if (!url_is_remote($file)) // HTTP/1.1 only $http_headers[] = 'Cache-Control: private, must-revalidate, max-age='.$max_age;*/ - if ( isset( $_SERVER['HTTP_IF_MODIFIED_SINCE'] ) ) + if ('f' != $_GET['part'] and isset( $_SERVER['HTTP_IF_MODIFIED_SINCE'] ) ) { set_status_header(304); foreach ($http_headers as $header) diff --git a/admin.php b/admin.php index 213f33b75..ac89babdd 100644 --- a/admin.php +++ b/admin.php @@ -2,7 +2,7 @@ // +-----------------------------------------------------------------------+ // | Piwigo - a PHP based photo gallery | // +-----------------------------------------------------------------------+ -// | Copyright(C) 2008-2014 Piwigo Team http://piwigo.org | +// | Copyright(C) 2008-2016 Piwigo Team http://piwigo.org | // | Copyright(C) 2003-2008 PhpWebGallery Team http://phpwebgallery.net | // | Copyright(C) 2002-2003 Pierrick LE GALL http://le-gall.net/pierrick | // +-----------------------------------------------------------------------+ @@ -240,6 +240,19 @@ if ($nb_photos_in_caddie > 0) ); } +// any orphan photo? +$nb_orphans = count(get_orphans()); + +if ($nb_orphans > 0) +{ + $template->assign( + array( + 'NB_ORPHANS' => $nb_orphans, + 'U_ORPHANS' => $link_start.'batch_manager&filter=prefilter-no_album', + ) + ); +} + // +-----------------------------------------------------------------------+ // | Plugin menu | // +-----------------------------------------------------------------------+ diff --git a/admin/album.php b/admin/album.php index d1186aae1..f5e692a9f 100644 --- a/admin/album.php +++ b/admin/album.php @@ -2,7 +2,7 @@ // +-----------------------------------------------------------------------+ // | Piwigo - a PHP based photo gallery | // +-----------------------------------------------------------------------+ -// | Copyright(C) 2008-2014 Piwigo Team http://piwigo.org | +// | Copyright(C) 2008-2016 Piwigo Team http://piwigo.org | // | Copyright(C) 2003-2008 PhpWebGallery Team http://phpwebgallery.net | // | Copyright(C) 2002-2003 Pierrick LE GALL http://le-gall.net/pierrick | // +-----------------------------------------------------------------------+ diff --git a/admin/album_notification.php b/admin/album_notification.php index cafaad170..fb2a1b027 100644 --- a/admin/album_notification.php +++ b/admin/album_notification.php @@ -2,7 +2,7 @@ // +-----------------------------------------------------------------------+ // | Piwigo - a PHP based photo gallery | // +-----------------------------------------------------------------------+ -// | Copyright(C) 2008-2014 Piwigo Team http://piwigo.org | +// | Copyright(C) 2008-2016 Piwigo Team http://piwigo.org | // | Copyright(C) 2003-2008 PhpWebGallery Team http://phpwebgallery.net | // | Copyright(C) 2002-2003 Pierrick LE GALL http://le-gall.net/pierrick | // +-----------------------------------------------------------------------+ @@ -46,7 +46,7 @@ $page['cat'] = $category['id']; // +-----------------------------------------------------------------------+ // info by email to an access granted group of category informations -if (isset($_POST['submitEmail']) and !empty($_POST['group'])) +if (isset($_POST['submitEmail'])) { set_make_full_url(); @@ -54,6 +54,8 @@ if (isset($_POST['submitEmail']) and !empty($_POST['group'])) is empty find child representative_picture_id */ if (!empty($category['representative_picture_id'])) { + $img = array(); + $query = ' SELECT id, file, path, representative_ext FROM '.IMAGES_TABLE.' @@ -65,56 +67,124 @@ SELECT id, file, path, representative_ext { $element = pwg_db_fetch_assoc($result); - $img_url = ''; + $img = array( + 'link' => make_picture_url( + array( + 'image_id' => $element['id'], + 'image_file' => $element['file'], + 'category' => $category + ) + ), + 'src' => DerivativeImage::url(IMG_THUMB, $element), + ); } } - if (!isset($img_url)) - { - $img_url = ''; - } - - pwg_mail_group( - $_POST['group'], - 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' => .... - ), - array( - 'filename' => 'cat_group_info', - 'assign' => array( - 'IMG_URL' => $img_url, - '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']), - ) + $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']), ) ); - unset_make_full_url(); + if ('users' == $_POST['who'] and isset($_POST['users']) and count($_POST['users']) > 0) + { + check_input_parameter('users', $_POST, true, PATTERN_ID); - $query = ' + // 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)) + { + $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).')'; + + $page['infos'][] = $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)); + list($group_name) = pwg_db_fetch_row(pwg_query($query)); - $page['infos'][] = l10n('An information email was sent to group "%s"', $group_name); + $page['infos'][] = l10n('An information email was sent to group "%s"', $group_name); + } + + unset_make_full_url(); } // +-----------------------------------------------------------------------+ @@ -135,6 +205,19 @@ $template->assign( ) ); +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 | // +-----------------------------------------------------------------------+ @@ -189,6 +272,64 @@ SELECT } } +// 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 | // +-----------------------------------------------------------------------+ diff --git a/admin/batch_manager.php b/admin/batch_manager.php index 257b11bb9..e81c59f0a 100644 --- a/admin/batch_manager.php +++ b/admin/batch_manager.php @@ -2,7 +2,7 @@ // +-----------------------------------------------------------------------+ // | Piwigo - a PHP based photo gallery | // +-----------------------------------------------------------------------+ -// | Copyright(C) 2008-2014 Piwigo Team http://piwigo.org | +// | Copyright(C) 2008-2016 Piwigo Team http://piwigo.org | // | Copyright(C) 2003-2008 PhpWebGallery Team http://phpwebgallery.net | // | Copyright(C) 2002-2003 Pierrick LE GALL http://le-gall.net/pierrick | // +-----------------------------------------------------------------------+ @@ -63,6 +63,21 @@ DELETE FROM '.CADDIE_TABLE.' redirect(get_root_url().'admin.php?page='.$_GET['page']); } + + if ('delete_orphans' == $_GET['action']) + { + $deleted_count = delete_elements(get_orphans(), true); + + if ($deleted_count > 0) + { + $_SESSION['page_infos'][] = l10n_dec( + '%d photo was deleted', '%d photos were deleted', + $deleted_count + ); + + redirect(get_root_url().'admin.php?page='.$_GET['page']); + } + } } // +-----------------------------------------------------------------------+ @@ -323,15 +338,7 @@ SELECT id break; case 'no_album': - $query = ' -SELECT - id - FROM '.IMAGES_TABLE.' - LEFT JOIN '.IMAGE_CATEGORY_TABLE.' ON id = image_id - WHERE category_id is null -;'; - $filter_sets[] = query2array($query, null, 'id'); - + $filter_sets[] = get_orphans(); break; case 'no_tag': diff --git a/admin/batch_manager_global.php b/admin/batch_manager_global.php index 4179ed284..ba3944abe 100644 --- a/admin/batch_manager_global.php +++ b/admin/batch_manager_global.php @@ -2,7 +2,7 @@ // +-----------------------------------------------------------------------+ // | Piwigo - a PHP based photo gallery | // +-----------------------------------------------------------------------+ -// | Copyright(C) 2008-2014 Piwigo Team http://piwigo.org | +// | Copyright(C) 2008-2016 Piwigo Team http://piwigo.org | // | Copyright(C) 2003-2008 PhpWebGallery Team http://phpwebgallery.net | // | Copyright(C) 2002-2003 Pierrick LE GALL http://le-gall.net/pierrick | // +-----------------------------------------------------------------------+ @@ -430,7 +430,7 @@ $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')), + 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')) diff --git a/admin/batch_manager_unit.php b/admin/batch_manager_unit.php index bed0cdc1c..f4d69d572 100644 --- a/admin/batch_manager_unit.php +++ b/admin/batch_manager_unit.php @@ -2,7 +2,7 @@ // +-----------------------------------------------------------------------+ // | Piwigo - a PHP based photo gallery | // +-----------------------------------------------------------------------+ -// | Copyright(C) 2008-2014 Piwigo Team http://piwigo.org | +// | Copyright(C) 2008-2016 Piwigo Team http://piwigo.org | // | Copyright(C) 2003-2008 PhpWebGallery Team http://phpwebgallery.net | // | Copyright(C) 2002-2003 Pierrick LE GALL http://le-gall.net/pierrick | // +-----------------------------------------------------------------------+ diff --git a/admin/cat_list.php b/admin/cat_list.php index d69bb4957..81e7c1804 100644 --- a/admin/cat_list.php +++ b/admin/cat_list.php @@ -2,7 +2,7 @@ // +-----------------------------------------------------------------------+ // | Piwigo - a PHP based photo gallery | // +-----------------------------------------------------------------------+ -// | Copyright(C) 2008-2014 Piwigo Team http://piwigo.org | +// | Copyright(C) 2008-2016 Piwigo Team http://piwigo.org | // | Copyright(C) 2003-2008 PhpWebGallery Team http://phpwebgallery.net | // | Copyright(C) 2002-2003 Pierrick LE GALL http://le-gall.net/pierrick | // +-----------------------------------------------------------------------+ diff --git a/admin/cat_modify.php b/admin/cat_modify.php index 3cf8239c1..3e50d8ff5 100644 --- a/admin/cat_modify.php +++ b/admin/cat_modify.php @@ -2,7 +2,7 @@ // +-----------------------------------------------------------------------+ // | Piwigo - a PHP based photo gallery | // +-----------------------------------------------------------------------+ -// | Copyright(C) 2008-2014 Piwigo Team http://piwigo.org | +// | Copyright(C) 2008-2016 Piwigo Team http://piwigo.org | // | Copyright(C) 2003-2008 PhpWebGallery Team http://phpwebgallery.net | // | Copyright(C) 2002-2003 Pierrick LE GALL http://le-gall.net/pierrick | // +-----------------------------------------------------------------------+ @@ -172,21 +172,6 @@ UPDATE '.CATEGORIES_TABLE.' $_SESSION['page_infos'][] = l10n('Album updated successfully'); $redirect = true; } -elseif (isset($_POST['set_random_representant'])) -{ - set_random_representant(array($_GET['cat_id'])); - $redirect = true; -} -elseif (isset($_POST['delete_representant'])) -{ - $query = ' -UPDATE '.CATEGORIES_TABLE.' - SET representative_picture_id = NULL - WHERE id = '.$_GET['cat_id'].' -;'; - pwg_query($query); - $redirect = true; -} if (isset($redirect)) { @@ -336,8 +321,7 @@ else } // representant management -if ($category['has_images'] - or !empty($category['representative_picture_id'])) +if ($category['has_images'] or !empty($category['representative_picture_id'])) { $tpl_representant = array(); @@ -345,20 +329,7 @@ if ($category['has_images'] // representant ? if (!empty($category['representative_picture_id'])) { - $query = ' -SELECT id,representative_ext,path - FROM '.IMAGES_TABLE.' - WHERE id = '.$category['representative_picture_id'].' -;'; - $row = pwg_db_fetch_assoc(pwg_query($query)); - $src = DerivativeImage::thumb_url($row); - $url = get_root_url().'admin.php?page=photo-'.$category['representative_picture_id']; - - $tpl_representant['picture'] = - array( - 'SRC' => $src, - 'URL' => $url - ); + $tpl_representant['picture'] = get_category_representant_properties($category['representative_picture_id']); } // can the admin choose to set a new random representant ? diff --git a/admin/cat_move.php b/admin/cat_move.php index d596d4e67..9e7e0b897 100644 --- a/admin/cat_move.php +++ b/admin/cat_move.php @@ -2,7 +2,7 @@ // +-----------------------------------------------------------------------+ // | Piwigo - a PHP based photo gallery | // +-----------------------------------------------------------------------+ -// | Copyright(C) 2008-2014 Piwigo Team http://piwigo.org | +// | Copyright(C) 2008-2016 Piwigo Team http://piwigo.org | // | Copyright(C) 2003-2008 PhpWebGallery Team http://phpwebgallery.net | // | Copyright(C) 2002-2003 Pierrick LE GALL http://le-gall.net/pierrick | // +-----------------------------------------------------------------------+ diff --git a/admin/cat_options.php b/admin/cat_options.php index f191095b6..41d5cd732 100644 --- a/admin/cat_options.php +++ b/admin/cat_options.php @@ -2,7 +2,7 @@ // +-----------------------------------------------------------------------+ // | Piwigo - a PHP based photo gallery | // +-----------------------------------------------------------------------+ -// | Copyright(C) 2008-2014 Piwigo Team http://piwigo.org | +// | Copyright(C) 2008-2016 Piwigo Team http://piwigo.org | // | Copyright(C) 2003-2008 PhpWebGallery Team http://phpwebgallery.net | // | Copyright(C) 2002-2003 Pierrick LE GALL http://le-gall.net/pierrick | // +-----------------------------------------------------------------------+ diff --git a/admin/cat_perm.php b/admin/cat_perm.php index c42b3eaa2..eb55f3e4a 100644 --- a/admin/cat_perm.php +++ b/admin/cat_perm.php @@ -2,7 +2,7 @@ // +-----------------------------------------------------------------------+ // | Piwigo - a PHP based photo gallery | // +-----------------------------------------------------------------------+ -// | Copyright(C) 2008-2014 Piwigo Team http://piwigo.org | +// | Copyright(C) 2008-2016 Piwigo Team http://piwigo.org | // | Copyright(C) 2003-2008 PhpWebGallery Team http://phpwebgallery.net | // | Copyright(C) 2002-2003 Pierrick LE GALL http://le-gall.net/pierrick | // +-----------------------------------------------------------------------+ diff --git a/admin/comments.php b/admin/comments.php index 0f09faf9f..580f03b90 100644 --- a/admin/comments.php +++ b/admin/comments.php @@ -2,7 +2,7 @@ // +-----------------------------------------------------------------------+ // | Piwigo - a PHP based photo gallery | // +-----------------------------------------------------------------------+ -// | Copyright(C) 2008-2014 Piwigo Team http://piwigo.org | +// | Copyright(C) 2008-2016 Piwigo Team http://piwigo.org | // | Copyright(C) 2003-2008 PhpWebGallery Team http://phpwebgallery.net | // | Copyright(C) 2002-2003 Pierrick LE GALL http://le-gall.net/pierrick | // +-----------------------------------------------------------------------+ diff --git a/admin/configuration.php b/admin/configuration.php index e7e6033c8..4a9c3c359 100644 --- a/admin/configuration.php +++ b/admin/configuration.php @@ -2,7 +2,7 @@ // +-----------------------------------------------------------------------+ // | Piwigo - a PHP based photo gallery | // +-----------------------------------------------------------------------+ -// | Copyright(C) 2008-2014 Piwigo Team http://piwigo.org | +// | Copyright(C) 2008-2016 Piwigo Team http://piwigo.org | // | Copyright(C) 2003-2008 PhpWebGallery Team http://phpwebgallery.net | // | Copyright(C) 2002-2003 Pierrick LE GALL http://le-gall.net/pierrick | // +-----------------------------------------------------------------------+ @@ -578,7 +578,7 @@ switch ($page['section']) $position = 'bottomright'; } - if ($wm->xrepeat != 0) + if ($wm->xrepeat != 0 || $wm->yrepeat != 0) { $position = 'custom'; } @@ -592,6 +592,7 @@ switch ($page['section']) 'xpos' => $wm->xpos, 'ypos' => $wm->ypos, 'xrepeat' => $wm->xrepeat, + 'yrepeat' => $wm->yrepeat, 'opacity' => $wm->opacity, 'position' => $position, ) diff --git a/admin/element_set_ranks.php b/admin/element_set_ranks.php index 8b68ce649..7ff57faee 100644 --- a/admin/element_set_ranks.php +++ b/admin/element_set_ranks.php @@ -2,7 +2,7 @@ // +-----------------------------------------------------------------------+ // | Piwigo - a PHP based photo gallery | // +-----------------------------------------------------------------------+ -// | Copyright(C) 2008-2014 Piwigo Team http://piwigo.org | +// | Copyright(C) 2008-2016 Piwigo Team http://piwigo.org | // | Copyright(C) 2003-2008 PhpWebGallery Team http://phpwebgallery.net | // | Copyright(C) 2002-2003 Pierrick LE GALL http://le-gall.net/pierrick | // +-----------------------------------------------------------------------+ @@ -45,38 +45,6 @@ if (!isset($_GET['cat_id']) or !is_numeric($_GET['cat_id'])) $page['category_id'] = $_GET['cat_id']; -// +-----------------------------------------------------------------------+ -// | functions | -// +-----------------------------------------------------------------------+ - -/** - * save the rank depending on given images order - * - * The list of ordered images id is supposed to be in the same parent - * category - * - * @param array categories - * @return void - */ -function save_images_order($category_id, $images) -{ - $current_rank = 0; - $datas = array(); - foreach ($images as $id) - { - $datas[] = array( - 'category_id' => $category_id, - 'image_id' => $id, - 'rank' => ++$current_rank, - ); - } - $fields = array( - 'primary' => array('image_id', 'category_id'), - 'update' => array('rank') - ); - mass_updates(IMAGE_CATEGORY_TABLE, $fields, $datas); -} - // +-----------------------------------------------------------------------+ // | global mode form submission | // +-----------------------------------------------------------------------+ diff --git a/admin/extend_for_templates.php b/admin/extend_for_templates.php index 0bab1215e..66b8009da 100644 --- a/admin/extend_for_templates.php +++ b/admin/extend_for_templates.php @@ -2,7 +2,7 @@ // +-----------------------------------------------------------------------+ // | Piwigo - a PHP based photo gallery | // +-----------------------------------------------------------------------+ -// | Copyright(C) 2008-2014 Piwigo Team http://piwigo.org | +// | Copyright(C) 2008-2016 Piwigo Team http://piwigo.org | // | Copyright(C) 2003-2008 PhpWebGallery Team http://phpwebgallery.net | // | Copyright(C) 2002-2003 Pierrick LE GALL http://le-gall.net/pierrick | // +-----------------------------------------------------------------------+ diff --git a/admin/group_list.php b/admin/group_list.php index 5c53a8b1f..9691f4913 100644 --- a/admin/group_list.php +++ b/admin/group_list.php @@ -2,7 +2,7 @@ // +-----------------------------------------------------------------------+ // | Piwigo - a PHP based photo gallery | // +-----------------------------------------------------------------------+ -// | Copyright(C) 2008-2014 Piwigo Team http://piwigo.org | +// | Copyright(C) 2008-2016 Piwigo Team http://piwigo.org | // | Copyright(C) 2003-2008 PhpWebGallery Team http://phpwebgallery.net | // | Copyright(C) 2002-2003 Pierrick LE GALL http://le-gall.net/pierrick | // +-----------------------------------------------------------------------+ diff --git a/admin/group_perm.php b/admin/group_perm.php index 28ea48111..d4311e09d 100644 --- a/admin/group_perm.php +++ b/admin/group_perm.php @@ -2,7 +2,7 @@ // +-----------------------------------------------------------------------+ // | Piwigo - a PHP based photo gallery | // +-----------------------------------------------------------------------+ -// | Copyright(C) 2008-2014 Piwigo Team http://piwigo.org | +// | Copyright(C) 2008-2016 Piwigo Team http://piwigo.org | // | Copyright(C) 2003-2008 PhpWebGallery Team http://phpwebgallery.net | // | Copyright(C) 2002-2003 Pierrick LE GALL http://le-gall.net/pierrick | // +-----------------------------------------------------------------------+ diff --git a/admin/help.php b/admin/help.php index 0625ea61e..cdc3bdf53 100644 --- a/admin/help.php +++ b/admin/help.php @@ -2,7 +2,7 @@ // +-----------------------------------------------------------------------+ // | Piwigo - a PHP based photo gallery | // +-----------------------------------------------------------------------+ -// | Copyright(C) 2008-2014 Piwigo Team http://piwigo.org | +// | Copyright(C) 2008-2016 Piwigo Team http://piwigo.org | // | Copyright(C) 2003-2008 PhpWebGallery Team http://phpwebgallery.net | // | Copyright(C) 2002-2003 Pierrick LE GALL http://le-gall.net/pierrick | // +-----------------------------------------------------------------------+ diff --git a/admin/history.php b/admin/history.php index 26855bb40..c2d3ecb9a 100644 --- a/admin/history.php +++ b/admin/history.php @@ -2,7 +2,7 @@ // +-----------------------------------------------------------------------+ // | Piwigo - a PHP based photo gallery | // +-----------------------------------------------------------------------+ -// | Copyright(C) 2008-2014 Piwigo Team http://piwigo.org | +// | Copyright(C) 2008-2016 Piwigo Team http://piwigo.org | // | Copyright(C) 2003-2008 PhpWebGallery Team http://phpwebgallery.net | // | Copyright(C) 2002-2003 Pierrick LE GALL http://le-gall.net/pierrick | // +-----------------------------------------------------------------------+ diff --git a/admin/include/add_core_tabs.inc.php b/admin/include/add_core_tabs.inc.php index 28cf1ce9e..9cef0f064 100644 --- a/admin/include/add_core_tabs.inc.php +++ b/admin/include/add_core_tabs.inc.php @@ -2,7 +2,7 @@ // +-----------------------------------------------------------------------+ // | Piwigo - a PHP based photo gallery | // +-----------------------------------------------------------------------+ -// | Copyright(C) 2008-2014 Piwigo Team http://piwigo.org | +// | Copyright(C) 2008-2016 Piwigo Team http://piwigo.org | // | Copyright(C) 2003-2008 PhpWebGallery Team http://phpwebgallery.net | // | Copyright(C) 2002-2003 Pierrick LE GALL http://le-gall.net/pierrick | // +-----------------------------------------------------------------------+ diff --git a/admin/include/albums_tab.inc.php b/admin/include/albums_tab.inc.php index 399778d01..8bccb5378 100644 --- a/admin/include/albums_tab.inc.php +++ b/admin/include/albums_tab.inc.php @@ -2,7 +2,7 @@ // +-----------------------------------------------------------------------+ // | Piwigo - a PHP based photo gallery | // +-----------------------------------------------------------------------+ -// | Copyright(C) 2008-2014 Piwigo Team http://piwigo.org | +// | Copyright(C) 2008-2016 Piwigo Team http://piwigo.org | // | Copyright(C) 2003-2008 PhpWebGallery Team http://phpwebgallery.net | // | Copyright(C) 2002-2003 Pierrick LE GALL http://le-gall.net/pierrick | // +-----------------------------------------------------------------------+ diff --git a/admin/include/c13y_internal.class.php b/admin/include/c13y_internal.class.php index 10375095a..acf4a32b6 100644 --- a/admin/include/c13y_internal.class.php +++ b/admin/include/c13y_internal.class.php @@ -2,7 +2,7 @@ // +-----------------------------------------------------------------------+ // | Piwigo - a PHP based photo gallery | // +-----------------------------------------------------------------------+ -// | Copyright(C) 2008-2014 Piwigo Team http://piwigo.org | +// | Copyright(C) 2008-2016 Piwigo Team http://piwigo.org | // | Copyright(C) 2003-2008 PhpWebGallery Team http://phpwebgallery.net | // | Copyright(C) 2002-2003 Pierrick LE GALL http://le-gall.net/pierrick | // +-----------------------------------------------------------------------+ @@ -23,7 +23,7 @@ class c13y_internal { - function c13y_internal() + function __construct() { add_event_handler('list_check_integrity', array(&$this, 'c13y_version')); add_event_handler('list_check_integrity', array(&$this, 'c13y_exif')); diff --git a/admin/include/check_integrity.class.php b/admin/include/check_integrity.class.php index 66ff1db8f..bf2104175 100644 --- a/admin/include/check_integrity.class.php +++ b/admin/include/check_integrity.class.php @@ -2,7 +2,7 @@ // +-----------------------------------------------------------------------+ // | Piwigo - a PHP based photo gallery | // +-----------------------------------------------------------------------+ -// | Copyright(C) 2008-2014 Piwigo Team http://piwigo.org | +// | Copyright(C) 2008-2016 Piwigo Team http://piwigo.org | // | Copyright(C) 2003-2008 PhpWebGallery Team http://phpwebgallery.net | // | Copyright(C) 2002-2003 Pierrick LE GALL http://le-gall.net/pierrick | // +-----------------------------------------------------------------------+ @@ -27,7 +27,7 @@ class check_integrity var $retrieve_list; var $build_ignore_list; - function check_integrity() + function __construct() { $this->ignore_list = array(); $this->retrieve_list = array(); diff --git a/admin/include/configuration_sizes_process.inc.php b/admin/include/configuration_sizes_process.inc.php index a731aa55f..92d746d4b 100644 --- a/admin/include/configuration_sizes_process.inc.php +++ b/admin/include/configuration_sizes_process.inc.php @@ -2,7 +2,7 @@ // +-----------------------------------------------------------------------+ // | Piwigo - a PHP based photo gallery | // +-----------------------------------------------------------------------+ -// | Copyright(C) 2008-2014 Piwigo Team http://piwigo.org | +// | Copyright(C) 2008-2016 Piwigo Team http://piwigo.org | // | Copyright(C) 2003-2008 PhpWebGallery Team http://phpwebgallery.net | // | Copyright(C) 2002-2003 Pierrick LE GALL http://le-gall.net/pierrick | // +-----------------------------------------------------------------------+ diff --git a/admin/include/configuration_watermark_process.inc.php b/admin/include/configuration_watermark_process.inc.php index ad23d92a2..bc1451791 100644 --- a/admin/include/configuration_watermark_process.inc.php +++ b/admin/include/configuration_watermark_process.inc.php @@ -2,7 +2,7 @@ // +-----------------------------------------------------------------------+ // | Piwigo - a PHP based photo gallery | // +-----------------------------------------------------------------------+ -// | Copyright(C) 2008-2014 Piwigo Team http://piwigo.org | +// | Copyright(C) 2008-2016 Piwigo Team http://piwigo.org | // | Copyright(C) 2003-2008 PhpWebGallery Team http://phpwebgallery.net | // | Copyright(C) 2002-2003 Pierrick LE GALL http://le-gall.net/pierrick | // +-----------------------------------------------------------------------+ @@ -126,6 +126,7 @@ if (count($errors) == 0) $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'])); @@ -135,6 +136,7 @@ if (count($errors) == 0) || $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 diff --git a/admin/include/functions.php b/admin/include/functions.php index 7d29f5734..4d3ccebe6 100644 --- a/admin/include/functions.php +++ b/admin/include/functions.php @@ -2,7 +2,7 @@ // +-----------------------------------------------------------------------+ // | Piwigo - a PHP based photo gallery | // +-----------------------------------------------------------------------+ -// | Copyright(C) 2008-2014 Piwigo Team http://piwigo.org | +// | Copyright(C) 2008-2016 Piwigo Team http://piwigo.org | // | Copyright(C) 2003-2008 PhpWebGallery Team http://phpwebgallery.net | // | Copyright(C) 2002-2003 Pierrick LE GALL http://le-gall.net/pierrick | // +-----------------------------------------------------------------------+ @@ -180,6 +180,25 @@ function delete_element_files($ids) } $new_ids = array(); + $formats_of = array(); + + $query = ' +SELECT + image_id, + ext + FROM '.IMAGE_FORMAT_TABLE.' + WHERE image_id IN ('.implode(',', $ids).') +;'; + $result = pwg_query($query); + while ($row = pwg_db_fetch_assoc($result)) + { + if (!isset($formats_of[ $row['image_id'] ])) + { + $formats_of[ $row['image_id'] ] = array(); + } + + $formats_of[ $row['image_id'] ][] = $row['ext']; + } $query = ' SELECT @@ -205,6 +224,14 @@ SELECT $files[] = original_to_representative( $files[0], $row['representative_ext']); } + if (isset($formats_of[ $row['id'] ])) + { + foreach ($formats_of[ $row['id'] ] as $format_ext) + { + $files[] = original_to_format($files[0], $format_ext); + } + } + $ok = true; if (!isset($conf['never_delete_originals'])) { @@ -277,6 +304,13 @@ DELETE FROM '.IMAGE_CATEGORY_TABLE.' ;'; pwg_query($query); + // destruction of the formats + $query = ' +DELETE FROM '.IMAGE_FORMAT_TABLE.' + WHERE image_id IN ('. $ids_str .') +;'; + pwg_query($query); + // destruction of the links between images and tags $query = ' DELETE FROM '.IMAGE_TAG_TABLE.' @@ -358,6 +392,7 @@ function delete_user($user_id) CADDIE_TABLE, // deletion of piwigo specific informations USER_INFOS_TABLE, + USER_AUTH_KEYS_TABLE ); foreach ($tables as $table) @@ -540,6 +575,7 @@ function get_fs_directories($path, $recursive = true) '.', '..', '.svn', 'thumbnail', 'pwg_high', 'pwg_representative', + 'pwg_format', ) ); $exclude_folders = array_flip($exclude_folders); @@ -886,6 +922,25 @@ SELECT uppercats return $uppercats; } +/** + */ +function get_category_representant_properties($image_id) +{ + $query = ' +SELECT id,representative_ext,path + FROM '.IMAGES_TABLE.' + WHERE id = '.$image_id.' +;'; + $row = pwg_db_fetch_assoc(pwg_query($query)); + $src = DerivativeImage::thumb_url($row); + $url = get_root_url().'admin.php?page=photo-'.$image_id; + + return array( + 'src' => $src, + 'url' => $url + ); +} + /** * Set a new random representant to the categories. * @@ -2775,4 +2830,51 @@ SELECT CONCAT( } return $keys; -} \ No newline at end of file +} + +/** + * Return the list of image ids associated to no album + * + * @return int[] $image_ids + */ +function get_orphans() +{ + $query = ' +SELECT + id + FROM '.IMAGES_TABLE.' + LEFT JOIN '.IMAGE_CATEGORY_TABLE.' ON id = image_id + WHERE category_id is null +;'; + + return query2array($query, null, 'id'); +} + +/** + * save the rank depending on given images order + * + * The list of ordered images id is supposed to be in the same parent + * category + * + * @param int category_id + * @param int[] images + * @return void + */ +function save_images_order($category_id, $images) +{ + $current_rank = 0; + $datas = array(); + foreach ($images as $id) + { + $datas[] = array( + 'category_id' => $category_id, + 'image_id' => $id, + 'rank' => ++$current_rank, + ); + } + $fields = array( + 'primary' => array('image_id', 'category_id'), + 'update' => array('rank') + ); + mass_updates(IMAGE_CATEGORY_TABLE, $fields, $datas); +} diff --git a/admin/include/functions_history.inc.php b/admin/include/functions_history.inc.php index e2bcc4d62..55783fd74 100644 --- a/admin/include/functions_history.inc.php +++ b/admin/include/functions_history.inc.php @@ -2,7 +2,7 @@ // +-----------------------------------------------------------------------+ // | Piwigo - a PHP based photo gallery | // +-----------------------------------------------------------------------+ -// | Copyright(C) 2008-2014 Piwigo Team http://piwigo.org | +// | Copyright(C) 2008-2016 Piwigo Team http://piwigo.org | // | Copyright(C) 2003-2008 PhpWebGallery Team http://phpwebgallery.net | // | Copyright(C) 2002-2003 Pierrick LE GALL http://le-gall.net/pierrick | // +-----------------------------------------------------------------------+ diff --git a/admin/include/functions_install.inc.php b/admin/include/functions_install.inc.php index a97835583..5a68964f8 100644 --- a/admin/include/functions_install.inc.php +++ b/admin/include/functions_install.inc.php @@ -2,7 +2,7 @@ // +-----------------------------------------------------------------------+ // | Piwigo - a PHP based photo gallery | // +-----------------------------------------------------------------------+ -// | Copyright(C) 2008-2014 Piwigo Team http://piwigo.org | +// | Copyright(C) 2008-2016 Piwigo Team http://piwigo.org | // | Copyright(C) 2003-2008 PhpWebGallery Team http://phpwebgallery.net | // | Copyright(C) 2002-2003 Pierrick LE GALL http://le-gall.net/pierrick | // +-----------------------------------------------------------------------+ diff --git a/admin/include/functions_metadata.php b/admin/include/functions_metadata.php index da0703774..1b5b5bb73 100644 --- a/admin/include/functions_metadata.php +++ b/admin/include/functions_metadata.php @@ -2,7 +2,7 @@ // +-----------------------------------------------------------------------+ // | Piwigo - a PHP based photo gallery | // +-----------------------------------------------------------------------+ -// | Copyright(C) 2008-2014 Piwigo Team http://piwigo.org | +// | Copyright(C) 2008-2016 Piwigo Team http://piwigo.org | // | Copyright(C) 2003-2008 PhpWebGallery Team http://phpwebgallery.net | // | Copyright(C) 2002-2003 Pierrick LE GALL http://le-gall.net/pierrick | // +-----------------------------------------------------------------------+ diff --git a/admin/include/functions_notification_by_mail.inc.php b/admin/include/functions_notification_by_mail.inc.php index 8d0fe2621..204be5c33 100644 --- a/admin/include/functions_notification_by_mail.inc.php +++ b/admin/include/functions_notification_by_mail.inc.php @@ -2,7 +2,7 @@ // +-----------------------------------------------------------------------+ // | Piwigo - a PHP based photo gallery | // +-----------------------------------------------------------------------+ -// | Copyright(C) 2008-2014 Piwigo Team http://piwigo.org | +// | Copyright(C) 2008-2016 Piwigo Team http://piwigo.org | // | Copyright(C) 2003-2008 PhpWebGallery Team http://phpwebgallery.net | // | Copyright(C) 2002-2003 Pierrick LE GALL http://le-gall.net/pierrick | // +-----------------------------------------------------------------------+ @@ -125,12 +125,12 @@ select U.'.$conf['user_fields']['username'].' as username, U.'.$conf['user_fields']['email'].' as mail_address, N.enabled, - N.last_send -from - '.USER_MAIL_NOTIFICATION_TABLE.' as N, - '.USERS_TABLE.' as U -where - N.user_id = U.'.$conf['user_fields']['id']; + 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') { @@ -159,7 +159,7 @@ order by'; else { $query .= ' - username;'; + username'; } $query .= ';'; diff --git a/admin/include/functions_permalinks.php b/admin/include/functions_permalinks.php index 6c8ae4aac..db0679661 100644 --- a/admin/include/functions_permalinks.php +++ b/admin/include/functions_permalinks.php @@ -2,7 +2,7 @@ // +-----------------------------------------------------------------------+ // | Piwigo - a PHP based photo gallery | // +-----------------------------------------------------------------------+ -// | Copyright(C) 2008-2014 Piwigo Team http://piwigo.org | +// | Copyright(C) 2008-2016 Piwigo Team http://piwigo.org | // | Copyright(C) 2003-2008 PhpWebGallery Team http://phpwebgallery.net | // | Copyright(C) 2002-2003 Pierrick LE GALL http://le-gall.net/pierrick | // +-----------------------------------------------------------------------+ diff --git a/admin/include/functions_plugins.inc.php b/admin/include/functions_plugins.inc.php index fb98c799c..8605f1ff2 100644 --- a/admin/include/functions_plugins.inc.php +++ b/admin/include/functions_plugins.inc.php @@ -2,7 +2,7 @@ // +-----------------------------------------------------------------------+ // | Piwigo - a PHP based photo gallery | // +-----------------------------------------------------------------------+ -// | Copyright(C) 2008-2014 Piwigo Team http://piwigo.org | +// | Copyright(C) 2008-2016 Piwigo Team http://piwigo.org | // | Copyright(C) 2003-2008 PhpWebGallery Team http://phpwebgallery.net | // | Copyright(C) 2002-2003 Pierrick LE GALL http://le-gall.net/pierrick | // +-----------------------------------------------------------------------+ diff --git a/admin/include/functions_upgrade.php b/admin/include/functions_upgrade.php index b7a8763c5..bf6ef2b88 100644 --- a/admin/include/functions_upgrade.php +++ b/admin/include/functions_upgrade.php @@ -2,7 +2,7 @@ // +-----------------------------------------------------------------------+ // | Piwigo - a PHP based photo gallery | // +-----------------------------------------------------------------------+ -// | Copyright(C) 2008-2014 Piwigo Team http://piwigo.org | +// | Copyright(C) 2008-2016 Piwigo Team http://piwigo.org | // | Copyright(C) 2003-2008 PhpWebGallery Team http://phpwebgallery.net | // | Copyright(C) 2002-2003 Pierrick LE GALL http://le-gall.net/pierrick | // +-----------------------------------------------------------------------+ @@ -174,10 +174,7 @@ UPDATE '.PREFIX_TABLE.'user_infos // Deactivate all templates function deactivate_templates() { - $query = ' - UPDATE '.PREFIX_TABLE.'config - SET value = \''. array() .'\' - WHERE param = \'extents_for_templates\';'; + conf_update_param('extents_for_templates', array()); } // Check access rights @@ -322,4 +319,4 @@ function upgrade_db_connect() my_error(l10n($e->getMessage()), true); } } -?> \ No newline at end of file +?> diff --git a/admin/include/functions_upload.inc.php b/admin/include/functions_upload.inc.php index d0ef6e67d..17e78a200 100644 --- a/admin/include/functions_upload.inc.php +++ b/admin/include/functions_upload.inc.php @@ -2,7 +2,7 @@ // +-----------------------------------------------------------------------+ // | Piwigo - a PHP based photo gallery | // +-----------------------------------------------------------------------+ -// | Copyright(C) 2008-2014 Piwigo Team http://piwigo.org | +// | Copyright(C) 2008-2016 Piwigo Team http://piwigo.org | // | Copyright(C) 2003-2008 PhpWebGallery Team http://phpwebgallery.net | // | Copyright(C) 2002-2003 Pierrick LE GALL http://le-gall.net/pierrick | // +-----------------------------------------------------------------------+ @@ -268,104 +268,19 @@ SELECT } @chmod($file_path, 0644); - if ($is_tiff and pwg_image::get_library() == 'ext_imagick') - { - // move the uploaded file to pwg_representative sub-directory - $representative_file_path = dirname($file_path).'/pwg_representative/'; - $representative_file_path.= get_filename_wo_extension(basename($file_path)).'.'; + // handle the uploaded file type by potentially making a + // pwg_representative file. + $representative_ext = trigger_change('upload_file', null, $file_path); - $representative_ext = $conf['tiff_representative_ext']; - $representative_file_path.= $representative_ext; - - prepare_directory(dirname($representative_file_path)); - - $exec = $conf['ext_imagick_dir'].'convert'; - - if ('jpg' == $conf['tiff_representative_ext']) - { - $exec .= ' -quality 98'; - } - - $exec .= ' "'.realpath($file_path).'"'; - - $dest = pathinfo($representative_file_path); - $exec .= ' "'.realpath($dest['dirname']).'/'.$dest['basename'].'"'; - - $exec .= ' 2>&1'; - @exec($exec, $returnarray); - - // sometimes ImageMagick creates file-0.jpg (full size) + file-1.jpg - // (thumbnail). I don't know how to avoid it. - $representative_file_abspath = realpath($dest['dirname']).'/'.$dest['basename']; - if (!file_exists($representative_file_abspath)) - { - $first_file_abspath = preg_replace( - '/\.'.$representative_ext.'$/', - '-0.'.$representative_ext, - $representative_file_abspath - ); - - if (file_exists($first_file_abspath)) - { - rename($first_file_abspath, $representative_file_abspath); - } - } - } - - // - // generate pwg_representative in case of video - // - $ffmpeg_video_exts = array( // extensions tested with FFmpeg - 'wmv','mov','mkv','mp4','mpg','flv','asf','xvid','divx','mpeg', - 'avi','rm', - ); + global $logger; + $logger->info("Handling " . (string)$file_path . " got " . (string)$representative_ext); - if (isset($original_extension) and in_array($original_extension, $ffmpeg_video_exts)) - { - $representative_file_path = dirname($file_path).'/pwg_representative/'; - $representative_file_path.= get_filename_wo_extension(basename($file_path)).'.'; - - $representative_ext = 'jpg'; - $representative_file_path.= $representative_ext; - - prepare_directory(dirname($representative_file_path)); - - $second = 1; - - $ffmpeg = $conf['ffmpeg_dir'].'ffmpeg'; - $ffmpeg.= ' -i "'.$file_path.'"'; - $ffmpeg.= ' -an -ss '.$second; - $ffmpeg.= ' -t 1 -r 1 -y -vcodec mjpeg -f mjpeg'; - $ffmpeg.= ' "'.$representative_file_path.'"'; - - // file_put_contents('/tmp/ffmpeg.log', "\n==== ".date('c')."\n".__FUNCTION__.' : '.$ffmpeg."\n", FILE_APPEND); - - @exec($ffmpeg); - - if (!file_exists($representative_file_path)) - { - $representative_ext = null; - } - } - - if (isset($original_extension) and 'pdf' == $original_extension and pwg_image::get_library() == 'ext_imagick') - { - $representative_file_path = dirname($file_path).'/pwg_representative/'; - $representative_file_path.= get_filename_wo_extension(basename($file_path)).'.'; - - $representative_ext = 'jpg'; - $representative_file_path.= $representative_ext; - - prepare_directory(dirname($representative_file_path)); - - $exec = $conf['ext_imagick_dir'].'convert'; - $exec.= ' -quality 98'; - $exec.= ' "'.realpath($file_path).'"[0]'; - - $dest = pathinfo($representative_file_path); - $exec.= ' "'.realpath($dest['dirname']).'/'.$dest['basename'].'"'; - $exec.= ' 2>&1'; - @exec($exec, $returnarray); + // If it is set to either true (the file didn't need a + // representative generated) or false (the generation of the + // representative failed), set it to null because we have no + // representative file. + if (is_bool($representative_ext)) { + $representative_ext = null; } if (pwg_image::get_library() != 'gd') @@ -492,6 +407,168 @@ SELECT return $image_id; } +add_event_handler('upload_file', 'upload_file_pdf'); +function upload_file_pdf($representative_ext, $file_path) +{ + global $logger, $conf; + + $logger->info(__FUNCTION__.', $file_path = '.$file_path.', $representative_ext = '.$representative_ext); + + if (isset($representative_ext)) + { + return $representative_ext; + } + + if (pwg_image::get_library() != 'ext_imagick') + { + return $representative_ext; + } + + if (!in_array(strtolower(get_extension($file_path)), array('pdf'))) + { + return $representative_ext; + } + + $ext = conf_get_param('pdf_representative_ext', 'jpg'); + $jpg_quality = conf_get_param('pdf_jpg_quality', 90); + + // move the uploaded file to pwg_representative sub-directory + $representative_file_path = original_to_representative($file_path, $ext); + prepare_directory(dirname($representative_file_path)); + + $exec = $conf['ext_imagick_dir'].'convert'; + if ('jpg' == $ext) + { + $exec.= ' -quality '.$jpg_quality; + } + $exec.= ' "'.realpath($file_path).'"[0]'; + $exec.= ' "'.$representative_file_path.'"'; + $exec.= ' 2>&1'; + @exec($exec, $returnarray); + + // Return the extension (if successful) or false (if failed) + if (file_exists($representative_file_path)) + { + $representative_ext = $ext; + } + + return $representative_ext; +} + +add_event_handler('upload_file', 'upload_file_tiff'); +function upload_file_tiff($representative_ext, $file_path) +{ + global $logger, $conf; + + $logger->info(__FUNCTION__.', $file_path = '.$file_path.', $representative_ext = '.$representative_ext); + + if (isset($representative_ext)) + { + return $representative_ext; + } + + if (pwg_image::get_library() != 'ext_imagick') + { + return $representative_ext; + } + + if (!in_array(strtolower(get_extension($file_path)), array('tif', 'tiff'))) + { + return $representative_ext; + } + + // move the uploaded file to pwg_representative sub-directory + $representative_file_path = dirname($file_path).'/pwg_representative/'; + $representative_file_path.= get_filename_wo_extension(basename($file_path)).'.'; + + $representative_ext = $conf['tiff_representative_ext']; + $representative_file_path.= $representative_ext; + + prepare_directory(dirname($representative_file_path)); + + $exec = $conf['ext_imagick_dir'].'convert'; + + if ('jpg' == $conf['tiff_representative_ext']) + { + $exec .= ' -quality 98'; + } + + $exec .= ' "'.realpath($file_path).'"'; + + $dest = pathinfo($representative_file_path); + $exec .= ' "'.realpath($dest['dirname']).'/'.$dest['basename'].'"'; + + $exec .= ' 2>&1'; + @exec($exec, $returnarray); + + // sometimes ImageMagick creates file-0.jpg (full size) + file-1.jpg + // (thumbnail). I don't know how to avoid it. + $representative_file_abspath = realpath($dest['dirname']).'/'.$dest['basename']; + if (!file_exists($representative_file_abspath)) + { + $first_file_abspath = preg_replace( + '/\.'.$representative_ext.'$/', + '-0.'.$representative_ext, + $representative_file_abspath + ); + + if (file_exists($first_file_abspath)) + { + rename($first_file_abspath, $representative_file_abspath); + } + } + + return get_extension($representative_file_abspath); +} + +add_event_handler('upload_file', 'upload_file_video'); +function upload_file_video($representative_ext, $file_path) +{ + global $logger, $conf; + + $logger->info(__FUNCTION__.', $file_path = '.$file_path.', $representative_ext = '.$representative_ext); + + if (isset($representative_ext)) + { + return $representative_ext; + } + + $ffmpeg_video_exts = array( // extensions tested with FFmpeg + 'wmv','mov','mkv','mp4','mpg','flv','asf','xvid','divx','mpeg', + 'avi','rm', + ); + + if (!in_array(strtolower(get_extension($file_path)), $ffmpeg_video_exts)) + { + return $representative_ext; + } + + $representative_file_path = dirname($file_path).'/pwg_representative/'; + $representative_file_path.= get_filename_wo_extension(basename($file_path)).'.'; + + $representative_ext = 'jpg'; + $representative_file_path.= $representative_ext; + + prepare_directory(dirname($representative_file_path)); + + $second = 1; + + $ffmpeg = $conf['ffmpeg_dir'].'ffmpeg'; + $ffmpeg.= ' -i "'.$file_path.'"'; + $ffmpeg.= ' -an -ss '.$second; + $ffmpeg.= ' -t 1 -r 1 -y -vcodec mjpeg -f mjpeg'; + $ffmpeg.= ' "'.$representative_file_path.'"'; + + @exec($ffmpeg); + + if (!file_exists($representative_file_path)) + { + return null; + } + + return $representative_ext; +} + function prepare_directory($directory) { if (!is_dir($directory)) { diff --git a/admin/include/image.class.php b/admin/include/image.class.php index ee9b9bb12..e713a84c9 100644 --- a/admin/include/image.class.php +++ b/admin/include/image.class.php @@ -2,7 +2,7 @@ // +-----------------------------------------------------------------------+ // | Piwigo - a PHP based photo gallery | // +-----------------------------------------------------------------------+ -// | Copyright(C) 2008-2014 Piwigo Team http://piwigo.org | +// | Copyright(C) 2008-2016 Piwigo Team http://piwigo.org | // | Copyright(C) 2003-2008 PhpWebGallery Team http://phpwebgallery.net | // | Copyright(C) 2002-2003 Pierrick LE GALL http://le-gall.net/pierrick | // +-----------------------------------------------------------------------+ diff --git a/admin/include/index.php b/admin/include/index.php index c8de97f60..0b96c3efa 100644 --- a/admin/include/index.php +++ b/admin/include/index.php @@ -2,7 +2,7 @@ // +-----------------------------------------------------------------------+ // | Piwigo - a PHP based photo gallery | // +-----------------------------------------------------------------------+ -// | Copyright(C) 2008-2014 Piwigo Team http://piwigo.org | +// | Copyright(C) 2008-2016 Piwigo Team http://piwigo.org | // | Copyright(C) 2003-2008 PhpWebGallery Team http://phpwebgallery.net | // | Copyright(C) 2002-2003 Pierrick LE GALL http://le-gall.net/pierrick | // +-----------------------------------------------------------------------+ diff --git a/admin/include/languages.class.php b/admin/include/languages.class.php index 351e36d53..6f6780592 100644 --- a/admin/include/languages.class.php +++ b/admin/include/languages.class.php @@ -2,7 +2,7 @@ // +-----------------------------------------------------------------------+ // | Piwigo - a PHP based photo gallery | // +-----------------------------------------------------------------------+ -// | Copyright(C) 2008-2014 Piwigo Team http://piwigo.org | +// | Copyright(C) 2008-2016 Piwigo Team http://piwigo.org | // | Copyright(C) 2003-2008 PhpWebGallery Team http://phpwebgallery.net | // | Copyright(C) 2002-2003 Pierrick LE GALL http://le-gall.net/pierrick | // +-----------------------------------------------------------------------+ @@ -30,7 +30,7 @@ class languages /** * Initialize $fs_languages and $db_languages */ - function languages($target_charset = null) + function __construct($target_charset = null) { $this->get_fs_languages($target_charset); } @@ -408,4 +408,4 @@ UPDATE '.USER_INFOS_TABLE.' return strcmp(strtolower($a['extension_name']), strtolower($b['extension_name'])); } } -?> \ No newline at end of file +?> diff --git a/admin/include/mysqldump.php b/admin/include/mysqldump.php index 515d86ae9..1432675c8 100644 --- a/admin/include/mysqldump.php +++ b/admin/include/mysqldump.php @@ -59,7 +59,7 @@ class MySQLDump { * @param boolean $compress It defines if the output file is compress (gzip) or not * @param boolean $hexValue It defines if the outup values are base-16 or not */ - function MYSQLDump($db = null, $filepath = 'dump.sql', $compress = false, $hexValue = false){ + function __construct($db = null, $filepath = 'dump.sql', $compress = false, $hexValue = false){ $this->compress = $compress; if ( !$this->setOutputFile($filepath) ) return false; @@ -418,4 +418,4 @@ class MySQLDump { @fclose($file); } } -?> \ No newline at end of file +?> diff --git a/admin/include/pclzip.lib.php b/admin/include/pclzip.lib.php index e7facc1ea..c2d09a50c 100644 --- a/admin/include/pclzip.lib.php +++ b/admin/include/pclzip.lib.php @@ -212,7 +212,7 @@ // Note that no real action is taken, if the archive does not exist it is not // created. Use create() for that. // -------------------------------------------------------------------------------- - function PclZip($p_zipname) + function __construct($p_zipname) { // ----- Tests the zlib diff --git a/admin/include/photos_add_direct_prepare.inc.php b/admin/include/photos_add_direct_prepare.inc.php index 34b025f13..4d852fee4 100644 --- a/admin/include/photos_add_direct_prepare.inc.php +++ b/admin/include/photos_add_direct_prepare.inc.php @@ -2,7 +2,7 @@ // +-----------------------------------------------------------------------+ // | Piwigo - a PHP based photo gallery | // +-----------------------------------------------------------------------+ -// | Copyright(C) 2008-2014 Piwigo Team http://piwigo.org | +// | Copyright(C) 2008-2016 Piwigo Team http://piwigo.org | // | Copyright(C) 2003-2008 PhpWebGallery Team http://phpwebgallery.net | // | Copyright(C) 2002-2003 Pierrick LE GALL http://le-gall.net/pierrick | // +-----------------------------------------------------------------------+ @@ -44,6 +44,7 @@ $template->assign( 'F_ADD_ACTION'=> PHOTOS_ADD_BASE_URL, 'upload_max_filesize' => $upload_max_filesize, 'upload_max_filesize_shorthand' => $upload_max_filesize_shorthand, + 'chunk_size' => $conf['upload_form_chunk_size'], ) ); @@ -229,4 +230,4 @@ if (!isset($_SESSION['upload_hide_warnings'])) ); } -?> \ No newline at end of file +?> diff --git a/admin/include/plugins.class.php b/admin/include/plugins.class.php index 71093a6c1..8b4b82b75 100644 --- a/admin/include/plugins.class.php +++ b/admin/include/plugins.class.php @@ -2,7 +2,7 @@ // +-----------------------------------------------------------------------+ // | Piwigo - a PHP based photo gallery | // +-----------------------------------------------------------------------+ -// | Copyright(C) 2008-2014 Piwigo Team http://piwigo.org | +// | Copyright(C) 2008-2016 Piwigo Team http://piwigo.org | // | Copyright(C) 2003-2008 PhpWebGallery Team http://phpwebgallery.net | // | Copyright(C) 2002-2003 Pierrick LE GALL http://le-gall.net/pierrick | // +-----------------------------------------------------------------------+ @@ -69,7 +69,7 @@ class plugins /** * Initialize $fs_plugins and $db_plugins_by_id */ - function plugins() + function __construct() { $this->get_fs_plugins(); @@ -716,4 +716,4 @@ DELETE FROM '. PLUGINS_TABLE .' $this->fs_plugins = $active_plugins + $inactive_plugins + $not_installed; } } -?> \ No newline at end of file +?> diff --git a/admin/include/tabsheet.class.php b/admin/include/tabsheet.class.php index c7681b611..cb89886fe 100644 --- a/admin/include/tabsheet.class.php +++ b/admin/include/tabsheet.class.php @@ -2,7 +2,7 @@ // +-----------------------------------------------------------------------+ // | Piwigo - a PHP based photo gallery | // +-----------------------------------------------------------------------+ -// | Copyright(C) 2008-2014 Piwigo Team http://piwigo.org | +// | Copyright(C) 2008-2016 Piwigo Team http://piwigo.org | // | Copyright(C) 2003-2008 PhpWebGallery Team http://phpwebgallery.net | // | Copyright(C) 2002-2003 Pierrick LE GALL http://le-gall.net/pierrick | // +-----------------------------------------------------------------------+ @@ -33,7 +33,7 @@ class tabsheet $name is the tabsheet's name inside the template .tpl file $titlename in the template is affected by $titlename value */ - function tabsheet($name = 'TABSHEET', $titlename = 'TABSHEET_TITLE') + function __construct($name = 'TABSHEET', $titlename = 'TABSHEET_TITLE') { $this->sheets = array(); $this->uniqid = null; diff --git a/admin/include/themes.class.php b/admin/include/themes.class.php index df0e29e66..6d55e11bd 100644 --- a/admin/include/themes.class.php +++ b/admin/include/themes.class.php @@ -2,7 +2,7 @@ // +-----------------------------------------------------------------------+ // | Piwigo - a PHP based photo gallery | // +-----------------------------------------------------------------------+ -// | Copyright(C) 2008-2014 Piwigo Team http://piwigo.org | +// | Copyright(C) 2008-2016 Piwigo Team http://piwigo.org | // | Copyright(C) 2003-2008 PhpWebGallery Team http://phpwebgallery.net | // | Copyright(C) 2002-2003 Pierrick LE GALL http://le-gall.net/pierrick | // +-----------------------------------------------------------------------+ @@ -60,7 +60,7 @@ class themes /** * Initialize $fs_themes and $db_themes_by_id */ - function themes() + function __construct() { $this->get_fs_themes(); @@ -736,4 +736,4 @@ SELECT } } -?> \ No newline at end of file +?> diff --git a/admin/include/updates.class.php b/admin/include/updates.class.php index 17a3b2578..d4e178f8a 100644 --- a/admin/include/updates.class.php +++ b/admin/include/updates.class.php @@ -2,7 +2,7 @@ // +-----------------------------------------------------------------------+ // | Piwigo - a PHP based photo gallery | // +-----------------------------------------------------------------------+ -// | Copyright(C) 2008-2014 Piwigo Team http://piwigo.org | +// | Copyright(C) 2008-2016 Piwigo Team http://piwigo.org | // | Copyright(C) 2003-2008 PhpWebGallery Team http://phpwebgallery.net | // | Copyright(C) 2002-2003 Pierrick LE GALL http://le-gall.net/pierrick | // +-----------------------------------------------------------------------+ @@ -135,15 +135,33 @@ class updates { return false; } + + $servers = array(); + foreach ($pem_exts as $ext) { if (isset($ext_to_check[$ext['extension_id']])) { - $server = 'server_'.$ext_to_check[$ext['extension_id']]; - $this->$ext_to_check[$ext['extension_id']]->$server += array($ext['extension_id'] => $ext); + $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; } diff --git a/admin/index.php b/admin/index.php index c8de97f60..0b96c3efa 100644 --- a/admin/index.php +++ b/admin/index.php @@ -2,7 +2,7 @@ // +-----------------------------------------------------------------------+ // | Piwigo - a PHP based photo gallery | // +-----------------------------------------------------------------------+ -// | Copyright(C) 2008-2014 Piwigo Team http://piwigo.org | +// | Copyright(C) 2008-2016 Piwigo Team http://piwigo.org | // | Copyright(C) 2003-2008 PhpWebGallery Team http://phpwebgallery.net | // | Copyright(C) 2002-2003 Pierrick LE GALL http://le-gall.net/pierrick | // +-----------------------------------------------------------------------+ diff --git a/admin/intro.php b/admin/intro.php index ee0149841..96b07d2a8 100644 --- a/admin/intro.php +++ b/admin/intro.php @@ -2,7 +2,7 @@ // +-----------------------------------------------------------------------+ // | Piwigo - a PHP based photo gallery | // +-----------------------------------------------------------------------+ -// | Copyright(C) 2008-2014 Piwigo Team http://piwigo.org | +// | Copyright(C) 2008-2016 Piwigo Team http://piwigo.org | // | Copyright(C) 2003-2008 PhpWebGallery Team http://phpwebgallery.net | // | Copyright(C) 2002-2003 Pierrick LE GALL http://le-gall.net/pierrick | // +-----------------------------------------------------------------------+ diff --git a/admin/languages.php b/admin/languages.php index c901d923c..0ea4c17df 100644 --- a/admin/languages.php +++ b/admin/languages.php @@ -2,7 +2,7 @@ // +-----------------------------------------------------------------------+ // | Piwigo - a PHP based photo gallery | // +-----------------------------------------------------------------------+ -// | Copyright(C) 2008-2014 Piwigo Team http://piwigo.org | +// | Copyright(C) 2008-2016 Piwigo Team http://piwigo.org | // | Copyright(C) 2003-2008 PhpWebGallery Team http://phpwebgallery.net | // | Copyright(C) 2002-2003 Pierrick LE GALL http://le-gall.net/pierrick | // +-----------------------------------------------------------------------+ diff --git a/admin/languages_installed.php b/admin/languages_installed.php index eb0a89578..16d9df651 100644 --- a/admin/languages_installed.php +++ b/admin/languages_installed.php @@ -2,7 +2,7 @@ // +-----------------------------------------------------------------------+ // | Piwigo - a PHP based photo gallery | // +-----------------------------------------------------------------------+ -// | Copyright(C) 2008-2014 Piwigo Team http://piwigo.org | +// | Copyright(C) 2008-2016 Piwigo Team http://piwigo.org | // | Copyright(C) 2003-2008 PhpWebGallery Team http://phpwebgallery.net | // | Copyright(C) 2002-2003 Pierrick LE GALL http://le-gall.net/pierrick | // +-----------------------------------------------------------------------+ diff --git a/admin/languages_new.php b/admin/languages_new.php index bf46cbb71..afa756c56 100644 --- a/admin/languages_new.php +++ b/admin/languages_new.php @@ -2,7 +2,7 @@ // +-----------------------------------------------------------------------+ // | Piwigo - a PHP based photo gallery | // +-----------------------------------------------------------------------+ -// | Copyright(C) 2008-2014 Piwigo Team http://piwigo.org | +// | Copyright(C) 2008-2016 Piwigo Team http://piwigo.org | // | Copyright(C) 2003-2008 PhpWebGallery Team http://phpwebgallery.net | // | Copyright(C) 2002-2003 Pierrick LE GALL http://le-gall.net/pierrick | // +-----------------------------------------------------------------------+ diff --git a/admin/maintenance.php b/admin/maintenance.php index 5c933461e..9befd5032 100644 --- a/admin/maintenance.php +++ b/admin/maintenance.php @@ -2,7 +2,7 @@ // +-----------------------------------------------------------------------+ // | Piwigo - a PHP based photo gallery | // +-----------------------------------------------------------------------+ -// | Copyright(C) 2008-2014 Piwigo Team http://piwigo.org | +// | Copyright(C) 2008-2016 Piwigo Team http://piwigo.org | // | Copyright(C) 2003-2008 PhpWebGallery Team http://phpwebgallery.net | // | Copyright(C) 2002-2003 Pierrick LE GALL http://le-gall.net/pierrick | // +-----------------------------------------------------------------------+ diff --git a/admin/menubar.php b/admin/menubar.php index 69e363ccc..e884fab56 100644 --- a/admin/menubar.php +++ b/admin/menubar.php @@ -2,7 +2,7 @@ // +-----------------------------------------------------------------------+ // | Piwigo - a PHP based photo gallery | // +-----------------------------------------------------------------------+ -// | Copyright(C) 2008-2014 Piwigo Team http://piwigo.org | +// | Copyright(C) 2008-2016 Piwigo Team http://piwigo.org | // | Copyright(C) 2003-2008 PhpWebGallery Team http://phpwebgallery.net | // | Copyright(C) 2002-2003 Pierrick LE GALL http://le-gall.net/pierrick | // +-----------------------------------------------------------------------+ diff --git a/admin/notification_by_mail.php b/admin/notification_by_mail.php index 38cadff6c..ca3d4127c 100644 --- a/admin/notification_by_mail.php +++ b/admin/notification_by_mail.php @@ -2,7 +2,7 @@ // +-----------------------------------------------------------------------+ // | Piwigo - a PHP based photo gallery | // +-----------------------------------------------------------------------+ -// | Copyright(C) 2008-2014 Piwigo Team http://piwigo.org | +// | Copyright(C) 2008-2016 Piwigo Team http://piwigo.org | // | Copyright(C) 2003-2008 PhpWebGallery Team http://phpwebgallery.net | // | Copyright(C) 2002-2003 Pierrick LE GALL http://le-gall.net/pierrick | // +-----------------------------------------------------------------------+ @@ -289,13 +289,24 @@ function do_action_send_mail_notification($action = 'list_to_send', $check_key_l 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']); + $news = news($nbm_user['last_send'], $dbnow, false, $conf['nbm_send_html_mail'], $auth); $exist_data = count($news) > 0; } else @@ -362,7 +373,7 @@ function do_action_send_mail_notification($action = 'list_to_send', $check_key_l array ( 'TITLE' => get_title_recent_post_date($date_detail), - 'HTML_DATA' => get_html_description_recent_post_date($date_detail) + 'HTML_DATA' => get_html_description_recent_post_date($date_detail, $auth) ) ); } @@ -373,7 +384,7 @@ function do_action_send_mail_notification($action = 'list_to_send', $check_key_l array ( 'GOTO_GALLERY_TITLE' => $conf['gallery_title'], - 'GOTO_GALLERY_URL' => get_gallery_home_url(), + 'GOTO_GALLERY_URL' => add_url_params(get_gallery_home_url(), $add_url_params), 'SEND_AS_NAME' => $env_nbm['send_as_name'], ) ); @@ -389,6 +400,7 @@ function do_action_send_mail_notification($action = 'list_to_send', $check_key_l '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, ) ); @@ -707,6 +719,20 @@ switch ($page['mode']) } } $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; } } diff --git a/admin/permalinks.php b/admin/permalinks.php index 72f951322..e09a2130b 100644 --- a/admin/permalinks.php +++ b/admin/permalinks.php @@ -2,7 +2,7 @@ // +-----------------------------------------------------------------------+ // | Piwigo - a PHP based photo gallery | // +-----------------------------------------------------------------------+ -// | Copyright(C) 2008-2014 Piwigo Team http://piwigo.org | +// | Copyright(C) 2008-2016 Piwigo Team http://piwigo.org | // | Copyright(C) 2003-2008 PhpWebGallery Team http://phpwebgallery.net | // | Copyright(C) 2002-2003 Pierrick LE GALL http://le-gall.net/pierrick | // +-----------------------------------------------------------------------+ diff --git a/admin/photo.php b/admin/photo.php index b99a76cfd..c1d0687a9 100644 --- a/admin/photo.php +++ b/admin/photo.php @@ -2,7 +2,7 @@ // +-----------------------------------------------------------------------+ // | Piwigo - a PHP based photo gallery | // +-----------------------------------------------------------------------+ -// | Copyright(C) 2008-2014 Piwigo Team http://piwigo.org | +// | Copyright(C) 2008-2016 Piwigo Team http://piwigo.org | // | Copyright(C) 2003-2008 PhpWebGallery Team http://phpwebgallery.net | // | Copyright(C) 2002-2003 Pierrick LE GALL http://le-gall.net/pierrick | // +-----------------------------------------------------------------------+ diff --git a/admin/photos_add.php b/admin/photos_add.php index 72bf99158..457e28150 100644 --- a/admin/photos_add.php +++ b/admin/photos_add.php @@ -2,7 +2,7 @@ // +-----------------------------------------------------------------------+ // | Piwigo - a PHP based photo gallery | // +-----------------------------------------------------------------------+ -// | Copyright(C) 2008-2014 Piwigo Team http://piwigo.org | +// | Copyright(C) 2008-2016 Piwigo Team http://piwigo.org | // | Copyright(C) 2003-2008 PhpWebGallery Team http://phpwebgallery.net | // | Copyright(C) 2002-2003 Pierrick LE GALL http://le-gall.net/pierrick | // +-----------------------------------------------------------------------+ diff --git a/admin/photos_add_applications.php b/admin/photos_add_applications.php index 82c95fddf..1cb35e939 100644 --- a/admin/photos_add_applications.php +++ b/admin/photos_add_applications.php @@ -2,7 +2,7 @@ // +-----------------------------------------------------------------------+ // | Piwigo - a PHP based photo gallery | // +-----------------------------------------------------------------------+ -// | Copyright(C) 2008-2014 Piwigo Team http://piwigo.org | +// | Copyright(C) 2008-2016 Piwigo Team http://piwigo.org | // | Copyright(C) 2003-2008 PhpWebGallery Team http://phpwebgallery.net | // | Copyright(C) 2002-2003 Pierrick LE GALL http://le-gall.net/pierrick | // +-----------------------------------------------------------------------+ diff --git a/admin/photos_add_direct.php b/admin/photos_add_direct.php index 9f3e88866..fd4efe5f7 100644 --- a/admin/photos_add_direct.php +++ b/admin/photos_add_direct.php @@ -2,7 +2,7 @@ // +-----------------------------------------------------------------------+ // | Piwigo - a PHP based photo gallery | // +-----------------------------------------------------------------------+ -// | Copyright(C) 2008-2014 Piwigo Team http://piwigo.org | +// | Copyright(C) 2008-2016 Piwigo Team http://piwigo.org | // | Copyright(C) 2003-2008 PhpWebGallery Team http://phpwebgallery.net | // | Copyright(C) 2002-2003 Pierrick LE GALL http://le-gall.net/pierrick | // +-----------------------------------------------------------------------+ diff --git a/admin/photos_add_ftp.php b/admin/photos_add_ftp.php index 5655d0f6e..e48a23754 100644 --- a/admin/photos_add_ftp.php +++ b/admin/photos_add_ftp.php @@ -2,7 +2,7 @@ // +-----------------------------------------------------------------------+ // | Piwigo - a PHP based photo gallery | // +-----------------------------------------------------------------------+ -// | Copyright(C) 2008-2014 Piwigo Team http://piwigo.org | +// | Copyright(C) 2008-2016 Piwigo Team http://piwigo.org | // | Copyright(C) 2003-2008 PhpWebGallery Team http://phpwebgallery.net | // | Copyright(C) 2002-2003 Pierrick LE GALL http://le-gall.net/pierrick | // +-----------------------------------------------------------------------+ diff --git a/admin/picture_coi.php b/admin/picture_coi.php index 6ad8fa98c..26540d63e 100644 --- a/admin/picture_coi.php +++ b/admin/picture_coi.php @@ -2,7 +2,7 @@ // +-----------------------------------------------------------------------+ // | Piwigo - a PHP based photo gallery | // +-----------------------------------------------------------------------+ -// | Copyright(C) 2008-2014 Piwigo Team http://piwigo.org | +// | Copyright(C) 2008-2016 Piwigo Team http://piwigo.org | // | Copyright(C) 2003-2008 PhpWebGallery Team http://phpwebgallery.net | // | Copyright(C) 2002-2003 Pierrick LE GALL http://le-gall.net/pierrick | // +-----------------------------------------------------------------------+ diff --git a/admin/picture_modify.php b/admin/picture_modify.php index bf0e458e6..ab62c5624 100644 --- a/admin/picture_modify.php +++ b/admin/picture_modify.php @@ -2,7 +2,7 @@ // +-----------------------------------------------------------------------+ // | Piwigo - a PHP based photo gallery | // +-----------------------------------------------------------------------+ -// | Copyright(C) 2008-2014 Piwigo Team http://piwigo.org | +// | Copyright(C) 2008-2016 Piwigo Team http://piwigo.org | // | Copyright(C) 2003-2008 PhpWebGallery Team http://phpwebgallery.net | // | Copyright(C) 2002-2003 Pierrick LE GALL http://le-gall.net/pierrick | // +-----------------------------------------------------------------------+ @@ -306,6 +306,25 @@ SELECT $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); diff --git a/admin/plugin.php b/admin/plugin.php index dd6d989e9..68e0c50d7 100644 --- a/admin/plugin.php +++ b/admin/plugin.php @@ -2,7 +2,7 @@ // +-----------------------------------------------------------------------+ // | Piwigo - a PHP based photo gallery | // +-----------------------------------------------------------------------+ -// | Copyright(C) 2008-2014 Piwigo Team http://piwigo.org | +// | Copyright(C) 2008-2016 Piwigo Team http://piwigo.org | // | Copyright(C) 2003-2008 PhpWebGallery Team http://phpwebgallery.net | // | Copyright(C) 2002-2003 Pierrick LE GALL http://le-gall.net/pierrick | // +-----------------------------------------------------------------------+ diff --git a/admin/plugins.php b/admin/plugins.php index efe3bd833..9377affdb 100644 --- a/admin/plugins.php +++ b/admin/plugins.php @@ -2,7 +2,7 @@ // +-----------------------------------------------------------------------+ // | Piwigo - a PHP based photo gallery | // +-----------------------------------------------------------------------+ -// | Copyright(C) 2008-2014 Piwigo Team http://piwigo.org | +// | Copyright(C) 2008-2016 Piwigo Team http://piwigo.org | // | Copyright(C) 2003-2008 PhpWebGallery Team http://phpwebgallery.net | // | Copyright(C) 2002-2003 Pierrick LE GALL http://le-gall.net/pierrick | // +-----------------------------------------------------------------------+ diff --git a/admin/plugins_installed.php b/admin/plugins_installed.php index a804e21ce..b87921c02 100644 --- a/admin/plugins_installed.php +++ b/admin/plugins_installed.php @@ -2,7 +2,7 @@ // +-----------------------------------------------------------------------+ // | Piwigo - a PHP based photo gallery | // +-----------------------------------------------------------------------+ -// | Copyright(C) 2008-2014 Piwigo Team http://piwigo.org | +// | Copyright(C) 2008-2016 Piwigo Team http://piwigo.org | // | Copyright(C) 2003-2008 PhpWebGallery Team http://phpwebgallery.net | // | Copyright(C) 2002-2003 Pierrick LE GALL http://le-gall.net/pierrick | // +-----------------------------------------------------------------------+ diff --git a/admin/plugins_new.php b/admin/plugins_new.php index a8df9359c..2ef02f1bb 100644 --- a/admin/plugins_new.php +++ b/admin/plugins_new.php @@ -2,7 +2,7 @@ // +-----------------------------------------------------------------------+ // | Piwigo - a PHP based photo gallery | // +-----------------------------------------------------------------------+ -// | Copyright(C) 2008-2014 Piwigo Team http://piwigo.org | +// | Copyright(C) 2008-2016 Piwigo Team http://piwigo.org | // | Copyright(C) 2003-2008 PhpWebGallery Team http://phpwebgallery.net | // | Copyright(C) 2002-2003 Pierrick LE GALL http://le-gall.net/pierrick | // +-----------------------------------------------------------------------+ diff --git a/admin/popuphelp.php b/admin/popuphelp.php index 7d0a0cf8b..51820fe0f 100644 --- a/admin/popuphelp.php +++ b/admin/popuphelp.php @@ -2,7 +2,7 @@ // +-----------------------------------------------------------------------+ // | Piwigo - a PHP based photo gallery | // +-----------------------------------------------------------------------+ -// | Copyright(C) 2008-2014 Piwigo Team http://piwigo.org | +// | Copyright(C) 2008-2016 Piwigo Team http://piwigo.org | // | Copyright(C) 2003-2008 PhpWebGallery Team http://phpwebgallery.net | // | Copyright(C) 2002-2003 Pierrick LE GALL http://le-gall.net/pierrick | // +-----------------------------------------------------------------------+ diff --git a/admin/profile.php b/admin/profile.php index 5554fe1cd..71a929950 100644 --- a/admin/profile.php +++ b/admin/profile.php @@ -2,7 +2,7 @@ // +-----------------------------------------------------------------------+ // | Piwigo - a PHP based photo gallery | // +-----------------------------------------------------------------------+ -// | Copyright(C) 2008-2014 Piwigo Team http://piwigo.org | +// | Copyright(C) 2008-2016 Piwigo Team http://piwigo.org | // | Copyright(C) 2003-2008 PhpWebGallery Team http://phpwebgallery.net | // | Copyright(C) 2002-2003 Pierrick LE GALL http://le-gall.net/pierrick | // +-----------------------------------------------------------------------+ diff --git a/admin/rating.php b/admin/rating.php index 1592125c6..3525cbdd1 100644 --- a/admin/rating.php +++ b/admin/rating.php @@ -2,7 +2,7 @@ // +-----------------------------------------------------------------------+ // | Piwigo - a PHP based photo gallery | // +-----------------------------------------------------------------------+ -// | Copyright(C) 2008-2014 Piwigo Team http://piwigo.org | +// | Copyright(C) 2008-2016 Piwigo Team http://piwigo.org | // | Copyright(C) 2003-2008 PhpWebGallery Team http://phpwebgallery.net | // | Copyright(C) 2002-2003 Pierrick LE GALL http://le-gall.net/pierrick | // +-----------------------------------------------------------------------+ diff --git a/admin/rating_user.php b/admin/rating_user.php index e6eea9ee9..e7789932d 100644 --- a/admin/rating_user.php +++ b/admin/rating_user.php @@ -2,7 +2,7 @@ // +-----------------------------------------------------------------------+ // | Piwigo - a PHP based photo gallery | // +-----------------------------------------------------------------------+ -// | Copyright(C) 2008-2014 Piwigo Team http://piwigo.org | +// | Copyright(C) 2008-2016 Piwigo Team http://piwigo.org | // | Copyright(C) 2003-2008 PhpWebGallery Team http://phpwebgallery.net | // | Copyright(C) 2002-2003 Pierrick LE GALL http://le-gall.net/pierrick | // +-----------------------------------------------------------------------+ diff --git a/admin/site_manager.php b/admin/site_manager.php index 21fdebd40..0712da3ea 100644 --- a/admin/site_manager.php +++ b/admin/site_manager.php @@ -2,7 +2,7 @@ // +-----------------------------------------------------------------------+ // | Piwigo - a PHP based photo gallery | // +-----------------------------------------------------------------------+ -// | Copyright(C) 2008-2014 Piwigo Team http://piwigo.org | +// | Copyright(C) 2008-2016 Piwigo Team http://piwigo.org | // | Copyright(C) 2003-2008 PhpWebGallery Team http://phpwebgallery.net | // | Copyright(C) 2002-2003 Pierrick LE GALL http://le-gall.net/pierrick | // +-----------------------------------------------------------------------+ diff --git a/admin/site_reader_local.php b/admin/site_reader_local.php index 7e618ca17..c157b38c7 100644 --- a/admin/site_reader_local.php +++ b/admin/site_reader_local.php @@ -2,7 +2,7 @@ // +-----------------------------------------------------------------------+ // | Piwigo - a PHP based photo gallery | // +-----------------------------------------------------------------------+ -// | Copyright(C) 2008-2014 Piwigo Team http://piwigo.org | +// | Copyright(C) 2008-2016 Piwigo Team http://piwigo.org | // | Copyright(C) 2003-2008 PhpWebGallery Team http://phpwebgallery.net | // | Copyright(C) 2002-2003 Pierrick LE GALL http://le-gall.net/pierrick | // +-----------------------------------------------------------------------+ @@ -100,14 +100,19 @@ function get_elements($path) { $representative_ext = $this->get_representative_ext($path, $filename_wo_ext); } - $fs[ $path.'/'.$node ] = array( - 'representative_ext' => $representative_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; @@ -182,6 +187,26 @@ function get_representative_ext($path, $filename_wo_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; +} } ?> \ No newline at end of file diff --git a/admin/site_update.php b/admin/site_update.php index 5bcaea12a..ad3ccba19 100644 --- a/admin/site_update.php +++ b/admin/site_update.php @@ -2,7 +2,7 @@ // +-----------------------------------------------------------------------+ // | Piwigo - a PHP based photo gallery | // +-----------------------------------------------------------------------+ -// | Copyright(C) 2008-2014 Piwigo Team http://piwigo.org | +// | Copyright(C) 2008-2016 Piwigo Team http://piwigo.org | // | Copyright(C) 2003-2008 PhpWebGallery Team http://phpwebgallery.net | // | Copyright(C) 2002-2003 Pierrick LE GALL http://le-gall.net/pierrick | // +-----------------------------------------------------------------------+ @@ -457,6 +457,7 @@ if (isset($_POST['submit']) and $_POST['sync'] == 'files' $start= $start_files; $fs = $site_reader->get_elements($basedir); + $template->append('footer_elements', '' ); @@ -486,6 +487,8 @@ SELECT id, path $inserts = array(); $insert_links = array(); + $insert_formats = array(); + $formats_to_delete = array(); foreach (array_diff(array_keys($fs), $db_elements) as $path) { @@ -535,20 +538,119 @@ SELECT id, path 'info' => l10n('added') ); + if ($conf['enable_formats']) + { + foreach ($fs[$path]['formats'] as $ext => $filesize) + { + $insert_formats[] = array( + 'image_id' => $insert['id'], + 'ext' => $ext, + 'filesize' => $filesize, + ); + + $infos[] = array( + 'path' => $insert['path'], + 'info' => l10n('format %s added', $ext) + ); + } + } + $caddiables[] = $insert['id']; } - if (count($inserts) > 0) + // search new/removed formats on photos already registered in database + if ($conf['enable_formats']) { - if (!$simulate) + $db_elements_flip = array_flip($db_elements); + + $existing_ids = array(); + + foreach (array_intersect_key($fs, $db_elements_flip) as $path => $existing) + { + $existing_ids[] = $db_elements_flip[$path]; + } + + $logger->debug('existing_ids', 'sync', $existing_ids); + + if (count($existing_ids) > 0) + { + $db_formats = array(); + + // find formats for existing photos (already in database) + $query = ' +SELECT * + FROM '.IMAGE_FORMAT_TABLE.' + WHERE image_id IN ('.implode(',', $existing_ids).') +;'; + $result = pwg_query($query); + while ($row = pwg_db_fetch_assoc($result)) + { + if (!isset($db_formats[$row['image_id']])) + { + $db_formats[$row['image_id']] = array(); + } + + $db_formats[$row['image_id']][$row['ext']] = $row['format_id']; + } + + // first we search the formats that were removed + foreach ($db_formats as $image_id => $formats) + { + $image_formats_to_delete = array_diff_key($formats, $fs[ $db_elements[$image_id] ]['formats']); + $logger->debug('image_formats_to_delete', 'sync', $image_formats_to_delete); + foreach ($image_formats_to_delete as $ext => $format_id) + { + $formats_to_delete[] = $format_id; + + $infos[] = array( + 'path' => $db_elements[$image_id], + 'info' => l10n('format %s removed', $ext) + ); + } + } + + // then we search for new formats on existing photos + foreach ($existing_ids as $image_id) + { + $path = $db_elements[$image_id]; + + $formats = array(); + if (isset($db_formats[$image_id])) + { + $formats = $db_formats[$image_id]; + } + + $image_formats_to_insert = array_diff_key($fs[$path]['formats'], $formats); + $logger->debug('image_formats_to_insert', 'sync', $image_formats_to_insert); + foreach ($image_formats_to_insert as $ext => $filesize) + { + $insert_formats[] = array( + 'image_id' => $image_id, + 'ext' => $ext, + 'filesize' => $filesize, + ); + + $infos[] = array( + 'path' => $db_elements[$image_id], + 'info' => l10n('format %s added', $ext) + ); + } + } + } + } + + + if (!$simulate) + { + // inserts all new elements + if (count($inserts) > 0) { - // inserts all new elements mass_inserts( IMAGES_TABLE, array_keys($inserts[0]), $inserts ); - + // inserts all links between new elements and their storage category mass_inserts( IMAGE_CATEGORY_TABLE, @@ -562,9 +664,30 @@ SELECT id, path fill_caddie($caddiables); } } - $counts['new_elements'] = count($inserts); + + // inserts all formats + if (count($insert_formats) > 0) + { + mass_inserts( + IMAGE_FORMAT_TABLE, + array_keys($insert_formats[0]), + $insert_formats + ); + } + + if (count($formats_to_delete) > 0) + { + $query = ' +DELETE + FROM '.IMAGE_FORMAT_TABLE.' + WHERE format_id IN ('.implode(',', $formats_to_delete).') +;'; + pwg_query($query); + } } + $counts['new_elements'] = count($inserts); + // delete elements that are in database but not in the filesystem $to_delete_elements = array(); foreach (array_diff($db_elements, array_keys($fs)) as $path) diff --git a/admin/stats.php b/admin/stats.php index e103c2ea9..5398d0b26 100644 --- a/admin/stats.php +++ b/admin/stats.php @@ -2,7 +2,7 @@ // +-----------------------------------------------------------------------+ // | Piwigo - a PHP based photo gallery | // +-----------------------------------------------------------------------+ -// | Copyright(C) 2008-2014 Piwigo Team http://piwigo.org | +// | Copyright(C) 2008-2016 Piwigo Team http://piwigo.org | // | Copyright(C) 2003-2008 PhpWebGallery Team http://phpwebgallery.net | // | Copyright(C) 2002-2003 Pierrick LE GALL http://le-gall.net/pierrick | // +-----------------------------------------------------------------------+ diff --git a/admin/tags.php b/admin/tags.php index c643391c9..ce503ba67 100644 --- a/admin/tags.php +++ b/admin/tags.php @@ -2,7 +2,7 @@ // +-----------------------------------------------------------------------+ // | Piwigo - a PHP based photo gallery | // +-----------------------------------------------------------------------+ -// | Copyright(C) 2008-2014 Piwigo Team http://piwigo.org | +// | Copyright(C) 2008-2016 Piwigo Team http://piwigo.org | // | Copyright(C) 2003-2008 PhpWebGallery Team http://phpwebgallery.net | // | Copyright(C) 2002-2003 Pierrick LE GALL http://le-gall.net/pierrick | // +-----------------------------------------------------------------------+ diff --git a/admin/theme.php b/admin/theme.php index 984ac451b..eef3fb199 100644 --- a/admin/theme.php +++ b/admin/theme.php @@ -2,7 +2,7 @@ // +-----------------------------------------------------------------------+ // | Piwigo - a PHP based photo gallery | // +-----------------------------------------------------------------------+ -// | Copyright(C) 2008-2014 Piwigo Team http://piwigo.org | +// | Copyright(C) 2008-2016 Piwigo Team http://piwigo.org | // | Copyright(C) 2003-2008 PhpWebGallery Team http://phpwebgallery.net | // | Copyright(C) 2002-2003 Pierrick LE GALL http://le-gall.net/pierrick | // +-----------------------------------------------------------------------+ diff --git a/admin/themes.php b/admin/themes.php index 5359974f4..a903ddb8f 100644 --- a/admin/themes.php +++ b/admin/themes.php @@ -2,7 +2,7 @@ // +-----------------------------------------------------------------------+ // | Piwigo - a PHP based photo gallery | // +-----------------------------------------------------------------------+ -// | Copyright(C) 2008-2014 Piwigo Team http://piwigo.org | +// | Copyright(C) 2008-2016 Piwigo Team http://piwigo.org | // | Copyright(C) 2003-2008 PhpWebGallery Team http://phpwebgallery.net | // | Copyright(C) 2002-2003 Pierrick LE GALL http://le-gall.net/pierrick | // +-----------------------------------------------------------------------+ diff --git a/admin/themes/clear/icon/index.php b/admin/themes/clear/icon/index.php index e3365959c..6a7aa65b4 100644 --- a/admin/themes/clear/icon/index.php +++ b/admin/themes/clear/icon/index.php @@ -2,7 +2,7 @@ // +-----------------------------------------------------------------------+ // | Piwigo - a PHP based photo gallery | // +-----------------------------------------------------------------------+ -// | Copyright(C) 2008-2014 Piwigo Team http://piwigo.org | +// | Copyright(C) 2008-2016 Piwigo Team http://piwigo.org | // | Copyright(C) 2003-2008 PhpWebGallery Team http://phpwebgallery.net | // | Copyright(C) 2002-2003 Pierrick LE GALL http://le-gall.net/pierrick | // +-----------------------------------------------------------------------+ diff --git a/admin/themes/clear/index.php b/admin/themes/clear/index.php index d959f2c09..f08fc4442 100644 --- a/admin/themes/clear/index.php +++ b/admin/themes/clear/index.php @@ -2,7 +2,7 @@ // +-----------------------------------------------------------------------+ // | Piwigo - a PHP based photo gallery | // +-----------------------------------------------------------------------+ -// | Copyright(C) 2008-2014 Piwigo Team http://piwigo.org | +// | Copyright(C) 2008-2016 Piwigo Team http://piwigo.org | // | Copyright(C) 2003-2008 PhpWebGallery Team http://phpwebgallery.net | // | Copyright(C) 2002-2003 Pierrick LE GALL http://le-gall.net/pierrick | // +-----------------------------------------------------------------------+ diff --git a/admin/themes/default/fontello/README.txt b/admin/themes/default/fontello/README.txt index 43e23f283..a91438a9a 100644 --- a/admin/themes/default/fontello/README.txt +++ b/admin/themes/default/fontello/README.txt @@ -11,7 +11,7 @@ webfont pack. Details available in LICENSE.txt file. - If your project is open-source, usually, it will be ok to make LICENSE.txt file publically available in your repository. -- Fonts, used in Fontello, don't require to make clickable links on your site. +- Fonts, used in Fontello, don't require a clickable link on your site. But any kind of additional authors crediting is welcome. ================================================================================ @@ -29,8 +29,8 @@ Comments on archive content - LICENSE.txt - license info about source fonts, used to build your one. -- config.json - keeps your settings. You can import it back to fontello anytime, - to continue your work +- config.json - keeps your settings. You can import it back into fontello + anytime, to continue your work Why so many CSS files ? @@ -38,17 +38,17 @@ Why so many CSS files ? Because we like to fit all your needs :) -- basic file, .css - is usually enougth, in contains @font-face - and character codes definition +- basic file, .css - is usually enough, it contains @font-face + and character code definitions - *-ie7.css - if you need IE7 support, but still don't wish to put char codes directly into html - *-codes.css and *-ie7-codes.css - if you like to use your own @font-face - rules, but still wish to benefit of css generation. That can be very - convenient for automated assets build systems. When you need to update font - - no needs to manually edit files, just override old version with archive - content. See fontello source codes for example. + rules, but still wish to benefit from css generation. That can be very + convenient for automated asset build systems. When you need to update font - + no need to manually edit files, just override old version with archive + content. See fontello source code for examples. - *-embedded.css - basic css file, but with embedded WOFF font, to avoid CORS issues in Firefox and IE9+, when fonts are hosted on the separate domain. @@ -63,11 +63,11 @@ Because we like to fit all your needs :) Attention for server setup -------------------------- -You MUST setup server to reply with proper `mime-types` for font files. In other -case, some browsers will fail to show fonts. +You MUST setup server to reply with proper `mime-types` for font files - +otherwise some browsers will fail to show fonts. Usually, `apache` already has necessary settings, but `nginx` and other -webservers should be tuned. Here is list of mime types for our file extentions: +webservers should be tuned. Here is list of mime types for our file extensions: - `application/vnd.ms-fontobject` - eot - `application/x-font-woff` - woff diff --git a/admin/themes/default/fontello/config.json b/admin/themes/default/fontello/config.json index 16b7c6070..20c3fe735 100644 --- a/admin/themes/default/fontello/config.json +++ b/admin/themes/default/fontello/config.json @@ -384,6 +384,12 @@ "code": 59407, "src": "iconic" }, + { + "uid": "862129f833b09f3d34ae39acf8484a7b", + "css": "heart-broken", + "code": 59429, + "src": "mfglabs" + }, { "uid": "05ef9b5e8742971aa85b23cfcbe71594", "css": "users", diff --git a/admin/themes/default/fontello/css/fontello-codes.css b/admin/themes/default/fontello/css/fontello-codes.css index b569e79a5..d31cf3433 100644 --- a/admin/themes/default/fontello/css/fontello-codes.css +++ b/admin/themes/default/fontello/css/fontello-codes.css @@ -52,6 +52,7 @@ .icon-cancel:before { content: '\e822'; } /* '' */ .icon-plus:before { content: '\e823'; } /* '' */ .icon-ok-circled:before { content: '\e824'; } /* '' */ +.icon-heart-broken:before { content: '\e825'; } /* '' */ .icon-zoom-in:before { content: '\e827'; } /* '' */ .icon-zoom-out:before { content: '\e828'; } /* '' */ .icon-tasks:before { content: '\f0ae'; } /* '' */ diff --git a/admin/themes/default/fontello/css/fontello-embedded.css b/admin/themes/default/fontello/css/fontello-embedded.css index c30c9f768..e17d676a8 100644 --- a/admin/themes/default/fontello/css/fontello-embedded.css +++ b/admin/themes/default/fontello/css/fontello-embedded.css @@ -2,16 +2,16 @@ @font-face { font-family: 'fontello'; - src: url('../font/fontello.eot?76878460'); - src: url('../font/fontello.eot?76878460#iefix') format('embedded-opentype'), - url('../font/fontello.svg?76878460#fontello') format('svg'); + src: url('../font/fontello.eot?37675340'); + src: url('../font/fontello.eot?37675340#iefix') format('embedded-opentype'), + url('../font/fontello.svg?37675340#fontello') format('svg'); font-weight: normal; font-style: normal; } @font-face { font-family: 'fontello'; - src: url('data:application/octet-stream;base64,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') format('woff'), - url('data:application/octet-stream;base64,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IzixKwEUKy2wQSyxCAQlQrAAFrAEJbAEJSAuRyNHI2EgsAQjQrAJQysgsGBQWCCwQFFYswIgAyAbswImAxpZQkIjIEewBEOwAmIgsABQWLBAYFlmsAFjYCCwASsgiophILACQ2BkI7ADQ2FkUFiwAkNhG7ADQ2BZsAMlsAJiILAAUFiwQGBZZrABY2GwAiVGYTgjIDwjOBshICBGI0ewASsjYTghWbErARQrLbBCLLA1Ky6xKwEUKy2wQyywNishIyAgPLAEI0IjOLErARQrsARDLrArKy2wRCywABUgR7AAI0KyAAEBFRQTLrAxKi2wRSywABUgR7AAI0KyAAEBFRQTLrAxKi2wRiyxAAEUE7AyKi2wRyywNCotsEgssAAWRSMgLiBGiiNhOLErARQrLbBJLLAII0KwSCstsEossgAAQSstsEsssgABQSstsEwssgEAQSstsE0ssgEBQSstsE4ssgAAQistsE8ssgABQistsFAssgEAQistsFEssgEBQistsFIssgAAPistsFMssgABPistsFQssgEAPistsFUssgEBPistsFYssgAAQCstsFcssgABQCstsFgssgEAQCstsFkssgEBQCstsFossgAAQystsFsssgABQystsFwssgEAQystsF0ssgEBQystsF4ssgAAPystsF8ssgABPystsGAssgEAPystsGEssgEBPystsGIssDcrLrErARQrLbBjLLA3K7A7Ky2wZCywNyuwPCstsGUssAAWsDcrsD0rLbBmLLA4Ky6xKwEUKy2wZyywOCuwOystsGgssDgrsDwrLbBpLLA4K7A9Ky2waiywOSsusSsBFCstsGsssDkrsDsrLbBsLLA5K7A8Ky2wbSywOSuwPSstsG4ssDorLrErARQrLbBvLLA6K7A7Ky2wcCywOiuwPCstsHEssDorsD0rLbByLLMJBAIDRVghGyMhWUIrsAhlsAMkUHiwARUwLQBLuADIUlixAQGOWbABuQgACABjcLEABUKxAAAqsQAFQrEACCqxAAVCsQAIKrEABUK5AAAACSqxAAVCuQAAAAkqsQMARLEkAYhRWLBAiFixA2REsSYBiFFYugiAAAEEQIhjVFixAwBEWVlZWbEADCq4Af+FsASNsQIARAA=') format('truetype'); + src: url('data:application/octet-stream;base64,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') format('woff'), + url('data:application/octet-stream;base64,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JUmwAiVhuQgACABjYyMgWGIbIVljuAQAYiCwAFBYsEBgWWawAWNgIy4jICA8ijgjIVktsDossAAWILAIQyAuRyNHI2EgYLAgYGawAmIgsABQWLBAYFlmsAFjIyAgPIo4LbA7LCMgLkawAiVGUlggPFkusSsBFCstsDwsIyAuRrACJUZQWCA8WS6xKwEUKy2wPSwjIC5GsAIlRlJYIDxZIyAuRrACJUZQWCA8WS6xKwEUKy2wPiywNSsjIC5GsAIlRlJYIDxZLrErARQrLbA/LLA2K4ogIDywBCNCijgjIC5GsAIlRlJYIDxZLrErARQrsARDLrArKy2wQCywABawBCWwBCYgLkcjRyNhsAlDKyMgPCAuIzixKwEUKy2wQSyxCAQlQrAAFrAEJbAEJSAuRyNHI2EgsAQjQrAJQysgsGBQWCCwQFFYswIgAyAbswImAxpZQkIjIEewBEOwAmIgsABQWLBAYFlmsAFjYCCwASsgiophILACQ2BkI7ADQ2FkUFiwAkNhG7ADQ2BZsAMlsAJiILAAUFiwQGBZZrABY2GwAiVGYTgjIDwjOBshICBGI0ewASsjYTghWbErARQrLbBCLLA1Ky6xKwEUKy2wQyywNishIyAgPLAEI0IjOLErARQrsARDLrArKy2wRCywABUgR7AAI0KyAAEBFRQTLrAxKi2wRSywABUgR7AAI0KyAAEBFRQTLrAxKi2wRiyxAAEUE7AyKi2wRyywNCotsEgssAAWRSMgLiBGiiNhOLErARQrLbBJLLAII0KwSCstsEossgAAQSstsEsssgABQSstsEwssgEAQSstsE0ssgEBQSstsE4ssgAAQistsE8ssgABQistsFAssgEAQistsFEssgEBQistsFIssgAAPistsFMssgABPistsFQssgEAPistsFUssgEBPistsFYssgAAQCstsFcssgABQCstsFgssgEAQCstsFkssgEBQCstsFossgAAQystsFsssgABQystsFwssgEAQystsF0ssgEBQystsF4ssgAAPystsF8ssgABPystsGAssgEAPystsGEssgEBPystsGIssDcrLrErARQrLbBjLLA3K7A7Ky2wZCywNyuwPCstsGUssAAWsDcrsD0rLbBmLLA4Ky6xKwEUKy2wZyywOCuwOystsGgssDgrsDwrLbBpLLA4K7A9Ky2waiywOSsusSsBFCstsGsssDkrsDsrLbBsLLA5K7A8Ky2wbSywOSuwPSstsG4ssDorLrErARQrLbBvLLA6K7A7Ky2wcCywOiuwPCstsHEssDorsD0rLbByLLMJBAIDRVghGyMhWUIrsAhlsAMkUHiwARUwLQBLuADIUlixAQGOWbABuQgACABjcLEABUKxAAAqsQAFQrEACCqxAAVCsQAIKrEABUK5AAAACSqxAAVCuQAAAAkqsQMARLEkAYhRWLBAiFixA2REsSYBiFFYugiAAAEEQIhjVFixAwBEWVlZWbEADCq4Af+FsASNsQIARAA=') format('truetype'); } /* Chrome hack: SVG is rendered more smooth in Windozze. 100% magic, uncomment if you need it. */ /* Note, that will break hinting! In other OS-es font will be not as sharp as it could be */ @@ -19,7 +19,7 @@ @media screen and (-webkit-min-device-pixel-ratio:0) { @font-face { font-family: 'fontello'; - src: url('../font/fontello.svg?76878460#fontello') format('svg'); + src: url('../font/fontello.svg?37675340#fontello') format('svg'); } } */ @@ -105,6 +105,7 @@ .icon-cancel:before { content: '\e822'; } /* '' */ .icon-plus:before { content: '\e823'; } /* '' */ .icon-ok-circled:before { content: '\e824'; } /* '' */ +.icon-heart-broken:before { content: '\e825'; } /* '' */ .icon-zoom-in:before { content: '\e827'; } /* '' */ .icon-zoom-out:before { content: '\e828'; } /* '' */ .icon-tasks:before { content: '\f0ae'; } /* '' */ diff --git a/admin/themes/default/fontello/css/fontello-ie7-codes.css b/admin/themes/default/fontello/css/fontello-ie7-codes.css index 49cd55343..708cfdf4a 100644 --- a/admin/themes/default/fontello/css/fontello-ie7-codes.css +++ b/admin/themes/default/fontello/css/fontello-ie7-codes.css @@ -50,6 +50,7 @@ .icon-cancel { *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = ' '); } .icon-plus { *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = ' '); } .icon-ok-circled { *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = ' '); } +.icon-heart-broken { *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = ' '); } .icon-zoom-in { *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = ' '); } .icon-zoom-out { *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = ' '); } .icon-tasks { *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = ' '); } diff --git a/admin/themes/default/fontello/css/fontello-ie7.css b/admin/themes/default/fontello/css/fontello-ie7.css index 9eec9e6d1..c1e1ec524 100644 --- a/admin/themes/default/fontello/css/fontello-ie7.css +++ b/admin/themes/default/fontello/css/fontello-ie7.css @@ -61,6 +61,7 @@ .icon-cancel { *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = ' '); } .icon-plus { *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = ' '); } .icon-ok-circled { *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = ' '); } +.icon-heart-broken { *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = ' '); } .icon-zoom-in { *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = ' '); } .icon-zoom-out { *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = ' '); } .icon-tasks { *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = ' '); } diff --git a/admin/themes/default/fontello/css/fontello.css b/admin/themes/default/fontello/css/fontello.css index 9b3319d7c..40777f186 100644 --- a/admin/themes/default/fontello/css/fontello.css +++ b/admin/themes/default/fontello/css/fontello.css @@ -2,11 +2,11 @@ @font-face { font-family: 'fontello'; - src: url('../font/fontello.eot?80487531'); - src: url('../font/fontello.eot?80487531#iefix') format('embedded-opentype'), - url('../font/fontello.woff?80487531') format('woff'), - url('../font/fontello.ttf?80487531') format('truetype'), - url('../font/fontello.svg?80487531#fontello') format('svg'); + src: url('../font/fontello.eot?38260160'); + src: url('../font/fontello.eot?38260160#iefix') format('embedded-opentype'), + url('../font/fontello.woff?38260160') format('woff'), + url('../font/fontello.ttf?38260160') format('truetype'), + url('../font/fontello.svg?38260160#fontello') format('svg'); font-weight: normal; font-style: normal; } @@ -16,7 +16,7 @@ @media screen and (-webkit-min-device-pixel-ratio:0) { @font-face { font-family: 'fontello'; - src: url('../font/fontello.svg?80487531#fontello') format('svg'); + src: url('../font/fontello.svg?38260160#fontello') format('svg'); } } */ @@ -37,7 +37,7 @@ /* For safety - reset parent styles, that can break glyph codes*/ font-variant: normal; text-transform: none; - + /* fix buttons height, for twitter bootstrap */ line-height: 1em; @@ -48,6 +48,10 @@ /* you can be more comfortable with increased icons size */ /* font-size: 120%; */ + /* Font smoothing. That was taken from TWBS */ + -webkit-font-smoothing: antialiased; + -moz-osx-font-smoothing: grayscale; + /* Uncomment for 3D effect */ /* text-shadow: 1px 1px 1px rgba(127, 127, 127, 0.3); */ } @@ -103,6 +107,7 @@ .icon-cancel:before { content: '\e822'; } /* '' */ .icon-plus:before { content: '\e823'; } /* '' */ .icon-ok-circled:before { content: '\e824'; } /* '' */ +.icon-heart-broken:before { content: '\e825'; } /* '' */ .icon-zoom-in:before { content: '\e827'; } /* '' */ .icon-zoom-out:before { content: '\e828'; } /* '' */ .icon-tasks:before { content: '\f0ae'; } /* '' */ diff --git a/admin/themes/default/fontello/demo.html b/admin/themes/default/fontello/demo.html index eeb1903f4..c7bd65f9e 100644 --- a/admin/themes/default/fontello/demo.html +++ b/admin/themes/default/fontello/demo.html @@ -227,8 +227,54 @@ body { .i-code { display: none; } - - +@font-face { + font-family: 'fontello'; + src: url('./font/fontello.eot?58887028'); + src: url('./font/fontello.eot?58887028#iefix') format('embedded-opentype'), + url('./font/fontello.woff?58887028') format('woff'), + url('./font/fontello.ttf?58887028') format('truetype'), + url('./font/fontello.svg?58887028#fontello') format('svg'); + font-weight: normal; + font-style: normal; + } + + + .demo-icon + { + font-family: "fontello"; + font-style: normal; + font-weight: normal; + speak: none; + + display: inline-block; + text-decoration: inherit; + width: 1em; + margin-right: .2em; + text-align: center; + /* opacity: .8; */ + + /* For safety - reset parent styles, that can break glyph codes*/ + font-variant: normal; + text-transform: none; + + /* fix buttons height, for twitter bootstrap */ + line-height: 1em; + + /* Animation center compensation - margins should be symmetric */ + /* remove if not needed */ + margin-left: .2em; + + /* You can be more comfortable with increased icons size */ + /* font-size: 120%; */ + + /* Font smoothing. That was taken from TWBS */ + -webkit-font-smoothing: antialiased; + -moz-osx-font-smoothing: grayscale; + + /* Uncomment for 3D effect */ + /* text-shadow: 1px 1px 1px rgba(127, 127, 127, 0.3); */ + } + + +
+
+
\ No newline at end of file diff --git a/admin/themes/default/theme.css b/admin/themes/default/theme.css index 4a151b9a4..0aa0dba1a 100644 --- a/admin/themes/default/theme.css +++ b/admin/themes/default/theme.css @@ -213,7 +213,7 @@ LI.menuLi { } /* */ -FORM#catModify TABLE { width: auto; } +#catModify TABLE { width: auto; } #catModify p { line-height: 20px; @@ -221,6 +221,11 @@ FORM#catModify TABLE { width: auto; } text-align: left; } +#catModify p.albumThumbnailActions { + text-align:center; + white-space:nowrap; +} + FIELDSET.elementEdit .thumb { display: block; float: right; @@ -1223,6 +1228,21 @@ a.group_perm { .userProperty {width:340px;float:left;margin-bottom:15px;} .userActions {float:right;text-align:right;} +.user_form_popin { + width:750px; + height:430px; + padding:20px; +} + +.userProperties form { + text-align:left; +} + +.popinWait { + padding-top:200px; +} + + .preview-box.icon-zoom-in { display:block; position:relative; diff --git a/admin/themes/roma/index.php b/admin/themes/roma/index.php index c8de97f60..0b96c3efa 100644 --- a/admin/themes/roma/index.php +++ b/admin/themes/roma/index.php @@ -2,7 +2,7 @@ // +-----------------------------------------------------------------------+ // | Piwigo - a PHP based photo gallery | // +-----------------------------------------------------------------------+ -// | Copyright(C) 2008-2014 Piwigo Team http://piwigo.org | +// | Copyright(C) 2008-2016 Piwigo Team http://piwigo.org | // | Copyright(C) 2003-2008 PhpWebGallery Team http://phpwebgallery.net | // | Copyright(C) 2002-2003 Pierrick LE GALL http://le-gall.net/pierrick | // +-----------------------------------------------------------------------+ diff --git a/admin/themes_installed.php b/admin/themes_installed.php index eb16dc144..f798f21f1 100644 --- a/admin/themes_installed.php +++ b/admin/themes_installed.php @@ -2,7 +2,7 @@ // +-----------------------------------------------------------------------+ // | Piwigo - a PHP based photo gallery | // +-----------------------------------------------------------------------+ -// | Copyright(C) 2008-2014 Piwigo Team http://piwigo.org | +// | Copyright(C) 2008-2016 Piwigo Team http://piwigo.org | // | Copyright(C) 2003-2008 PhpWebGallery Team http://phpwebgallery.net | // | Copyright(C) 2002-2003 Pierrick LE GALL http://le-gall.net/pierrick | // +-----------------------------------------------------------------------+ diff --git a/admin/themes_new.php b/admin/themes_new.php index 803327e8d..e1360792b 100644 --- a/admin/themes_new.php +++ b/admin/themes_new.php @@ -2,7 +2,7 @@ // +-----------------------------------------------------------------------+ // | Piwigo - a PHP based photo gallery | // +-----------------------------------------------------------------------+ -// | Copyright(C) 2008-2014 Piwigo Team http://piwigo.org | +// | Copyright(C) 2008-2016 Piwigo Team http://piwigo.org | // | Copyright(C) 2003-2008 PhpWebGallery Team http://phpwebgallery.net | // | Copyright(C) 2002-2003 Pierrick LE GALL http://le-gall.net/pierrick | // +-----------------------------------------------------------------------+ diff --git a/admin/updates.php b/admin/updates.php index bfd6b6a1f..a38a0e538 100644 --- a/admin/updates.php +++ b/admin/updates.php @@ -2,7 +2,7 @@ // +-----------------------------------------------------------------------+ // | Piwigo - a PHP based photo gallery | // +-----------------------------------------------------------------------+ -// | Copyright(C) 2008-2014 Piwigo Team http://piwigo.org | +// | Copyright(C) 2008-2016 Piwigo Team http://piwigo.org | // | Copyright(C) 2003-2008 PhpWebGallery Team http://phpwebgallery.net | // | Copyright(C) 2002-2003 Pierrick LE GALL http://le-gall.net/pierrick | // +-----------------------------------------------------------------------+ diff --git a/admin/updates_ext.php b/admin/updates_ext.php index 72b2e13a7..c8586f08d 100644 --- a/admin/updates_ext.php +++ b/admin/updates_ext.php @@ -2,7 +2,7 @@ // +-----------------------------------------------------------------------+ // | Piwigo - a PHP based photo gallery | // +-----------------------------------------------------------------------+ -// | Copyright(C) 2008-2014 Piwigo Team http://piwigo.org | +// | Copyright(C) 2008-2016 Piwigo Team http://piwigo.org | // | Copyright(C) 2003-2008 PhpWebGallery Team http://phpwebgallery.net | // | Copyright(C) 2002-2003 Pierrick LE GALL http://le-gall.net/pierrick | // +-----------------------------------------------------------------------+ diff --git a/admin/updates_pwg.php b/admin/updates_pwg.php index 4619ad3bd..023ff8e48 100644 --- a/admin/updates_pwg.php +++ b/admin/updates_pwg.php @@ -2,7 +2,7 @@ // +-----------------------------------------------------------------------+ // | Piwigo - a PHP based photo gallery | // +-----------------------------------------------------------------------+ -// | Copyright(C) 2008-2014 Piwigo Team http://piwigo.org | +// | Copyright(C) 2008-2016 Piwigo Team http://piwigo.org | // | Copyright(C) 2003-2008 PhpWebGallery Team http://phpwebgallery.net | // | Copyright(C) 2002-2003 Pierrick LE GALL http://le-gall.net/pierrick | // +-----------------------------------------------------------------------+ diff --git a/admin/user_list.php b/admin/user_list.php index 83815f66f..183f771f7 100644 --- a/admin/user_list.php +++ b/admin/user_list.php @@ -2,7 +2,7 @@ // +-----------------------------------------------------------------------+ // | Piwigo - a PHP based photo gallery | // +-----------------------------------------------------------------------+ -// | Copyright(C) 2008-2014 Piwigo Team http://piwigo.org | +// | Copyright(C) 2008-2016 Piwigo Team http://piwigo.org | // | Copyright(C) 2003-2008 PhpWebGallery Team http://phpwebgallery.net | // | Copyright(C) 2002-2003 Pierrick LE GALL http://le-gall.net/pierrick | // +-----------------------------------------------------------------------+ diff --git a/admin/user_list_backend.php b/admin/user_list_backend.php index 1edaa1369..290873c87 100644 --- a/admin/user_list_backend.php +++ b/admin/user_list_backend.php @@ -2,7 +2,7 @@ // +-----------------------------------------------------------------------+ // | Piwigo - a PHP based photo gallery | // +-----------------------------------------------------------------------+ -// | Copyright(C) 2008-2014 Piwigo Team http://piwigo.org | +// | Copyright(C) 2008-2016 Piwigo Team http://piwigo.org | // | Copyright(C) 2003-2008 PhpWebGallery Team http://phpwebgallery.net | // | Copyright(C) 2002-2003 Pierrick LE GALL http://le-gall.net/pierrick | // +-----------------------------------------------------------------------+ diff --git a/admin/user_perm.php b/admin/user_perm.php index e40c064c2..68b8c60c5 100644 --- a/admin/user_perm.php +++ b/admin/user_perm.php @@ -2,7 +2,7 @@ // +-----------------------------------------------------------------------+ // | Piwigo - a PHP based photo gallery | // +-----------------------------------------------------------------------+ -// | Copyright(C) 2008-2014 Piwigo Team http://piwigo.org | +// | Copyright(C) 2008-2016 Piwigo Team http://piwigo.org | // | Copyright(C) 2003-2008 PhpWebGallery Team http://phpwebgallery.net | // | Copyright(C) 2002-2003 Pierrick LE GALL http://le-gall.net/pierrick | // +-----------------------------------------------------------------------+ diff --git a/comments.php b/comments.php index c3c470256..7b05249e8 100644 --- a/comments.php +++ b/comments.php @@ -2,7 +2,7 @@ // +-----------------------------------------------------------------------+ // | Piwigo - a PHP based photo gallery | // +-----------------------------------------------------------------------+ -// | Copyright(C) 2008-2014 Piwigo Team http://piwigo.org | +// | Copyright(C) 2008-2016 Piwigo Team http://piwigo.org | // | Copyright(C) 2003-2008 PhpWebGallery Team http://phpwebgallery.net | // | Copyright(C) 2002-2003 Pierrick LE GALL http://le-gall.net/pierrick | // +-----------------------------------------------------------------------+ diff --git a/doc/index.php b/doc/index.php index c8de97f60..0b96c3efa 100644 --- a/doc/index.php +++ b/doc/index.php @@ -2,7 +2,7 @@ // +-----------------------------------------------------------------------+ // | Piwigo - a PHP based photo gallery | // +-----------------------------------------------------------------------+ -// | Copyright(C) 2008-2014 Piwigo Team http://piwigo.org | +// | Copyright(C) 2008-2016 Piwigo Team http://piwigo.org | // | Copyright(C) 2003-2008 PhpWebGallery Team http://phpwebgallery.net | // | Copyright(C) 2002-2003 Pierrick LE GALL http://le-gall.net/pierrick | // +-----------------------------------------------------------------------+ diff --git a/feed.php b/feed.php index 24e9f6846..6a7a80855 100644 --- a/feed.php +++ b/feed.php @@ -2,7 +2,7 @@ // +-----------------------------------------------------------------------+ // | Piwigo - a PHP based photo gallery | // +-----------------------------------------------------------------------+ -// | Copyright(C) 2008-2014 Piwigo Team http://piwigo.org | +// | Copyright(C) 2008-2016 Piwigo Team http://piwigo.org | // | Copyright(C) 2003-2008 PhpWebGallery Team http://phpwebgallery.net | // | Copyright(C) 2002-2003 Pierrick LE GALL http://le-gall.net/pierrick | // +-----------------------------------------------------------------------+ diff --git a/galleries/index.php b/galleries/index.php index c8de97f60..0b96c3efa 100644 --- a/galleries/index.php +++ b/galleries/index.php @@ -2,7 +2,7 @@ // +-----------------------------------------------------------------------+ // | Piwigo - a PHP based photo gallery | // +-----------------------------------------------------------------------+ -// | Copyright(C) 2008-2014 Piwigo Team http://piwigo.org | +// | Copyright(C) 2008-2016 Piwigo Team http://piwigo.org | // | Copyright(C) 2003-2008 PhpWebGallery Team http://phpwebgallery.net | // | Copyright(C) 2002-2003 Pierrick LE GALL http://le-gall.net/pierrick | // +-----------------------------------------------------------------------+ diff --git a/i.php b/i.php index c9a807aac..6be12888b 100644 --- a/i.php +++ b/i.php @@ -2,7 +2,7 @@ // +-----------------------------------------------------------------------+ // | Piwigo - a PHP based photo gallery | // +-----------------------------------------------------------------------+ -// | Copyright(C) 2008-2014 Piwigo Team http://piwigo.org | +// | Copyright(C) 2008-2016 Piwigo Team http://piwigo.org | // +-----------------------------------------------------------------------+ // | 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 | @@ -313,6 +313,8 @@ function try_switch_source(DerivativeParams $params, $original_mtime) } else { + if ($use_watermark && $candidate->use_watermark) + continue; //a square that requires watermark should not be generated from a larger derivative with watermark, because if the watermark is not centered on the large image, it will be cropped. if ($candidate->sizing->max_crop!=0) continue; // this could be optimized if ($candidate_size[0] < $params->sizing->min_size[0] || $candidate_size[1] < $params->sizing->min_size[1] ) @@ -573,17 +575,23 @@ if ($params->will_watermark($d_size)) if ($image->compose($wm_image, $x, $y, $wm->opacity)) { $changes++; - if ($wm->xrepeat) + if ($wm->xrepeat || $wm->yrepeat) { - // todo - $pad = $wm_size[0] + max(30, round($wm_size[0]/4)); + $xpad = $wm_size[0] + max(30, round($wm_size[0]/4)); + $ypad = $wm_size[1] + max(30, round($wm_size[1]/4)); + for($i=-$wm->xrepeat; $i<=$wm->xrepeat; $i++) { - if (!$i) continue; - $x2 = $x + $i * $pad; - if ($x2>=0 && $x2+$wm_size[0]<$d_size[0]) - if (!$image->compose($wm_image, $x2, $y, $wm->opacity)) - break; + for($j=-$wm->yrepeat; $j<=$wm->yrepeat; $j++) + { + if (!$i && !$j) continue; + $x2 = $x + $i * $xpad; + $y2 = $y + $j * $ypad; + if ($x2>=0 && $x2+$wm_size[0]<$d_size[0] && + $y2>=0 && $y2+$wm_size[1]<$d_size[1] ) + if (!$image->compose($wm_image, $x2, $y2, $wm->opacity)) + break; + } } } } diff --git a/identification.php b/identification.php index fe8a80263..be22eb571 100644 --- a/identification.php +++ b/identification.php @@ -2,7 +2,7 @@ // +-----------------------------------------------------------------------+ // | Piwigo - a PHP based photo gallery | // +-----------------------------------------------------------------------+ -// | Copyright(C) 2008-2014 Piwigo Team http://piwigo.org | +// | Copyright(C) 2008-2016 Piwigo Team http://piwigo.org | // | Copyright(C) 2003-2008 PhpWebGallery Team http://phpwebgallery.net | // | Copyright(C) 2002-2003 Pierrick LE GALL http://le-gall.net/pierrick | // +-----------------------------------------------------------------------+ diff --git a/include/Logger.class.php b/include/Logger.class.php index 90fa9e491..6b4172faa 100644 --- a/include/Logger.class.php +++ b/include/Logger.class.php @@ -2,7 +2,7 @@ // +-----------------------------------------------------------------------+ // | Piwigo - a PHP based photo gallery | // +-----------------------------------------------------------------------+ -// | Copyright(C) 2008-2015 Piwigo Team http://piwigo.org | +// | Copyright(C) 2008-2016 Piwigo Team http://piwigo.org | // | Copyright(C) 2003-2008 PhpWebGallery Team http://phpwebgallery.net | // | Copyright(C) 2002-2003 Pierrick LE GALL http://le-gall.net/pierrick | // +-----------------------------------------------------------------------+ diff --git a/include/block.class.php b/include/block.class.php index cce92ec4e..ea11cb82e 100644 --- a/include/block.class.php +++ b/include/block.class.php @@ -2,7 +2,7 @@ // +-----------------------------------------------------------------------+ // | Piwigo - a PHP based photo gallery | // +-----------------------------------------------------------------------+ -// | Copyright(C) 2008-2014 Piwigo Team http://piwigo.org | +// | Copyright(C) 2008-2016 Piwigo Team http://piwigo.org | // +-----------------------------------------------------------------------+ // | 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 | diff --git a/include/cache.class.php b/include/cache.class.php index 5b97cb1f1..4a1a4aa60 100644 --- a/include/cache.class.php +++ b/include/cache.class.php @@ -2,7 +2,7 @@ // +-----------------------------------------------------------------------+ // | Piwigo - a PHP based photo gallery | // +-----------------------------------------------------------------------+ -// | Copyright(C) 2008-2014 Piwigo Team http://piwigo.org | +// | Copyright(C) 2008-2016 Piwigo Team http://piwigo.org | // | Copyright(C) 2003-2008 PhpWebGallery Team http://phpwebgallery.net | // | Copyright(C) 2002-2003 Pierrick LE GALL http://le-gall.net/pierrick | // +-----------------------------------------------------------------------+ diff --git a/include/calendar_base.class.php b/include/calendar_base.class.php index f48fae1e3..020265d17 100644 --- a/include/calendar_base.class.php +++ b/include/calendar_base.class.php @@ -2,7 +2,7 @@ // +-----------------------------------------------------------------------+ // | Piwigo - a PHP based photo gallery | // +-----------------------------------------------------------------------+ -// | Copyright(C) 2008-2014 Piwigo Team http://piwigo.org | +// | Copyright(C) 2008-2016 Piwigo Team http://piwigo.org | // | Copyright(C) 2003-2008 PhpWebGallery Team http://phpwebgallery.net | // | Copyright(C) 2002-2003 Pierrick LE GALL http://le-gall.net/pierrick | // +-----------------------------------------------------------------------+ @@ -360,7 +360,7 @@ GROUP BY period'; if ( !empty($tpl_var) ) { $existing = $template->smarty->getVariable('chronology_navigation_bars'); - if (! ($existing instanceof Undefined_Smarty_Variable)) + if (! ($existing instanceof Smarty_Undefined_Variable)) { $existing->value[ sizeof($existing->value)-1 ] = array_merge( $existing->value[ sizeof($existing->value)-1 ], $tpl_var); diff --git a/include/calendar_monthly.class.php b/include/calendar_monthly.class.php index 9ab38aee7..f82849ce1 100644 --- a/include/calendar_monthly.class.php +++ b/include/calendar_monthly.class.php @@ -2,7 +2,7 @@ // +-----------------------------------------------------------------------+ // | Piwigo - a PHP based photo gallery | // +-----------------------------------------------------------------------+ -// | Copyright(C) 2008-2014 Piwigo Team http://piwigo.org | +// | Copyright(C) 2008-2016 Piwigo Team http://piwigo.org | // | Copyright(C) 2003-2008 PhpWebGallery Team http://phpwebgallery.net | // | Copyright(C) 2002-2003 Pierrick LE GALL http://le-gall.net/pierrick | // +-----------------------------------------------------------------------+ diff --git a/include/calendar_weekly.class.php b/include/calendar_weekly.class.php index 346f658d4..91ae9b7d4 100644 --- a/include/calendar_weekly.class.php +++ b/include/calendar_weekly.class.php @@ -2,7 +2,7 @@ // +-----------------------------------------------------------------------+ // | Piwigo - a PHP based photo gallery | // +-----------------------------------------------------------------------+ -// | Copyright(C) 2008-2014 Piwigo Team http://piwigo.org | +// | Copyright(C) 2008-2016 Piwigo Team http://piwigo.org | // | Copyright(C) 2003-2008 PhpWebGallery Team http://phpwebgallery.net | // | Copyright(C) 2002-2003 Pierrick LE GALL http://le-gall.net/pierrick | // +-----------------------------------------------------------------------+ diff --git a/include/category_cats.inc.php b/include/category_cats.inc.php index 4cab63d27..930594510 100644 --- a/include/category_cats.inc.php +++ b/include/category_cats.inc.php @@ -2,7 +2,7 @@ // +-----------------------------------------------------------------------+ // | Piwigo - a PHP based photo gallery | // +-----------------------------------------------------------------------+ -// | Copyright(C) 2008-2014 Piwigo Team http://piwigo.org | +// | Copyright(C) 2008-2016 Piwigo Team http://piwigo.org | // | Copyright(C) 2003-2008 PhpWebGallery Team http://phpwebgallery.net | // | Copyright(C) 2002-2003 Pierrick LE GALL http://le-gall.net/pierrick | // +-----------------------------------------------------------------------+ diff --git a/include/category_default.inc.php b/include/category_default.inc.php index 6106ccb55..6962fd08a 100644 --- a/include/category_default.inc.php +++ b/include/category_default.inc.php @@ -2,7 +2,7 @@ // +-----------------------------------------------------------------------+ // | Piwigo - a PHP based photo gallery | // +-----------------------------------------------------------------------+ -// | Copyright(C) 2008-2014 Piwigo Team http://piwigo.org | +// | Copyright(C) 2008-2016 Piwigo Team http://piwigo.org | // | Copyright(C) 2003-2008 PhpWebGallery Team http://phpwebgallery.net | // | Copyright(C) 2002-2003 Pierrick LE GALL http://le-gall.net/pierrick | // +-----------------------------------------------------------------------+ diff --git a/include/common.inc.php b/include/common.inc.php index 8fab02ab2..a01fced8a 100644 --- a/include/common.inc.php +++ b/include/common.inc.php @@ -2,7 +2,7 @@ // +-----------------------------------------------------------------------+ // | Piwigo - a PHP based photo gallery | // +-----------------------------------------------------------------------+ -// | Copyright(C) 2008-2014 Piwigo Team http://piwigo.org | +// | Copyright(C) 2008-2016 Piwigo Team http://piwigo.org | // | Copyright(C) 2003-2008 PhpWebGallery Team http://phpwebgallery.net | // | Copyright(C) 2002-2003 Pierrick LE GALL http://le-gall.net/pierrick | // +-----------------------------------------------------------------------+ @@ -26,7 +26,7 @@ defined('PHPWG_ROOT_PATH') or trigger_error('Hacking attempt!', E_USER_ERROR); // determine the initial instant to indicate the generation time of this page $t2 = microtime(true); -@set_magic_quotes_runtime(0); // Disable magic_quotes_runtime +// @set_magic_quotes_runtime(0); // Disable magic_quotes_runtime // // addslashes to vars if magic_quotes_gpc is off this is a security @@ -201,6 +201,16 @@ if (is_a_guest()) $user['username'] = l10n('guest'); } +// in case an auth key was provided and is no longer valid, we must wait to +// be here, with language loaded, to prepare the message +if (isset($page['auth_key_invalid']) and $page['auth_key_invalid']) +{ + $page['errors'][] = + l10n('Your authentication key is no longer valid.') + .sprintf(' %s', get_root_url().'identification.php', l10n('Login')) + ; +} + // template instance if (defined('IN_ADMIN') and IN_ADMIN ) {// Admin template diff --git a/include/config_default.inc.php b/include/config_default.inc.php index 09d11132e..f38942d15 100644 --- a/include/config_default.inc.php +++ b/include/config_default.inc.php @@ -2,7 +2,7 @@ // +-----------------------------------------------------------------------+ // | Piwigo - a PHP based photo gallery | // +-----------------------------------------------------------------------+ -// | Copyright(C) 2008-2014 Piwigo Team http://piwigo.org | +// | Copyright(C) 2008-2016 Piwigo Team http://piwigo.org | // | Copyright(C) 2003-2008 PhpWebGallery Team http://phpwebgallery.net | // | Copyright(C) 2002-2003 Pierrick LE GALL http://le-gall.net/pierrick | // +-----------------------------------------------------------------------+ @@ -63,6 +63,13 @@ $conf['file_ext'] = array_merge( array('tiff', 'tif', 'mpg','zip','avi','mp3','ogg','pdf') ); +// enable_formats: should Piwigo search for multiple formats? +$conf['enable_formats'] = false; + +// format_ext : file extensions for formats, ie additional versions of a +// photo (or nay other file). Formats are in sub-directory pwg_format. +$conf['format_ext'] = array('cr2', 'tif', 'tiff', 'nef', 'dng', 'ai', 'psd'); + // top_number : number of element to display for "best rated" and "most // visited" categories $conf['top_number'] = 15; @@ -639,6 +646,10 @@ $conf['recent_post_dates'] = array( // the author shown in the RSS feed element $conf['rss_feed_author'] = 'Piwigo notifier'; +// how long does the authentication key stays valid, in seconds. 3 days by +// default. 0 to disable. +$conf['auth_key_duration'] = 3*24*60*60; + // +-----------------------------------------------------------------------+ // | Set admin layout | // +-----------------------------------------------------------------------+ @@ -800,6 +811,10 @@ $conf['tiff_representative_ext'] = 'png'; // (TIFF, videos, PDF) $conf['upload_form_all_types'] = false; +// Size of chunks, in kilobytes. Fast connections will have better +// performances with high values, such as 5000. +$conf['upload_form_chunk_size'] = 500; + // If we try to generate a pwg_representative for a video we use ffmpeg. If // "ffmpeg" is not visible by the web user, you can define the full path of // the directory where "ffmpeg" executable is. @@ -817,4 +832,4 @@ $conf['log_level'] = 'DEBUG'; // Keep logs file during X days $conf['log_archive_days'] = 30; -?> \ No newline at end of file +?> diff --git a/include/constants.php b/include/constants.php index 1a7201416..8363f0d69 100644 --- a/include/constants.php +++ b/include/constants.php @@ -2,7 +2,7 @@ // +-----------------------------------------------------------------------+ // | Piwigo - a PHP based photo gallery | // +-----------------------------------------------------------------------+ -// | Copyright(C) 2008-2014 Piwigo Team http://piwigo.org | +// | Copyright(C) 2008-2016 Piwigo Team http://piwigo.org | // | Copyright(C) 2003-2008 PhpWebGallery Team http://phpwebgallery.net | // | Copyright(C) 2002-2003 Pierrick LE GALL http://le-gall.net/pierrick | // +-----------------------------------------------------------------------+ @@ -22,7 +22,7 @@ // +-----------------------------------------------------------------------+ // Default settings -define('PHPWG_VERSION', '2.7.0'); +define('PHPWG_VERSION', '2.8.0RC1'); define('PHPWG_DEFAULT_LANGUAGE', 'en_UK'); define('PHPWG_DEFAULT_TEMPLATE', 'elegant'); @@ -81,6 +81,8 @@ if (!defined('USER_FEED_TABLE')) define('USER_FEED_TABLE', $prefixeTable.'user_feed'); if (!defined('RATE_TABLE')) define('RATE_TABLE', $prefixeTable.'rate'); +if (!defined('USER_AUTH_KEYS_TABLE')) + define('USER_AUTH_KEYS_TABLE', $prefixeTable.'user_auth_keys'); if (!defined('USER_CACHE_TABLE')) define('USER_CACHE_TABLE', $prefixeTable.'user_cache'); if (!defined('USER_CACHE_CATEGORIES_TABLE')) @@ -105,5 +107,7 @@ if (!defined('THEMES_TABLE')) define('THEMES_TABLE', $prefixeTable.'themes'); if (!defined('LANGUAGES_TABLE')) define('LANGUAGES_TABLE', $prefixeTable.'languages'); +if (!defined('IMAGE_FORMAT_TABLE')) + define('IMAGE_FORMAT_TABLE', $prefixeTable.'image_format'); ?> diff --git a/include/dblayer/functions_mysql.inc.php b/include/dblayer/functions_mysql.inc.php index a1853b223..6a173686d 100644 --- a/include/dblayer/functions_mysql.inc.php +++ b/include/dblayer/functions_mysql.inc.php @@ -2,7 +2,7 @@ // +-----------------------------------------------------------------------+ // | Piwigo - a PHP based photo gallery | // +-----------------------------------------------------------------------+ -// | Copyright(C) 2008-2014 Piwigo Team http://piwigo.org | +// | Copyright(C) 2008-2016 Piwigo Team http://piwigo.org | // | Copyright(C) 2003-2008 PhpWebGallery Team http://phpwebgallery.net | // | Copyright(C) 2002-2003 Pierrick LE GALL http://le-gall.net/pierrick | // +-----------------------------------------------------------------------+ @@ -53,7 +53,7 @@ function pwg_db_check_charset() { $db_charset = DB_CHARSET; } - pwg_query('SET NAMES "'.$db_charset.'"'); + mysql_set_charset($db_charset); } function pwg_db_check_version() diff --git a/include/dblayer/functions_mysqli.inc.php b/include/dblayer/functions_mysqli.inc.php index 390cf2e06..5b40cfe5b 100644 --- a/include/dblayer/functions_mysqli.inc.php +++ b/include/dblayer/functions_mysqli.inc.php @@ -2,7 +2,7 @@ // +-----------------------------------------------------------------------+ // | Piwigo - a PHP based photo gallery | // +-----------------------------------------------------------------------+ -// | Copyright(C) 2008-2014 Piwigo Team http://piwigo.org | +// | Copyright(C) 2008-2016 Piwigo Team http://piwigo.org | // | Copyright(C) 2003-2008 PhpWebGallery Team http://phpwebgallery.net | // | Copyright(C) 2002-2003 Pierrick LE GALL http://le-gall.net/pierrick | // +-----------------------------------------------------------------------+ @@ -80,12 +80,14 @@ function pwg_db_connect($host, $user, $password, $database) */ function pwg_db_check_charset() { + global $mysqli; + $db_charset = 'utf8'; if (defined('DB_CHARSET') and DB_CHARSET != '') { $db_charset = DB_CHARSET; } - pwg_query('SET NAMES "'.$db_charset.'"'); + $mysqli->set_charset($db_charset); } /** @@ -901,4 +903,4 @@ function query2array($query, $key_name=null, $value_name=null) return $data; } -?> \ No newline at end of file +?> diff --git a/include/derivative.inc.php b/include/derivative.inc.php index a6e0642ff..8b65e8ad1 100644 --- a/include/derivative.inc.php +++ b/include/derivative.inc.php @@ -2,7 +2,7 @@ // +-----------------------------------------------------------------------+ // | Piwigo - a PHP based photo gallery | // +-----------------------------------------------------------------------+ -// | Copyright(C) 2008-2014 Piwigo Team http://piwigo.org | +// | Copyright(C) 2008-2016 Piwigo Team http://piwigo.org | // +-----------------------------------------------------------------------+ // | 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 | diff --git a/include/derivative_params.inc.php b/include/derivative_params.inc.php index cb1f22e5e..2fcd40467 100644 --- a/include/derivative_params.inc.php +++ b/include/derivative_params.inc.php @@ -2,7 +2,7 @@ // +-----------------------------------------------------------------------+ // | Piwigo - a PHP based photo gallery | // +-----------------------------------------------------------------------+ -// | Copyright(C) 2008-2014 Piwigo Team http://piwigo.org | +// | Copyright(C) 2008-2016 Piwigo Team http://piwigo.org | // +-----------------------------------------------------------------------+ // | 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 | diff --git a/include/derivative_std_params.inc.php b/include/derivative_std_params.inc.php index a0f1edb76..9fed9c15f 100644 --- a/include/derivative_std_params.inc.php +++ b/include/derivative_std_params.inc.php @@ -2,7 +2,7 @@ // +-----------------------------------------------------------------------+ // | Piwigo - a PHP based photo gallery | // +-----------------------------------------------------------------------+ -// | Copyright(C) 2008-2014 Piwigo Team http://piwigo.org | +// | Copyright(C) 2008-2016 Piwigo Team http://piwigo.org | // +-----------------------------------------------------------------------+ // | 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 | @@ -52,6 +52,8 @@ final class WatermarkParams /** @var int */ public $xrepeat = 0; /** @var int */ + public $yrepeat = 0; + /** @var int */ public $opacity = 100; } diff --git a/include/filter.inc.php b/include/filter.inc.php index 05665a036..2d0523897 100644 --- a/include/filter.inc.php +++ b/include/filter.inc.php @@ -2,7 +2,7 @@ // +-----------------------------------------------------------------------+ // | Piwigo - a PHP based photo gallery | // +-----------------------------------------------------------------------+ -// | Copyright(C) 2008-2014 Piwigo Team http://piwigo.org | +// | Copyright(C) 2008-2016 Piwigo Team http://piwigo.org | // | Copyright(C) 2003-2008 PhpWebGallery Team http://phpwebgallery.net | // | Copyright(C) 2002-2003 Pierrick LE GALL http://le-gall.net/pierrick | // +-----------------------------------------------------------------------+ diff --git a/include/functions.inc.php b/include/functions.inc.php index a9ae35baf..0f26fde77 100644 --- a/include/functions.inc.php +++ b/include/functions.inc.php @@ -2,7 +2,7 @@ // +-----------------------------------------------------------------------+ // | Piwigo - a PHP based photo gallery | // +-----------------------------------------------------------------------+ -// | Copyright(C) 2008-2014 Piwigo Team http://piwigo.org | +// | Copyright(C) 2008-2016 Piwigo Team http://piwigo.org | // | Copyright(C) 2003-2008 PhpWebGallery Team http://phpwebgallery.net | // | Copyright(C) 2002-2003 Pierrick LE GALL http://le-gall.net/pierrick | // +-----------------------------------------------------------------------+ @@ -407,7 +407,7 @@ SELECT id, name * @param string $image_type * @return bool */ -function pwg_log($image_id = null, $image_type = null) +function pwg_log($image_id = null, $image_type = null, $format_id = null) { global $conf, $user, $page; @@ -445,6 +445,8 @@ INSERT INTO '.HISTORY_TABLE.' category_id, image_id, image_type, + format_id, + auth_key_id, tag_ids ) VALUES @@ -457,6 +459,8 @@ INSERT INTO '.HISTORY_TABLE.' '.(isset($page['category']['id']) ? $page['category']['id'] : 'NULL').', '.(isset($image_id) ? $image_id : 'NULL').', '.(isset($image_type) ? "'".$image_type."'" : 'NULL').', + '.(isset($format_id) ? $format_id : 'NULL').', + '.(isset($page['auth_key_id']) ? $page['auth_key_id'] : 'NULL').', '.(isset($tags_string) ? "'".$tags_string."'" : 'NULL').' ) ;'; @@ -952,6 +956,21 @@ function original_to_representative($path, $representative_ext) return substr_replace($path, $representative_ext, $pos+1); } +/** + * Transforms an original path to its format + * + * @param string $path + * @param string $format_ext + * @return string + */ +function original_to_format($path, $format_ext) +{ + $pos = strrpos($path, '/'); + $path = substr_replace($path, 'pwg_format/', $pos+1, 0); + $pos = strrpos($path, '.'); + return substr_replace($path, $format_ext, $pos+1); +} + /** * get the full path of an image * @@ -1140,9 +1159,7 @@ function l10n_args($key_args, $sep = "\n") */ function get_themeconf($key) { - global $template; - - return $template->get_themeconf($key); + return $GLOBALS['template']->get_themeconf($key); } /** @@ -1277,6 +1294,27 @@ DELETE FROM '.CONFIG_TABLE.' } } +/** + * Return a default value for a configuration parameter. + * @since 2.8 + * + * @param string $param the configuration value to be extracted (if it exists) + * @param mixed $default_value the default value for the configuration value if it does not exist. + * + * @return mixed The configuration value if the variable exists, otherwise the default. + */ +function conf_get_param($param, $default_value=null) +{ + global $conf; + + if (isset($conf[$param])) + { + return $conf[$param]; + } + return $default_value; +} + + /** * Apply *unserialize* on a value only if it is a string * @since 2.7 @@ -1631,7 +1669,7 @@ function convert_charset($str, $source_charset, $dest_charset) } if (function_exists('iconv')) { - return iconv($source_charset, $dest_charset, $str); + return iconv($source_charset, $dest_charset.'//TRANSLIT', $str); } if (function_exists('mb_convert_encoding')) { @@ -2092,4 +2130,4 @@ function safe_version_compare($a, $b, $op=null) } } -?> \ No newline at end of file +?> diff --git a/include/functions_calendar.inc.php b/include/functions_calendar.inc.php index 850ccdccf..829d6d18c 100644 --- a/include/functions_calendar.inc.php +++ b/include/functions_calendar.inc.php @@ -2,7 +2,7 @@ // +-----------------------------------------------------------------------+ // | Piwigo - a PHP based photo gallery | // +-----------------------------------------------------------------------+ -// | Copyright(C) 2008-2014 Piwigo Team http://piwigo.org | +// | Copyright(C) 2008-2016 Piwigo Team http://piwigo.org | // | Copyright(C) 2003-2008 PhpWebGallery Team http://phpwebgallery.net | // | Copyright(C) 2002-2003 Pierrick LE GALL http://le-gall.net/pierrick | // +-----------------------------------------------------------------------+ diff --git a/include/functions_category.inc.php b/include/functions_category.inc.php index 15ab84c25..76c9fbaae 100644 --- a/include/functions_category.inc.php +++ b/include/functions_category.inc.php @@ -2,7 +2,7 @@ // +-----------------------------------------------------------------------+ // | Piwigo - a PHP based photo gallery | // +-----------------------------------------------------------------------+ -// | Copyright(C) 2008-2014 Piwigo Team http://piwigo.org | +// | Copyright(C) 2008-2016 Piwigo Team http://piwigo.org | // | Copyright(C) 2003-2008 PhpWebGallery Team http://phpwebgallery.net | // | Copyright(C) 2002-2003 Pierrick LE GALL http://le-gall.net/pierrick | // +-----------------------------------------------------------------------+ @@ -491,6 +491,7 @@ SELECT image_id function get_computed_categories(&$userdata, $filter_days=null) { $query = 'SELECT c.id AS cat_id, id_uppercat'; + $query.= ', global_rank'; // Count by date_available to avoid count null $query .= ', MAX(date_available) AS date_last, COUNT(date_available) AS nb_images @@ -533,6 +534,11 @@ FROM '.CATEGORIES_TABLE.' as c $cats[$row['cat_id']] = $row; } + // it is important to logically sort the albums because some operations + // (like removal) rely on this logical order. Child album doesn't always + // have a bigger id than its parent (if it was moved afterwards). + uasort($cats, 'global_rank_compare'); + foreach ($cats as $cat) { if ( !isset( $cat['id_uppercat'] ) ) diff --git a/include/functions_comment.inc.php b/include/functions_comment.inc.php index 2dcc4fcc1..0e6a5714b 100644 --- a/include/functions_comment.inc.php +++ b/include/functions_comment.inc.php @@ -2,7 +2,7 @@ // +-----------------------------------------------------------------------+ // | Piwigo - a PHP based photo gallery | // +-----------------------------------------------------------------------+ -// | Copyright(C) 2008-2014 Piwigo Team http://piwigo.org | +// | Copyright(C) 2008-2016 Piwigo Team http://piwigo.org | // | Copyright(C) 2003-2008 PhpWebGallery Team http://phpwebgallery.net | // | Copyright(C) 2002-2003 Pierrick LE GALL http://le-gall.net/pierrick | // +-----------------------------------------------------------------------+ diff --git a/include/functions_cookie.inc.php b/include/functions_cookie.inc.php index 4e547e10e..2c61eecaf 100644 --- a/include/functions_cookie.inc.php +++ b/include/functions_cookie.inc.php @@ -2,7 +2,7 @@ // +-----------------------------------------------------------------------+ // | Piwigo - a PHP based photo gallery | // +-----------------------------------------------------------------------+ -// | Copyright(C) 2008-2014 Piwigo Team http://piwigo.org | +// | Copyright(C) 2008-2016 Piwigo Team http://piwigo.org | // | Copyright(C) 2003-2008 PhpWebGallery Team http://phpwebgallery.net | // | Copyright(C) 2002-2003 Pierrick LE GALL http://le-gall.net/pierrick | // +-----------------------------------------------------------------------+ diff --git a/include/functions_filter.inc.php b/include/functions_filter.inc.php index 47d0ffde2..ded932e9d 100644 --- a/include/functions_filter.inc.php +++ b/include/functions_filter.inc.php @@ -2,7 +2,7 @@ // +-----------------------------------------------------------------------+ // | Piwigo - a PHP based photo gallery | // +-----------------------------------------------------------------------+ -// | Copyright(C) 2008-2014 Piwigo Team http://piwigo.org | +// | Copyright(C) 2008-2016 Piwigo Team http://piwigo.org | // | Copyright(C) 2003-2008 PhpWebGallery Team http://phpwebgallery.net | // | Copyright(C) 2002-2003 Pierrick LE GALL http://le-gall.net/pierrick | // +-----------------------------------------------------------------------+ diff --git a/include/functions_html.inc.php b/include/functions_html.inc.php index 8668e68ad..b0f123a14 100644 --- a/include/functions_html.inc.php +++ b/include/functions_html.inc.php @@ -2,7 +2,7 @@ // +-----------------------------------------------------------------------+ // | Piwigo - a PHP based photo gallery | // +-----------------------------------------------------------------------+ -// | Copyright(C) 2008-2014 Piwigo Team http://piwigo.org | +// | Copyright(C) 2008-2016 Piwigo Team http://piwigo.org | // | Copyright(C) 2003-2008 PhpWebGallery Team http://phpwebgallery.net | // | Copyright(C) 2002-2003 Pierrick LE GALL http://le-gall.net/pierrick | // +-----------------------------------------------------------------------+ @@ -103,10 +103,17 @@ function get_cat_display_name($cat_informations, $url='') function get_cat_display_name_cache($uppercats, $url = '', $single_link = false, - $link_class = null) + $link_class = null, + $auth_key=null) { global $cache, $conf; + $add_url_params = array(); + if (isset($auth_key)) + { + $add_url_params['auth'] = $auth_key; + } + if (!isset($cache['cat_names'])) { $query = ' @@ -119,7 +126,7 @@ SELECT id, name, permalink $output = ''; if ($single_link) { - $single_url = get_root_url().$url.array_pop(explode(',', $uppercats)); + $single_url = add_url_params(get_root_url().$url.array_pop(explode(',', $uppercats)), $add_url_params); $output.= ' $cat, ) + ), + $add_url_params ) .'">'.$cat['name'].''; } diff --git a/include/functions_mail.inc.php b/include/functions_mail.inc.php index ed1081713..9032d8311 100644 --- a/include/functions_mail.inc.php +++ b/include/functions_mail.inc.php @@ -2,7 +2,7 @@ // +-----------------------------------------------------------------------+ // | Piwigo - a PHP based photo gallery | // +-----------------------------------------------------------------------+ -// | Copyright(C) 2008-2014 Piwigo Team http://piwigo.org | +// | Copyright(C) 2008-2016 Piwigo Team http://piwigo.org | // | Copyright(C) 2003-2008 PhpWebGallery Team http://phpwebgallery.net | // | Copyright(C) 2002-2003 Pierrick LE GALL http://le-gall.net/pierrick | // +-----------------------------------------------------------------------+ @@ -514,6 +514,8 @@ SELECT DISTINCT language // get subset of users in this group for a specific language $query = ' SELECT + ui.user_id, + ui.status, u.'.$conf['user_fields']['username'].' AS name, u.'.$conf['user_fields']['email'].' AS email FROM '.USER_GROUP_TABLE.' AS ug @@ -534,13 +536,33 @@ SELECT switch_lang_to($language); - $return&= pwg_mail(null, - array_merge( - $args, - array('Bcc' => $users) - ), - $tpl - ); + foreach ($users as $u) + { + $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 ($authkey !== false) + { + $user_args['auth_key'] = $authkey['auth_key']; + } + + $return &= pwg_mail($u['email'], $user_args, $user_tpl); + } switch_lang_back(); } @@ -563,6 +585,7 @@ SELECT * o theme: theme to use [default value $conf_mail['mail_theme']] * o mail_title: main title of the mail [default value $conf['gallery_title']] * o mail_subtitle: subtitle of the mail [default value subject] + * o auth_key: authentication key to add on footer link [default value null] * @param array $tpl - use these options to define a custom content template file * o filename * o dirname (optional) @@ -695,6 +718,10 @@ function pwg_mail($to, $args=array(), $tpl=array()) { // key compose of indexes witch allow to cache mail data $cache_key = $content_type.'-'.$lang_info['code']; + if (!empty($args['auth_key'])) + { + $cache_key.= '-'.$args['auth_key']; + } if (!isset($conf_mail[$cache_key])) { @@ -709,9 +736,15 @@ function pwg_mail($to, $args=array(), $tpl=array()) $template->set_filename('mail_header', 'header.tpl'); $template->set_filename('mail_footer', 'footer.tpl'); + $add_url_params = array(); + if (!empty($args['auth_key'])) + { + $add_url_params['auth'] = $args['auth_key']; + } + $template->assign( array( - 'GALLERY_URL' => get_gallery_home_url(), + 'GALLERY_URL' => add_url_params(get_gallery_home_url(), $add_url_params), 'GALLERY_TITLE' => isset($page['gallery_title']) ? $page['gallery_title'] : $conf['gallery_title'], 'VERSION' => $conf['show_version'] ? PHPWG_VERSION : '', 'PHPWG_URL' => defined('PHPWG_URL') ? PHPWG_URL : '', diff --git a/include/functions_metadata.inc.php b/include/functions_metadata.inc.php index ab3d6a7f1..3d3590007 100644 --- a/include/functions_metadata.inc.php +++ b/include/functions_metadata.inc.php @@ -2,7 +2,7 @@ // +-----------------------------------------------------------------------+ // | Piwigo - a PHP based photo gallery | // +-----------------------------------------------------------------------+ -// | Copyright(C) 2008-2014 Piwigo Team http://piwigo.org | +// | Copyright(C) 2008-2016 Piwigo Team http://piwigo.org | // | Copyright(C) 2003-2008 PhpWebGallery Team http://phpwebgallery.net | // | Copyright(C) 2002-2003 Pierrick LE GALL http://le-gall.net/pierrick | // +-----------------------------------------------------------------------+ diff --git a/include/functions_notification.inc.php b/include/functions_notification.inc.php index bc4d1a374..6e063d1dc 100644 --- a/include/functions_notification.inc.php +++ b/include/functions_notification.inc.php @@ -2,7 +2,7 @@ // +-----------------------------------------------------------------------+ // | Piwigo - a PHP based photo gallery | // +-----------------------------------------------------------------------+ -// | Copyright(C) 2008-2014 Piwigo Team http://piwigo.org | +// | Copyright(C) 2008-2016 Piwigo Team http://piwigo.org | // | Copyright(C) 2003-2008 PhpWebGallery Team http://phpwebgallery.net | // | Copyright(C) 2002-2003 Pierrick LE GALL http://le-gall.net/pierrick | // +-----------------------------------------------------------------------+ @@ -395,27 +395,45 @@ function add_news_line(&$news, $count, $singular_key, $plural_key, $url='', $add * @param bool $add_url add html link around news * @return array */ -function news($start=null, $end=null, $exclude_img_cats=false, $add_url=false) +function news($start=null, $end=null, $exclude_img_cats=false, $add_url=false, $auth_key=null) { $news = array(); - if (!$exclude_img_cats) + $add_url_params = array(); + if (isset($auth_key)) { - add_news_line( $news, - nb_new_elements($start, $end), '%d new photo', '%d new photos', - make_index_url(array('section'=>'recent_pics')), $add_url ); + $add_url_params['auth'] = $auth_key; } if (!$exclude_img_cats) { - add_news_line( $news, - nb_updated_categories($start, $end), '%d album updated', '%d albums updated', - make_index_url(array('section'=>'recent_cats')), $add_url ); + add_news_line( + $news, + nb_new_elements($start, $end), + '%d new photo', + '%d new photos', + add_url_params(make_index_url(array('section'=>'recent_pics')), $add_url_params), + $add_url + ); + + add_news_line( + $news, + nb_updated_categories($start, $end), + '%d album updated', + '%d albums updated', + add_url_params(make_index_url(array('section'=>'recent_cats')), $add_url_params), + $add_url + ); } - add_news_line( $news, - nb_new_comments($start, $end), '%d new comment', '%d new comments', - get_root_url().'comments.php', $add_url ); + add_news_line( + $news, + nb_new_comments($start, $end), + '%d new comment', + '%d new comments', + add_url_params(get_root_url().'comments.php', $add_url_params), + $add_url + ); if (is_admin()) { @@ -527,17 +545,23 @@ function get_recent_post_dates_array($args) * @param array $date_detail returned value of get_recent_post_dates() * @return string */ -function get_html_description_recent_post_date($date_detail) +function get_html_description_recent_post_date($date_detail, $auth_key=null) { global $conf; + $add_url_params = array(); + if (isset($auth_key)) + { + $add_url_params['auth'] = $auth_key; + } + $description = '
    '; $description .= '
  • ' .l10n_dec('%d new photo', '%d new photos', $date_detail['nb_elements']) .' (' - .'' + .'' .l10n('Recent photos').'' .')' .'

  • '; @@ -546,11 +570,16 @@ function get_html_description_recent_post_date($date_detail) { $tn_src = DerivativeImage::thumb_url($element); $description .= ''; + add_url_params( + make_picture_url( + array( + 'image_id' => $element['id'], + 'image_file' => $element['file'], + ) + ), + $add_url_params + ) + .'">'; } $description .= '...
    '; @@ -564,7 +593,7 @@ function get_html_description_recent_post_date($date_detail) { $description .= '
  • ' - .get_cat_display_name_cache($cat['uppercats']) + .get_cat_display_name_cache($cat['uppercats'],'', false, null, $auth_key) .' ('. l10n_dec('%d new photo', '%d new photos', $cat['img_count']).')' .'
  • '; diff --git a/include/functions_picture.inc.php b/include/functions_picture.inc.php index ae3f944b0..9e923b0de 100644 --- a/include/functions_picture.inc.php +++ b/include/functions_picture.inc.php @@ -2,7 +2,7 @@ // +-----------------------------------------------------------------------+ // | Piwigo - a PHP based photo gallery | // +-----------------------------------------------------------------------+ -// | Copyright(C) 2008-2014 Piwigo Team http://piwigo.org | +// | Copyright(C) 2008-2016 Piwigo Team http://piwigo.org | // | Copyright(C) 2003-2008 PhpWebGallery Team http://phpwebgallery.net | // | Copyright(C) 2002-2003 Pierrick LE GALL http://le-gall.net/pierrick | // +-----------------------------------------------------------------------+ diff --git a/include/functions_plugins.inc.php b/include/functions_plugins.inc.php index 8700a599f..429167bb0 100644 --- a/include/functions_plugins.inc.php +++ b/include/functions_plugins.inc.php @@ -2,7 +2,7 @@ // +-----------------------------------------------------------------------+ // | Piwigo - a PHP based photo gallery | // +-----------------------------------------------------------------------+ -// | Copyright(C) 2008-2014 Piwigo Team http://piwigo.org | +// | Copyright(C) 2008-2016 Piwigo Team http://piwigo.org | // | Copyright(C) 2003-2008 PhpWebGallery Team http://phpwebgallery.net | // | Copyright(C) 2002-2003 Pierrick LE GALL http://le-gall.net/pierrick | // +-----------------------------------------------------------------------+ diff --git a/include/functions_rate.inc.php b/include/functions_rate.inc.php index 45d3e9e7f..3b27f5c8e 100644 --- a/include/functions_rate.inc.php +++ b/include/functions_rate.inc.php @@ -2,7 +2,7 @@ // +-----------------------------------------------------------------------+ // | Piwigo - a PHP based photo gallery | // +-----------------------------------------------------------------------+ -// | Copyright(C) 2008-2014 Piwigo Team http://piwigo.org | +// | Copyright(C) 2008-2016 Piwigo Team http://piwigo.org | // | Copyright(C) 2003-2008 PhpWebGallery Team http://phpwebgallery.net | // | Copyright(C) 2002-2003 Pierrick LE GALL http://le-gall.net/pierrick | // +-----------------------------------------------------------------------+ diff --git a/include/functions_search.inc.php b/include/functions_search.inc.php index 2f42473b3..69c57faa7 100644 --- a/include/functions_search.inc.php +++ b/include/functions_search.inc.php @@ -2,7 +2,7 @@ // +-----------------------------------------------------------------------+ // | Piwigo - a PHP based photo gallery | // +-----------------------------------------------------------------------+ -// | Copyright(C) 2008-2014 Piwigo Team http://piwigo.org | +// | Copyright(C) 2008-2016 Piwigo Team http://piwigo.org | // | Copyright(C) 2003-2008 PhpWebGallery Team http://phpwebgallery.net | // | Copyright(C) 2002-2003 Pierrick LE GALL http://le-gall.net/pierrick | // +-----------------------------------------------------------------------+ diff --git a/include/functions_session.inc.php b/include/functions_session.inc.php index aaa07fd07..9c12e26c1 100644 --- a/include/functions_session.inc.php +++ b/include/functions_session.inc.php @@ -2,7 +2,7 @@ // +-----------------------------------------------------------------------+ // | Piwigo - a PHP based photo gallery | // +-----------------------------------------------------------------------+ -// | Copyright(C) 2008-2014 Piwigo Team http://piwigo.org | +// | Copyright(C) 2008-2016 Piwigo Team http://piwigo.org | // | Copyright(C) 2003-2008 PhpWebGallery Team http://phpwebgallery.net | // | Copyright(C) 2002-2003 Pierrick LE GALL http://le-gall.net/pierrick | // +-----------------------------------------------------------------------+ @@ -71,7 +71,7 @@ function generate_key($size) str_replace( array('+', '/'), '', - base64_encode(openssl_random_pseudo_bytes($size)) + base64_encode(openssl_random_pseudo_bytes($size+10)) ), 0, $size @@ -260,4 +260,4 @@ function pwg_unset_session_var($var) return true; } -?> \ No newline at end of file +?> diff --git a/include/functions_tag.inc.php b/include/functions_tag.inc.php index 90474494f..752a2be7e 100644 --- a/include/functions_tag.inc.php +++ b/include/functions_tag.inc.php @@ -2,7 +2,7 @@ // +-----------------------------------------------------------------------+ // | Piwigo - a PHP based photo gallery | // +-----------------------------------------------------------------------+ -// | Copyright(C) 2008-2014 Piwigo Team http://piwigo.org | +// | Copyright(C) 2008-2016 Piwigo Team http://piwigo.org | // | Copyright(C) 2003-2008 PhpWebGallery Team http://phpwebgallery.net | // | Copyright(C) 2002-2003 Pierrick LE GALL http://le-gall.net/pierrick | // +-----------------------------------------------------------------------+ diff --git a/include/functions_url.inc.php b/include/functions_url.inc.php index 5a471bc10..ea329b4f9 100644 --- a/include/functions_url.inc.php +++ b/include/functions_url.inc.php @@ -2,7 +2,7 @@ // +-----------------------------------------------------------------------+ // | Piwigo - a PHP based photo gallery | // +-----------------------------------------------------------------------+ -// | Copyright(C) 2008-2014 Piwigo Team http://piwigo.org | +// | Copyright(C) 2008-2016 Piwigo Team http://piwigo.org | // | Copyright(C) 2003-2008 PhpWebGallery Team http://phpwebgallery.net | // | Copyright(C) 2002-2003 Pierrick LE GALL http://le-gall.net/pierrick | // +-----------------------------------------------------------------------+ @@ -62,14 +62,21 @@ function get_absolute_root_url($with_scheme=true) { $url .= 'http://'; } - $url .= $_SERVER['HTTP_HOST']; - if ( (!$is_https && $_SERVER['SERVER_PORT'] != 80) - ||($is_https && $_SERVER['SERVER_PORT'] != 443)) + if (isset($_SERVER['HTTP_X_FORWARDED_HOST'])) { - $url_port = ':'.$_SERVER['SERVER_PORT']; - if (strrchr($url, ':') != $url_port) + $url .= $_SERVER['HTTP_X_FORWARDED_HOST']; + } + else + { + $url .= $_SERVER['HTTP_HOST']; + if ( (!$is_https && $_SERVER['SERVER_PORT'] != 80) + ||($is_https && $_SERVER['SERVER_PORT'] != 443)) { - $url .= $url_port; + $url_port = ':'.$_SERVER['SERVER_PORT']; + if (strrchr($url, ':') != $url_port) + { + $url .= $url_port; + } } } } @@ -372,7 +379,7 @@ function make_section_in_url($params) $section_string.= '/'.$tag['id']; break; case 'tag': - if (isset($tag['url_name']) and !is_numeric($tag['url_name']) ) + if (isset($tag['url_name'])) { $section_string.= '/'.$tag['url_name']; break; @@ -817,4 +824,4 @@ function url_is_remote($url) return false; } -?> \ No newline at end of file +?> diff --git a/include/functions_user.inc.php b/include/functions_user.inc.php index 5f503b36e..ac85d1b47 100644 --- a/include/functions_user.inc.php +++ b/include/functions_user.inc.php @@ -2,7 +2,7 @@ // +-----------------------------------------------------------------------+ // | Piwigo - a PHP based photo gallery | // +-----------------------------------------------------------------------+ -// | Copyright(C) 2008-2014 Piwigo Team http://piwigo.org | +// | Copyright(C) 2008-2016 Piwigo Team http://piwigo.org | // | Copyright(C) 2003-2008 PhpWebGallery Team http://phpwebgallery.net | // | Copyright(C) 2002-2003 Pierrick LE GALL http://le-gall.net/pierrick | // +-----------------------------------------------------------------------+ @@ -945,7 +945,7 @@ function log_user($user_id, $remember_me) { // make sure we clean any remember me ... setcookie($conf['remember_me_name'], '', 0, cookie_path(),ini_get('session.cookie_domain')); } - if ( session_id()!="" ) + if ( session_id()!="" and (version_compare(PHP_VERSION, '7') <= 0 or version_compare(PHP_VERSION, '7.0.3') >= 0)) { // we regenerate the session for security reasons // see http://www.acros.si/papers/session_fixation.pdf session_regenerate_id(true); @@ -1462,4 +1462,135 @@ function get_recent_photos_sql($db_field) .pwg_db_get_recent_period_expression($user['recent_period']) .','.pwg_db_get_recent_period_expression(1,$user['last_photo_date']).')'; } -?> \ No newline at end of file + +/** + * Performs auto-connection if authentication key is valid. + * + * @since 2.8 + * + * @return bool + */ +function auth_key_login($auth_key) +{ + global $conf, $user, $page; + + if (!preg_match('/^[a-z0-9]{30}$/i', $auth_key)) + { + return false; + } + + $query = ' +SELECT + *, + '.$conf['user_fields']['username'].' AS username, + NOW() AS dbnow + FROM '.USER_AUTH_KEYS_TABLE.' AS uak + JOIN '.USER_INFOS_TABLE.' AS ui ON uak.user_id = ui.user_id + JOIN '.USERS_TABLE.' AS u ON u.'.$conf['user_fields']['id'].' = ui.user_id + WHERE auth_key = \''.$auth_key.'\' +;'; + $keys = query2array($query); + + if (count($keys) == 0) + { + return false; + } + + $key = $keys[0]; + + // is the key still valid? + if (strtotime($key['expired_on']) < strtotime($key['dbnow'])) + { + $page['auth_key_invalid'] = true; + return false; + } + + // admin/webmaster/guest can't get connected with authentication keys + if (!in_array($key['status'], array('normal','generic'))) + { + return false; + } + + $user['id'] = $key['user_id']; + log_user($user['id'], false); + trigger_notify('login_success', $key['username']); + + // to be registered in history table by pwg_log function + $page['auth_key_id'] = $key['auth_key_id']; + + return true; +} + +/** + * Creates an authentication key. + * + * @since 2.8 + * @param int $user_id + * @return array + */ +function create_user_auth_key($user_id, $user_status=null) +{ + global $conf; + + if (0 == $conf['auth_key_duration']) + { + return false; + } + + if (!isset($user_status)) + { + // we have to find the user status + $query = ' +SELECT + status + FROM '.USER_INFOS_TABLE.' + WHERE user_id = '.$user_id.' +;'; + $user_infos = query2array($query); + + if (count($user_infos) == 0) + { + return false; + } + + $user_status = $user_infos[0]['status']; + } + + if (!in_array($user_status, array('normal','generic'))) + { + return false; + } + + $candidate = generate_key(30); + + $query = ' +SELECT + COUNT(*), + NOW(), + ADDDATE(NOW(), INTERVAL '.$conf['auth_key_duration'].' SECOND) + FROM '.USER_AUTH_KEYS_TABLE.' + WHERE auth_key = \''.$candidate.'\' +;'; + list($counter, $now, $expiration) = pwg_db_fetch_row(pwg_query($query)); + if (0 == $counter) + { + $key = array( + 'auth_key' => $candidate, + 'user_id' => $user_id, + 'created_on' => $now, + 'duration' => $conf['auth_key_duration'], + 'expired_on' => $expiration, + ); + + single_insert(USER_AUTH_KEYS_TABLE, $key); + + $key['auth_key_id'] = pwg_db_insert_id(); + + return $key; + } + else + { + return create_user_auth_key($user_id, $user_status); + } +} +?> diff --git a/include/index.php b/include/index.php index c8de97f60..0b96c3efa 100644 --- a/include/index.php +++ b/include/index.php @@ -2,7 +2,7 @@ // +-----------------------------------------------------------------------+ // | Piwigo - a PHP based photo gallery | // +-----------------------------------------------------------------------+ -// | Copyright(C) 2008-2014 Piwigo Team http://piwigo.org | +// | Copyright(C) 2008-2016 Piwigo Team http://piwigo.org | // | Copyright(C) 2003-2008 PhpWebGallery Team http://phpwebgallery.net | // | Copyright(C) 2002-2003 Pierrick LE GALL http://le-gall.net/pierrick | // +-----------------------------------------------------------------------+ diff --git a/include/inflectors/en.php b/include/inflectors/en.php index 63571440d..ae8e9378b 100644 --- a/include/inflectors/en.php +++ b/include/inflectors/en.php @@ -2,7 +2,7 @@ // +-----------------------------------------------------------------------+ // | Piwigo - a PHP based photo gallery | // +-----------------------------------------------------------------------+ -// | Copyright(C) 2008-2014 Piwigo Team http://piwigo.org | +// | Copyright(C) 2008-2016 Piwigo Team http://piwigo.org | // | Copyright(C) 2003-2008 PhpWebGallery Team http://phpwebgallery.net | // | Copyright(C) 2002-2003 Pierrick LE GALL http://le-gall.net/pierrick | // +-----------------------------------------------------------------------+ diff --git a/include/inflectors/fr.php b/include/inflectors/fr.php index f634d2a65..28edbcefd 100644 --- a/include/inflectors/fr.php +++ b/include/inflectors/fr.php @@ -2,7 +2,7 @@ // +-----------------------------------------------------------------------+ // | Piwigo - a PHP based photo gallery | // +-----------------------------------------------------------------------+ -// | Copyright(C) 2008-2014 Piwigo Team http://piwigo.org | +// | Copyright(C) 2008-2016 Piwigo Team http://piwigo.org | // | Copyright(C) 2003-2008 PhpWebGallery Team http://phpwebgallery.net | // | Copyright(C) 2002-2003 Pierrick LE GALL http://le-gall.net/pierrick | // +-----------------------------------------------------------------------+ diff --git a/include/menubar.inc.php b/include/menubar.inc.php index 3d39cd8e5..9fe2ceaab 100644 --- a/include/menubar.inc.php +++ b/include/menubar.inc.php @@ -2,7 +2,7 @@ // +-----------------------------------------------------------------------+ // | Piwigo - a PHP based photo gallery | // +-----------------------------------------------------------------------+ -// | Copyright(C) 2008-2014 Piwigo Team http://piwigo.org | +// | Copyright(C) 2008-2016 Piwigo Team http://piwigo.org | // | Copyright(C) 2003-2008 PhpWebGallery Team http://phpwebgallery.net | // | Copyright(C) 2002-2003 Pierrick LE GALL http://le-gall.net/pierrick | // +-----------------------------------------------------------------------+ diff --git a/include/no_photo_yet.inc.php b/include/no_photo_yet.inc.php index 61daf35a8..15d12dcc0 100644 --- a/include/no_photo_yet.inc.php +++ b/include/no_photo_yet.inc.php @@ -2,7 +2,7 @@ // +-----------------------------------------------------------------------+ // | Piwigo - a PHP based photo gallery | // +-----------------------------------------------------------------------+ -// | Copyright(C) 2008-2014 Piwigo Team http://piwigo.org | +// | Copyright(C) 2008-2016 Piwigo Team http://piwigo.org | // | Copyright(C) 2003-2008 PhpWebGallery Team http://phpwebgallery.net | // | Copyright(C) 2002-2003 Pierrick LE GALL http://le-gall.net/pierrick | // +-----------------------------------------------------------------------+ diff --git a/include/page_header.php b/include/page_header.php index 6710f20d9..8a62fc487 100644 --- a/include/page_header.php +++ b/include/page_header.php @@ -2,7 +2,7 @@ // +-----------------------------------------------------------------------+ // | Piwigo - a PHP based photo gallery | // +-----------------------------------------------------------------------+ -// | Copyright(C) 2008-2014 Piwigo Team http://piwigo.org | +// | Copyright(C) 2008-2016 Piwigo Team http://piwigo.org | // | Copyright(C) 2003-2008 PhpWebGallery Team http://phpwebgallery.net | // | Copyright(C) 2002-2003 Pierrick LE GALL http://le-gall.net/pierrick | // +-----------------------------------------------------------------------+ diff --git a/include/page_tail.php b/include/page_tail.php index f47dc2d91..82420ffc9 100644 --- a/include/page_tail.php +++ b/include/page_tail.php @@ -2,7 +2,7 @@ // +-----------------------------------------------------------------------+ // | Piwigo - a PHP based photo gallery | // +-----------------------------------------------------------------------+ -// | Copyright(C) 2008-2014 Piwigo Team http://piwigo.org | +// | Copyright(C) 2008-2016 Piwigo Team http://piwigo.org | // | Copyright(C) 2003-2008 PhpWebGallery Team http://phpwebgallery.net | // | Copyright(C) 2002-2003 Pierrick LE GALL http://le-gall.net/pierrick | // +-----------------------------------------------------------------------+ diff --git a/include/passwordhash.class.php b/include/passwordhash.class.php index 84447b277..8b8b11319 100644 --- a/include/passwordhash.class.php +++ b/include/passwordhash.class.php @@ -1,18 +1,18 @@ in 2004-2006 and placed in # the public domain. Revised in subsequent years, still public domain. # # There's absolutely no warranty. # -# The homepage URL for this framework is: -# -# http://www.openwall.com/phpass/ -# # Please be sure to update the Version line if you edit this file in any way. # It is suggested that you leave the main version number intact, but indicate # your project name (after the slash) and add your own revision information. @@ -24,13 +24,25 @@ # Obviously, since this code is in the public domain, the above are not # requirements (there can be none), but merely suggestions. # + +/** + * Portable PHP password hashing framework. + * + * @package phpass + * @version 0.3 / WordPress + * @link http://www.openwall.com/phpass/ + * @since 2.5.0 + */ class PasswordHash { var $itoa64; var $iteration_count_log2; var $portable_hashes; var $random_state; - function PasswordHash($iteration_count_log2, $portable_hashes) + /** + * PHP5 constructor. + */ + function __construct( $iteration_count_log2, $portable_hashes ) { $this->itoa64 = './0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz'; @@ -40,15 +52,20 @@ class PasswordHash { $this->portable_hashes = $portable_hashes; - $this->random_state = microtime(); - if (function_exists('getmypid')) - $this->random_state .= getmypid(); + $this->random_state = microtime() . uniqid(rand(), TRUE); // removed getmypid() for compatibility reasons + } + + /** + * PHP4 constructor. + */ + public function PasswordHash( $iteration_count_log2, $portable_hashes ) { + self::__construct( $iteration_count_log2, $portable_hashes ); } function get_random_bytes($count) { $output = ''; - if (@is_readable('/dev/urandom') && + if ( @is_readable('/dev/urandom') && ($fh = @fopen('/dev/urandom', 'rb'))) { $output = fread($fh, $count); fclose($fh); @@ -207,6 +224,10 @@ class PasswordHash { function HashPassword($password) { + if ( strlen( $password ) > 4096 ) { + return '*'; + } + $random = ''; if (CRYPT_BLOWFISH == 1 && !$this->portable_hashes) { @@ -242,12 +263,14 @@ class PasswordHash { function CheckPassword($password, $stored_hash) { + if ( strlen( $password ) > 4096 ) { + return false; + } + $hash = $this->crypt_private($password, $stored_hash); if ($hash[0] == '*') $hash = crypt($password, $stored_hash); - return $hash == $stored_hash; + return $hash === $stored_hash; } -} - -?> +} \ No newline at end of file diff --git a/include/php_compat/index.php b/include/php_compat/index.php index c8de97f60..0b96c3efa 100644 --- a/include/php_compat/index.php +++ b/include/php_compat/index.php @@ -2,7 +2,7 @@ // +-----------------------------------------------------------------------+ // | Piwigo - a PHP based photo gallery | // +-----------------------------------------------------------------------+ -// | Copyright(C) 2008-2014 Piwigo Team http://piwigo.org | +// | Copyright(C) 2008-2016 Piwigo Team http://piwigo.org | // | Copyright(C) 2003-2008 PhpWebGallery Team http://phpwebgallery.net | // | Copyright(C) 2002-2003 Pierrick LE GALL http://le-gall.net/pierrick | // +-----------------------------------------------------------------------+ diff --git a/include/picture_comment.inc.php b/include/picture_comment.inc.php index fd9a7b7fd..20a72e5ca 100644 --- a/include/picture_comment.inc.php +++ b/include/picture_comment.inc.php @@ -2,7 +2,7 @@ // +-----------------------------------------------------------------------+ // | Piwigo - a PHP based photo gallery | // +-----------------------------------------------------------------------+ -// | Copyright(C) 2008-2014 Piwigo Team http://piwigo.org | +// | Copyright(C) 2008-2016 Piwigo Team http://piwigo.org | // | Copyright(C) 2003-2008 PhpWebGallery Team http://phpwebgallery.net | // | Copyright(C) 2002-2003 Pierrick LE GALL http://le-gall.net/pierrick | // +-----------------------------------------------------------------------+ diff --git a/include/picture_metadata.inc.php b/include/picture_metadata.inc.php index 0df50dfbf..f43fa5a08 100644 --- a/include/picture_metadata.inc.php +++ b/include/picture_metadata.inc.php @@ -2,7 +2,7 @@ // +-----------------------------------------------------------------------+ // | Piwigo - a PHP based photo gallery | // +-----------------------------------------------------------------------+ -// | Copyright(C) 2008-2014 Piwigo Team http://piwigo.org | +// | Copyright(C) 2008-2016 Piwigo Team http://piwigo.org | // | Copyright(C) 2003-2008 PhpWebGallery Team http://phpwebgallery.net | // | Copyright(C) 2002-2003 Pierrick LE GALL http://le-gall.net/pierrick | // +-----------------------------------------------------------------------+ diff --git a/include/picture_rate.inc.php b/include/picture_rate.inc.php index c3119bd53..9c024ecf0 100644 --- a/include/picture_rate.inc.php +++ b/include/picture_rate.inc.php @@ -2,7 +2,7 @@ // +-----------------------------------------------------------------------+ // | Piwigo - a PHP based photo gallery | // +-----------------------------------------------------------------------+ -// | Copyright(C) 2008-2014 Piwigo Team http://piwigo.org | +// | Copyright(C) 2008-2016 Piwigo Team http://piwigo.org | // | Copyright(C) 2003-2008 PhpWebGallery Team http://phpwebgallery.net | // | Copyright(C) 2002-2003 Pierrick LE GALL http://le-gall.net/pierrick | // +-----------------------------------------------------------------------+ diff --git a/include/section_init.inc.php b/include/section_init.inc.php index c2c3ee676..e2e0c0712 100644 --- a/include/section_init.inc.php +++ b/include/section_init.inc.php @@ -2,7 +2,7 @@ // +-----------------------------------------------------------------------+ // | Piwigo - a PHP based photo gallery | // +-----------------------------------------------------------------------+ -// | Copyright(C) 2008-2014 Piwigo Team http://piwigo.org | +// | Copyright(C) 2008-2016 Piwigo Team http://piwigo.org | // | Copyright(C) 2003-2008 PhpWebGallery Team http://phpwebgallery.net | // | Copyright(C) 2002-2003 Pierrick LE GALL http://le-gall.net/pierrick | // +-----------------------------------------------------------------------+ diff --git a/include/smarty/.gitattributes b/include/smarty/.gitattributes new file mode 100644 index 000000000..412eeda78 --- /dev/null +++ b/include/smarty/.gitattributes @@ -0,0 +1,22 @@ +# Auto detect text files and perform LF normalization +* text=auto + +# Custom for Visual Studio +*.cs diff=csharp +*.sln merge=union +*.csproj merge=union +*.vbproj merge=union +*.fsproj merge=union +*.dbproj merge=union + +# Standard to msysgit +*.doc diff=astextplain +*.DOC diff=astextplain +*.docx diff=astextplain +*.DOCX diff=astextplain +*.dot diff=astextplain +*.DOT diff=astextplain +*.pdf diff=astextplain +*.PDF diff=astextplain +*.rtf diff=astextplain +*.RTF diff=astextplain diff --git a/include/smarty/.gitignore b/include/smarty/.gitignore new file mode 100644 index 000000000..0ff15aa49 --- /dev/null +++ b/include/smarty/.gitignore @@ -0,0 +1,221 @@ +################# +## Eclipse +################# + +*.pydevproject +.project +.metadata +bin/ +tmp/ +*.tmp +*.bak +*.swp +*~.nib +local.properties +.classpath +.settings/ +.loadpath + +# External tool builders +.externalToolBuilders/ + +# Locally stored "Eclipse launch configurations" +*.launch + +# CDT-specific +.cproject + +# PDT-specific +.buildpath + + +################# +## Visual Studio +################# + +## Ignore Visual Studio temporary files, build results, and +## files generated by popular Visual Studio add-ons. + +# User-specific files +*.suo +*.user +*.sln.docstates + +# Build results + +[Dd]ebug/ +[Rr]elease/ +x64/ +build/ +[Bb]in/ +[Oo]bj/ + +# MSTest test Results +[Tt]est[Rr]esult*/ +[Bb]uild[Ll]og.* + +*_i.c +*_p.c +*.ilk +*.meta +*.obj +*.pch +*.pdb +*.pgc +*.pgd +*.rsp +*.sbr +*.tlb +*.tli +*.tlh +*.tmp +*.tmp_proj +*.log +*.vspscc +*.vssscc +.builds +*.pidb +*.log +*.scc + +# Visual C++ cache files +ipch/ +*.aps +*.ncb +*.opensdf +*.sdf +*.cachefile + +# Visual Studio profiler +*.psess +*.vsp +*.vspx + +# Guidance Automation Toolkit +*.gpState + +# ReSharper is a .NET coding add-in +_ReSharper*/ +*.[Rr]e[Ss]harper + +# TeamCity is a build add-in +_TeamCity* + +# DotCover is a Code Coverage Tool +*.dotCover + +# NCrunch +*.ncrunch* +.*crunch*.local.xml + +# Installshield output folder +[Ee]xpress/ + +# DocProject is a documentation generator add-in +DocProject/buildhelp/ +DocProject/Help/*.HxT +DocProject/Help/*.HxC +DocProject/Help/*.hhc +DocProject/Help/*.hhk +DocProject/Help/*.hhp +DocProject/Help/Html2 +DocProject/Help/html + +# Click-Once directory +publish/ + +# Publish Web Output +*.Publish.xml +*.pubxml + +# NuGet Packages Directory +## TODO: If you have NuGet Package Restore enabled, uncomment the next line +#packages/ + +# Windows Azure Build Output +csx +*.build.csdef + +# Windows Store app package directory +AppPackages/ + +# Others +sql/ +*.Cache +ClientBin/ +[Ss]tyle[Cc]op.* +~$* +*~ +*.dbmdl +*.[Pp]ublish.xml +*.pfx +*.publishsettings + +# RIA/Silverlight projects +Generated_Code/ + +# Backup & report files from converting an old project file to a newer +# Visual Studio version. Backup files are not needed, because we have git ;-) +_UpgradeReport_Files/ +Backup*/ +UpgradeLog*.XML +UpgradeLog*.htm + +# SQL Server files +App_Data/*.mdf +App_Data/*.ldf + +############# +## Windows detritus +############# + +# Windows image file caches +Thumbs.db +ehthumbs.db + +# Folder config file +Desktop.ini + +# Recycle Bin used on file shares +$RECYCLE.BIN/ + +# Mac crap +.DS_Store + + +############# +## Python +############# + +*.py[co] + +# Packages +*.egg +*.egg-info +dist/ +build/ +eggs/ +parts/ +var/ +sdist/ +develop-eggs/ +.installed.cfg + +# Installer logs +pip-log.txt + +# Unit test / coverage reports +.coverage +.tox + +#Translations +*.mo + +#Mr Developer +.mr.developer.cfg + +.idea/ + +# Smarty +lexer/*.php +lexer/*.out diff --git a/include/smarty/.travis.yml b/include/smarty/.travis.yml new file mode 100644 index 000000000..fbf081bac --- /dev/null +++ b/include/smarty/.travis.yml @@ -0,0 +1,25 @@ +language: php + +php: + - 5.3 + - 5.4 + - 5.5 + - 5.6 + - 7.0 + - hhvm + +matrix: + allow_failures: + - php: hhvm + +before_script: + - travis_retry composer self-update + - travis_retry composer --prefer-source --dev install + +install: + - git clone --depth=50 --branch=master git://github.com/smarty-php/smarty-phpunit.git + +script: + - cd smarty-phpunit + - phpunit ./ + diff --git a/include/smarty/COMPOSER_RELEASE_NOTES.txt b/include/smarty/COMPOSER_RELEASE_NOTES.txt new file mode 100644 index 000000000..c943d9f2e --- /dev/null +++ b/include/smarty/COMPOSER_RELEASE_NOTES.txt @@ -0,0 +1,29 @@ + + +Starting with Smarty 3.1.21 Composer has been configured to load the packages from github. + +******************************************************************************* +* * +* NOTE: Because of this change you must clear your local composer cache with * +* the "composer clearcache" command * +* * +******************************************************************************* + +To get the latest stable version use + "require": { + "smarty/smarty": "~3.1" + } +in your composer.json file. + +To get the trunk version use + "require": { + "smarty/smarty": "~3.1@dev" + } + +The "smarty/smarty" package will start at libs/.... subfolder. + +To retrieve the development and documentation folders add + "require-dev": { + "smarty/smarty-dev": "~3.1@dev" + } + diff --git a/include/smarty/INHERITANCE_RELEASE_NOTES.txt b/include/smarty/INHERITANCE_RELEASE_NOTES.txt new file mode 100644 index 000000000..8b2c64a1b --- /dev/null +++ b/include/smarty/INHERITANCE_RELEASE_NOTES.txt @@ -0,0 +1,67 @@ +Starting with version 3.1.28 template inheritance is no longer a compile time process. +All {block} tag parent/child relations are resolved at run time. +This does resolve all known existing restrictions (see below). + +The $smarty::$inheritance_merge_compiled_includes property has been removed. +Any access to it is ignored. + +This does enable some new features: + +Any code outside root {block} tags in child templates is now executed but any output will be ignored. + + {extends 'foo.tpl'} + {$bar = 'on'} // assigns variable $bar seen in parent templates + {block 'buh'}{/block} + + {extends 'foo.tpl'} + {$bar} // the output of variable bar is ignored + {block 'buh'}{/block} + +{block} tags can be dynamically en/disabled by conditions. + + {block 'root'} + {if $foo} + {block 'v1'} + .... + {/block} + {else} + {block 'v1'} + .... + {/block} + {/if} + {/block} + + + +THE FOLLOWING RESTRICTIONS ARE NO LONGER EXISTING: +In Smarty 3.1 template inheritance is a compile time process. All the extending of {block} tags +is done at compile time and the parent and child templates are compiled in a single compiled template. +{include} subtemplate could also {block} tags. Such subtemplate could not compiled by it's own because +it could be used in other context where the {block} extended with a different result. For that reasion +the compiled code of {include} subtemplates gets also merged in compiled inheritance template. + +Merging the code into a single compile template has some drawbacks. +1. You could not use variable file names in {include} Smarty would use the {include} of compilation time. +2. You could not use individual compile_id in {include} +3. Seperate caching of subtemplate was not possible +4. Any change of the template directory structure between calls was not necessarily seen. + +Starting with 3.1.15 some of the above conditions got checked and resulted in an exception. It turned out +that a couple of users did use some of above and now got exceptions. + +To resolve this starting with 3.1.16 there is a new configuration parameter $inheritance_merge_compiled_includes. +For most backward compatibility its default setting is true. +With this setting all {include} subtemplate will be merge into the compiled inheritance template, but the above cases +could be rejected by exception. + + +If $smarty->inheritance_merge_compiled_includes = false; {include} subtemplate will not be merged. +You must now manually merge all {include} subtemplate which do contain {block} tags. This is done by setting the "inline" option. +{include file='foo.bar' inline} + +1. In case of a variable file name like {include file=$foo inline} you must use the variable in a compile_id $smarty->compile_id = $foo; +2. If you use individual compile_id in {include file='foo.tpl' compile_id=$bar inline} it must be used in the + global compile_id as well $smarty->compile_id = $bar; +3. If call templates with different template_dir configurations and a parent could same named child template from different folders + you must make the folder name part of the compile_id. + diff --git a/include/smarty/NEW_FEATURES.txt b/include/smarty/NEW_FEATURES.txt new file mode 100644 index 000000000..1a51c71d9 --- /dev/null +++ b/include/smarty/NEW_FEATURES.txt @@ -0,0 +1,133 @@ + + +This file contains a brief description of new features which have been added to Smarty 3.1 + +Smarty 3.1.28 + + OPCACHE + ======= + Smarty does now invalidate automatically updated and cleared compiled or cached template files in OPCACHE. + Correct operation is no longer dependent on OPCACHE configuration settings. + + Template inheritance + ==================== + Template inheritance is now processed in run time. + See the INHERITANCE_RELEASE_NOTES + + Modifier regex_replace + ====================== + An optional limit parameter was added + + fetch() and display() + ===================== + The fetch() and display() methods of the template object accept now optionally the same parameter + as the corresponding Smarty methods to get the content of another template. + Example: + $template->display(); Does display template of template object + $template->display('foo.tpl'); Does display template 'foo.bar' + + File: resource + ============== + Multiple template_dir entries can now be selected by a comma separated list of indices. + The template_dir array is searched in the order of the indices. (Could be used to change the default search order) + Example: + $smarty->display('[1],[0]foo.bar'); + + Filter support + ============== + Optional filter names + An optional filter name was added to $smarty->registerFilter(). It can be used to unregister a filter by name. + - $smarty->registerFilter('output', $callback, 'name'); + $smarty->unregister('output', 'name'); + + Closures + $smarty->registerFilter() does now accept closures. + - $smarty->registerFilter('pre', function($source) {return $source;}); + If no optional filter name was specified it gets the default name 'closure'. + If you register multiple closures register each with a unique filter name. + - $smarty->registerFilter('pre', function($source) {return $source;}, 'closure_1'); + - $smarty->registerFilter('pre', function($source) {return $source;}, 'closure_2'); + + +Smarty 3.1.22 + + Namespace support within templates + ================================== + Within templates you can now use namespace specifications on: + - Constants like foo\bar\FOO + - Class names like foo\bar\Baz::FOO, foo\bar\Baz::$foo, foo\bar\Baz::foo() + - PHP function names like foo\bar\baz() + + Security + ======== + - disable special $smarty variable - + The Smarty_Security class has the new property $disabled_special_smarty_vars. + It's an array which can be loaded with the $smarty special variable names like + 'template_object', 'template', 'current_dir' and others which will be disabled. + Note: That this security check is performed at compile time. + + - limit template nesting - + Property $max_template_nesting of Smarty_Security does set the maximum template nesting level. + The main template is level 1. The nesting level is checked at run time. When the maximum will be exceeded + an Exception will be thrown. The default setting is 0 which does disable this check. + + - trusted static methods - + The Smarty_Security class has the new property $trusted_static_methods to restrict access to static methods. + It's an nested array of trusted class and method names. + Format: + array ( + 'class_1' => array('method_1', 'method_2'), // allowed methods + 'class_2' => array(), // all methods of class allowed + ) + To disable access for all methods of all classes set $trusted_static_methods = null; + The default value is an empty array() which does enables all methods of all classes, but for backward compatibility + the setting of $static_classes will be checked. + Note: That this security check is performed at compile time. + + - trusted static properties - + The Smarty_Security class has the new property $trusted_static_properties to restrict access to static properties. + It's an nested array of trusted class and property names. + Format: + array ( + 'class_1' => array('prop_1', 'prop_2'), // allowed properties listed + 'class_2' => array(), // all properties of class allowed + } + To disable access for all properties of all classes set $trusted_static_properties = null; + The default value is an empty array() which does enables all properties of all classes, but for backward compatibility + the setting of $static_classes will be checked. + Note: That this security check is performed at compile time. + + - trusted constants . + The Smarty_Security class has the new property $trusted_constants to restrict access to constants. + It's an array of trusted constant names. + Format: + array ( + 'SMARTY_DIR' , // allowed constant + } + If the array is empty (default) the usage of constants can be controlled with the + Smarty_Security::$allow_constants property (default true) + + + + Compiled Templates + ================== + Smarty does now automatically detects a change of the $merge_compiled_includes and $escape_html + property and creates different compiled templates files depending on the setting. + + Same applies to config files and the $config_overwrite, $config_booleanize and + $config_read_hidden properties. + + Debugging + ========= + The layout of the debug window has been changed for better readability + + New class constants + Smarty::DEBUG_OFF + Smarty::DEBUG_ON + Smarty::DEBUG_INDIVIDUAL + have been introduced for setting the $debugging property. + + Smarty::DEBUG_INDIVIDUAL will create for each display() and fetch() call an individual debug window. + + . + diff --git a/include/smarty/README b/include/smarty/README index bf03403aa..08b397c3f 100644 --- a/include/smarty/README +++ b/include/smarty/README @@ -1,4 +1,4 @@ -Smarty 3.1.13 +Smarty 3.x Author: Monte Ohrt Author: Uwe Tews @@ -120,7 +120,7 @@ $smarty->unregisterObject($object_name) $smarty->unregisterFilter($type, $function_name) $smarty->unregisterResource($resource_type) -$smarty->compileAllTemplates($extention = '.tpl', $force_compile = false, $time_limit = 0, $max_errors = null) +$smarty->compileAllTemplates($extension = '.tpl', $force_compile = false, $time_limit = 0, $max_errors = null) $smarty->clearCompiledTemplate($resource_name = null, $compile_id = null, $exp_time = null) $smarty->testInstall() @@ -460,12 +460,13 @@ included template. PLUGINS ======= -Smarty3 are following the same coding rules as in Smarty2. -The only difference is that the template object is passed as additional third parameter. +Smarty 3 plugins follow the same coding rules as in Smarty 2. +The main difference is that the template object is now passed in place of the smarty object. +The smarty object can be still be accessed through $template->smarty. -smarty_plugintype_name (array $params, object $smarty, object $template) +smarty_plugintype_name (array $params, Smarty_Internal_Template $template) -The Smarty 2 plugins are still compatible as long as they do not make use of specific Smarty2 internals. +The Smarty 2 plugins are still compatible as long as they do not make use of specific Smarty 2 internals. TEMPLATE INHERITANCE: diff --git a/include/smarty/README.md b/include/smarty/README.md new file mode 100644 index 000000000..5783eb3e0 --- /dev/null +++ b/include/smarty/README.md @@ -0,0 +1,65 @@ +#Smarty 3 template engine +##Distribution repository + +> Smarty 3.1.28 introduces run time template inheritance + +> Read the NEW_FEATURES and INHERITANCE_RELEASE_NOTES file for recent extensions to Smarty 3.1 functionality + +Smarty versions 3.1.11 or later are now on github and can be installed with Composer. + + +The "smarty/smarty" package will start at libs/.... subfolder. + +To get the latest stable version of Smarty 3.1 use + +```json +"require": { + "smarty/smarty": "~3.1" +} +``` + +in your composer.json file. + +To get the trunk version use + +```json +"require": { + "smarty/smarty": "~3.1@dev" +} +``` + +For a specific version use something like + +```json +"require": { + "smarty/smarty": "3.1.19" +} +``` + +PHPUnit test can be installed by corresponding composer entries like + +```json +"require": { + "smarty/smarty-phpunit": "3.1.19" +} +``` + +Similar applies for the lexer/parser generator + +```json +"require": { + "smarty/smarty-lexer": "3.1.19" +} +``` + +Or you could use + +```json +"require": { + "smarty/smarty-dev": "3.1.19" +} +``` + +Which is a wrapper to install all 3 packages + +Composer can also be used for Smarty2 versions 2.6.24 to 2.6.28 diff --git a/include/smarty/SMARTY_3.1_NOTES.txt b/include/smarty/SMARTY_3.1_NOTES.txt index e56e56f67..57709f0d7 100644 --- a/include/smarty/SMARTY_3.1_NOTES.txt +++ b/include/smarty/SMARTY_3.1_NOTES.txt @@ -199,7 +199,7 @@ Relative paths are available with {include file="..."} and $smarty->fetch('./foo.tpl') cannot be relative to a template, an exception is thrown. - Adressing a specific $template_dir + Addressing a specific $template_dir Smarty 3.1 introduces the $template_dir index notation. $smarty->fetch('[foo]bar.tpl') and {include file="[foo]bar.tpl"} diff --git a/include/smarty/change_log.txt b/include/smarty/change_log.txt index 69642e276..dadc5d17d 100644 --- a/include/smarty/change_log.txt +++ b/include/smarty/change_log.txt @@ -1,9 +1,720 @@ -===== Smarty-3.1.13 ===== + ===== 3.1.29 ===== (21.12.2015) + 21.12.2015 + - optimization improve speed of filetime checks on extends and extendsall resource + + 20.12.2015 + - bugfix failure when the default resource type was set to 'extendsall' https://github.com/smarty-php/smarty/issues/123 + - update compilation of Smarty special variables + - bugfix add addition check for OS type on normalizaition of file path https://github.com/smarty-php/smarty/issues/134 + - bugfix the source uid of the extendsall resource must contain $template_dir settings https://github.com/smarty-php/smarty/issues/123 + + 19.12.2015 + - bugfix using $smarty.capture.foo in expressions could fail https://github.com/smarty-php/smarty/pull/138 + - bugfix broken PHP 5.2 compatibility https://github.com/smarty-php/smarty/issues/139 + - remove no longer used code + - improvement make sure that compiled and cache templates never can contain a trailing '?>? + + 18.12.2015 + - bugfix regression when modifier parameter was follow by math https://github.com/smarty-php/smarty/issues/132 + + 17.12.2015 + - bugfix {$smarty.capture.nameFail} did lowercase capture name https://github.com/smarty-php/smarty/issues/135 + - bugfix using {block append/prepend} on same block in multiple levels of inheritance templates could fail (forum topic 25827) + - bugfix text content consisting of just a single '0' like in {if true}0{/if} was suppressed (forum topic 25834) + + 16.12.2015 + - bugfix {foreach} did fail if from atrribute is a Generator class https://github.com/smarty-php/smarty/issues/128 + - bugfix direct access $smarty->template_dir = 'foo'; should call Smarty::setTemplateDir() https://github.com/smarty-php/smarty/issues/121 + + 15.12.2015 + - bugfix {$smarty.cookies.foo} did return the $_COOKIE array not the 'foo' value https://github.com/smarty-php/smarty/issues/122 + - bugfix a call to clearAllCache() and other should clear all internal template object caches (forum topic 25828) + + 14.12.2015 + - bugfix {$smarty.config.foo} broken in 3.1.28 https://github.com/smarty-php/smarty/issues/120 + - bugfix multiple calls of {section} with same name droped E_NOTICE error https://github.com/smarty-php/smarty/issues/118 + + ===== 3.1.28 ===== (13.12.2015) + 13.12.2015 + - bugfix {foreach} and {section} with uppercase characters in name attribute did not work (forum topic 25819) + - bugfix $smarty->debugging_ctrl = 'URL' did not work (forum topic 25811) + - bugfix Debug Console could display incorrect data when using subtemplates + + 09.12.2015 + - bugfix Smarty did fail under PHP 7.0.0 with use_include_path = true; + + 09.12.2015 + - bugfix {strip} should exclude some html tags from stripping, related to fix for https://github.com/smarty-php/smarty/issues/111 + + 08.12.2015 + - bugfix internal template function data got stored in wrong compiled file https://github.com/smarty-php/smarty/issues/114 + + 05.12.2015 + -bugfix {strip} should insert a single space https://github.com/smarty-php/smarty/issues/111 + + 25.11.2015 + -bugfix a left delimter like '[%' did fail on [%$var_[%$variable%]%] (forum topic 25798) + + 02.11.2015 + - bugfix {include} with variable file name like {include file="foo_`$bar`.tpl"} did fail in 3.1.28-dev https://github.com/smarty-php/smarty/issues/102 + + 01.11.2015 + - update config file processing + + 31.10.2015 + - bugfix add missing $trusted_dir property to SmartyBC class (forum topic 25751) + + 29.10.2015 + - improve template scope handling + + 24.10.2015 + - more optimizations of template processing + - bugfix Error when using {include} within {capture} https://github.com/smarty-php/smarty/issues/100 + + 21.10.2015 + - move some code into runtime extensions + + 18.10.2015 + - optimize filepath normalization + - rework of template inheritance + - speed and size optimizations + - bugfix under HHVM temporary cache file must only be created when caches template was updated + - fix compiled code for new {block} assign attribute + - update code generated by template function call handler + + 18.09.2015 + - bugfix {if $foo instanceof $bar} failed to compile if 2nd value is a variable https://github.com/smarty-php/smarty/issues/92 + + 17.09.2015 + - bugfix {foreach} first attribute was not correctly reset since commit 05a8fa2 of 02.08.2015 https://github.com/smarty-php/smarty/issues/90 + + 16.09.2015 + - update compiler by moving no longer needed properties, code optimizations and other + + 14.09.2015 + - optimize autoloader + - optimize subtemplate handling + - update template inheritance processing + - move code of {call} processing back into Smarty_Internal_Template class + - improvement invalidate OPCACHE for cleared compiled and cached template files (forum topic 25557) + - bugfix unintended multiple debug windows (forum topic 25699) + + 30.08.2015 + - size optimization move some runtime functions into extension + - optimize inline template processing + - optimization merge inheritance child and parent templates into one compiled template file + + 29.08.2015 + - improvement convert template inheritance into runtime processing + - bugfix {$smarty.block.parent} did always reference the root parent block https://github.com/smarty-php/smarty/issues/68 + + 23.08.2015 + - introduce Smarty::$resource_cache_mode and cache template object of {include} inside loop + - load seldom used Smarty API methods dynamically to reduce memory footprint + - cache template object of {include} if same template is included several times + - convert debug console processing to object + - use output buffers for better performance and less memory usage + - optimize nocache hash processing + - remove not really needed properties + - optimize rendering + - move caching to Smarty::_cache + - remove properties with redundant content + - optimize Smarty::templateExists() + - optimize use_include_path processing + - relocate properties for size optimization + - remove redundant code + - bugfix compiling super globals like {$smarty.get.foo} did fail in the master branch https://github.com/smarty-php/smarty/issues/77 + + 06.08.2015 + - avoid possible circular object references caused by parser/lexer objects + - rewrite compileAll... utility methods + - commit several internal improvements + - bugfix Smarty failed when compile_id did contain "|" + + 03.08.2015 + - rework clear cache methods + - bugfix compileAllConfig() was broken since 3.1.22 because of the changes in config file processing + - improve getIncludePath() to return directory if no file was given + + 02.08.2015 + - optimization and code cleanup of {foreach} and {section} compiler + - rework {capture} compiler + + 01.08.2015 + - update DateTime object can be instance of DateTimeImmutable since PHP5.5 https://github.com/smarty-php/smarty/pull/75 + - improvement show resource type and start of template source instead of uid on eval: and string: resource (forum topic 25630) + + 31.07.2015 + - optimize {foreach} and {section} compiler + + 29.07.2015 + - optimize {section} compiler for speed and size of compiled code + + 28.07.2015 + - update for PHP 7 compatibility + + 26.07.2015 + - improvement impement workaround for HHVM PHP incompatibillity https://github.com/facebook/hhvm/issues/4797 + + 25.07.2015 + - bugfix parser did hang on text starting fetch('foo.tpl') https://github.com/smarty-php/smarty/issues/70 + - improvement Added $limit parameter to regex_replace modifier #71 + - new feature multiple indices on file: resource + + 06.07.2015 + - optimize {block} compilation + - optimization get rid of __get and __set in source object + + 01.07.2015 + - optimize compile check handling + - update {foreach} compiler + - bugfix debugging console did not display string values containing \n, \r or \t correctly https://github.com/smarty-php/smarty/issues/66 + - optimize source resources + + 28.06.2015 + - move $smarty->enableSecurity() into Smarty_Security class + - optimize security isTrustedResourceDir() + - move auto load filter methods into extension + - move $smarty->getTemplateVars() into extension + - move getStreamVariable() into extension + - move $smarty->append() and $smarty->appendByRef() into extension + - optimize autoloader + - optimize file path normalization + - bugfix PATH_SEPARATOR was replaced by mistake in autoloader + - remove redundant code + + 27.06.2015 + - bugfix resolve naming conflict between custom Smarty delimiter '<%' and PHP ASP tags https://github.com/smarty-php/smarty/issues/64 + - update $smarty->_realpath for relative path not starting with './' + - update Smarty security with new realpath handling + - update {include_php} with new realpath handling + - move $smarty->loadPlugin() into extension + - minor compiler optimizations + - bugfix allow function plugins with name ending with 'close' https://github.com/smarty-php/smarty/issues/52 + - rework of $smarty->clearCompiledTemplate() and move it to its own extension + + 19.06.2015 + - improvement allow closures as callback at $smarty->registerFilter() https://github.com/smarty-php/smarty/issues/59 + + ===== 3.1.27===== (18.06.2015) + 18.06.2015 + - bugfix another update on file path normalization failed on path containing something like "/.foo/" https://github.com/smarty-php/smarty/issues/56 + + ===== 3.1.26===== (18.06.2015) + 18.06.2015 + - bugfix file path normalization failed on path containing something like "/.foo/" https://github.com/smarty-php/smarty/issues/56 + + 17.06.2015 + - bugfix calling a plugin with nocache option but no other attributes like {foo nocache} caused call to undefined function https://github.com/smarty-php/smarty/issues/55 + + ===== 3.1.25===== (15.06.2015) + 15.06.2015 + - optimization of smarty_cachereource_keyvaluestore.php code + + 14.06.2015 + - bugfix a relative sub template path could fail if template_dir path did contain /../ https://github.com/smarty-php/smarty/issues/50 + - optimization rework of path normalization + - bugfix an output tag with variable, modifier followed by an operator like {$foo|modifier+1} did fail https://github.com/smarty-php/smarty/issues/53 + + 13.06.2015 + - bugfix a custom cache resource using smarty_cachereource_keyvaluestore.php did fail if php.ini mbstring.func_overload = 2 (forum topic 25568) + + 11.06.2015 + - bugfix the lexer could hang on very large quoted strings (forum topic 25570) + + 08.06.2015 + - bugfix using {$foo} as array index like $bar.{$foo} or in double quoted string like "some {$foo} thing" failed https://github.com/smarty-php/smarty/issues/49 + + 04.06.2015 + - bugfix possible error message on unset() while compiling {block} tags https://github.com/smarty-php/smarty/issues/46 + + 01.06.2015 + - bugfix including template variables broken since 3.1.22 https://github.com/smarty-php/smarty/issues/47 + + 27.05.2015 + - bugfix {include} with variable file name must not create by default individual cache file (since 3.1.22) https://github.com/smarty-php/smarty/issues/43 + + 24.05.2015 + - bugfix if condition string 'neq' broken due to a typo https://github.com/smarty-php/smarty/issues/42 + + ===== 3.1.24===== (23.05.2015) + 23.05.2015 + - improvement on php_handling to allow very large PHP sections, better error handling + - improvement allow extreme large comment sections (forum 25538) + + 21.05.2015 + - bugfix broken PHP 5.2 compatibility when compiling 1 did compile into wrong code https://github.com/smarty-php/smarty/issues/41 + + 19.05.2015 + - bugfix compiler did overwrite existing variable value when setting the nocache attribute https://github.com/smarty-php/smarty/issues/39 + - bugfix output filter trimwhitespace could run into the pcre.backtrack_limit on large output (code.google issue 220) + - bugfix compiler could run into the pcre.backtrack_limit on larger comment or {php} tag sections (forum 25538) + + 18.05.2015 + - improvement introduce shortcuts in lexer/parser rules for most frequent terms for higher + compilation speed + + 16.05.2015 + - bugfix {php}{/php} did work just for single lines https://github.com/smarty-php/smarty/issues/33 + - improvement remove not needed ?> handling from parser to new compiler module + + 05.05.2015 + - bugfix code could be messed up when {tags} are used in multiple attributes https://github.com/smarty-php/smarty/issues/23 + + 04.05.2015 + - bugfix Smarty_Resource::parseResourceName incompatible with Google AppEngine (https://github.com/smarty-php/smarty/issues/22) + - improvement use is_file() checks to avoid errors suppressed by @ which could still cause problems (https://github.com/smarty-php/smarty/issues/24) + + 28.04.2015 + - bugfix plugins of merged subtemplates not loaded in 3.1.22-dev (forum topic 25508) 2nd fix + + 28.04.2015 + - bugfix plugins of merged subtemplates not loaded in 3.1.22-dev (forum topic 25508) + + 23.04.2015 + - bugfix a nocache template variable used as parameter at {insert} was by mistake cached + + 20.04.2015 + - bugfix at a template function containing nocache code a parmeter could overwrite a template variable of same name + + 27.03.2015 + - bugfix Smarty_Security->allow_constants=false; did also disable true, false and null (change of 16.03.2015) + - improvement added a whitelist for trusted constants to security Smarty_Security::$trusted_constants (forum topic 25471) + + 20.03.2015 + - bugfix make sure that function properties get saved only in compiled files containing the fuction definition {forum topic 25452} + - bugfix correct update of global variable values on exit of template functions. (reported under Smarty Developers) + + 16.03.2015 + - bugfix problems with {function}{/function} and {call} tags in different subtemplate cache files {forum topic 25452} + - bugfix Smarty_Security->allow_constants=false; did not disallow direct usage of defined constants like {SMARTY_DIR} {forum topic 25457} + - bugfix {block}{/block} tags did not work inside double quoted strings https://github.com/smarty-php/smarty/issues/18 + + + 15.03.2015 + - bugfix $smarty->compile_check must be restored before rendering of a just updated cache file {forum 25452} + + 14.03.2015 + - bugfix {nocache} {/nocache} tags corrupted code when used within a nocache section caused by a nocache template variable. + + - bugfix template functions defined with {function} in an included subtemplate could not be called in nocache + mode with {call... nocache} if the subtemplate had it's own cache file {forum 25452} + + 10.03.2015 + - bugfix {include ... nocache} whith variable file or compile_id attribute was not executed in nocache mode. + + 12.02.2015 + - bugfix multiple Smarty::fetch() of same template when $smarty->merge_compiled_includes = true; could cause function already defined error + + 11.02.2015 + - bugfix recursive {includes} did create E_NOTICE message when $smarty->merge_compiled_includes = true; (github issue #16) + + 22.01.2015 + - new feature security can now control access to static methods and properties + see also NEW_FEATURES.txt + + 21.01.2015 + - bugfix clearCompiledTemplates(), clearAll() and clear() could try to delete whole drive at wrong path permissions because realpath() fail (forum 25397) + - bugfix 'self::' and 'parent::' was interpreted in template syntax as static class + + 04.01.2015 + - push last weeks changes to github + + - different optimizations + - improvement automatically create different versions of compiled templates and config files depending + on property settings. + - optimization restructure template processing by moving code into classes it better belongs to + - optimization restructure config file processing + + 31.12.2014 + - bugfix use function_exists('mb_get_info') for setting Smarty::$_MBSTRING. + Function mb_split could be overloaded depending on php.ini mbstring.func_overload + + + 29.12.2014 + - new feature security can now limit the template nesting level by property $max_template_nesting + see also NEW_FEATURES.txt (forum 25370) + + 29.12.2014 + - new feature security can now disable special $smarty variables listed in property $disabled_special_smarty_vars + see also NEW_FEATURES.txt (forum 25370) + + 27.12.2014 + - bugfix clear internal _is_file_cache when plugins_dir was modified + + 13.12.2014 + - improvement optimization of lexer and parser resulting in a up to 30% higher compiling speed + + 11.12.2014 + - bugfix resolve parser ambiguity between constant print tag {CONST} and other smarty tags after change of 09.12.2014 + + 09.12.2014 + - bugfix variables $null, $true and $false did not work after the change of 12.11.2014 (forum 25342) + - bugfix call of template function by a variable name did not work after latest changes (forum 25342) + + 23.11.2014 + - bugfix a plugin with attached modifier could fail if the tag was immediately followed by another Smarty tag (since 3.1.21) (forum 25326) + + 13.11.2014 + - improvement move autoload code into Autoloader.php. Use Composer autoloader when possible + + 12.11.2014 + - new feature added support of namespaces to template code + + 08.11.2014 - 10.11.2014 + - bugfix subtemplate called in nocache mode could be called with wrong compile_id when it did change on one of the calling templates + - improvement add code of template functions called in nocache mode dynamically to cache file (related to bugfix of 01.11.2014) + - bugfix Debug Console did not include all data from merged compiled subtemplates + + 04.11.2014 + - new feature $smarty->debugging = true; => overwrite existing Debug Console window (old behaviour) + $smarty->debugging = 2; => individual Debug Console window by template name + + 03.11.2014 + - bugfix Debug Console did not show included subtemplates since 3.1.17 (forum 25301) + - bugfix Modifier debug_print_var did not limit recursion or prevent recursive object display at Debug Console + (ATTENTION: parameter order has changed to be able to specify maximum recursion) + - bugfix Debug consol did not include subtemplate information with $smarty->merge_compiled_includes = true + - improvement The template variables are no longer displayed as objects on the Debug Console + - improvement $smarty->createData($parent = null, $name = null) new optional name parameter for display at Debug Console + - addition of some hooks for future extension of Debug Console + + 01.11.2014 + - bugfix and enhancement on subtemplate {include} and template {function} tags. + * Calling a template which has a nocache section could fail if it was called from a cached and a not cached subtemplate. + * Calling the same subtemplate cached and not cached with the $smarty->merge_compiled_includes enabled could cause problems + * Many smaller related changes + + 30.10.2014 + - bugfix access to class constant by object like {$object::CONST} or variable class name {$class::CONST} did not work (forum 25301) + + 26.10.2014 + - bugfix E_NOTICE message was created during compilation when ASP tags '<%' or '%>' are in template source text + - bugfix merge_compiled_includes option failed when caching enables and same subtemplate was included cached and not cached + + ===== 3.1.21 ===== (18.10.2014) + 18.10.2014 + - composer moved to github + + 17.10.2014 + - bugfix on $php_handling security and optimization of smarty_internal_parsetree (Thue Kristensen) + + 16.10.2014 + - bugfix composer.json update + + 15.10.2014 + - bugfix calling a new created cache file with fetch() and Smarty::CACHING_LIFETIME_SAVED multiple times did fail (forum 22350) + + 14.10.2014 + - bugfix any tag placed within " diff --git a/include/smarty/libs/plugins/block.textformat.php b/include/smarty/libs/plugins/block.textformat.php index b22b104a5..abf544939 100644 --- a/include/smarty/libs/plugins/block.textformat.php +++ b/include/smarty/libs/plugins/block.textformat.php @@ -2,13 +2,12 @@ /** * Smarty plugin to format text blocks * - * @package Smarty + * @package Smarty * @subpackage PluginsBlock */ /** * Smarty {textformat}{/textformat} block plugin - * * Type: block function
    * Name: textformat
    * Purpose: format text a certain way with preset styles @@ -23,12 +22,14 @@ * - wrap_boundary - boolean (true) * * - * @link http://www.smarty.net/manual/en/language.function.textformat.php {textformat} - * (Smarty online manual) + * @link http://www.smarty.net/manual/en/language.function.textformat.php {textformat} + * (Smarty online manual) + * * @param array $params parameters * @param string $content contents of the block * @param Smarty_Internal_Template $template template object * @param boolean &$repeat repeat flag + * * @return string content re-formatted * @author Monte Ohrt */ @@ -53,17 +54,17 @@ function smarty_block_textformat($params, $content, $template, &$repeat) case 'indent_char': case 'wrap_char': case 'assign': - $$_key = (string)$_val; + $$_key = (string) $_val; break; case 'indent': case 'indent_first': case 'wrap': - $$_key = (int)$_val; + $$_key = (int) $_val; break; case 'wrap_cut': - $$_key = (bool)$_val; + $$_key = (bool) $_val; break; default: @@ -76,8 +77,6 @@ function smarty_block_textformat($params, $content, $template, &$repeat) } // split into paragraphs $_paragraphs = preg_split('![\r\n]{2}!', $content); - $_output = ''; - foreach ($_paragraphs as &$_paragraph) { if (!$_paragraph) { @@ -102,12 +101,10 @@ function smarty_block_textformat($params, $content, $template, &$repeat) } } $_output = implode($wrap_char . $wrap_char, $_paragraphs); - + if ($assign) { $template->assign($assign, $_output); } else { return $_output; } } - -?> \ No newline at end of file diff --git a/include/smarty/libs/plugins/function.counter.php b/include/smarty/libs/plugins/function.counter.php index 3906badf0..4da85a14e 100644 --- a/include/smarty/libs/plugins/function.counter.php +++ b/include/smarty/libs/plugins/function.counter.php @@ -1,22 +1,24 @@ * Name: counter
    * Purpose: print out a counter value * * @author Monte Ohrt - * @link http://www.smarty.net/manual/en/language.function.counter.php {counter} - * (Smarty online manual) + * @link http://www.smarty.net/manual/en/language.function.counter.php {counter} + * (Smarty online manual) + * * @param array $params parameters * @param Smarty_Internal_Template $template template object + * * @return string|null */ function smarty_function_counter($params, $template) @@ -26,16 +28,16 @@ function smarty_function_counter($params, $template) $name = (isset($params['name'])) ? $params['name'] : 'default'; if (!isset($counters[$name])) { $counters[$name] = array( - 'start'=>1, - 'skip'=>1, - 'direction'=>'up', - 'count'=>1 - ); + 'start' => 1, + 'skip' => 1, + 'direction' => 'up', + 'count' => 1 + ); } $counter =& $counters[$name]; if (isset($params['start'])) { - $counter['start'] = $counter['count'] = (int)$params['start']; + $counter['start'] = $counter['count'] = (int) $params['start']; } if (!empty($params['assign'])) { @@ -45,9 +47,9 @@ function smarty_function_counter($params, $template) if (isset($counter['assign'])) { $template->assign($counter['assign'], $counter['count']); } - + if (isset($params['print'])) { - $print = (bool)$params['print']; + $print = (bool) $params['print']; } else { $print = empty($counter['assign']); } @@ -61,18 +63,16 @@ function smarty_function_counter($params, $template) if (isset($params['skip'])) { $counter['skip'] = $params['skip']; } - + if (isset($params['direction'])) { $counter['direction'] = $params['direction']; } - if ($counter['direction'] == "down") + if ($counter['direction'] == "down") { $counter['count'] -= $counter['skip']; - else + } else { $counter['count'] += $counter['skip']; - - return $retval; - -} + } -?> \ No newline at end of file + return $retval; +} diff --git a/include/smarty/libs/plugins/function.cycle.php b/include/smarty/libs/plugins/function.cycle.php index 1778ffb53..8dc5cd9d5 100644 --- a/include/smarty/libs/plugins/function.cycle.php +++ b/include/smarty/libs/plugins/function.cycle.php @@ -2,13 +2,12 @@ /** * Smarty plugin * - * @package Smarty + * @package Smarty * @subpackage PluginsFunction */ /** * Smarty {cycle} function plugin - * * Type: function
    * Name: cycle
    * Date: May 3, 2002
    @@ -31,15 +30,17 @@ * {cycle name=row} * * - * @link http://www.smarty.net/manual/en/language.function.cycle.php {cycle} - * (Smarty online manual) - * @author Monte Ohrt - * @author credit to Mark Priatel - * @author credit to Gerard - * @author credit to Jason Sweat + * @link http://www.smarty.net/manual/en/language.function.cycle.php {cycle} + * (Smarty online manual) + * @author Monte Ohrt + * @author credit to Mark Priatel + * @author credit to Gerard + * @author credit to Jason Sweat * @version 1.3 + * * @param array $params parameters * @param Smarty_Internal_Template $template template object + * * @return string|null */ @@ -48,18 +49,20 @@ function smarty_function_cycle($params, $template) static $cycle_vars; $name = (empty($params['name'])) ? 'default' : $params['name']; - $print = (isset($params['print'])) ? (bool)$params['print'] : true; - $advance = (isset($params['advance'])) ? (bool)$params['advance'] : true; - $reset = (isset($params['reset'])) ? (bool)$params['reset'] : false; + $print = (isset($params['print'])) ? (bool) $params['print'] : true; + $advance = (isset($params['advance'])) ? (bool) $params['advance'] : true; + $reset = (isset($params['reset'])) ? (bool) $params['reset'] : false; if (!isset($params['values'])) { - if(!isset($cycle_vars[$name]['values'])) { + if (!isset($cycle_vars[$name]['values'])) { trigger_error("cycle: missing 'values' parameter"); + return; } } else { - if(isset($cycle_vars[$name]['values']) - && $cycle_vars[$name]['values'] != $params['values'] ) { + if (isset($cycle_vars[$name]['values']) + && $cycle_vars[$name]['values'] != $params['values'] + ) { $cycle_vars[$name]['index'] = 0; } $cycle_vars[$name]['values'] = $params['values']; @@ -71,13 +74,13 @@ function smarty_function_cycle($params, $template) $cycle_vars[$name]['delimiter'] = ','; } - if(is_array($cycle_vars[$name]['values'])) { + if (is_array($cycle_vars[$name]['values'])) { $cycle_array = $cycle_vars[$name]['values']; } else { - $cycle_array = explode($cycle_vars[$name]['delimiter'],$cycle_vars[$name]['values']); + $cycle_array = explode($cycle_vars[$name]['delimiter'], $cycle_vars[$name]['values']); } - if(!isset($cycle_vars[$name]['index']) || $reset ) { + if (!isset($cycle_vars[$name]['index']) || $reset) { $cycle_vars[$name]['index'] = 0; } @@ -86,21 +89,19 @@ function smarty_function_cycle($params, $template) $template->assign($params['assign'], $cycle_array[$cycle_vars[$name]['index']]); } - if($print) { + if ($print) { $retval = $cycle_array[$cycle_vars[$name]['index']]; } else { $retval = null; } - if($advance) { - if ( $cycle_vars[$name]['index'] >= count($cycle_array) -1 ) { + if ($advance) { + if ($cycle_vars[$name]['index'] >= count($cycle_array) - 1) { $cycle_vars[$name]['index'] = 0; } else { - $cycle_vars[$name]['index']++; + $cycle_vars[$name]['index'] ++; } } return $retval; } - -?> \ No newline at end of file diff --git a/include/smarty/libs/plugins/function.fetch.php b/include/smarty/libs/plugins/function.fetch.php index eca1182d5..3506d4a8d 100644 --- a/include/smarty/libs/plugins/function.fetch.php +++ b/include/smarty/libs/plugins/function.fetch.php @@ -2,50 +2,53 @@ /** * Smarty plugin * - * @package Smarty + * @package Smarty * @subpackage PluginsFunction */ /** * Smarty {fetch} plugin - * * Type: function
    * Name: fetch
    * Purpose: fetch file, web or ftp data and display results * - * @link http://www.smarty.net/manual/en/language.function.fetch.php {fetch} - * (Smarty online manual) + * @link http://www.smarty.net/manual/en/language.function.fetch.php {fetch} + * (Smarty online manual) * @author Monte Ohrt + * * @param array $params parameters * @param Smarty_Internal_Template $template template object + * + * @throws SmartyException * @return string|null if the assign parameter is passed, Smarty assigns the result to a template variable */ function smarty_function_fetch($params, $template) { if (empty($params['file'])) { - trigger_error("[plugin] fetch parameter 'file' cannot be empty",E_USER_NOTICE); + trigger_error("[plugin] fetch parameter 'file' cannot be empty", E_USER_NOTICE); + return; } - + // strip file protocol if (stripos($params['file'], 'file://') === 0) { $params['file'] = substr($params['file'], 7); } - + $protocol = strpos($params['file'], '://'); if ($protocol !== false) { $protocol = strtolower(substr($params['file'], 0, $protocol)); } - + if (isset($template->smarty->security_policy)) { if ($protocol) { // remote resource (or php stream, …) - if(!$template->smarty->security_policy->isTrustedUri($params['file'])) { + if (!$template->smarty->security_policy->isTrustedUri($params['file'])) { return; } } else { // local file - if(!$template->smarty->security_policy->isTrustedResourceDir($params['file'])) { + if (!$template->smarty->security_policy->isTrustedResourceDir($params['file'])) { return; } } @@ -54,53 +57,54 @@ function smarty_function_fetch($params, $template) $content = ''; if ($protocol == 'http') { // http fetch - if($uri_parts = parse_url($params['file'])) { + if ($uri_parts = parse_url($params['file'])) { // set defaults $host = $server_name = $uri_parts['host']; $timeout = 30; $accept = "image/gif, image/x-xbitmap, image/jpeg, image/pjpeg, */*"; - $agent = "Smarty Template Engine ". Smarty::SMARTY_VERSION; + $agent = "Smarty Template Engine " . Smarty::SMARTY_VERSION; $referer = ""; $uri = !empty($uri_parts['path']) ? $uri_parts['path'] : '/'; $uri .= !empty($uri_parts['query']) ? '?' . $uri_parts['query'] : ''; $_is_proxy = false; - if(empty($uri_parts['port'])) { + if (empty($uri_parts['port'])) { $port = 80; } else { $port = $uri_parts['port']; } - if(!empty($uri_parts['user'])) { + if (!empty($uri_parts['user'])) { $user = $uri_parts['user']; } - if(!empty($uri_parts['pass'])) { + if (!empty($uri_parts['pass'])) { $pass = $uri_parts['pass']; } // loop through parameters, setup headers - foreach($params as $param_key => $param_value) { - switch($param_key) { + foreach ($params as $param_key => $param_value) { + switch ($param_key) { case "file": case "assign": case "assign_headers": break; case "user": - if(!empty($param_value)) { + if (!empty($param_value)) { $user = $param_value; } break; case "pass": - if(!empty($param_value)) { + if (!empty($param_value)) { $pass = $param_value; } break; case "accept": - if(!empty($param_value)) { + if (!empty($param_value)) { $accept = $param_value; } break; case "header": - if(!empty($param_value)) { - if(!preg_match('![\w\d-]+: .+!',$param_value)) { - trigger_error("[plugin] invalid header format '".$param_value."'",E_USER_NOTICE); + if (!empty($param_value)) { + if (!preg_match('![\w\d-]+: .+!', $param_value)) { + trigger_error("[plugin] invalid header format '" . $param_value . "'", E_USER_NOTICE); + return; } else { $extra_headers[] = $param_value; @@ -108,99 +112,104 @@ function smarty_function_fetch($params, $template) } break; case "proxy_host": - if(!empty($param_value)) { + if (!empty($param_value)) { $proxy_host = $param_value; } break; case "proxy_port": - if(!preg_match('!\D!', $param_value)) { + if (!preg_match('!\D!', $param_value)) { $proxy_port = (int) $param_value; } else { - trigger_error("[plugin] invalid value for attribute '".$param_key."'",E_USER_NOTICE); + trigger_error("[plugin] invalid value for attribute '" . $param_key . "'", E_USER_NOTICE); + return; } break; case "agent": - if(!empty($param_value)) { + if (!empty($param_value)) { $agent = $param_value; } break; case "referer": - if(!empty($param_value)) { + if (!empty($param_value)) { $referer = $param_value; } break; case "timeout": - if(!preg_match('!\D!', $param_value)) { + if (!preg_match('!\D!', $param_value)) { $timeout = (int) $param_value; } else { - trigger_error("[plugin] invalid value for attribute '".$param_key."'",E_USER_NOTICE); + trigger_error("[plugin] invalid value for attribute '" . $param_key . "'", E_USER_NOTICE); + return; } break; default: - trigger_error("[plugin] unrecognized attribute '".$param_key."'",E_USER_NOTICE); + trigger_error("[plugin] unrecognized attribute '" . $param_key . "'", E_USER_NOTICE); + return; } } - if(!empty($proxy_host) && !empty($proxy_port)) { + if (!empty($proxy_host) && !empty($proxy_port)) { $_is_proxy = true; - $fp = fsockopen($proxy_host,$proxy_port,$errno,$errstr,$timeout); + $fp = fsockopen($proxy_host, $proxy_port, $errno, $errstr, $timeout); } else { - $fp = fsockopen($server_name,$port,$errno,$errstr,$timeout); + $fp = fsockopen($server_name, $port, $errno, $errstr, $timeout); } - if(!$fp) { - trigger_error("[plugin] unable to fetch: $errstr ($errno)",E_USER_NOTICE); + if (!$fp) { + trigger_error("[plugin] unable to fetch: $errstr ($errno)", E_USER_NOTICE); + return; } else { - if($_is_proxy) { + if ($_is_proxy) { fputs($fp, 'GET ' . $params['file'] . " HTTP/1.0\r\n"); } else { fputs($fp, "GET $uri HTTP/1.0\r\n"); } - if(!empty($host)) { + if (!empty($host)) { fputs($fp, "Host: $host\r\n"); } - if(!empty($accept)) { + if (!empty($accept)) { fputs($fp, "Accept: $accept\r\n"); } - if(!empty($agent)) { + if (!empty($agent)) { fputs($fp, "User-Agent: $agent\r\n"); } - if(!empty($referer)) { + if (!empty($referer)) { fputs($fp, "Referer: $referer\r\n"); } - if(isset($extra_headers) && is_array($extra_headers)) { - foreach($extra_headers as $curr_header) { - fputs($fp, $curr_header."\r\n"); + if (isset($extra_headers) && is_array($extra_headers)) { + foreach ($extra_headers as $curr_header) { + fputs($fp, $curr_header . "\r\n"); } } - if(!empty($user) && !empty($pass)) { - fputs($fp, "Authorization: BASIC ".base64_encode("$user:$pass")."\r\n"); + if (!empty($user) && !empty($pass)) { + fputs($fp, "Authorization: BASIC " . base64_encode("$user:$pass") . "\r\n"); } fputs($fp, "\r\n"); - while(!feof($fp)) { - $content .= fgets($fp,4096); + while (!feof($fp)) { + $content .= fgets($fp, 4096); } fclose($fp); - $csplit = preg_split("!\r\n\r\n!",$content,2); + $csplit = preg_split("!\r\n\r\n!", $content, 2); $content = $csplit[1]; - if(!empty($params['assign_headers'])) { - $template->assign($params['assign_headers'],preg_split("!\r\n!",$csplit[0])); + if (!empty($params['assign_headers'])) { + $template->assign($params['assign_headers'], preg_split("!\r\n!", $csplit[0])); } } } else { - trigger_error("[plugin fetch] unable to parse URL, check syntax",E_USER_NOTICE); + trigger_error("[plugin fetch] unable to parse URL, check syntax", E_USER_NOTICE); + return; } } else { $content = @file_get_contents($params['file']); if ($content === false) { - throw new SmartyException("{fetch} cannot read resource '" . $params['file'] ."'"); + throw new SmartyException("{fetch} cannot read resource '" . $params['file'] . "'"); } } @@ -210,5 +219,3 @@ function smarty_function_fetch($params, $template) return $content; } } - -?> \ No newline at end of file diff --git a/include/smarty/libs/plugins/function.html_checkboxes.php b/include/smarty/libs/plugins/function.html_checkboxes.php index 1866bc2f3..d78680368 100644 --- a/include/smarty/libs/plugins/function.html_checkboxes.php +++ b/include/smarty/libs/plugins/function.html_checkboxes.php @@ -2,13 +2,12 @@ /** * Smarty plugin * - * @package Smarty + * @package Smarty * @subpackage PluginsFunction */ /** * Smarty {html_checkboxes} function plugin - * * File: function.html_checkboxes.php
    * Type: function
    * Name: html_checkboxes
    @@ -32,15 +31,17 @@ * - escape (optional) - escape the content (not value), defaults to true * * - * @link http://www.smarty.net/manual/en/language.function.html.checkboxes.php {html_checkboxes} - * (Smarty online manual) + * @link http://www.smarty.net/manual/en/language.function.html.checkboxes.php {html_checkboxes} + * (Smarty online manual) * @author Christopher Kvarme - * @author credits to Monte Ohrt + * @author credits to Monte Ohrt * @version 1.0 - * @param array $params parameters + * + * @param array $params parameters * @param object $template template object + * * @return string - * @uses smarty_function_escape_special_chars() + * @uses smarty_function_escape_special_chars() */ function smarty_function_html_checkboxes($params, $template) { @@ -58,8 +59,8 @@ function smarty_function_html_checkboxes($params, $template) $extra = ''; - foreach($params as $_key => $_val) { - switch($_key) { + foreach ($params as $_key => $_val) { + switch ($_key) { case 'name': case 'separator': $$_key = (string) $_val; @@ -89,7 +90,7 @@ function smarty_function_html_checkboxes($params, $template) if (method_exists($_sel, "__toString")) { $_sel = smarty_function_escape_special_chars((string) $_sel->__toString()); } else { - trigger_error("html_checkboxes: selected attribute contains an object of class '". get_class($_sel) ."' without __toString() method", E_USER_NOTICE); + trigger_error("html_checkboxes: selected attribute contains an object of class '" . get_class($_sel) . "' without __toString() method", E_USER_NOTICE); continue; } } else { @@ -101,7 +102,7 @@ function smarty_function_html_checkboxes($params, $template) if (method_exists($_val, "__toString")) { $selected = smarty_function_escape_special_chars((string) $_val->__toString()); } else { - trigger_error("html_checkboxes: selected attribute is an object of class '". get_class($_val) ."' without __toString() method", E_USER_NOTICE); + trigger_error("html_checkboxes: selected attribute is an object of class '" . get_class($_val) . "' without __toString() method", E_USER_NOTICE); } } else { $selected = smarty_function_escape_special_chars((string) $_val); @@ -116,7 +117,8 @@ function smarty_function_html_checkboxes($params, $template) case 'assign': break; - case 'strict': break; + case 'strict': + break; case 'disabled': case 'readonly': @@ -131,11 +133,11 @@ function smarty_function_html_checkboxes($params, $template) break; } - // omit break; to fall through! + // omit break; to fall through! default: - if(!is_array($_val)) { - $extra .= ' '.$_key.'="'.smarty_function_escape_special_chars($_val).'"'; + if (!is_array($_val)) { + $extra .= ' ' . $_key . '="' . smarty_function_escape_special_chars($_val) . '"'; } else { trigger_error("html_checkboxes: extra attribute '$_key' cannot be an array", E_USER_NOTICE); } @@ -143,76 +145,79 @@ function smarty_function_html_checkboxes($params, $template) } } - if (!isset($options) && !isset($values)) - return ''; /* raise error here? */ + if (!isset($options) && !isset($values)) { + return ''; + } /* raise error here? */ $_html_result = array(); if (isset($options)) { - foreach ($options as $_key=>$_val) { + foreach ($options as $_key => $_val) { $_html_result[] = smarty_function_html_checkboxes_output($name, $_key, $_val, $selected, $extra, $separator, $labels, $label_ids, $escape); } } else { - foreach ($values as $_i=>$_key) { + foreach ($values as $_i => $_key) { $_val = isset($output[$_i]) ? $output[$_i] : ''; $_html_result[] = smarty_function_html_checkboxes_output($name, $_key, $_val, $selected, $extra, $separator, $labels, $label_ids, $escape); } } - if(!empty($params['assign'])) { + if (!empty($params['assign'])) { $template->assign($params['assign'], $_html_result); } else { return implode("\n", $_html_result); } - } -function smarty_function_html_checkboxes_output($name, $value, $output, $selected, $extra, $separator, $labels, $label_ids, $escape=true) { +function smarty_function_html_checkboxes_output($name, $value, $output, $selected, $extra, $separator, $labels, $label_ids, $escape = true) +{ $_output = ''; - + if (is_object($value)) { if (method_exists($value, "__toString")) { $value = (string) $value->__toString(); } else { - trigger_error("html_options: value is an object of class '". get_class($value) ."' without __toString() method", E_USER_NOTICE); + trigger_error("html_options: value is an object of class '" . get_class($value) . "' without __toString() method", E_USER_NOTICE); + return ''; } } else { $value = (string) $value; } - + if (is_object($output)) { if (method_exists($output, "__toString")) { $output = (string) $output->__toString(); } else { - trigger_error("html_options: output is an object of class '". get_class($output) ."' without __toString() method", E_USER_NOTICE); + trigger_error("html_options: output is an object of class '" . get_class($output) . "' without __toString() method", E_USER_NOTICE); + return ''; } } else { $output = (string) $output; } - + if ($labels) { if ($label_ids) { $_id = smarty_function_escape_special_chars(preg_replace('![^\w\-\.]!' . Smarty::$_UTF8_MODIFIER, '_', $name . '_' . $value)); $_output .= '