r3042 - maintenance->trunk sync of changeset:3040
authorDenis Ovsienko <infrastation@yandex.ru>
Thu, 6 Aug 2009 07:17:43 +0000 (07:17 +0000)
committerDenis Ovsienko <infrastation@yandex.ru>
Thu, 6 Aug 2009 07:17:43 +0000 (07:17 +0000)
ChangeLog
ajax.php
download.php
inc/functions.php
inc/interface.php
inc/navigation.php
index.php
popup.php
process.php
render_image.php

index fee9beb86ef4b4520f5f29fb6ce269cc33336da2..8a7eb3f8f54392d3f5da8f21cd08cba33d9bf772 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -7,6 +7,7 @@
        bugfix: rack row removal sometimes failed (by Marcin Suchocki)
        bugfix: improve usage counters for IPv4 networks
        bugfix: make ADDNEW_AT_TOP options really work everywhere (ticket:213)
+       bugfix: authorize file preview as a download (ticket:241)
 0.17.2 2009-07-22
        new feature: configure default SNMP community (by jthurman)
        new feature: "$untagged", "$portless", "$nameless" and "$masklen_OP_NN" autotags
index e8be75a6ce41e3df6b15c71aabd0bb149a9dd300..b7620ec4a211ef7518aa2f49c4a5c3d377f80fae 100644 (file)
--- a/ajax.php
+++ b/ajax.php
@@ -3,18 +3,12 @@ ob_start();
 try {
 
 require 'inc/init.php';
-$_REQUEST['page'] = 'perms';
-$_REQUEST['tab'] = 'edit';
+$pageno = 'perms';
+$tabno = 'edit';
 fixContext();
 
-// We have a chance to handle an error before starting HTTP header.
 if (!permitted())
 {
-       $errlog = array
-       (
-               'v' => 2,
-               'm' => array (0 => array ('c' => 157)) // operation not permitted
-       );
        echo "NAK\nPermission denied";
        exit();
 }
@@ -38,5 +32,4 @@ catch (Exception $e)
        printException($e);
 }
 
-
 ?>
index 12f321fca84c92325992409116514dabca442140..62b99faef88715e20014301337afab790eb95a8e 100644 (file)
@@ -1,22 +1,23 @@
 <?php
 require 'inc/init.php';
+// purely for renderAccessDenied()
+require 'inc/interface.php';
 
 assertUIntArg ('file_id', __FILE__);
 $pageno = 'file';
-$tabno = 'default';
+$tabno = 'download';
 fixContext();
 if (!permitted())
-{
-       showError ("Permission denied", __FILE__);
-       die();
-}
+       renderAccessDenied();
 
+$asattach = (isset ($_REQUEST['asattach']) and $_REQUEST['asattach'] == 'no') ? FALSE : TRUE;
 $file = getFile($_REQUEST['file_id']);
 if ($file != NULL) 
 {
        header("Content-Type: {$file['type']}");
        header("Content-Length: {$file['size']}");
-       header("Content-Disposition: attachment; filename={$file['name']}");
+       if ($asattach)
+               header("Content-Disposition: attachment; filename={$file['name']}");
        echo $file['contents'];
 }
 ?>
index ce2ce5fb0ebc94878bb2fa6b174ea351db78a8f3..eacbd7556388024699c86e1716c17b5c82c8336d 100644 (file)
@@ -1127,23 +1127,9 @@ function tagChainCmp ($chain1, $chain2)
        return FALSE;
 }
 
