--- NodeBase.pm 2005-08-24 00:39:41.433256400 +0200 +++ NodeBase.mod 2005-08-24 00:31:12.277006400 +0200 @@ -1919,7 +1919,7 @@ sub getRef sub isNodetype { my ($this, $NODE) = @_; - $this->getRef($NODE); + $this->getRef($NODE) if !ref $NODE; return 0 if (not ref $NODE); @@ -1947,14 +1947,8 @@ sub isNodetype sub isGroup { my ($this, $NODETYPE) = @_; - my $groupTable; - $this->getRef($NODETYPE); - - $groupTable = $$NODETYPE{grouptable}; - - return $groupTable if($groupTable); - - return 0; + $this->getRef($NODETYPE) if !ref $NODETYPE; + return $NODETYPE->{grouptable} || 0 } @@ -1963,25 +1957,27 @@ sub canCreateNode { my( $this, $USER, $TYPE )= @_; $TYPE = $this->getType( $TYPE ); + my $writers= $TYPE->{writers_user}; # The default is that everyone can create - return 1 if ! $TYPE->{writers_user}; - $this->isApproved( $USER, $TYPE->{writers_user} ); + return 1 if ! $writers; + return $this->isApproved( $USER, $writers, $TYPE ); } ############################################################################# sub canDeleteNode { my( $this, $USER, $NODE )= @_; - $this->getRef($NODE); + $this->getRef($NODE) if !ref $NODE; + my $deleters= $NODE->{type}{deleters_user}; # The default is that nobody can delete - return 0 if ! $NODE || ! $NODE->{type}{deleters_user}; + return 0 if ! $NODE || ! $deleters; # -2 means "owner" can delete (anonymous?) - return $this->isApproved( $USER, $NODE->{author_user} ) - if -2 == $NODE->{type}{deleters_user}; + return $this->isApproved( $USER, $NODE->{author_user}, $NODE ) + if -2 == $deleters; - return $this->isApproved( $USER, $NODE->{type}{deleters_user} ); + return $this->isApproved( $USER, $deleters, $NODE ); } @@ -2001,7 +1997,7 @@ sub canUpdateNode { $updaters = $NODE->{author_user}; } - return $this->isApproved( $USER, $updaters ); + return $this->isApproved( $USER, $updaters, $NODE ); } @@ -2009,18 +2005,20 @@ sub canUpdateNode { sub canReadNode { my( $this, $USER, $NODE )= @_; - $this->getRef($NODE); + $this->getRef($NODE) if !ref($NODE); return 0 if ! $NODE; + my $readers= $NODE->{type}{readers_user}; + # the default is that everyone can read - return 1 if ! $NODE->{type}{readers_user}; + return 1 if !$readers; # -2 means only "owner" can read - return $this->isApproved( $USER, $NODE->{author_user} ) - if -2 == $NODE->{type}{readers_user}; + return $this->isApproved( $USER, $NODE->{author_user}, $NODE ) + if -2 == $readers; - return $this->isApproved( $USER, $$NODE{type}{readers_user} ); + return $this->isApproved( $USER, $readers, $NODE ); } @@ -2032,37 +2030,53 @@ sub canReadNode { # Checks to see if the given user is approved within a given group # # Parameters -# $user - reference to a user node hash (-1 if super user) -# $NODE - reference to a nodegroup that the user might be in +# $USER - reference to a user node hash (-1 if super user) +# $GROUP - reference to a nodegroup that the user might be in +# $NODE - optional reference to the item being tested against. +# its prescence allows rules to be applied against the +# the item. # # Returns # true if the user is authorized, false otherwise # sub isApproved { - my( $this, $USER, $NODE )= @_; + my( $this, $USER, $GROUP, $NODE )= @_; + + my $vars=\%Everything::HTML::HTMLVARS; - return 0 if ! $USER || ! $NODE; + delete $vars->{isApproved}; + return 0 if ! $USER || ! $GROUP; return 1 if $this->isGod($USER); my $user_id = $this->getId($USER); #you're always approved if it's yourself... - return 1 if $user_id == $this->getId($NODE); + return 1 if $user_id == $this->getId($GROUP); - foreach my $node ( @{ $this->selectNodegroupFlat($NODE) } ) { + foreach my $node ( @{ $this->selectNodegroupFlat($GROUP) } ) { return 1 if $user_id == $this->getId($node); if( $node->{type}{title} =~ /accessrule$/i ) { - my $res= eval $node->{code}; + my $RULE= $node; + my $res= do { + package Everything::HTML; + eval $node->{code}; + }; + if ($@ or (!$res and defined $res)) { + $vars->{isApproved}{rule}=$node; + $vars->{isApproved}{group}=$GROUP; + } if( $@ ) { Everything::printLog( "Access Rule eval error in $node->{node_id}\n" . "$@\n$node->{code}" ); + $vars->{isApproved}{error}=$@; return 0; } - return $res if defined $res; + return $res if defined $res; } } + $vars->{isApproved}{group}=$GROUP; return 0; } @@ -2127,7 +2141,7 @@ sub selectNodegroupFlat { my ($this, $NODE) = @_; - return $this->flattenNodegroup($NODE); + return $this->flattenNodegroup($NODE,{},[]); } @@ -2141,48 +2155,51 @@ sub selectNodegroupFlat # a single node is in its own "group". # # Parameters -# $NODE - the node (preferably a group node) in which to get the -# nodes that are within its group. +# $NODE - the node (preferably a group node) in which to get the +# nodes that are within its group. +# $seen - hash of id's already seen during traverse. This can be used +# to filter the result set and is used internally for preventing +# infinite recursion. +# $array - container for the result set. This can be used to "prestuff" +# the array, and is used internally to avoid repeatedly passing the +# results up the stack. # # Returns # An array of node hashrefs of all of the nodes in this group. # sub flattenNodegroup { - my ($this, $NODE, $groupsTraversed) = @_; - my @listref; - my $group; - - return undef if (not defined $NODE); - - # If groupsTraversed is not defined, initialize it to an empty - # hash reference. - $groupsTraversed ||= {}; # anonymous empty hash + my ( $this, $GROUP, $seen, $array ) = @_; - $this->getRef($NODE); + return if !$GROUP; - if ($this->isGroup($$NODE{type})) - { - # return if we have already been through this group. Otherwise, - # we will get stuck in infinite recursion. - return undef if($$groupsTraversed{$$NODE{node_id}}); - $$groupsTraversed{$$NODE{node_id}} = $$NODE{node_id}; + $seen||= {}; + $array||= []; - foreach my $groupref (@{ $$NODE{group} }) - { - $group = $this->flattenNodegroup($groupref); - push(@listref, @$group) if(defined $group); - } + $this->getRef($GROUP); - return \@listref; + if ( $this->isGroup($GROUP->{type}) ) { + my @items= @{ $GROUP->{group} }; + $this->getRef(@items); + foreach my $item (@items) { + if ( !$seen->{$item->{node_id}}++ ) { + if ( $this->isGroup($item->{type}) ) { + $this->flattenNodegroup($item,$seen,$array); + } + else { + push @$array,$item; + } + } + } } - else - { - return [$NODE]; + elsif ( !$seen->{$GROUP->{node_id}}++ ) { + push @$array,$GROUP; } + return $array; } + ############################################################################# # Sub # insertIntoNodegroup