Open source software security

Moving Conditional PHP Block Display Logic

4 May 2011
In Drupal 7 it is quite convenient to be able to display blocks using conditional PHP logic. To set this up we merely need to enable a block in the block display interface (at #overlay=admin/structure/block). If we wanted, say, to display the "Who's online" block only to users not running Chrome we could use some conditional PHP to do this. Chrome doesn't report its HTTP user agent in requests, so we can check if the variable $_SERVER['HTTP_USER_AGENT'] is set. First we need to make sure that the Block and the PHP filter module are enabled. You can view these settings by clicking on the 'Modules' link in the administrative header, or find them at #overlay=admin/structure/block. You can later disable the PHP input filter, but weird things happen (the PHP code you use is left intact and displayed, and block display specifications remain, but the radio button used is no longer visible, which could create confusion). Once these two modules are enabled simply enable the 'Who's online' block by clicking on Structure, then Blocks in the administrative menu at the top, or by going to #overlay=admin/structure/block. Next find the 'Who's online' block in the disabled blocks from the list and select 'Sidebar second' (or another location) from the 'Region' drop down menu and save the settings. Once saved click the 'Configure' link under the 'Operations' column in the block list (or go to #overlay=admin/structure/block/manage/user/online/configure) to view the configuration form. Next, in the 'Visibility settings' choose the radio button for 'Pages on which this PHP code returns TRUE (experts only)' and then enter the following PHP into the text area:
<?php return( isset($_SERVER['HTTP_USER_AGENT']));?>
Click the 'Save block' button and then view the pages in Firefox and in Chrome to note how the block is not displayed under Chrome. This effect can also be achieved using a template file, which is safer than embedding the PHP code in your block display. Using PHP in the administration interface is a security risk since an attacker who gained control of an account with the ability to write PHP could easily compromise your entire installation. It's also easier for maintenance as display logic is normally found in the template. Block templates are found in the theme for your site. Firstly we'll need to create a new template file in our theme directory. Create a new file named block.tpl.php in your theme's "templates" directory. This file will be used for the display logic for all blocks (if you want to create a template that will only be used for display of blocks rendered by the user module (such as the "Who's online" block) you can name the block block--user.tpl.php). In this file put the following code:
<?php
  // Conditional check for "Who's online block'"
  if ($block->bid == 21 && ! isset($_SERVER['HTTP_USER_AGENT'])) {
  	// Don't display for Chrome
  }
  else {
    $output = "  <div id=\"$block_html_id\" class=\"$classes\">\n";
    if ($block->subject != '')  $output .= "<h2>".$block->subject."</h2>\n";
    $output .= "<div class=\"content\">".$content."</div>\n";
    $output .= "</div>\n";
    print $output;
  }
?>
As you can see we're conditionally checking the bid value for each block before display. If the bid is 21 (the bid for the Who's online block) then we're suppressing display based on our earlier rule. If you need to find the bid for your blocks a handy trick is to add the line:
$output .= var_export($block);
right before the print statement. Var_export is a PHP function (http://us3.php.net/manual/en/function.var-export.php) that dumps a variable as a string, so you can inspect the value. This is especially handy for looking at PHP objects and their contents. At this point we've moved our PHP display logic out of an obscure text area in the Drupal administration interface and into a theme template file. Not only is this a more appropriate location, but it's also easier to manage. Now we can delete the PHP filter and revoke any PHP permissions on the site to increase security. For more information on variables in block templates see http://api.drupal.org/api/drupal/modules--block--block.tpl.php/7. For more information about block naming convention see http://drupal.org/node/1089656. For more information about theming blocks using templates see http://drupal.org/node/104319.