-// If the page-tab-op triplet is final, make $expl_tags and $impl_tags
-// hold all appropriate (explicit and implicit) tags respectively.
-// Otherwise some limited redirection is necessary (only page and tab
-// names are preserved, ophandler name change isn't handled).
-function fixContext ()
+function redirectIfNecessary ()
 {
-       global
-               $pageno,
-               $tabno,
-               $auto_tags,
-               $expl_tags,
-               $impl_tags,
-               $target_given_tags,
-               $user_given_tags,
-               $etype_by_pageno,
-               $page;
-
+       global $pageno, $tabno;
        $pmap = array
        (
                'accounts' => 'userlist',
@@ -1165,19 +1151,38 @@ function fixContext ()
                redirectUser ($pmap[$pageno], $tabno);
        if (isset ($tmap[$pageno][$tabno]))
                redirectUser ($pageno, $tmap[$pageno][$tabno]);
+}
+
+function fixContext ($target = NULL)
+{
+       global
+               $pageno,
+               $auto_tags,
+               $expl_tags,
+               $impl_tags,
+               $target_given_tags,
+               $user_given_tags,
+               $etype_by_pageno,
+               $page;
 
-       if (isset ($etype_by_pageno[$pageno]))
+       if ($target !== NULL)
+       {
+               $target_given_tags = $target['etags'];
+               // Don't reset autochain, because auth procedures could push stuff there in.
+               // Another important point is to ignore 'user' realm, so we don't infuse effective
+               // context with autotags of the displayed account.
+               if ($target['realm'] != 'user')
+                       $auto_tags = array_merge ($auto_tags, $target['atags']);
+       }
+       elseif (array_key_exists ($pageno, $etype_by_pageno))
        {
                // Each page listed in the map above requires one uint argument.
-               assertUIntArg ($page[$pageno]['bypass'], __FUNCTION__);
                $target_realm = $etype_by_pageno[$pageno];
+               assertUIntArg ($page[$pageno]['bypass'], __FUNCTION__);
                $target_id = $_REQUEST[$page[$pageno]['bypass']];
                $target = spotEntity ($target_realm, $target_id);
                $target_given_tags = $target['etags'];
-               // Don't reset autochain, because auth procedures could push stuff there in.
-               // Another important point is to ignore 'user' realm, so we don't infuse effective
-               // context with autotags of the displayed account.
-               if ($pageno != 'user')
+               if ($target['realm'] != 'user')
                        $auto_tags = array_merge ($auto_tags, $target['atags']);
        }
        // Explicit and implicit chains should be normally empty at this point, so
@@ -2181,4 +2186,32 @@ function decodeObjectType ($objtype_id, $style = 'r')
        return $types[$style][$objtype_id];
 }
 
+function isolatedPermission ($p, $t, $cell)
+{
+       // This function is called from both "file" page and a number of other pages,
+       // which have already fixed security context and authorized the user for it.
+       // OTOH, it is necessary here to authorize against the current file, which
+       // means saving the current context and building a new one.
+       global
+               $expl_tags,
+               $impl_tags,
+               $target_given_tags,
+               $auto_tags;
+       // push current context
+       $orig_expl_tags = $expl_tags;
+       $orig_impl_tags = $impl_tags;
+       $orig_target_given_tags = $target_given_tags;
+       $orig_auto_tags = $auto_tags;
+       // retarget
+       fixContext ($cell);
+       // remember decision
+       $ret = permitted ($p, $t);
+       // pop context
+       $expl_tags = $orig_expl_tags;
+       $impl_tags = $orig_impl_tags;
+       $target_given_tags = $orig_target_given_tags;
+       $auto_tags = $orig_auto_tags;
+       return $ret;
+}
+
 ?>
index 15acd738fefa2fb3a342c4680462c03be7975741..aa32a645ddd210a202d173b0b72fb0034224f37e 100644 (file)
@@ -5242,6 +5242,7 @@ function renderAccessDenied ()
        echo "<tr><td colspan=2 align=center>Click <a href='${root}?logout'>here</a> to logout.</td></tr>\n";
        echo "</table>\n";
        echo "</body></html>";
+       die;
 }
 
 function renderMyAccount ()
@@ -5270,10 +5271,14 @@ function renderFile ($file_id)
        echo "<table border=0 cellspacing=0 cellpadding=3 width='100%'>\n";
        echo "<tr><th width='50%' class=tdright>Type:</th>";
        printf("<td class=tdleft>%s</td></tr>", htmlspecialchars ($file['type']));
