11.7 Mason ComponentsMason allows construction of complex web sites through the notion of components. A Mason component is a file with any combination of HTML, Perl, and Mason code. For a simple example, we will create a header file and footer file that will be applied across the web site. First, we'll create some header HTML and put it in the file /var/www/html/mason/_header . The following HTML is the beginning HTML for the example: <html> <head> <title>Mason Component Example</title> </head> <body bgcolor="#ffffff"> <i>This text is in the header.</i> <hr> Don't panic [3] ”this is just basic HTML. No new stuff here. This illustrates that a Mason component need not contain any Mason at all ”plain HTML is fine. This HTML is then included when the component is used.
And now for the footer ( /var/www/html/mason/_footer ): % my $url =http://www.opensourcewebbook.com/; % my $email = webmaster@opensourcewebbook.com; <hr> Website: <a href="<% $url %>"><% $url %></a> <br> Comments: <a href="mailto:<% $email %>"><% $email %></a> </body> </html> This file does indeed contain Mason code. The variables $url and $email are defined. The component then generates a bit of HTML, using both variables. The name of each of these two component files starts with the underscore character. We'll explain why in a bit. To use these header and footer components, create the file /var/www/html/mason/components.html : <& _header &> <i>this text is in components.html:</i> <b>hello, world!</b> <& _footer &> The new tag in this example is <& ... &> , which reads in the component within. For instance, <& _header &> reads in the _header component, and <& _footer &> reads in the _footer component. If one loads components.html , it reads in the header and footer to create this HTML (lines wrapped for readability): <html> <head> <title>Mason Component Example</title> </head> <body bgcolor="#ffffff"> <i>This text is in the header.</i> <hr> <i>this text is in components.html:</i> <b>hello, world!</b> <hr> Website: <a href="http://www.opensourcewebbook.com/"> http://www.opensourcewebbook.com/</a> <br> Comments: <a href="mailto:webmaster@opensourcewebbook.com"> webmaster@opensourcewebbook.com</a> </body> </html> To view the result, load either of these URLs into the browser: http://localhost/mason/components.html or www.opensourcewebbook.com/mason/components.html. This produces Figure 11.8. Figure 11.8. Mason components
11.7.1 Components and <%args>Variables and their values can be passed into components and then accessed using <%args> much as if they were posted data. As an example, create the file /var/www/html/mason/components2.html . It will be a duplicate of the preceding example, with two differences: <& _header2, title => The Second Component Example &> <i>this text is in components2.html:</i> <b>hello, world!</b> <& _footer2, url => http://www.opensourcewebbook.com, email => webmaster@opensourcewebbook.com &> The change you probably noticed right away occurs within the <& ... &> tags. In this example, the component included is _header2 (as opposed to _header ), and a name/value pair is passed into the component: title => The Second Component Example This name/value pair is passed into the component just as posted data would be passed in. In this example, the key title and its value The Second Component Example are passed in. This value can be accessed using the <%args> tag just as if it were posted data. Look at the new _header2 component (found in the file /var/www/html/mason/_header2 ): <html> <head> <title><% $title %></title> </head> <body bgcolor="#ffffff"> <i>This text is in the header.</i> <hr> <%args> $title => Mason Component Example </%args> Notice the addition of the <%args> ... </%args> tag. This assigns $title the value "posted" (or in the example, the value passed in when we ask for the component), defaulting to the string Mason Component Example . The variable $title is then used within the <title> ... </title> tag. Because a default has been provided to the variable $title , we can ask for this component without providing a title: <& _header2 &> In this case, the default string Mason Component Example is used for the title. Another difference in components2.html is in the included _footer2 component: <& _footer2, url => http://www.opensourcewebbook.com, email => webmaster@opensourcewebbook.com &> This requests the component _footer2 , passing data to the component. The values of the arguments are contained within the <%args> tag in the _footer2 component. This component is contained in the file /var/www/html/mason/_footer2 : <hr> Website: <a href="<% $url %>"><% $url %></a> <br> Comments: <a href="mailto:<% $email %>"><% $email %></a> </body> </html> <%args> $url => http://www.onsight.com/ $email => webmaster@onsight.com </%args> At the bottom of this file, $url is assigned the value passed into the component, or it defaults to http://www.onsight.com/. The variable $email is handled similarly. When the components2.html page is requested , it generates this HTML (links are wrapped for readability): <html> <head> <title>The Second Component Example</title> </head> <body bgcolor="#ffffff"> <i>This text is in the header.</i> <hr> <i>this text is in components2.html:</i> <b>hello, world!</b> <hr> Website: <a href="http://www.opensourcewebbook.com"> http://www.opensourcewebbook.com</a> <br> Comments: <a href="mailto:webmaster@opensourcewebbook.com"> webmaster@opensourcewebbook.com</a> </body> </html> To view the result, load one of these URLs: http://localhost/mason/components2.html or www.opensourcewebbook.com/mason/components2.html. The result should be similar to Figure 11.9. Figure 11.9. Mason components, take
11.7.2 The <%init> ... </%init> SectionRecall the _footer example: % my $url =http://www.opensourcewebbook.com/; % my $email = webmaster@opensourcewebbook.com; <hr> Website: <a href="<% $url %>"><% $url %></a> <br> Comments: <a href="mailto:<% $email %>"><% $email %></a> </body> </html> At the top of this file is some executable Perl code: the declaration of the variables $url and $email . Having Perl code at the top of the file is fine, but remember, in Mason the convention is to put the code at the bottom of the file instead of the top. How can we include code that must be executed before the HTML is processed , yet have it be physically after said HTML? The answer is the <%init> block. [4]
The <%init> ... </%init> block is a block of Perl code that is executed first, [5] before anything else in the file is processed. So if you want to have a block of Perl code that has to be executed first but have it at the bottom of the file, this block can be used. The _footer file can be rewritten as:
<hr> Website: <a href="<% $url %>"><% $url %></a> <br> Comments: <a href="mailto:<% $email %>"><% $email %></a> </body> </html> <%init> my $url = http://www.opensourcewebbook.com/; my $email = webmaster@opensourcewebbook.com; </%init> 11.7.3 The <%once> ... </%once> SectionThe <%once> ... </%once> tag defines a block of code that is executed only once, when the component is first loaded. Variables and functions that are declared/defined in this block can be seen in all the component's code and persist for the entire life of the component in the httpd process. This block is useful for declaring persistent component-scoped lexical variables and for defining functions. For example: <%once> my $var = this is a test; sub important { ... } </%once> 11.7.4 A Note about Mason SecurityThis method of including components is fine, as far as it goes, but it has one major flaw: Apache serves up the components as simple text files. To prove this, try loading the URL http://localhost/mason/_header . You'll see Figure 11.10. D'oh! Our Mason component source code is being served up on a platter, thereby making our Mason component source code available. A cracker may be able to learn something about how our site works and perhaps leverage that knowledge in an attack. Figure 11.10. Serving up Mason components
There are several ways of securing the Mason components (see www.masonhq.com/docs/manual/Admin.html#securing_top_level_components). One method, the one we'll use, is to deny access to files in the Mason directory that start with the underscore character ( _foo.bar ). Now the reason Mason files are named with a leading underscore becomes clear. Here we used the underscore character, but one could as well choose to prefix the files with "." The advantage of the underscore is that files still show up with the standard ls command ” ls -a is not necessary to see the Mason files in the directory. To implement this security measure, modify the Apache configuration for Mason: PerlSetVar MasonCompRoot /var/www/html/mason PerlSetVar MasonDataDir /var/www/misc/mason PerlModule HTML::Mason::ApacheHandler <Directory /var/www/html/mason> SetHandler perl-script PerlHandler HTML::Mason::ApacheHandler <Files ~ " ^ _"> SetHandler perl-script PerlInitHandler Apache::Constants::NOT_FOUND </Files> </Directory> Here the <Files> directive is added. This directive instructs Apache to handle all files that begin with an underscore and to send the response that that file is not found. Alternatively, access to the file could have simply been denied by modifying the preceding Apache configuration as follows : <Files ~ " ^ _"> Order allow,deny Deny from all </Files> This directive tells Apache to deny access, which is printed on the browser as "Forbidden". This is fine because it doesn't serve up the file, but it tells the user that the file is there and they cannot access it. But why tell a would-be cracker that the component actually exists at all? [6] Instead, trick them into thinking that the component is not found, and give no information about the component's state of existence.
So, we will stick with this: <Files ~ " ^_ "> SetHandler perl-script PerlInitHandler Apache::Constants::NOT FOUND </Files> After changing the configuration file, restart Apache: # /etc/init.d/httpd graceful Now, loading the URL http://localhost/mason/_header produces Figure 11.11. Figure 11.11. Serving up Mason components ”fixed!
|