Changeset 16495


Ignore:
Timestamp:
Jul 8, 2012, 5:02:01 PM (8 years ago)
Author:
icy
Message:

Version 2.0.0, advance ACL . Code copied from git/master.

I could not use merging with git svn . Stupidly copy-&-paste ;)

Location:
extensions/Icy_Picture_Modify
Files:
4 added
7 edited

Legend:

Unmodified
Added
Removed
  • extensions/Icy_Picture_Modify/CHANGELOG

    r16357 r16495  
     12.0.0 2012-07-09
     2
     3  - Advance ACL support in local ZAML file
     4  - Upload permission can be specified in new ACL
     5  - Doesn't require any settings from the plugin `community`
     6
    171.1.2 2012-07-04
    28
    39  - Make plugin compatible with Piwigo 2.3.5 and Piwigo 2.4.1
    410  - Fix minor bugs. Fix caching issue when updating images.
     11
     121.2.0 2012-01-07
     13
     14  - Support advanced ACL in local file <ROOT/local/config/icy_acl.php>
     15    + Allow user to edit images in any set of categories
     16    + Allow user to (dis)associate image (from)to any categories
     17    + Allow user to upload images to any categories
    518
    6191.1.0 2011-09-02
  • extensions/Icy_Picture_Modify/README.md

    r16494 r16495  
    1 NAME
     1# NAME
    22
    3   icy_picture_modify -- Allow user to modify their pictures
     3  `icy_picture_modify` -- Allow user to modify any pictures
    44
    5 DESCRIPTION
     5# DESCRIPTION
    66
    7   A piwigo extension that allows users to modify pictures they uploaded.
    8   This extension just works as the 'picture_modify.php' for administrator.
     7  A piwigo extension that allows users to edit any set of images.
     8  This extension just works as the `picture_modify.php` for administrator.
    99
    10   The code of this plugin is heavily based on the original source
    11   'picture_modify.php' of the Piwigo distribution (version 2.2.3.)
     10  The code of this plugin is based on the original source
     11  `picture_modify.php` of the Piwigo distribution (version 2.2.3.)
    1212
    13 USAGE
     13  Advanced ACL is supported since version 1.2.0.
    1414
    15   1. Install and enable the plugin "community" which allows users to
    16      upload pictures to some albums. Please configure the plugin before
    17      you install "icy_picture_modify".
     15# FEATURES
    1816
    19   2. Install and enable this plugin
     17  Normal users in Piwigo system can delete image or modify image's metadata
     18  (author, date, tags, description, metada, linking/represented categories).
     19  They can upload some images to some categories.
    2020
    21   3. When users view a picture they uploaded, they will be provided a link
    22      to modify that picture's information.
     21  Advanced ACL allows users to work with any set of images / categories.
    2322
    24 FEATURES
     23# USAGE
    2524
    26   Users can delete image or modify image's properties (author, date, tags,
    27   description, metada, associcate/aissociated/represented categories).
     25  * Install and enable this plugin and the plugin `community`.
     26  * Create and edit ACL file in `local/config/icy_acl.zml` in your Piwigo
     27    installation. A sample file can be found in `doc/icy_acl.zml.sample`.
     28    You don't have to modify any settings for the plugin `community`.
     29    Moverover, any settings of the plugin `community` will be ignored.
     30  * If you are using a development of the plugin, please clean up the
     31    obsolete files (See `OBSOLETE FILES` below.)
    2832
    29 KNOWN PROBLEMS
     33# OBSOLETE FILES
    3034
    31   * If an image is replaced by other version (using plugin 'Photo update')
    32     the author of (new) image will be owned by administrator, not the
    33     current user. Hence the image won't be editable anymore
     35  The following files are obsolsete. They need to be ported to new format
     36  and/or to be removed
    3437
     38  * `local/config/icy_acl.php`:
     39    need to be ported to `local/config/icy_acl.zml`. After your old ACL
     40    settings are ported to new format, you can safely delete this file;
     41
     42  * `_data/icy.log`:
     43    if you are using `icy_picture_modify` version 2.0.0 or higher, you
     44    can safely remove this file.
     45
     46# KNOWN PROBLEMS
     47
     48  * No webUI for ACL editting
     49  * If an image is replaced by a new version (using plugin `Photo update`)
     50    the new version is owned by administrator, not the current user.
     51    Hence the image may not be editable by themself.
    3552  * This plugin doesn't support all known templates
    36 
    37   * This plugin may not work smoothly without the plugin 'community'
    38 
     53  * This plugin may not work smoothly without the plugin `community`.
    3954  * User can delete an image which is associated to some albums to which
    4055    the user doesn't have permission to write/access. This is true as the
    4156    plugin only checks owner of the image.
    4257
    43 AUTHOR
     58# SUPPORT
    4459
    45   Anh K. Huỳnh (icy)
     60  To get support, please create new issue at
     61    https://github.com/icy/icy_picture_modify/issues
    4662
    47 LICENSE
     63# DEVELOPMENT
     64
     65  The plugin requires a webUI for ACL editting. Unfortunately, the author
     66  isn't good at template system used by Piwigo. Feel free to help us to
     67  write a webUI :)
     68
     69# DONATION
     70
     71  If you know what `donation` is and how it works in Open source develoment,
     72  feel free to donate ;) My Paypal email is `xkyanh@gmail.com`.
     73
     74# AUTHOR
     75
     76  The author's information
     77
     78  * Real name: Anh K. Huỳnh
     79  * Email: kyanh@viettug.org, xkyanh@gmail.com
     80  * Nickname on Piwigo's forum: icy
     81
     82# LICENSE
    4883
    4984  GPL2
    5085
    51 HOMGEPAGE
     86# HOMGEPAGE
    5287
    53   At Github.com:  https://github.com/icy/icy_picture_modify
    54   At Piwigo.com:  http://piwigo.org/ext/extension_view.php?eid=563
    55   SVN repository: http://piwigo.org/svn/extensions/Icy_Picture_Modify/
    56   Forum link:     http://piwigo.org/forum/viewtopic.php?pid=131585#p131585
     88  * At Github.com:  https://github.com/icy/icy_picture_modify
     89  * At Piwigo.com:  http://piwigo.org/ext/extension_view.php?eid=563
     90  * SVN repository: http://piwigo.org/svn/extensions/Icy_Picture_Modify/
     91  * Forum link:     http://piwigo.org/forum/viewtopic.php?pid=131585#p131585
  • extensions/Icy_Picture_Modify/icy_picture_modify.php

    r16355 r16495  
    2525if (!defined('ICY_PICTURE_MODIFY_PATH')) die('Hacking attempt!');
    2626
    27 include_once(PHPWG_ROOT_PATH.'admin/include/functions.php');
    28 include_once(ICY_PICTURE_MODIFY_PATH.'include/functions_icy_picture_modify.inc.php');
    29 
    30 global $template, $conf, $user, $page, $lang, $cache;
    31 
    32 // <admin.php>
    33 $page['errors'] = array();
    34 $page['infos']  = array();
    35 $page['warnings']  = array();
    36 // </admin.php>
    37 
    38 // +-----------------------------------------------------------------------+
    39 // |                             check permission                          |
    40 // +-----------------------------------------------------------------------+
    41 
    42 // redirect users to the index page or category page if 'image_id' isn't provided
    43 if (!isset($_GET['image_id']))
    44 {
    45   if (isset($_GET['cat_id']))
    46   {
    47     redirect_http(get_root_url().'?/category/'.$_GET['cat_id']);
    48   }
    49   else
    50   {
    51     // FIXME: $_SESSION['page_infos'] = array(l10n('Permission denied'));
    52     redirect_http(make_index_url());
    53   }
    54 }
    55 
    56 check_input_parameter('cat_id', $_GET, false, PATTERN_ID);
    57 check_input_parameter('image_id', $_GET, false, PATTERN_ID);
    58 
    59 // Simplify redirect to administrator page if current user == admin
     27require_once(PHPWG_ROOT_PATH.'admin/include/functions.php');
     28require_once(ICY_PICTURE_MODIFY_PATH.'include/functions_icy_picture_modify.inc.php');
     29
     30// <ADMIN_ONLY>
    6031if (is_admin())
    6132{
    62   if (icy_does_image_exist($_GET['image_id']))
     33  if (icy_image_exists($_GET['image_id']))
    6334  {
    6435    $url = get_root_url().'admin.php?page=picture_modify';
     
    7041  else
    7142  {
     43    // FIXME: language support ^^
    7244    bad_request('invalid picture identifier');
    7345  }
    7446}
    75 elseif (!icy_check_image_owner($_GET['image_id'], $user['id']))
     47// </ADMIN_ONLY>
     48
     49global $template, $conf, $user, $page, $lang, $cache, $ICY_ACL;
     50
     51// <load_from_admin.php>
     52$page['errors'] = array();
     53$page['infos']  = array();
     54$page['warnings']  = array();
     55// </load_from_admin.php>
     56
     57#! icy_log("body from icy_picture_modify.php");
     58icy_acl_load_configuration();
     59
     60// +-----------------------------------------------------------------------+
     61// |                             check permission                          |
     62// +-----------------------------------------------------------------------+
     63
     64// <CHECK_IF_IMAGE_ID_IS_VALID>
     65// redirect users to the index page or category page if 'image_id' isn't provided
     66if (!isset($_GET['image_id']))
     67{
     68  if (isset($_GET['cat_id']))
     69  {
     70    redirect_http(get_root_url().'?/category/'.$_GET['cat_id']);
     71  }
     72  else
     73  {
     74    // FIXME: $_SESSION['page_infos'] = array(l10n('Permission denied'));
     75    redirect_http(make_index_url());
     76  }
     77}
     78// </CHECK_IF_IMAGE_ID_IS_VALID>
     79
     80// FIXME: check and then !?
     81check_input_parameter('cat_id', $_GET, false, PATTERN_ID);
     82check_input_parameter('image_id', $_GET, false, PATTERN_ID);
     83
     84// Return if the image isn't editable
     85if (!icy_acl("edit_image_of", $_GET['image_id'], icy_get_user_owner_of_image($_GET['image_id'])))
    7686{
    7787  $url = make_picture_url(
     
    8696
    8797// Update the page sessions
     98// FIXME: why?
    8899if (isset($_SESSION['page_infos']))
    89100{
     
    93104
    94105// <find writable categories>
    95 
    96 // * Purpose: Find all categories that are reachable for the current user.
    97 // * FIXME:   This query will include all readable categories, included
    98 //            the ones user can't write to them.
    99 
    100106$my_categories = array();
    101 $my_permissions = null;
    102 $has_plugin_community = false;
    103 
    104 // <community support>
    105 if (is_file(PHPWG_PLUGINS_PATH.'community/include/functions_community.inc.php'))
    106 {
    107   include_once(PHPWG_PLUGINS_PATH.'community/include/functions_community.inc.php');
    108   $has_plugin_community = true;
    109 
    110   $user_permissions = community_get_user_permissions($user['id']);
    111   $my_categories = $user_permissions['upload_categories'];
    112 }
    113 // </community support>
    114 
    115 if (($has_plugin_community == false) or $user_permissions['create_whole_gallery'])
    116 {
    117   $query = '
    118   SELECT category_id
    119     FROM '.IMAGE_CATEGORY_TABLE.'
    120   ;';
    121 
    122   // list of categories to which the user can read
    123   $my_categories = array_diff(
    124     array_from_query($query, 'category_id'),
    125     explode(',',calculate_permissions($user['id'], $user['status'])));
    126 }
    127 // </find writable categories>
     107// FIXME: delete this line ^^
     108$my_categories = array_from_query('SELECT category_id FROM '
     109                        .IMAGE_CATEGORY_TABLE.';', 'category_id');
    128110
    129111// +-----------------------------------------------------------------------+
     
    131113// +-----------------------------------------------------------------------+
    132114
    133 if (isset($_GET['delete']))
     115// ACTION => :delete_image
     116
     117if (isset($_GET['delete'])
     118      and icy_acl("delete_image_of",
     119            $_GET['image_id'],
     120            icy_get_user_owner_of_image($_GET['image_id'])))
    134121{
    135122  check_pwg_token();
     
    183170// +-----------------------------------------------------------------------+
    184171
    185 if (isset($_GET['sync_metadata']))
     172// ACTION => synchronize_image_metadata
     173// This includes other sub-actions and other permissions
     174//  (tag update, timestamp updated, ...)
     175
     176if (version_compare(PHPWG_VERSION, '2.4.0', '<')
     177    and isset($_GET['sync_metadata']))
    186178{
    187179  $query = '
     
    246238  }
    247239
     240  // FIXME: why mass_updates here ? Used with a simple array?
    248241  mass_updates(
    249242    IMAGES_TABLE,
     
    271264// associate the element to other categories than its storage category
    272265//
     266
     267// SUB-ACTION => associate_image_to_gallery
     268
    273269if (isset($_POST['associate'])
    274     and ($has_plugin_community == true)
    275270    and isset($_POST['cat_dissociated'])
    276     and count($_POST['cat_dissociated']) > 0
     271    and (count($_POST['cat_dissociated']) > 0)
    277272  )
    278273{
    279   associate_images_to_categories(
    280     array($_GET['image_id']),
    281     array_intersect($_POST['cat_dissociated'], $my_categories)
    282     );
     274  $_categories = array_intersect($_POST['cat_dissociated'],
     275                    icy_acl_get_categories("associate_image_to"));
     276  //! $_categories = array_filter($_categories,
     277  //!    create_function('$item', 'return icy_acl("associate_image_to", $item);'));
     278
     279  associate_images_to_categories(array($_GET['image_id']), $_categories);
    283280  invalidate_user_cache();
    284281}
    285282
     283// SUB-ACTION => dissociate_image_from_gallery
    286284
    287285// dissociate the element from categories (but not from its storage category)
    288286if (isset($_POST['dissociate'])
    289     and ($has_plugin_community == true)
    290287    and isset($_POST['cat_associated'])
    291288    and count($_POST['cat_associated']) > 0
    292289  )
    293290{
    294   $arr_dissociate = array_intersect($_POST['cat_associated'], $my_categories);
     291
     292  $_categories = array_intersect($_POST['cat_associated'],
     293                    icy_acl_get_categories("associate_image_to"));
     294  //! $_categories = array_filter($_categories,
     295  //!    create_function('$item', 'return icy_acl("associate_image_to", $item);'));
     296
    295297  $query = '
    296298DELETE FROM '.IMAGE_CATEGORY_TABLE.'
    297299  WHERE image_id = '.$_GET['image_id'].'
    298     AND category_id IN ('.implode(',', $arr_dissociate).')
     300    AND category_id IN (0'.join(',', $_categories).')
    299301';
     302
    300303  pwg_query($query);
    301 
    302   update_category($arr_dissociate);
     304  update_category($_categories);
    303305  invalidate_user_cache();
    304306}
     
    308310// +-----------------------------------------------------------------------+
    309311
    310 // select the element to represent the given categories
     312// SUB-ACTION => select the element to represent the given categories
     313// FIXME: select or elect?
     314
    311315if (isset($_POST['elect'])
    312     and ($has_plugin_community == true)
    313316    and isset($_POST['cat_dismissed'])
    314317    and count($_POST['cat_dismissed']) > 0
     
    316319{
    317320  $datas = array();
    318   $arr_dimissed = array_intersect($_POST['cat_dismissed'], $my_categories);
     321  $arr_dimissed = array_intersect($_POST['cat_dismissed'],
     322                        icy_acl_get_categories("present_image_to"));
     323
    319324  if (count($arr_dimissed) > 0)
    320325  {
     
    332337}
    333338
    334 // dismiss the element as representant of the given categories
     339// SUB-ACTION => dismiss the element as representant of the given categories
     340
    335341if (isset($_POST['dismiss'])
    336     and ($has_plugin_community == true)
    337342    and isset($_POST['cat_elected'])
    338343    and count($_POST['cat_elected']) > 0
    339344  )
    340345{
    341   $arr_dismiss = array_intersect($_POST['cat_elected'], $my_categories);
     346  $arr_dismiss = array_intersect($_POST['cat_elected'],
     347                        icy_acl_get_categories("present_image_to"));
    342348  if (count($arr_dismiss) > 0)
    343349  {
     
    350356// |                             tagging support                           |
    351357// +-----------------------------------------------------------------------+
     358
     359// FIXME: tag is always updatable?
    352360
    353361if (version_compare(PHPWG_VERSION, '2.2.5', '<')) {
     
    410418    'tag_selection' => $tag_selection,
    411419    'tags' => $tags,
    412     'U_SYNC' => $admin_url_start.'&amp;sync_metadata=1',
    413     'U_DELETE' => $admin_url_start.'&amp;delete=1&amp;pwg_token='.get_pwg_token(),
    414420
    415421    'PATH'=>$row['path'],
     
    436442      htmlspecialchars( isset($_POST['description']) ?
    437443        stripslashes($_POST['description']) : @$row['comment'] ),
    438 
    439     'F_ACTION' =>
    440         get_root_url() # .'index.php?/icy_picture_modify'
    441         .get_query_string_diff(array('sync_metadata'))
    442444    )
    443445  );
     446
     447if (version_compare(PHPWG_VERSION, '2.4.0', '<')) {
     448  $template->assign(
     449    array(
     450      'U_SYNC' => $admin_url_start.'&amp;sync_metadata=1',
     451      'F_ACTION' => get_root_url() . get_query_string_diff(array('sync_metadata'))
     452    )
     453  );
     454}
     455
     456if (icy_image_deletable($_GET['image_id'])) {
     457  $template->assign(
     458    'U_DELETE', $admin_url_start.'&amp;delete=1&amp;pwg_token='.get_pwg_token()
     459  );
     460}
    444461
    445462if (array_key_exists('has_high', $row) and $row['has_high'] == 'true')
     
    577594}
    578595
    579 // associate to another category ?
     596$_categories = icy_acl_get_categories("associate_image_to");
     597// Select list of categories this image is associcated to
    580598$query = '
    581599SELECT id,name,uppercats,global_rank
     
    583601    INNER JOIN '.IMAGE_CATEGORY_TABLE.' ON id = category_id
    584602  WHERE image_id = '.$_GET['image_id'] . '
    585     AND id IN ('. join(",", $my_categories).')';
    586 // if the image belongs to a physical storage,
    587 // we simply ignore that storage album
     603    AND id IN (0'.join(",",$_categories).')';
     604// FIMXE: if the image belongs to a physical storage,
     605// FIXME: we simply ignore that storage album
    588606if (isset($storage_category_id))
    589607{
     
    605623  array_push($associateds, $row['id']);
    606624}
     625  // FIXME: Also display some forbidden presentations
    607626$query = '
    608627SELECT id,name,uppercats,global_rank
    609628  FROM '.CATEGORIES_TABLE.'
    610629  WHERE id NOT IN ('.implode(',', $associateds).')
    611   AND id IN ('. join(",", $my_categories).')
     630  AND id IN (0'.join(",", $_categories).')
    612631;';
    613632display_select_cat_wrapper($query, array(), 'dissociated_options');
    614633
    615634// display list of categories for representing
     635$_categories = icy_acl_get_categories("present_image_to");
    616636$query = '
    617637SELECT id,name,uppercats,global_rank
    618638  FROM '.CATEGORIES_TABLE.'
    619639  WHERE representative_picture_id = '.$_GET['image_id'].'
    620     AND id IN ('. join(",", $my_categories).')
     640    AND id IN (0'. join(",", $_categories).')
    621641;';
    622642display_select_cat_wrapper($query, array(), 'elected_options');
    623 
    624643$query = '
    625644SELECT id,name,uppercats,global_rank
    626645  FROM '.CATEGORIES_TABLE.'
    627   WHERE id IN ('. join(",", $my_categories).')
     646  WHERE id IN (0'. join(",", $_categories).')
    628647    AND (representative_picture_id != '.$_GET['image_id'].'
    629648    OR representative_picture_id IS NULL)
  • extensions/Icy_Picture_Modify/include/functions_icy_picture_modify.inc.php

    r11637 r16495  
    2929 *
    3030*/
    31 function icy_check_image_owner($image_id, $user_id = 0)
     31function icy_check_image_owner($image_id)
    3232{
    33   if (!preg_match(PATTERN_ID, $image_id))
    34   {
    35     bad_request('invalid picture identifier');
    36   }
    37   if (!preg_match(PATTERN_ID, $user_id))
    38   {
    39     bad_request('invalid category identifier');
    40   }
    41 
    42   $query = '
    43 SELECT COUNT(id)
    44   FROM '.IMAGES_TABLE.'
    45   WHERE id = '.$image_id.'
    46   AND added_by = '.$user_id.'
    47 ;';
    48 
    49   list($count) = pwg_db_fetch_row(pwg_query($query));
    50 
    51   return ($count > 0 ? true: false);
     33  global $user;
     34  return $user['id'] == icy_get_user_owner_of_image($image_id);
    5235}
    5336
     
    5841 *
    5942*/
    60 function icy_does_image_exist($image_id)
     43function icy_image_exists($image_id)
    6144{
    6245  if (!preg_match(PATTERN_ID, $image_id))
     
    7255  return ($count > 0 ? true: false);
    7356}
     57
     58/*
     59 * Check if an image is editable by current user
     60 * @icy_acl   access rules (provided by icy module)
     61 * @image_id  identity of the image
     62 * @return    boolean value
     63 * @author    icy
     64 */
     65function icy_image_editable($image_id) {
     66  return icy_acl("edit_image_of", $image_id, icy_get_user_owner_of_image($image_id));
     67}
     68
     69function icy_image_deletable($image_id) {
     70  return icy_acl("delete_image_of", $image_id, icy_get_user_owner_of_image($image_id));
     71}
     72
     73
     74/*
     75 * Return list of visible/uploadable categories
     76 * @author  icy
     77 */
     78function icy_acl_get_data($symbol) {
     79  global $user, $ICY_ACL;
     80
     81  // Load ACL setting for this user
     82  $this_user = $user['username'];
     83  $my_acl = $ICY_ACL['default'];
     84  if (array_key_exists($this_user, $ICY_ACL)) {
     85    $my_acl = array_replace($my_acl, $ICY_ACL[$this_user]);
     86  }
     87
     88  // Load ACL setting for the symbol
     89  if (!array_key_exists($symbol, $my_acl)) {
     90    return NULL;
     91  }
     92
     93  return $my_acl[$symbol];
     94}
     95
     96/*
     97 *
     98 * visible: upload, assosiate,...
     99 * @symbol    must be ended by "_to" or "_from"
     100 */
     101function icy_acl_get_categories($symbol) {
     102  global $user, $conf;
     103
     104  $all_categories = array();
     105  $symbol_categories = array();
     106  $symbol_settings = NULL;
     107
     108  // It's always EMPTY array for any kind of guests
     109  if ($user['id'] == $conf['guest_id']) {
     110    return $symbol_categories;
     111  }
     112
     113  // check if $symbol is valid
     114  if (!preg_match("/_(to|from)$/", $symbol)) {
     115    return $symbol_categories;
     116  }
     117
     118  $symbol_settings = icy_acl_get_data($symbol);
     119  if (!$symbol_settings) {
     120    return $symbol_categories;
     121  }
     122
     123  // all known categories in the system
     124  $query = 'SELECT id FROM '.CATEGORIES_TABLE.';';
     125  $all_categories = array_unique(array_from_query($query, 'id'));
     126  $forbidden_categories = explode(',',calculate_permissions($user['id'], $user['status']));
     127
     128  // ICY_ACL allows user to access all categories. In this case,
     129  // the plugin 'community' plays an empty role (we just supress it)
     130  if (icy_acl_symbol_data_wide_open($symbol_settings)) {
     131    $symbol_categories = $all_categories;
     132  }
     133  elseif (is_array($symbol_settings)) {
     134    $symbol_categories = array_values(array_intersect($symbol_settings, $all_categories));
     135  }
     136  else {
     137    // not wide-open, not an-array. So waht!?
     138    $symbol_settings = array();
     139  }
     140
     141  // Make sure categories are in our sytem
     142  // remove all forbidden categories from the list
     143  if (in_array('sub', icy_acl_get_data($symbol))) {
     144    // FIXME: (get_subcat_ids) requires a 0-based array
     145    // FIXME: + array(0) is really a trick :) In Piwigo 2.4, (get_subcat_ids)
     146    // FIXME: will generate NOTICE (SQL syntax error) if $symbol_categories is empty.
     147    $symbol_categories = array_merge($symbol_categories, get_subcat_ids($symbol_categories + array(0)));
     148  }
     149  $symbol_categories = array_diff($symbol_categories, $forbidden_categories);
     150  return array_values($symbol_categories);
     151}
     152/*
     153 * FIXME: Test if current user is logged in
     154 * FIXME: $guestowner must be provided explicitly
     155 *
     156 * Check if the current user has permission to do something
     157 * @symbol     Action to be checked
     158 * @guestdata  Object of the action
     159 * @guestowner Owner of @guestdata
     160 *
     161 * There are two cases of @symbol:
     162 * - _from/_to: action on an category
     163 * - _of      : action on the author
     164 * - others   : boolean flag
     165 *
     166 * There are three cases of symbol data
     167 * - Array of categories (' identities)    [_from/_to]
     168 *    $guestowner is simply ignored
     169 * - Array of usernames (list of authors)  [_of]
     170 *    $guestowner must be specified
     171 * - Others: {"any", "owner", TRUE, FALSE} [others]
     172 */
     173 function icy_acl($symbol, $guestdata = NULL, $guestowner = NULL) {
     174  global $user, $ICY_ACL, $conf;
     175
     176  // Load ACL setting for this user
     177  $this_user = $user['id'];
     178
     179  if ($user['id'] == $conf['guest_id']) {
     180    return FALSE;
     181  }
     182  elseif (is_admin()) {
     183    return TRUE;
     184  }
     185
     186  $symbol_settings = icy_acl_get_data($symbol);
     187
     188
     189  if (! preg_match("/_(to|from|of)$/", $symbol)) {
     190    return is_bool($symbol_settings) ? $symbol_settings: FALSE;
     191  }
     192
     193  if (! is_array($symbol_settings) ) {
     194    return FALSE;
     195  } elseif (icy_acl_symbol_data_wide_open($symbol_settings)) {
     196    return TRUE;
     197  }
     198
     199  if (preg_match("/_(to|from)$/", $symbol)) {
     200    return in_array($guestdata, $symbol_settings);
     201  }
     202  elseif (preg_match("/_of$/", $symbol)) {
     203    $guestowner = icy_get_username_of($guestowner);
     204    // Replace 'owner' by the $guestowner. For example
     205    //  array('owner','ruby', 12) => array($guestowner, 'ruby', 12)
     206    array_walk($symbol_settings,
     207     create_function('&$val, $key',
     208       'if ($val == "owner") {$val = "'.$user['username'].'";}'));
     209    return in_array($guestowner, $symbol_settings);
     210  }
     211}
     212
     213function icy_acl_symbol_data_wide_open($symbol_data) {
     214  return (is_array($symbol_data) and in_array("any", $symbol_data));
     215}
     216
     217/*
     218 * Write some logs for debugging
     219 * @notes     Data will be written to STDERRR (default)
     220 *            or to file `<ROOT>/_data/icy.log`
     221 * @author    icy
     222 */
     223function icy_log($st, $stderr = FALSE) {
     224  if ($stderr === TRUE) {
     225    $_f_log = "php://stderr";
     226  }
     227  else {
     228    $_f_log = PHPWG_ROOT_PATH.'_data/icy.log';
     229  }
     230
     231  $_f_handle = fopen($_f_log, 'a');
     232  if ($_f_handle) {
     233    $new_line = "\n";
     234    fwrite($_f_handle, "piwigo/icy_picture_modify: $st". $new_line );
     235    if ($stderr !== TRUE) {
     236      fclose($_f_handle);
     237    }
     238  }
     239}
     240
     241/*
     242 * Get UserId from their UserName
     243 * @user_name   username as string
     244 * @author      icy
     245 */
     246function icy_get_user_id_from_name($user_name) {
     247  $user_name = pwg_db_real_escape_string($user_name);
     248
     249  $query = '
     250SELECT id
     251  FROM '.USERS_TABLE.'
     252  WHERE username = "'.$user_name.'"
     253  LIMIT 1
     254;';
     255
     256  list($user_id) = pwg_db_fetch_row(pwg_query($query));
     257
     258  // FIXME: Is this the best way?
     259  if ($user_id == NULL) $user_id = 0;
     260
     261  #! icy_log("icy_get_user_id_from_name: map userid <= username: $user_name <= $user_id");
     262  return $user_id;
     263}
     264
     265/*
     266 * Rerturn the owner id of an image
     267 * @author    icy
     268 * @image_id  identity of the image
     269 */
     270function icy_get_user_owner_of_image($image_id) {
     271  // FIXME: Clean this up!!!
     272  if (!preg_match(PATTERN_ID, $image_id))
     273    bad_request('invalid picture identifier');
     274
     275  $query = '
     276SELECT added_by
     277  FROM '.IMAGES_TABLE.'
     278  WHERE id = '.$image_id.'
     279  LIMIT 1
     280;';
     281
     282  list($owner) = pwg_db_fetch_row(pwg_query($query));
     283  #! icy_log("icy_get_user_owner_of_image: image_id, added_by = $image_id, $owner");
     284  return $owner ? $owner : 0;
     285}
     286
     287/*
     288 * Return the username from user_id
     289 */
     290function icy_get_username_of($user_id) {
     291  if (!preg_match(PATTERN_ID, $user_id))
     292    bad_request('invalid user identifier');
     293
     294  $query = '
     295SELECT username
     296  FROM '.USERS_TABLE.'
     297  WHERE id = '.$user_id.'
     298  LIMIT 1
     299;';
     300
     301  list($username) = pwg_db_fetch_row(pwg_query($query));
     302  #! icy_log("icy_get_username_of: user_id, user_name = $user_id, $username");
     303  return $username;
     304}
     305
     306/*
     307 * Check if a plugin is enabled
     308 * @plugin_name   name of the plugin
     309 * @author        icy
     310 */
     311function icy_plugin_enabled($plugin_name) {
     312  $return = false;
     313
     314  $query = '
     315SELECT count(id)
     316  FROM '.PLUGINS_TABLE.'
     317  WHERE id = "'.pwg_db_real_escape_string($plugin_name).'"
     318  AND state="active"
     319  LIMIT 1
     320;';
     321
     322  list($count) = pwg_db_fetch_row(pwg_query($query));
     323  $return = ($count == 1 ? true : false);
     324
     325  // we need the file ^^
     326  if ($plugin_name == "community")
     327    $return = $return
     328                and is_file(PHPWG_PLUGINS_PATH
     329                  .'community/include/functions_community.inc.php');
     330
     331  return $return;
     332}
     333
     334/*
     335 * Load ICY_ACL configuration from files
     336 * @author   icy
     337 */
     338function icy_acl_load_configuration($force = FALSE) {
     339  global $ICY_ACL;
     340  $conf_path = PHPWG_ROOT_PATH.PWG_LOCAL_DIR.'config/icy_acl.zml';
     341
     342  if (($force == FALSE)
     343      and isset($ICY_ACL['default'])
     344      and isset($_SESSION['icy_picture_modify_acl_mtime'])
     345      and ($_SESSION['icy_picture_modify_acl_mtime'] == filemtime($conf_path))) {
     346    #! icy_log("icy_acl_load_configuration: configuration is up-to-date");
     347    return FALSE;
     348  }
     349
     350  $ICY_ACL = icy_zml_parser(<<<EOF
     351default:
     352  edit_image_of: owner
     353  delete_image_of:
     354  upload_image_to: sub
     355  moderate_image: no
     356  create_gallery_to: sub
     357  associate_image_to:
     358  present_image_to: sub
     359EOF
     360);
     361
     362  if (file_exists($conf_path)) {
     363    #! icy_log("icy_acl_load_configuration: now loading ACL from $conf_path");
     364    $ICY_ACL = array_replace($ICY_ACL, icy_zml_parser(file($conf_path)));
     365    $_SESSION['icy_picture_modify_acl_mtime'] = filemtime($conf_path);
     366  }
     367
     368  return TRUE;
     369}
     370
     371/*
     372 * Return array of variable from a `.zml` array  / string
     373 * Syntax of the `.zml` file can be found in `doc/zaml.md`
     374 * @author icy
     375 */
     376function icy_zml_parser($data) {
     377  $acl = array();
     378  $author = 'default';
     379  $acl[$author] = array();
     380
     381  if (is_string($data)) {
     382    $data = preg_split("/[\r\n]/", $data);
     383  }
     384
     385  foreach($data as $line) {
     386    # AUTHOR:
     387    if (preg_match('/^([^[:space:]:]+):$/', $line, $gs)) {
     388      $author = trim($gs[1]);
     389      if (! array_key_exists($author, $acl)) {
     390        $acl[$author] = array();
     391      }
     392      continue;
     393    }
     394
     395    # AUTHOR: @REFERENCE
     396    if (preg_match('/^([^[:space:]:]+):[[:space:]]+@([^[:space:]:]+)$/', $line, $gs)) {
     397      $ref_author = trim($gs[2]);
     398      if (!array_key_exists($ref_author, $acl)) {
     399        continue;
     400      }
     401      $author = trim($gs[1]);
     402      if (! array_key_exists($author, $acl)) {
     403        $acl[$author] = array();
     404      }
     405      $acl[$author] = array_replace($acl[$ref_author], $acl[$author]);
     406    }
     407
     408    # <two spaces> KEY: [VALUE]
     409    if (preg_match('/  ([^:]+):(.*)$/', $line, $gs)) {
     410      $key = $gs[1];
     411      $val = trim($gs[2]);
     412      if (in_array($val, array("","false","no"))) {
     413        $val = FALSE;
     414      }
     415      elseif (in_array($val, array("yes", "true"))) {
     416        $val = TRUE;
     417      }
     418      else {
     419        $val = array_unique(preg_split("/[[:space:],:;]+/", $val));
     420      }
     421      $acl[$author][$key] = $val;
     422    }
     423
     424    # Other line is ignored :)
     425  }
     426  return $acl;
     427}
     428
     429/*
     430 * Overwrite the ACl setings from community plugin
     431 * @author: icy
     432 */
     433function icy_acl_fix_community($force = FALSE) {
     434  global $user, $_SESSION;
     435
     436  if (!icy_plugin_enabled("community")) {
     437    return TRUE;
     438  }
     439
     440  require_once(PHPWG_PLUGINS_PATH.'community/include/functions_community.inc.php');
     441
     442  # <community_support>
     443  $cache_key = community_get_cache_key();
     444  if (!isset($cache_key))  {
     445    $cache_key = community_update_cache_key();
     446  }
     447
     448  if (($force == FALSE)
     449      and isset($_SESSION['community_user_permissions'])
     450      and isset($_SESSION['community_user_permissions']['icy_acl_fixed'])) {
     451    #! icy_log("icy_fix_community_acl: the fix is up-to-date " . print_r($_SESSION['community_user_permissions'], true));
     452    return TRUE;
     453  }
     454
     455  # icy_log("WARNING: icy_fix_community_acl: the fix is out-of-date. will fix it again");
     456  # </community_support>
     457
     458  $return = array(
     459    'create_categories' => array(),
     460    'upload_categories' => array(),
     461    'permission_ids' => array(),
     462    );
     463
     464  $return['upload_whole_gallery'] = icy_acl_symbol_data_wide_open(icy_acl_get_data("upload_image_to"));
     465  $return['create_whole_gallery'] = icy_acl_symbol_data_wide_open(icy_acl_get_data("create_gallery_to"));
     466  $return['upload_categories'] = icy_acl_get_categories("upload_image_to");
     467  $return['create_categories'] = icy_acl_get_categories("create_gallery_to");
     468  $return['permission_ids'] = array();
     469  $return['icy_acl_fixed'] = 1;
     470
     471  $_SESSION['community_user_permissions'] = $return;
     472  $_SESSION['community_cache_key'] = $cache_key;
     473  $_SESSION['community_user_id'] = $user['id'];
     474}
     475
     476
     477if (!function_exists('array_replace')) {
     478  function array_replace() {
     479    $array=array();
     480    $n=func_num_args();
     481    while ($n-- >0) $array+=func_get_arg($n);
     482    return $array;
     483  }
     484}
    74485?>
  • extensions/Icy_Picture_Modify/index.php

    r11610 r16495  
    44// | Copyright (C) 2002-2003 Pierrick LE GALL - pierrick@phpwebgallery.net |
    55// | Copyright (C) 2003-2007 PhpWebGallery Team - http://phpwebgallery.net |
    6 // +-----------------------------------------------------------------------+
    7 // | file          : $Id: index.php 1912 2007-03-16 06:30:07Z rub $
    8 // | last update   : $Date: 2007-03-16 07:30:07 +0100 (ven, 16 mar 2007) $
    9 // | last modifier : $Author: rub $
    10 // | revision      : $Revision: 1912 $
    116// +-----------------------------------------------------------------------+
    127// | This program is free software; you can redistribute it and/or modify  |
  • extensions/Icy_Picture_Modify/main.inc.php

    r16356 r16495  
    22/*
    33Plugin Name: Icy Modify Picture
    4 Version: 1.1.2
     4Version: 2.0.0
    55Description: Allow users to modify pictures they uploaded
    66Plugin URI: http://piwigo.org/ext/extension_view.php?eid=563
     
    1414}
    1515
    16 # Should be ./plugins/icy_picture_modify/
    1716define('ICY_PICTURE_MODIFY_PATH' , PHPWG_PLUGINS_PATH.basename(dirname(__FILE__)).'/');
    18 include_once(ICY_PICTURE_MODIFY_PATH.'include/functions_icy_picture_modify.inc.php');
     17require_once(ICY_PICTURE_MODIFY_PATH.'include/functions_icy_picture_modify.inc.php');
    1918
    20 # Hooks declaration
     19# Variable declarations ################################################
     20
     21global $ICY_ACL;
     22
     23# Hooks declarations ###################################################
    2124
    2225add_event_handler('loc_end_section_init', 'icy_picture_modify_section_init');
    23 add_event_handler('loc_end_index', 'icy_picture_modify_index');
     26remove_event_handler('loc_end_index', 'community_index');
     27add_event_handler('loc_end_index', 'icy_picture_modify_index', 40);
     28
    2429add_event_handler('loc_begin_picture', 'icy_picture_modify_loc_begin_picture');
     30add_event_handler('init','icy_picture_modify_fix_community_acl', 40);
     31# add_event_handler('login_success', );
    2532
    26 # Hooks definitions
     33add_event_handler('blockmanager_apply', 'icy_picture_modify_fix_community_acl', 40);
     34add_event_handler('ws_invoke_allowed', 'icy_picture_modify_fix_community_acl', 40);
     35add_event_handler('ws_add_methods', 'icy_picture_modify_fix_community_acl', 40);
     36add_event_handler('community_ws_categories_getList', 'icy_picture_modify_fix_community_acl', 40);
     37add_event_handler('sendResponse', 'icy_picture_modify_fix_community_acl', 40);
     38
     39# Hooks definitions ####################################################
     40
     41function icy_picture_modify_fix_community_acl()
     42{
     43  icy_acl_fix_community(icy_acl_load_configuration());
     44}
    2745
    2846function icy_picture_modify_section_init()
     
    4058  global $page;
    4159
    42   if (isset($page['section']) and $page['section'] == 'icy_picture_modify')
     60  if (! isset($page['section'])) {
     61    return TRUE;
     62  }
     63
     64  if ($page['section'] == 'icy_picture_modify')
    4365  {
    4466    include(ICY_PICTURE_MODIFY_PATH.'icy_picture_modify.php');
     67  }
     68  elseif ($page['section'] == 'add_photos') {
     69    icy_picture_modify_fix_community_acl(TRUE);
     70    include(ICY_PICTURE_MODIFY_PATH.'add_photos.php');
    4571  }
    4672}
     
    5177{
    5278  global $conf, $template, $page, $user;
    53   if ((!is_admin()) and icy_check_image_owner($page['image_id'], $user['id']))
     79
     80  icy_acl_load_configuration();
     81
     82  if (icy_image_editable($page['image_id']))
    5483  {
    5584    $url_admin =
  • extensions/Icy_Picture_Modify/template/icy_picture_modify.tpl

    r11934 r16495  
    4747  {/if}
    4848  {if !url_is_remote($PATH)}
     49  {if isset($U_SYNC) }
    4950  <li><a href="{$U_SYNC}" title="{'synchronize'|@translate}"><img src="{$ICY_PICTURE_MODIFY_PATH}/template/icon/sync_metadata.png" class="button" alt="{'synchronize'|@translate}"></a></li>
    50 
     51  {/if}
     52  {if isset($U_IMAGE_DELETABLE) }
    5153  <li><a href="{$U_DELETE}" title="{'delete photo'|@translate}"><img src="{$ICY_PICTURE_MODIFY_PATH}/template/icon/category_delete.png" class="button" alt="{'delete photo'|@translate}" onclick="return confirm('{'Are you sure?'|@translate|@escape:javascript}');"></a></li>
     54  {/if}
    5255  {/if}
    5356</ul>
Note: See TracChangeset for help on using the changeset viewer.