-       echo "<tr><th width='50%' class=tdright>Size:</th>";
-       echo "<td class=tdleft><a href='${root}download.php?file_id=${file_id}'>";
-       printImageHREF ('download', 'Download file');
-       printf("</a>&nbsp;%s</td></tr>", formatFileSize($file['size']));
+       echo "<tr><th width='50%' class=tdright>Size:</th><td class=tdleft>";
+       if (isolatedPermission ('file', 'download', $file))
+       {
+               echo "<a href='${root}download.php?file_id=${file_id}'>";
+               printImageHREF ('download', 'Download file');
+               echo '</a>&nbsp;';
+       }
+       printf("%s</td></tr>", formatFileSize($file['size']));
        echo "<tr><th width='50%' class=tdright>Created:</th>";
        printf("<td class=tdleft>%s</td></tr>", formatTimestamp($file['ctime']));
        echo "<tr><th width='50%' class=tdright>Modified:</th>";
@@ -5320,7 +5325,7 @@ function renderFile ($file_id)
                finishPortlet();
        }
 
-       if ('' != ($pcode = getFilePreviewCode ($file)))
+       if (isolatedPermission ('file', 'download', $file) and '' != ($pcode = getFilePreviewCode ($file)))
        {
                echo "</td><td class=pcright>";
                startPortlet ('preview');
@@ -5342,6 +5347,14 @@ function renderFileReuploader ()
        finishPortlet();
 }
 
+function renderFileDownloader ($file_id)
+{
+       global $root;
+       echo "<br><center><a target='_blank' href='${root}download.php?file_id=${file_id}&asattach=1'>";
+       printImageHREF ('DOWNLOAD');
+       echo '</a></center>';
+}
+
 function renderFileProperties ($file_id)
 {
        $file = spotEntity ('file', $file_id);
@@ -5440,9 +5453,10 @@ function renderFilesPortlet ($entity_type = NULL, $entity_id = 0)
                        echo "<tr valign=top><td class=tdleft>";
                        // That's a bit of overkill and ought to be justified after
                        // getFilesOfEntity() returns a standard cell list.
-                       renderCell (spotEntity ('file', $file['id']));
+                       $file = spotEntity ('file', $file['id']);
+                       renderCell ($file);
                        echo "</td><td class=tdleft>${file['comment']}</td></tr>";
-                       if ('' != ($pcode = getFilePreviewCode ($file)))
+                       if (isolatedPermission ('file', 'download', $file) and '' != ($pcode = getFilePreviewCode ($file)))
                                echo "<tr><td colspan=2>${pcode}</td></tr>\n";
                }
                echo "</table><br>\n";
@@ -5647,9 +5661,13 @@ function renderCell ($cell)
                        printf ("<small>%s</small>", serializeFileLinks ($cell['links']));
                echo "</td></tr><tr><td>";
                echo count ($cell['etags']) ? ("<small>" . serializeTags ($cell['etags']) . "</small>") : '&nbsp;';
-               echo "</td></tr><tr><td><a href='${root}download.php?file_id=${cell['id']}'>";
-               printImageHREF ('download', 'Download file');
-               echo '</a>&nbsp;';
+               echo '</td></tr><tr><td>';
+               if (isolatedPermission ('file', 'download', $cell))
+               {
+                       echo "<a href='${root}download.php?file_id=${cell['id']}'>";
+                       printImageHREF ('download', 'Download file');
+                       echo '</a>&nbsp;';
+               }
                echo formatFileSize ($cell['size']);
                echo "</td></tr></table>";
                break;
@@ -5772,10 +5790,10 @@ function getFilePreviewCode ($file)
                                $resampled = TRUE;
                        }
                        if ($resampled)
-                               $ret .= "<a href='${root}render_image.php?img=view&file_id=${file['id']}'>";
+                               $ret .= "<a href='${root}download.php?file_id=${file['id']}&asattach=no'>";
                        $ret .= "<img width=${width} height=${height} src='${root}render_image.php?img=preview&file_id=${file['id']}'>";
                        if ($resampled)
-                               $ret .= '</a>';
+                               $ret .= '</a><br>(click to zoom)';
                        break;
                case 'text/plain':
                        if ($file['size'] < getConfigVar ('PREVIEW_TEXT_MAXCHARS'))
