Changeset 4606


Ignore:
Timestamp:
08/06/09 08:32:27 (3 years ago)
Author:
CrawfordCurrie
Message:

Item935: the access rights that were checked are those expressed in the *new* topic text, instead of the old. Took the opportunity to deprecate the crappy readTopicText and saveTopicText interfaces while I was in there.

Location:
trunk
Files:
2 edited

Legend:

Unmodified
Added
Removed
  • trunk/UnitTestContrib/test/unit/FuncTests.pm

    r4541 r4606  
    155155    $this->assert( !$login ); 
    156156    $this->assert_equals( 0, $time ); 
     157} 
     158 
     159# As much as I'd like to remove this dumb function, make sure it's still 
     160# compatible 
     161sub test_saveTopicText { 
     162    my $this = shift; 
     163    my $topic = 'SaveTopicText'; 
     164    Foswiki::Func::saveTopicText( 
     165        $this->{test_web}, $topic, <<NONNY ); 
     166   * Set ALLOWTOPICCHANGE = NotMeNoNotMe 
     167NONNY 
     168    $this->assert(! 
     169      Foswiki::Func::checkAccessPermission( 'CHANGE', 
     170        Foswiki::Func::getWikiName(), undef, $topic, $this->{test_web} )); 
     171 
     172    # This should fail and return an oopsUrl (FFS, what a shit spec) 
     173    my $oopsURL = Foswiki::Func::saveTopicText( 
     174        $this->{test_web}, $topic, 'Gasp' ); 
     175    $this->assert($oopsURL); 
     176    my @ri = Foswiki::Func::getRevisionInfo($this->{test_web}, $topic); 
     177    $this->assert_matches(qr/1$/, $ri[2]); 
     178 
     179    # This should succeed and return undef 
     180    $oopsURL = Foswiki::Func::saveTopicText( 
     181        $this->{test_web}, $topic, 'Beam', 1 ); 
     182    $this->assert(!$oopsURL, $oopsURL); 
     183} 
     184 
     185sub test_saveTopic { 
     186    my $this = shift; 
     187    my $topic = 'SaveTopic'; 
     188    Foswiki::Func::saveTopic( 
     189        $this->{test_web}, $topic, undef, <<NONNY ); 
     190%META:PREFERENCE{name="Bird" value="Kakapo"}% 
     191   * Set ALLOWTOPICCHANGE = NotMeNoNotMe 
     192NONNY 
     193    $this->assert(! 
     194      Foswiki::Func::checkAccessPermission( 'CHANGE', 
     195        Foswiki::Func::getWikiName(), undef, $topic, $this->{test_web} )); 
     196    my @ri = Foswiki::Func::getRevisionInfo($this->{test_web}, $topic); 
     197    $this->assert_matches(qr/1$/, $ri[2]); 
     198 
     199    # Make sure the meta got into the topic 
     200    my ($m, $t) = Foswiki::Func::readTopic($this->{test_web}, $topic); 
     201    my $el = $m->get('PREFERENCE', 'Bird'); 
     202    $this->assert_equals('Kakapo', $el->{value}); 
     203 
     204    # This should succeed 
     205    Foswiki::Func::saveTopic($this->{test_web}, $topic, undef, 'Gasp', 
     206                            { forcenewrevision => 1 }); 
     207    @ri = Foswiki::Func::getRevisionInfo($this->{test_web}, $topic); 
     208    $this->assert_matches(qr/2$/, $ri[2]); 
    157209} 
    158210 
  • trunk/core/lib/Foswiki/Func.pm

    r4599 r4606  
    13541354</verbatim> 
    13551355 
    1356 __Note:__ Plugins handlers ( e.g. =beforeSaveHandler= ) will be called as 
    1357 appropriate. 
     1356__Note:__ Access controls are *not* checked by this function. You should 
     1357always call =checkAccessPermission= beforehand. Plugins handlers ( e.g. 
     1358=beforeSaveHandler= ) will be called as appropriate. 
    13581359 
    13591360In the event of an error an exception will be thrown. Callers can elect 
    13601361to trap the exceptions thrown, or allow them to propagate to the calling 
    1361 environment. May throw Foswiki::OopsException, Foswiki::AccessControlException or Error::Simple. 
     1362environment. May throw Foswiki::OopsException or Error::Simple. 
    13621363 
    13631364=cut 
     
    13701371    $topicObject->copyFrom($smeta) if $smeta; 
    13711372    return $topicObject->save(%$options); 
    1372 } 
    1373  
    1374 =begin TML 
    1375  
    1376 ---+++ saveTopicText( $web, $topic, $text, $ignorePermissions, $dontNotify ) -> $oopsUrl 
    1377  
    1378 Save topic text, typically obtained by readTopicText(). Topic data usually includes meta data; the file attachment meta data is replaced by the meta data from the topic file if it exists. 
    1379    * =$web=                - Web name, e.g. ='Main'=, or empty 
    1380    * =$topic=              - Topic name, e.g. ='MyTopic'=, or ="Main.MyTopic"= 
    1381    * =$text=               - Topic text to save, assumed to include meta data 
    1382    * =$ignorePermissions=  - Set to ="1"= if checkAccessPermission() is already performed and OK 
    1383    * =$dontNotify=         - Set to ="1"= if not to notify users of the change 
    1384 Return: =$oopsUrl=               Empty string if OK; the =$oopsUrl= for calling redirectCgiQuery() in case of error 
    1385  
    1386 This method is a lot less efficient and much more dangerous than =saveTopic=. 
    1387  
    1388 <verbatim> 
    1389 my $text = Foswiki::Func::readTopicText( $web, $topic ); 
    1390  
    1391 # check for oops URL in case of error: 
    1392 if( $text =~ /^http.*?\/oops/ ) { 
    1393     Foswiki::Func::redirectCgiQuery( $query, $text ); 
    1394     return; 
    1395 } 
    1396 # do topic text manipulation like: 
    1397 $text =~ s/old/new/g; 
    1398 # do meta data manipulation like: 
    1399 $text =~ s/(META\:FIELD.*?name\=\"TopicClassification\".*?value\=\")[^\"]*/$1BugResolved/; 
    1400 $oopsUrl = Foswiki::Func::saveTopicText( $web, $topic, $text ); # save topic text 
    1401 </verbatim> 
    1402  
    1403 =cut 
    1404  
    1405 sub saveTopicText { 
    1406     my ( $web, $topic, $text, $ignorePermissions, $dontNotify ) = @_; 
    1407     ASSERT($Foswiki::Plugins::SESSION) if DEBUG; 
    1408  
    1409     my $session = $Foswiki::Plugins::SESSION; 
    1410  
    1411     # extract meta data and merge old attachment meta data 
    1412     require Foswiki::Meta; 
    1413     my $topicObject = Foswiki::Meta->new( $session, $web, $topic, $text ); 
    1414     $topicObject->remove('FILEATTACHMENT'); 
    1415  
    1416     my $oldMeta = Foswiki::Meta->load( $session, $web, $topic ); 
    1417     $topicObject->copyFrom( $oldMeta, 'FILEATTACHMENT' ); 
    1418  
    1419     my $outcome = ''; 
    1420     unless ( $ignorePermissions || $topicObject->haveAccess('CHANGE') ) { 
    1421         my @caller = caller(); 
    1422         return getScriptUrl( 
    1423             $web, $topic, 'oops', 
    1424             template => 'oopsattention', 
    1425             def      => 'topic_access', 
    1426             param1   => ( $caller[0] || 'unknown' ) 
    1427         ); 
    1428     } 
    1429  
    1430     try { 
    1431         $topicObject->save( notify => $dontNotify ); 
    1432     } 
    1433     catch Error::Simple with { 
    1434         $outcome = getScriptUrl( 
    1435             $web, $topic, 'oops', 
    1436             template => 'oopsattention', 
    1437             def      => 'save_error', 
    1438             param1   => shift->{-text} 
    1439         ); 
    1440     }; 
    1441     return $outcome; 
    14421373} 
    14431374 
     
    15801511    my $meta = Foswiki::Meta->load( $Foswiki::Plugins::SESSION, @_ ); 
    15811512    return ( $meta, $meta->text() ); 
    1582 } 
    1583  
    1584 =begin TML 
    1585  
    1586 ---+++ readTopicText( $web, $topic, $rev, $ignorePermissions ) -> $text 
    1587  
    1588 Read topic text, including meta data 
    1589    * =$web=                - Web name, e.g. ='Main'=, or empty 
    1590    * =$topic=              - Topic name, e.g. ='MyTopic'=, or ="Main.MyTopic"= 
    1591    * =$rev=                - Topic revision to read, optional. Specify the minor part of the revision, e.g. ="5"=, not ="1.5"=; the top revision is returned if omitted or empty. 
    1592    * =$ignorePermissions=  - Set to ="1"= if checkAccessPermission() is already performed and OK; an oops URL is returned if user has no permission 
    1593 Return: =$text=                  Topic text with embedded meta data; an oops URL for calling redirectCgiQuery() is returned in case of an error 
    1594  
    1595 This method is more efficient than =readTopic=, but returns meta-data embedded in the text. Plugins authors must be very careful to avoid damaging meta-data. You are recommended to use readTopic instead, which is a lot safer. 
    1596  
    1597 =cut 
    1598  
    1599 sub readTopicText { 
    1600     my ( $web, $topic, $rev, $ignorePermissions ) = @_; 
    1601     ASSERT($Foswiki::Plugins::SESSION) if DEBUG; 
    1602  
    1603     my $user; 
    1604     $user = $Foswiki::Plugins::SESSION->{user} 
    1605       unless defined($ignorePermissions); 
    1606  
    1607     my $topicObject = 
    1608       Foswiki::Meta->load( $Foswiki::Plugins::SESSION, $web, $topic, $rev ); 
    1609     my $text; 
    1610     if ( 
    1611         $topicObject->haveAccess( 'VIEW', $Foswiki::Plugins::SESSION->{user} ) ) 
    1612     { 
    1613         $text = $topicObject->getEmbeddedStoreForm(); 
    1614     } 
    1615     else { 
    1616         $text = getScriptUrl( 
    1617             $web, $topic, 'oops', 
    1618             template => 'oopsaccessdenied', 
    1619             def      => 'topic_access', 
    1620             param1   => 'VIEW', 
    1621             param2   => $Foswiki::Meta::reason 
    1622         ); 
    1623     } 
    1624  
    1625     return $text; 
    16261513} 
    16271514 
     
    29822869---+++ getDataDir( ) -> $dir 
    29832870 
    2984 *Deprecated* 28 Nov 2008 - use the "Webs, Topics and Attachments" functions to manipulate topics instead 
     2871*Deprecated* 28 Nov 2008 - use the "Webs, Topics and Attachments" functions 
     2872to manipulate topics instead 
    29852873 
    29862874=cut 
     
    29942882---+++ getPubDir( ) -> $dir 
    29952883 
    2996 *Deprecated* 28 Nov 2008 - use the "Webs, Topics and Attachments" functions to manipulateattachments instead 
     2884*Deprecated* 28 Nov 2008 - use the "Webs, Topics and Attachments" functions 
     2885to manipulate attachments instead 
    29972886 
    29982887=cut 
     
    30042893---+++ getCgiQuery( ) -> $query 
    30052894 
    3006 *Deprecated* 31 Mar 2009 - use getRequestObject instead. 
     2895*Deprecated* 31 Mar 2009 - use =getRequestObject= instead. 
    30072896 
    30082897=cut 
     
    30142903    die 
    30152904"checkDependencies removed; contact plugin author or maintainer and tell them to use BuildContrib DEPENDENCIES instead"; 
     2905} 
     2906 
     2907 
     2908=begin TML 
     2909 
     2910---+++ readTopicText( $web, $topic, $rev, $ignorePermissions ) -> $text 
     2911 
     2912Read topic text, including meta data 
     2913   * =$web=                - Web name, e.g. ='Main'=, or empty 
     2914   * =$topic=              - Topic name, e.g. ='MyTopic'=, or ="Main.MyTopic"= 
     2915   * =$rev=                - Topic revision to read, optional. Specify the minor part of the revision, e.g. ="5"=, not ="1.5"=; the top revision is returned if omitted or empty. 
     2916   * =$ignorePermissions=  - Set to ="1"= if checkAccessPermission() is already performed and OK; an oops URL is returned if user has no permission 
     2917 
     2918Return: =$text=                  Topic text with embedded meta data; an oops URL for calling redirectCgiQuery() is returned in case of an error 
     2919 
     2920*Deprecated: 6 Aug 2009. Use =readTopic= instead. 
     2921This method returns meta-data embedded in the text. Plugins authors must be very careful to avoid damaging meta-data. Use readTopic instead, which is a lot safer and supports the full set of read options. 
     2922 
     2923=cut 
     2924 
     2925sub readTopicText { 
     2926    my ( $web, $topic, $rev, $ignorePermissions ) = @_; 
     2927    ASSERT($Foswiki::Plugins::SESSION) if DEBUG; 
     2928 
     2929    my $user; 
     2930    $user = $Foswiki::Plugins::SESSION->{user} 
     2931      unless defined($ignorePermissions); 
     2932 
     2933    my $topicObject = 
     2934      Foswiki::Meta->load( $Foswiki::Plugins::SESSION, $web, $topic, $rev ); 
     2935 
     2936    my $text; 
     2937    if ( $ignorePermissions || 
     2938         $topicObject->haveAccess( 
     2939             'VIEW', $Foswiki::Plugins::SESSION->{user} ) ) { 
     2940        $text = $topicObject->getEmbeddedStoreForm(); 
     2941    } 
     2942    else { 
     2943        $text = getScriptUrl( 
     2944            $web, $topic, 'oops', 
     2945            template => 'oopsaccessdenied', 
     2946            def      => 'topic_access', 
     2947            param1   => 'VIEW', 
     2948            param2   => $Foswiki::Meta::reason 
     2949        ); 
     2950    } 
     2951 
     2952    return $text; 
     2953} 
     2954 
     2955=begin TML 
     2956 
     2957---+++ saveTopicText( $web, $topic, $text, \%options ) -> $oopsUrl 
     2958 
     2959Save topic text, typically obtained by readTopicText(). Topic data usually includes meta data; the file attachment meta data is replaced by the meta data from the topic file if it exists. 
     2960   * =$web=                - Web name, e.g. ='Main'=, or empty 
     2961   * =$topic=              - Topic name, e.g. ='MyTopic'=, or ="Main.MyTopic"= 
     2962   * =$text=               - Topic text to save, assumed to include meta data 
     2963   * =$ignorePermissions=  - Set to ="1"= if checkAccessPermission() is already performed and OK 
     2964   * =$dontNotify=         - Set to ="1"= if not to notify users of the change 
     2965 
     2966*Deprecated* 6 Aug 2009 - use saveTopic instead. 
     2967=saveTopic= supports embedded meta-data in the saved text, and also 
     2968supports the full set of save options. 
     2969 
     2970Return: =$oopsUrl=               Empty string if OK; the =$oopsUrl= for calling redirectCgiQuery() in case of error 
     2971 
     2972<verbatim> 
     2973my $text = Foswiki::Func::readTopicText( $web, $topic ); 
     2974 
     2975# check for oops URL in case of error: 
     2976if( $text =~ /^http.*?\/oops/ ) { 
     2977    Foswiki::Func::redirectCgiQuery( $query, $text ); 
     2978    return; 
     2979} 
     2980# do topic text manipulation like: 
     2981$text =~ s/old/new/g; 
     2982# do meta data manipulation like: 
     2983$text =~ s/(META\:FIELD.*?name\=\"TopicClassification\".*?value\=\")[^\"]*/$1BugResolved/; 
     2984$oopsUrl = Foswiki::Func::saveTopicText( $web, $topic, $text ); # save topic text 
     2985</verbatim> 
     2986 
     2987=cut 
     2988 
     2989sub saveTopicText { 
     2990    my ( $web, $topic, $text, $ignorePermissions, $dontNotify ) = @_; 
     2991    ASSERT($Foswiki::Plugins::SESSION) if DEBUG; 
     2992 
     2993    my $session = $Foswiki::Plugins::SESSION; 
     2994 
     2995    # extract meta data and merge old attachment meta data 
     2996    require Foswiki::Meta; 
     2997    my $topicObject = Foswiki::Meta->new( $session, $web, $topic ); 
     2998    $topicObject->remove('FILEATTACHMENT'); 
     2999 
     3000    my $oldMeta = Foswiki::Meta->load( $session, $web, $topic ); 
     3001    $topicObject->copyFrom( $oldMeta, 'FILEATTACHMENT' ); 
     3002 
     3003    my $outcome = ''; 
     3004    unless ( $ignorePermissions || $topicObject->haveAccess('CHANGE') ) { 
     3005        my @caller = caller(); 
     3006        return getScriptUrl( 
     3007            $web, $topic, 'oops', 
     3008            template => 'oopsattention', 
     3009            def      => 'topic_access', 
     3010            param1   => ( $caller[0] || 'unknown' ) 
     3011        ); 
     3012    } 
     3013    $topicObject->text($text); 
     3014 
     3015    try { 
     3016        $topicObject->save( minor => $dontNotify ); 
     3017    } 
     3018    catch Error::Simple with { 
     3019        $outcome = getScriptUrl( 
     3020            $web, $topic, 'oops', 
     3021            template => 'oopsattention', 
     3022            def      => 'save_error', 
     3023            param1   => shift->{-text} 
     3024        ); 
     3025    }; 
     3026    return $outcome; 
    30163027} 
    30173028 
Note: See TracChangeset for help on using the changeset viewer.