I'm trying to get my head around the full process drupal uses regarding making nodes safe for display and whether there are any changes in 4.7 regarding this. I did a quick search and could not find this decision tree written out, so I thought I'd take a quick stab. Can anyone double-check that this sounds correct:

The process begins with node.module’s node_view making the following decision: If the node type’s module has a hook_view, let the module handle any filtering. Otherwise node.module will pass the body or teaser through node_prepare.

If we are using a hook_view, the module should first call node_prepare on the body / teaser. Then the module will pass it on to the theme. An example from forum.module’s forum_view:

$node = node_prepare($node, $teaser);
$node->body .= theme('forum_topic_navigation', $node);

This would suggest that the theme should not have to worry about making user-supplied content safe, but it appears that the general practice for custom content fields is to filter them in the theme function. On reason for this might be the l() function, which seems to filter the title of the link. If we were to filter all content at the hook_view level, things might get double-encoded[1]. However, in theory this opens the door for site admins and theme developers to overlook these calls to check_plain or l() while overwriting the theme function in their theme.

Three examples that I can come up with off the top of my head where a theme filters content are:

//check_plain for simple fields with plain text.
$output .= '<div class="organization_name">'. check_plain($node->organization_name) .'</div>'."\n";

//check_markup for textareas where you want to allow users some html options
$output .= '<div class="organization_description">'. check_markup($node->organization_desc, $node->filter) .'</div>'."\n";

// links 
$output .= '<div class="organization_description">'. l($node->organization_link_title, $node->organization_link_url) .'</div>'."\n";

After the node passes the hook_view / node_prepare decision, node_view checks for any nodeapi hooks that apply to this node. As a general rule, the body / teaser is safe by this point, so $node->body and $node->teaser should not be passed to node_prepare, etc. In most of the examples I’ve seen, the nodeapi modules call a theme function to generate the html, then append the resulting content to the front or the back of $node->body.

It is possible to instead call it like this instead:

  // in the nodeapi's view case
  $node->body = theme('example_nodeapi_theme_function', $node);

// the theme function
function theme_example_nodeapi_theme_function($node){
  $output = 'all the extra nodeapi stuff here';
  $node->body = $output . $node->body;
}

This would allow theme developers to change where a nodeapi element is in relation to the node. For example, if you wanted your events time to appear at the end of the story instead of at the beginning, it would be easier than trying to convince css to drop it down there. Has anyone run into any issues with this method?

Thanks in advance for any feedback.

Sean B. Fuller
seanbfuller.com

[1] This assumes that site admins are encoding tags and not stripping them. I would guess that double stripping content would not be noticable, but double encoding would be?

Comments

seanbfuller’s picture

Nedjo pointed out this additional link to a handbook entry called "How to handle text in a secure fashion": http://drupal.org/node/28984

--------------------
Sean B. Fuller
www.seanbfuller.com
www.tractiv.com

--------------------
Sean B. Fuller
www.seanbfuller.com

edrupalec’s picture

Sean,
thank you for taking the time to write this up. This adds some useful information/explanation that's not in the handbook.

-----
Drupal ecommerce, at http://www.drupalecommerce.com is a new site written using language that Drupal beginners and intermediate users can understand. Quick links to "Modules" and "Module Groupings."