index 20526ed2768685c26ae9296a0e5b699fc1723c9b..97679188ded76f6a76327303420eb918480ae25b 100644 (file)
@@ -415,6 +415,7 @@ $tab['file']['edit'] = 'Properties';
 $tab['file']['tags'] = 'Tags';
 $tab['file']['editText'] = 'Edit text';
 $tab['file']['replaceData'] = 'Upload replacement';
+$tab['file']['download'] = 'Download';
 $trigger['file']['tags'] = 'trigger_tags';
 $trigger['file']['editText'] = 'trigger_file_editText';
 $tabhandler['file']['default'] = 'renderFile';
@@ -422,6 +423,7 @@ $tabhandler['file']['edit'] = 'renderFileProperties';
 $tabhandler['file']['tags'] = 'renderEntityTags';
 $tabhandler['file']['editText'] = 'renderTextEditor';
 $tabhandler['file']['replaceData'] = 'renderFileReuploader';
+$tabhandler['file']['download'] = 'renderFileDownloader';
 $ophandler['file']['edit']['updateFile'] = 'updateFile';
 $ophandler['file']['tags']['saveTags'] = 'saveEntityTags';
 $ophandler['file']['editText']['updateFileText'] = 'updateFileText';
index f2e5a7360ce286494a38cb203c92deb6a11d65f8..35676aa0d18372d730fe47d7b2c4ae7f9ebbdd45 100644 (file)
--- a/index.php
+++ b/index.php
@@ -4,12 +4,10 @@ try {
 require 'inc/interface.php';
 require 'inc/init.php';
 // no ctx override is necessary
+redirectIfNecessary();
 fixContext();
 if (!permitted())
-{
        renderAccessDenied();
-       die;
-}
 // Only store the tab name after clearance is got. Any failure is unhandleable.
 $_SESSION['RTLT'][$pageno] = $tabno;
 
index 7f01322d4a5cded8be2e01b6098dc35d94b09b95..2ed057dea87d81876f775eaf4cc47b2d2c8d69ce 100644 (file)
--- a/popup.php
+++ b/popup.php
                        $tabno = 'ports';
                        fixContext();
                        if (!permitted())
-                       {
                                renderAccessDenied();
-                               die;
-                       }
                        assertUIntArg ('type', __FILE__);
                        assertUIntArg ('port', __FILE__);
                        assertUIntArg ('object_id', __FILE__);
                        $tabno = 'default';
                        fixContext();
                        if (!permitted())
-                       {
                                renderAccessDenied();
-                               die;
-                       }
                        echo '<div style="background-color: #f0f0f0; border: 1px solid #3c78b5; padding: 10px; height: 100%; text-align: center; margin: 5px;">';
                        echo '<h2>Choose a port:</h2><br><br>';
                        echo '<form action="javascript:;">';
index b2e8a7faafb579a023450ffdd71677491e16c4b0..baa6ca88c3337e0ea7603d171d8076381df996f0 100644 (file)
@@ -12,6 +12,7 @@ if ($op == 'addFile' && !isset($_FILES['file']['error'])) {
        showError ("File upload error, it's size probably exceeds upload_max_filesize directive in php.ini");
        die;
 }
+redirectIfNecessary();
 fixContext();
 
 if (!isset ($ophandler[$pageno][$tabno][$op]))
index d4ee1f4ff85f12b8f5114efbcadae356221f8f7f..835ecca29d200c48ffc7c4c217a4218a3d6777fc 100644 (file)
@@ -22,11 +22,10 @@ switch ($_REQUEST['img'])
                assertUIntArg ('done', __FILE__, TRUE);
                renderProgressBarImage ($_REQUEST['done']);
                break;
-       case 'view': // file security context
-       case 'preview':
+       case 'preview': // file security context
                assertUIntArg ('file_id', __FILE__);
                $pageno = 'file';
-               $tabno = 'default';
+               $tabno = 'download';
                fixContext();
                if (!permitted())
                        renderAccessDeniedImage();
@@ -170,6 +169,7 @@ function renderAccessDeniedImage ()
        header("Content-type: image/png");
        imagepng ($img);
        imagedestroy ($img);
+       die;
 }
 
 function renderFilePreview ($file_id = 0, $mode = 'view')