Navigation Menu

Skip to content

Commit

Permalink
merge r27925 from branch 2.6 to trunk
Browse files Browse the repository at this point in the history
bug 3057: avoid warnings and SQL crash when encountering inconsistent
permissions + rewrite permissions consistancy check when setting albums
to private status.



git-svn-id: http://piwigo.org/svn/trunk@27926 68402e56-0260-453c-a942-63ccdbb3a9ee
  • Loading branch information
plegall committed Mar 24, 2014
1 parent 6b5940c commit fa53820
Show file tree
Hide file tree
Showing 2 changed files with 161 additions and 38 deletions.
190 changes: 152 additions & 38 deletions admin/include/functions.php
Expand Up @@ -705,15 +705,166 @@ function set_cat_status($categories, $value)
;';
pwg_query($query);
}

// make a category private => all its child categories become private
if ($value == 'private')
{
$subcats = get_subcat_ids($categories);

$query = '
UPDATE '.CATEGORIES_TABLE.'
SET status = \'private\'
WHERE id IN ('.implode(',', $subcats).')';
pwg_query($query);

// We have to keep permissions consistant: a sub-album can't be
// permitted to a user or group if its parent album is not permitted to
// the same user or group. Let's remove all permissions on sub-albums if
// it is not consistant. Let's take the following example:
//
// A1 permitted to U1,G1
// A1/A2 permitted to U1,U2,G1,G2
// A1/A2/A3 permitted to U3,G1
// A1/A2/A4 permitted to U2
// A1/A5 permitted to U4
// A6 permitted to U4
// A6/A7 permitted to G1
//
// (we consider that it can be possible to start with inconsistant
// permission, given that public albums can have hidden permissions,
// revealed once the album returns to private status)
//
// The admin selects A2,A3,A4,A5,A6,A7 to become private (all but A1,
// which is private, which can be true if we're moving A2 into A1). The
// result must be:
//
// A2 permission removed to U2,G2
// A3 permission removed to U3
// A4 permission removed to U2
// A5 permission removed to U2
// A6 permission removed to U4
// A7 no permission removed
//
// 1) we must extract "top albums": A2, A5 and A6
// 2) for each top album, decide which album is the reference for permissions
// 3) remove all inconsistant permissions from sub-albums of each top-album

// step 1, search top albums
$all_categories = array();
$top_categories = array();
$parent_ids = array();

$query = '
SELECT
id,
name,
id_uppercat,
uppercats,
global_rank
FROM '.CATEGORIES_TABLE.'
WHERE id IN ('.implode(',', $categories).')
;';
$result = pwg_query($query);
while ($row = pwg_db_fetch_assoc($result))
{
$all_categories[] = $row;
}

usort($all_categories, 'global_rank_compare');

foreach ($all_categories as $cat)
{
$is_top = true;

if (!empty($cat['id_uppercat']))
{
foreach (explode(',', $cat['uppercats']) as $id_uppercat)
{
if (isset($top_categories[$id_uppercat]))
{
$is_top = false;
break;
}
}
}

if ($is_top)
{
$top_categories[$cat['id']] = $cat;

if (!empty($cat['id_uppercat']))
{
$parent_ids[] = $cat['id_uppercat'];
}
}
}

// step 2, search the reference album for permissions
//
// to find the reference of each top album, we will need the parent albums
$parent_cats = array();

if (count($parent_ids) > 0)
{
$query = '
SELECT
id,
status
FROM '.CATEGORIES_TABLE.'
WHERE id IN ('.implode(',', $parent_ids).')
;';
$result = pwg_query($query);
while ($row = pwg_db_fetch_assoc($result))
{
$parent_cats[$row['id']] = $row;
}
}

$tables = array(
USER_ACCESS_TABLE => 'user_id',
GROUP_ACCESS_TABLE => 'group_id'
);

foreach ($top_categories as $top_category)
{
// what is the "reference" for list of permissions? The parent album
// if it is private, else the album itself
$ref_cat_id = $top_category['id'];

if (!empty($top_category['id_uppercat'])
and isset($parent_cats[ $top_category['id_uppercat'] ])
and 'private' == $parent_cats[ $top_category['id_uppercat'] ]['status'])
{
$ref_cat_id = $top_category['id_uppercat'];
}

$subcats = get_subcat_ids(array($top_category['id']));

foreach ($tables as $table => $field)
{
// what are the permissions user/group of the reference album
$query = '
SELECT '.$field.'
FROM '.$table.'
WHERE cat_id = '.$ref_cat_id.'
;';
$ref_access = array_from_query($query, $field);

if (count($ref_access) == 0)
{
$ref_access[] = -1;
}

// step 3, remove the inconsistant permissions from sub-albums
$query = '
DELETE
FROM '.$table.'
WHERE '.$field.' NOT IN ('.implode(',', $ref_access).')
AND cat_id IN ('.implode(',', $subcats).')
;';
pwg_query($query);
}
}
}
}

Expand Down Expand Up @@ -1145,44 +1296,7 @@ function move_categories($category_ids, $new_parent = -1)

if ('private' == $parent_status)
{
foreach ($categories as $cat_id => $category)
{
if ('public' == $category['status'])
{
set_cat_status(array($cat_id), 'private');
}

$subcats = get_subcat_ids(array($cat_id));

foreach ($tables as $table => $field)
{
$query = '
SELECT '.$field.'
FROM '.$table.'
WHERE cat_id = '.$cat_id.'
;';
$category_access = array_from_query($query, $field);

$query = '
SELECT '.$field.'
FROM '.$table.'
WHERE cat_id = '.$new_parent.'
;';
$parent_access = array_from_query($query, $field);

$to_delete = array_diff($category_access, $parent_access);

if (count($to_delete) > 0)
{
$query = '
DELETE FROM '.$table.'
WHERE '.$field.' IN ('.implode(',', $to_delete).')
AND cat_id IN ('.implode(',', $subcats).')
;';
pwg_query($query);
}
}
}
set_cat_status(array_keys($categories), 'private');
}

$page['infos'][] = l10n_dec(
Expand Down
9 changes: 9 additions & 0 deletions include/functions_category.inc.php
Expand Up @@ -538,6 +538,15 @@ function get_computed_categories(&$userdata, $filter_days=null)
if ( !isset( $cat['id_uppercat'] ) )
continue;

// Piwigo before 2.5.3 may have generated inconsistent permissions, ie
// private album A1/A2 permitted to user U1 but private album A1 not
// permitted to U1.
//
// TODO 2.7: add an upgrade script to repair permissions and remove this
// test
if ( !isset($cats[ $cat['id_uppercat'] ]))
continue;

$parent = & $cats[ $cat['id_uppercat'] ];
$parent['nb_categories']++;

Expand Down

0 comments on commit fa53820

Please sign in to comment.