Ignore:
Timestamp:
Jul 8, 2012, 5:02:01 PM (12 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 ;)

File:
1 edited

Legend:

Unmodified
Added
Removed
  • 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?>
Note: See TracChangeset for help on using the changeset viewer.