throbber
d mod_perl
`
`piijj.-,-,'•-_^ '.'•T (cid:127) -^'".i'"
`
`m
`
`; •• r-x^^^.;-. :• \i
`
`i/5^
`
`>%;•
`
`-/yp^ &;
`
`Modu
`
`Perl and C
`
`O'REILLY
`
`Lincoln Stein & Doug MacEachern
`
`1
`
`AT&T - Exhibit 1008
`
`

`
`Writing Apache Modules
`with Perl and C
`
`Lincoln Stein and Doug MacEachern
`
`Beijing - Cambridge - Famlaam - Kéiln - Sebastopol - Toleyo
`
`O’RE|LLY°
`
`2
`
`2
`
`

`
`Writing Apache Modules with Perl and B
`hy Lincoln Stein and Doug .\rIaeF.a<:l1ern
`
`Copyifiglit CC) 1999 O‘Reilly e\' Associates, Inc. All rights reserx ed.
`Printecl in the United States of America.
`
`Ptihlished hy O’Reilly & Associates, Inc., 101 Morris Street, Sehrtstopol, CA 95472.
`
`Editor: Linda Mui
`
`Production Editor: Melanie Wzing
`
`Printing History:
`
`March 1999:
`
`First Edition.
`
`The association between the image of a white-tailed eagle and the topic of Apache modules
`is a trademark oi'O’Reilly & Associates, Inc. Nutshell Handbook, the Nutshell I-iandhook logo,
`and the O‘Reilly logo are registered trademarks ol’ O’Reilly & Associates, Inc. Many of the
`designations used by manufacturers and sellers to distinguish their products are claimed as
`trademarks. Where those designations appear in this hook, and O’Reilly & Associates. Inc.
`was aware of a trademark claim, the designations have been printed in caps or initial caps.
`
`\\’fhile every precaution has been taken in the preparation ofthis hook, the publisher /,1.‘-2SL!I]1C.‘a‘
`no responsibility for errors or omissions, or for damages resulting from the use of the
`information contained herein.
`
`ISBN: 978-1565-92567-(J
`ILSII
`
`|2(il1-1 I-U4]
`
`3
`
`

`
`V
`
`1)., mi’: c:I_1c:prer.'
`. Cm1fentHci.ml1ers as
`,.--,-,_r(, P7‘ocessors
`
`. Vr'rfua!1)ocmnents
`
`.
`
`serif-recrfon
`
`. Processing Irzput
`
`. ,-ipctCbe:.'Regrlstrjt
`.
`Iczndlfirg Errors
`2/.-m:1'nt'7'zg Content
`
`Hcmrtle-rs
`
`. Method Handlers
`
`7/1t t H017’!
`
`This chapter is about writing content handlers for the Apache response phase,
`when the contents of the page are actually produced. In this chapter you'll learn
`how to produce dynamic pages from thin air, how to modify real documents on
`the fly to produce effects like server—side includes, and how Apache interacts with
`the MIiv[F,—typing system to select which handler to invoke.
`
`to using the Apache Perl API exclusively for
`Starting with this chapter we shift
`code examples and function prototypes. The Perl AP] covers the majority of what
`C programmers need to use the Glanguage AP]. What’s missing are various mem-
`ory management functions that are essential to C programmers but irrelevant in
`Perl. If you are a C programmer, just have patience and the missing pieces will be
`filled in eventually. In the meantime, follow along with the Perl examples and
`
`enjoy yourself. Maybe you’ll even become a convert.
`
`Content Handlers as File Processors
`
`Early web servers were designed as engines for transmitting physical files from the
`host machine to the browser. Even though Apache does much more,
`the file-
`oriented legacy still
`remains. Files can be sent
`to the browser unmodified or
`passed through content handlers to transform them in various ways before send-
`
`ing them on to the browser. Even though many of the documents that you pro-
`
`duce with modules have no corresponcling physical files, some parts of Apache
`
`still behave as if they did.
`
`translation
`is passed through any URI
`When Apache receives a request, the URI
`handlers that may be installed (see Chapter 7. Other Reqtiesr Pbases, for informa-
`tion on how to roll your own),
`transforming it
`into a file path. The mool_czlz'as
`translation handler (compiled in by default) will first process any Al-m'.s‘, SCripfAZias,
`
`4
`
`

`
`
`
`86 Chapter 4: Content Hcmdlers
`
`Redirect, or other nzon.’_ctf:fczs directives. If none applies, the br1;D_core default trans-
`lator will simply prepend the Doctrmemffeoot directory to the beginning of the URI.
`
`Next, Apache attempts to divide the file path into two parts: a “filename” part
`which usually (but not always) corresponds to a physical file on the host’s filesys-
`tem, and an “additional path information” part corresponding to additional stuff
`that follows the filename. Apache divides the path using a very simple-minded
`algorithm. It steps through the path components from left to right until
`it finds
`something that doesn’t correspond to a directory on the host machine. The part of
`the path up to and including this component becomes the filename, and every-
`thing that’s left over becomes the additional path information.
`
`Consider a site with a document root of /bome/www that has just received a
`
`request for URI /abt:/n.'e_/'/gbi. The way Apache splits the file path into filename and
`path information parts depends on what directories it finds in the document root:
`
`Physical Directory
`/!.2rJrn.e/www
`
`| Translated Filename
`/borne/wwttt/cu'JC
`
`Additional Path Information
`/cI.'ej7glJi
`
`/home/www/ctbc
`
`/bome/tttwttfictbc/def
`
`/gbi
`
`
`
`
`
`
`
`/home/www/abc/de/'
`
`/bome/www/ctbe/ale/Kg/J1'
`
`
`
`/br)me/tttuzttmbc/cieflgbi
`
`//Jome/wtuttfictlztc/dcflglsti
`
`empty
`
`
`e mpty
`
`Note that the presence of any actual files in the path is irrelevant to this process.
`The division between the filename and the path information dep~‘ends only on
`
`what directories are present.
`
`it determines what MIME
`Once Apache has decided where the file is in the path,
`type it might be. This is again one of the places where you can intervene to alter
`the process with a custom type handler. The default type handler (moa.’_-mime) just
`compares the filename’s extension to a table of MIME types. If there’s a match, this
`becomes the MIME type. If no match is found, then the MIME type is undefined.
`Again, note that
`this mapping from filename to MIME type occurs even when
`there’s no actual file there.
`
`There are two special cases. If the last component of the filename happens to be a
`physical directory, then Apache internally assigns it a “magic" MIME type, defined
`by the DIR_MAGIC_TYPE constant as bt‘tpd/unix-directory. This is used by the
`directory module to generate automatic directory listings. The second special case
`occurs when you have the optional m0a'Hmz'me_magz'c module installed and the
`file actually exists. In this case Apache will peek at the first few bytes of the file’s
`contents to determine what type of file it might be. Chapter 7' shows you how to
`write your own MIME type checker handlers to implement more sophisticated
`
`MIME type determination schemes.
`
`
`
`h-T-‘l~n.v-:I»:';_t::.'«3.«r.
`
`5
`
`

`
`7
`
`Coflrerrt Iilcmdlers as File [’roce.x'so-rs
`
`87
`
`After Apache has determined the name and type of the file referenced by the lllll,
`i[ decides what to do about it. One way is to use information hard—wired into the
`modules static data structures. The :nodule’s handle-r_rec table, which we
`describe in detail in Chapter ll"), CAP! Re/erertce Gtride, Part I, declares the mod-
`ule’s willingness to handle one or more tu;t§_{ic MIME types and associates a con-
`[ent handler with each one. For example,
`the mod_cgt' module associates MIME
`type 5rj)])z.'t'ccm'o'rz/:c—i9trg0a’—cgf with its
`cgf_/.m1m’fei~() handler subroutine. When
`Apaclie detects that a filename is of type crpp.lr'ecm'orrKr—bItp.cl—.:'gif it
`invokes egL'_
`]g(1i’£6.l/8?'(_) and passes it inl’ormation about the file. A module can also declare it.s
`desire to handle an ordinary MIME type. such as £'l'Cl’(30/c]llfCrl?!I'?l‘l(3. or even a wild-
`Cdrd type, such as video/*. In this case, all requests for [Fills with matching MIME
`types will be passed through the modules content handler unless some other
`module registers a more specific type.
`
`Newer modules use a more flexible method in which content handlers are associ-
`ated with files at runtime using explicit names. When this method is used,
`the
`
`module declares one or more content handler names in its handler_rec array
`instead of", or in addition to,
`l\/llMF.
`types. Some examples of content handler
`names you might have seen include cgi—5ci-apt, seruer—:frt_./O, sert.»ei'—pmsed,
`r'map¢/2'19,
`and pe7‘l—5crr;DI. Handler names can be associated with files using either Add]-Ian"
`dler‘ or 5etHcmdZer directives. Aa.'dHa'rza.’lei-‘ associates a handler with a particular
`
`file extension. For example, a typical configttration file will contain this line to
`associate sbrml files with the server-side include handler:
`
`Addfiandler server—parsed .shtm1
`
`Now, the server-parseci handler defined by rrroc2.’_:'nclude will be called on to pro-
`cess all files ending in “.shtm1" regardless of their MIME type.
`
`SeIHcmdl.’er is used within <Directo2y>, <f.occm'on>, and <F:'/'es> sections to associ-
`
`ate a particular handler with an entire section of the site's URI space. In the two
`examples that follow, the <L0ccm'on> section attaches the se-ruer—par5ea’ method to
`all files within the virtual directory /sbrml, while the <Files> section attaches i'map—
`
`flle to all files that begin with the prefix “map—”:
`
`<Location /shtml>
`SetHand1er server—parsed
`</Location>
`
`<Files map—*>
`SetHandler imap—file
`</Files>
`
`the Acicihlczrzcilei" and Set!-Imrcller directives are not actually imple-
`Surprisingly,
`mented in the Apache core. They are implemented by the standard mod_actz'orts
`
`6
`
`

`
`
`
`(Jrapter 4: (jrmtent Haridlem
`88
`4a______4,______c_______.________d_____________,____._____s._______#__________H
`
`module, which is compiled into the server by del’aul1. In Chapter 7, we show how
`to reimplement mocI'_ctcti'o'rzs using the Perl API.
`
`to use explicitly named content handlers in your modules
`You'll probably want
`rather than hardcoded MIME types. Explicit handler names malte configuration
`iiies cleaner and easier to understand. Plus, you don't have to invent a new magic
`i\/IIMl*". t.ype every time you add a handler.
`
`Things are slightly dil"t'erent for moa'_pen’ users because two directives are needed
`to assign a content handler to a directory or tile. The reason For this is that the
`only real content handler defined by moc£_pen'
`is its internal pe-n’—sc:rtTpt handler.
`You use SetHan.dler to assign per1—sc1‘i'p! the respmisibility for a directory or partial
`URI, and then Lise a Pen.’Hcmdler directive to tell the pen.’—scri?pt handler which Perl
`module to execute. Directories supervised by Perl AP! content handlers will look
`
`something like this:
`
`<Location /graph>
`Setflandler per1—script
`PerlHandler Apaehe::Graph
`</Location>
`
`Don't tiy to assign per!'—5crt'pr to a file extension using something like AddHa.nd1er
`perl—seript .131;
`this is generally useless because you’d need to set PerlHcm—
`dler too. If you'd like to associate a Perl content handler with an extension, you
`should use the <Fz'les> directive. Here’s an example:
`
`<Files ~ "\.graph$">
`SetHandler per1»script
`Per1Handler Apache::Graph
`4/Fi1es>
`
`There is no U2'zSetHand!ei' directive to undo the effects of SeIHcma.'ler. However,
`should you ever need to restore a subdirectory‘s handler to the default, you can
`do it with the directive Setj-Iandler defau1t:—handler, as follows:
`
`<Location /graph/tutorial>
`SetHandler default—handler
`</Location>
`
`Adding oz Canned Footer to Pages
`
`To show you how content handlers work, we’ll develop a module with the Perl
`API that adds a canned footer to all pages in a particular directory. You could use
`this, for example,
`to automatically add copyright iiitoi‘1i121tioi1 and a link back to
`the home page. Later on, well turn this module into a l"ull—t’eatured navigation bar.
`
`Example 4-1 gives the code for Apache.-.-Footer, and Figure 4-—1 shows a screenshot
`of it in action. Since this is our first substantial module, we‘ll step through the code
`
`section by section.
`
`7
`
`

`
`V
`
`Content" Hcmdlers as File Processors
`
`File
`
`Edit View
`
`Go
`
`Bookmarks Options
`
`Directory
`
`Window
`
`Reload lxsaci !t1t—atces 0 en... "Print... Fin
`Ed't
`Wu!-Jackl Ftrwartil Home’
`l__.......-E__| __JP _
`_ .
`,..'_l
`l
`.
`‘
`i
`E
`Location: ttp : //l ocal hostffoote rfdemo. html
`
`This page contains a" canned footer
`
`The two lines at the bottom of this page aren't in the original source. code, but were
`added by .€=.::acl1e::l7oor.:'-.r
`
`© 1998 -.'."'Rt-iii}! 3.: A.\‘soc.iates
`Last Moe’! ted: Wedzlpr 8 07:48:04 1998
`
`Fz'gu.-re 4-1.
`
`'Ill)tJ_fl)()!(:‘I‘ on Ibis page ZU'.CIS generatecl cl-Ltftjfficllfccilb.’ by Apache.-:Foo!ei'.
`
`package Apache: :Foot:er;
`
`use strict;
`
`use Apache: :Constants qwtzcommonl;
`use Apache::File (l;
`
`The code begins by declaring its package name and loading various Perl modules
`that
`it depends on. The use strict pragma activates Perl checks that prevent us
`from using global variables before declaring them, disallows the use of function
`calls without
`the parentheses,
`and prevents other unsafe practices. The
`Apczc/ye.-.-Cortsianrs module defines constants for the various Apache and H’I”I‘P
`result codes; we bring in only those constants that belong to the frequently used
`.-common? set. Apczcbe.-.-File defines methods that are useful for manipulating files.
`
`sub handler {
`my $r : shift;
`return DECLINED unless Sr->content_type() eq ‘text/html‘;
`
`The bcma.’/er() subroutine does all the work of generating the content. It is roughly
`
`divided into three parts. In the first part, it fetches information about the requested
`file and decides whether it wants to handle it. In the second part,
`it creates the
`
`canned footer dynamically from inforination that it gleans about the file. In the
`third part,
`it rewrites the file to include the footer.
`
`In the first part of the process, the handler retrieves the Apache request object and
`
`stores it
`in $r. Next
`it calls the requests cortIenI_rype() method to retrieve its
`MIME type. Unless the document is of type text/brml, the handler stops here and
`returns a DECLINED result code to the server. This tells Apache to pass the
`
`8
`
`

`
`
`
`90 Chapter‘ 4: Content .Hrmdlers
`
`document on to any other handlers that have declared their willingness to handle
`this type of document. In most cases, this means that the document or image will
`he passed through to the browser in the usual way.
`
`
`
`my Sfile = $r—>filename;
`
`{
`unless (ee Sr—>finfo)
`$re>1og_error(“File does not exist: Sfile");
`return NOT_FOUND;
`
`} u
`
`}
`
`nless (rr _)
`
`{
`
`$r—>log_error("File permissions deny access: Sfile");
`return FORBIDDEN;
`
`At this point we go ahead and recover the file path, by calling the request 0bject’s
`fl'lerta:tne() method. just because Apache has assigned the document a MIME type
`doesn’t mean that it actually exists or,
`if it exists, that its permissions allow it to be
`read by the current process. The next two blocks of code check for these cases.
`Using the Perl —e file test, we check whether the file exists. If not, we log an error
`to the server log using the request objects i.'og_error() method and return a result
`code of NOT_FOUND. This will cause the server to return a page displaying the
`404 “Not Found” error (exactly what's displayed is under the control of the Error-
`Docmnenl directive).
`
`There are several ways to perform file status checks in the Perl API. The simplest
`way is to recover the file’s pathname using the request object’s filemzme() method,
`and pass the result to the Perl -2 file test:
`
`unless (—e $r~>fi1ename)
`
`{
`
`$r~>log_error("File does not exist: Sfile“);
`return NOT_FOUND;
`
`}
`
`A more efficient way, however, is to take advantage of the fact that during its path
`walking operation Apache already performed a system smr() call to collect filesys-
`tem information on the file. The resulting status structure is stored in the request
`object and can be retrieved with the objects ‘/IrTry"0() method. So the more efficient
`idiom is to use the test —e $r—>finfo.
`I
`
`file-
`the 5tat() information is stored into the magic Perl
`Once fz'rzfo() is called,
`handle _ and can be used for subsequent file testing and statO operations, saving
`even more CPU time. Using the _ filehandie, we next test that the file is readable
`by the current process and return FORBIDDEN if this isn’t the case. This displays a
`405 “Forbidden" error.
`
`my $modtime = loealtime((stat _)[9]);
`
`9
`
`

`
`(.0H“;-,1-,v,.r. 1m-rzctlers as File Processors
`
`9!
`
`Wm. performing these tests, we get the file moclillcation time by calling sIat(). We
`in L193 the _ filehandle here too, avoiding the overhead of repeating the stat()
`‘M
`.y_;1L.[n call. The modification time is passed to the burlt—m Perl 1oca.r.’rzme() func-
`s -
`_
`mm U) eonvert it into a ht1man—readable string.
`my Sfhi
`{
`unless (Sfh = Apache::File+>new{$file)l
`$rA>log_error("Couldn't open $file for reading: $1");
`return SERVEILERROR;
`
`}
`
`Ar this point, we attempt to open the file for reading using Apache.-.~File’s nc-'w(')
`method. For the most part, Apache.-.-File acts just like Perl's IO.-.-File object—oriented
`[/0 package, returning a filehandle on success or nrzdcg/" on failure. Since we've
`already handled the two failure modes that we know how to deal with, we return
`a result code of SERVER_ERROR if the open is unsuccesslul. This immediately
`;1h()t‘[S all processing of the document and causes Apache to display a 500 “Inter-
`nal Server Error” message.
`
`my Sfooter = <<END;
`
`<hr>
`
`&copy; 1998 <a href=“http://www.ora.com/”>O‘Rei11y &amp; Associates</a><br>
`<em>Last Modified: $modtime</em>
`END
`
`Having successfully opened the file, we build the footer. The footer in this
`example script is entirely static, except For the document rnodification date that is
`computed on the fly.
`
`$r—>send_http_header;
`
`{
`while (<$fh>)
`s1(</BODY>)!$footer$1!oi;
`} continue {
`$r->print ( $_) .-
`
`}
`
`The last phase is to rewrite the document. First we tell Apache to send the HTTP
`header. There’s no need to set the content type first because it already has the
`
`looking for the closing
`appropriate value. We then loop through the document
`</l3OD‘Y'> tag. When we find it, we use a substitution statement to insert the footer
`in front of it. The possibly modified line is now sent to the browser using the
`
`request object’s pr-*z.'m() method.
`
`return OK;
`
`10
`
`10
`
`

`
`
`
`92 Chapter 4: Content Handlers
`
`
`
`At the end, we return an OK result code to Apache and end the handler subrou-
`tine definition. Like any other .pm file, the module itself must end by returning a
`true value (usually 1) to signal Perl that it compiled correctly.
`
`lx
`llu
`l
`
`If all this checking for the existence and readability of the file before processing
`seems a bit pedantic, don’t worry.
`It’s actually unnecessary for you to do this.
`Instead of explicitly checking the file, we could have simply returned DECLINED if
`the attempt to open the file failed. Apache would then pass the URI to the default
`file handler which will perform its own checks and display the appropriate error
`messages. Therefore we could have replaced the file tests with the single line:‘
`
`my $fh = Apache::File—>new($file)
`
`|| return DECLINED;
`
`Doing the tests inside the module this way makes the checks explicit and gives us
`a chance to intervene to rescue the situation. For example, we might choose to
`
`search for a text file of the same name and present it instead. The explicit tests
`also improve module performance slightly, since the system wastes a small amount
`of CPU time when it attempts to open a nonexistent file. If most of the files the
`module serves do exist, however, this penalty won’t be significant.
`
`
`
`
`
`,_:__....i..,._.........._._...._._.........._...._._...._.._.,._,_,.,.__...,.,,........-4......-.s..........,.....,,.._._-__
`
`
`
`
`
`
`
`Example 4-]. Adding oz Cmmed Footer to H771/II. Pages
`
`package Apache::Footer;
`# file: Apache/Footer.pm
`
`use strict;
`use Apache::Constants qw(:comon);
`use Apache::File ();
`
`sub handler {
`
`my Sr = shift;
`return DECLINED unless $r—>content_type() eq ‘text/html';
`
`my $fi1e = $r—>fi1ename;
`
`unless (—e $r—>finfo)
`
`{
`
`$r—>1og_error(“File does not exist: Sfile");
`return NOT_FOUND;
`
`} u
`
`{
`nless (-r _)
`$r->log_error("File permissions deny access: $fi1e");
`return FORBIDDEN ;
`
`} m
`
`y smodtime = 1oca1time((stat _)[9]);
`
`my $fh;
`{
`unless ($fh = Apache::File->new($file))
`$r—>log_error("Couldn't open $file for reading: $2");
`return SERVER_ERROR;
`
`11
`
`11
`
`

`
`1i'\.'m7'zple 4-1. .4ctcl'z'i-rig oi (,'cn'mea.' 1'?'rm!er Io lI'!_ila’1.l’c£gc.x' (C()I1HI1Ii'(’(U
`my Sfooter = <<END;
`4'11-">
`&Copy; 1998 <a href=">http://www.0ra.C0m/“>O'Rei1ly &amp; Associates</a><br>
`<em>Last Modified: $m0dtime</em>
`END
`
`Sr->send_http_header;
`
`while (<$fh>)
`
`t
`
`s!{</BODY>)!$footer$1loi;
`} continue [
`$r—>print($_);
`
`} r
`
`eturn OK;
`
`END _
`
`} 1
`
`;
`
`There are several ways to install and use the Apcmbe.-.-Footer content handler. If all
`the files that needed footers were _<_=,atl1ei‘ed in one place in the directory tree, you
`would probably want to attach xlpczc/2e.~.-Footertr) that location:
`
`<Location /footer>
`
`SetHandler per1~script
`Perlfiandler Apache::Footer
`</Location>
`
`If the files were scattered about the document tree, it might be more convenient to
`map Apache.-.-Footer to a unique iilename extension, such as footer: To achieve
`this, the following directives would stiliice:
`
`.footer
`AddType text/html
`<Fi1es ~ "\.footer$“>
`
`SetHandler perl—seript
`Perlfiandler Apache::Footer
`</Fi1es>
`
`Note that it's important to associate MIME type text‘/btrnl with the new extension;
`otherwise, Apache won’t be able to determine its content type during the MIME
`
`type checl<ing phase.
`
`If your server is set up to allow per—directory access control files to include file
`information directives, you can place any of these handler directives inside a brac-
`cess file. This allows you to change handlers without restarting the server. For
`example, you could replace the <£ocaH'o1'z> section shown earlier with a Jalaccess
`file in the directory where you want the footer module to be active:
`
`Setflandler perl—script
`Per1Handler Apache::Footer
`
`12
`
`12
`
`

`
`
`94
`Cbczpter 4." Content 1—Irmd1'ers
`
`A Server-Sz'cz’e Include System
`
`The obvious limitation of the Apac/:1e:.-Footer example is that
`
`the footer text
`
`is
`
`hardeoded into the code. Changing the footer becomes a nontrivial task, and using
`
`different footers for various parts of the site becomes impractical. A much more
`flexible solution is provided by Vivek Khera’s Apacl9e:.-5mzdwr'cb module. This
`module “sandwiches" HTML pages between canned headers and footers that are
`
`determined by runtime configuration directives. The Apache.-.-Sandrutcb module
`also avoids the overhead of parsing the request document; it simply uses the sub-
`
`request mechanism to send the header, body, and footer files in sequence.
`
`than Apache.-.-Srmdwicb by using server-side
`We can provide more power
`includes. Sewer—side includes are small snippets of code embedded within HTML
`
`in the standard server—side includes that are imple-
`comments. For example,
`mented in Apache, you can insert the current time and date into the page with a
`comment that looks like this:
`
`Today is <!——#echo var="DATEfiLOCAL"——>.
`
`In this section, we Lise mod_pen.'
`
`to develop our own system of server—side
`
`includes, using a simple but extensible scheme that lets you add new types of
`includes at a moment’s whim. The basic idea is that HTML authors will create files
`
`that contain comments of this form:
`
`<!--#DIREC'TIE PARAM1 PARAM2 PARAM3 PARAM4.. .-—>
`
`A directive name consists of any sequence of alphanumeric characters or under—
`
`scores. This is followed by a series of optional parameters, separated by spaces or
`
`commas.
`
`’arameters that contain whitespace must be enclosed in single or dou-
`
`ble quotes in shell command style. Backslash escapes also work in the expected
`manner.
`
`The directives themselves are not hardcoded into the module but are instead
`
`dynamically loaded from one or more configuration files created by the site
`administrator. This allows the administrator to create a standard menu of includes
`
`that are available to the site’s HTML authors. Each directive is a short Perl subrou-
`
`tine. A simple directive looks like this one:
`
`sub HELLO { “Hello Worldl“:
`
`}
`
`This defines a subroutine named HELLOO that returns the string “Hello World!" /\
`
`document can now include the string in its text with a comment formatted like this
`one:
`
`I said <1-—#HLLO——>
`
`A more complex subroutine will need access to the Apache object and the server-
`
`side include parameters. To accommodate this, the Apache object is passed as the
`
`first function argument, and the server—side include parameters,
`
`if any,
`
`follow.
`
`13
`
`13
`
`

`
`
`
`Cgflfeilf Handlers as File PI”'0CBSS0l‘S 95
`
`Here’s a function definition that returns any field from the incoming request’s
`HTTP header, using the Apache object's /9ecm,’er'_m() method:
`
`sub HTTP_HEADER {
`my (Sr,$field) = @_;
`$r—>header_in($field);
`
`}
`
`‘xx’/ith this subroutine definition in place, HTML authors can insert the [fser—Agr3m
`
`iield into their document using a comment like this one:
`
`You are using the browser <!—— #HTTP_HEADER User—Agent ——>_
`
`Example 4-2 shows an HTML file that uses a few of these includes, and Figure 4-2
`shows what the page looks like after processing.
`
`Exmnple 4-2. /in HTML File 7736!! U.\'es Exiertdea’ .S‘ei‘iier—_S‘i'cfe lnclmles
`
`<html> <head> <title>Server—Side Includes</title></head>
`(body bgcolor=white>
`<h1>server—Side Inc1udes</h1>
`This is some straight text.<p>
`
`This is a "<!—— #HELLO ——>"
`
`include <p>
`
`The file size is <strong><!—— #FSIZE ——></strong>, and it was
`last modified on <i—— #MODTIME %x ——><p>
`
`Today is <!—— #DATE "%A,
`
`in <em>anno domini</em> %Y“——>.<p>
`
`The user agent is <em><!~~#HTTP_HEADER User—Agent——></em>.<p>
`
`Oops: <!——#OOPS O——><p>
`
`Here is an included file:
`<pre>
`<!——#INCLUDE /include.txt l——>
`
`</pre>
`
`<!——fiFOOTER——>
`
`</body> </html>
`
`Implementing this type of server—side include system might seem to be something
`of a challenge, but in fact the code is surprisingly compact (Example 4-3). This
`module is named Apache.-.-E551, for “extensible serve1'—side includes.”
`
`Again, we’ll step through the code one section at a time.
`
`package Apache::ESSI;
`
`use strict;
`
`use Apache::Constants qw(:comon);
`use Apache::File ();
`use Text::ParseWords qw(quoteword5);
`my (%MODIFIED, %SU'BSTITUTION);
`
`14
`
`14
`
`

`
`
`
` 96 Chapter 4': Contem Hmzrliers
`
`e: Server-Side Includes -
`Netsc
`Baal-crnarks Options Directory Window
`Edit View (in
`
`iiarunmii Home}
`Edit]
`Reload] mad ll'i't(i{_[('ESl 0pen...l PrinL.;|
`
`File
`
`Bankl
`
`.1
`
`I-‘It
`
`
`
`Location:
`.. _.-..,,->,e. .._
`
`oca'|hast;'test.ehtml
`,-,o....._..._..._.._.._..........-.
`
`.._..
`
`Serve-1‘— Side Includes
`
`This is some straight text.
`
`This is a "Hello World!" include.
`
`Thefilesizeis59?bytes,anditwaslastmodifiedonU4./18;"98
`
`Today is Saturday, in arms domains" 1998.
`
`The user ag-_ent is Mazaffas/3.01Go!d(X3l,'f;Lemax 2. 0.33 .1585).
`
`Oops: flffegczi r:£e'vz'sz'c:rz fiy zero at/zzsrlfzome/immu/cor1fi’essz'.defs (me 45, chzuaflr 24. j
`
`Hereisanineludedfile:
`
`7 —»
`
`
`
`i III 1
`
`\
`
`I
`
`
`
`the quick brown fox jumps over the sleeping dog
`
`J
`to 1993 -_?_i?gilli3 Associates
`Last iivforlzfieti: Sm.‘ Apr E6’ 0?:50:57 1998‘
`-. __.._____._._.__:_+.,..........__._.-.,‘#.__._..______. .w.7 ,, __ e-._.__,,,,,,,.
`
`'
`
`.3-R;
`
`F£gr,r.i'e 4-2. /1 pugegeizenzited by /lj.'J6£C/J8.‘.'}L'55I
`
`We start as before by declaring the package name and loading various Perl libraiy
`modules. in addilion to the modules that we loaded in the Apache.-.-Footer‘ exznn—
`ple, we import the quoIewom's() function from the standard Perl Text.-.-Parsell’/ora’5
`module. This routine provides command shell—~like parsing of strings that coniain
`quote marks and backslash escapes. We also define two lexical variables,
`%MODIFIED and %SUBSTITUTION, which are global to the package.
`
`sub handler {
`
`my $r = shift;
`return DECLINED;
`$r—>cor1t;ent_type() eq ‘text/html'
`my $fh 2 Apache::E'ile—>new($r—>filename)
`return DECLINED;
`my Ssub = read_definit:ions($r)
`|
`i return SERV'E:R_ERROR;
`$ 1: —> ser1d_ht tp_header;
`$r->print($sub->($r, $fh)):
`return OK ;
`
`15
`
`15
`
`

`
`C0f£f8fll'1'1'(£?’l(UG?'S as File Processors
`
`‘)7
`
`in the /lpcrcbe;-/*'oorer example,
`subroutine is quite short. As
`The f.?C£i’iC£'f€‘.*‘(V)‘
`,{7gti'idler(') starts by examining the content type of the document being requested
`and declines to handle requests for non—i‘l'l'l‘vlL documents. The handler recovers
`the file's physical path by calling the request object's _/i‘i’ei'icime() method and
`attempts to open it. if the file open fails, the handler again returns an error code oi’
`DECLINED. This avoids Apcidie.-:Fooi'ei"‘s tedious checking of the file's existence
`and access permissions, at the cost of some efficiency every time a nonexistent file
`
`is requested.
`
`Once the file is opened, we call an internal function named reaci'_a’cf/iirii'ii'oris().
`This function reads the server—side includes configuration file and generates an
`;1n()l'1}’ITl()Ll.‘~i subroutine to do the actual processing of the document.
`If an error
`occurs while processing the configuration file,
`'I'(36£Cf__£fi:f/fl’!.fff()}1S() returns irrza,'cff
`and we return SE:RVER__ERROR in order to abort the transaction. Otherwise, we
`send the I-ITTP header and invoke the anonymous subroutine to perform the sub-
`
`stitutions on the contents of the file. The result of invoking the subroutine is sent
`to the client using the request objects prmr() method, and we return a result code
`of OK to indicate that everything went smoothly.
`
`sub reac1_deEiniti0ns {
`my Sr = shift;
`my Sdef 2 $r~>c3ir_c:onfig( 'ESSIDefs' );
`return unless Sdef;
`return unless —e
`($def = $r—>server__root_relat;ive{$def));
`
`Most of the interesting work occurs in i'ecic£_dc{/ii'1i£ioiis(). The idea here is to read
`the server—side include definitions, compile them, and then Lise them to generate
`
`in order to avoid
`an anonymous subroutine that does the actual substitutions.
`recompiling this subroutine unnecessarily, we cache its code reference in the
`package variable %SUBS'I‘ITUTION and reuse it if we can.
`
`subroutine begins by retrieving the path to the file that
`The f€CI6?L6fE"fl!'??l.[;f0T!$()
`contains the server—side include definitions. This information is contained in a per-
`
`in the configura—
`tlirectoiy configuration variable named ESSIDefs, which is set
`tion file using the PerlSerl/‘ctr directive and retrieved within the handler with the
`request objects a’i'r_co'rifz'g() method (see the end of the example for a representa-
`tive configuration file entry).
`If,
`for some reason,
`this variable isn‘t present, we
`return imdef Like other Apache configuration files, we allow this file to be speci-
`fied as either an absolute path or a partial path relative to the server root. We pass
`the path to the request object’s serue7;rooi_r‘e!at:.'ue(_) method. This convenient
`function prepends the server root
`to relative paths and leaves absolute paths
`alone. W/e next check that the file exists using the -9 file test operator and return
`
`Lmdefif not.
`
`return $SUBSTITUTION{$def} if $MODIFIED{$def} && SMODII-‘IED{$def} <= —M
`
`;
`
`16
`
`16
`
`

`
`
`
`98 C'l.mpter 4'.‘ Content l—L:mcl!e2's
`
`Having recovered the name of the definitions file, we next check the cache to see
`
`whether the subroutine definitions are already cached and,
`
`if so, whether the file
`
`hasn’t changed since the code was compiled and cached. We use two hashes for
`
`this purpose. The %SUBSTI'I'UTION array holds the compiled code and %I~/IODIFIED
`contains the modification date of the definition file the last time it was compiled.
`
`Both hashes are indexed by the definition file's path, allowing the module to han-
`dle the case in which several server—side include definition files are used for differ-
`
`ent parts of the document tree. if the modification time listed in %MODIFIED is less
`than or equal
`to the definition file’s current modification date, we return the
`cached subroutine.
`
`: ", #_PACKAGE__, $def;
`my $pae]-zage = join " :
`Spackage =~ tr/a—zA—ZD~9_/_/C;
`
`The next two lines are concerned with finding a unique namespace in which to
`compile the server—side include functions. Putting the functions in their own
`namespace decreases the chance that function side effects will have unwanted
`effects elsewhere in the module. We take the easy way out here by using the path
`to the definition file to synthesize a package name, which we store in a variable
`
`named $package.
`
`eval "package Spaekage; do ‘$def"';
`if($@l
`{
`
`$r—>log_error("Eva1 of $def did not return true: $@“);
`return;
`
`}
`
`We then invoke ez2al() to compile the subroutine definitions into the newly cho-
`sen namespace. We use the package declaration to set the namespace and do to
`load and run the definitions file. We use do here rather than the more common
`
`require because do unconditionally recompiles code files even if they have been
`loaded previously. If the em! was unsuccessful, we log an error and return imdejf
`
`$SUBS‘I‘ITUTION{$def} = sub {
`do_substitutions ($paekage, @_) ,-
`
`};
`
`$MODIFIED{$def} : —M $def;
`return $SUBSTITUTION[$def};
`
`# store modification date
`
`}
`
`Before we exit
`
`2“(2‘6lC?L6!‘E_’f1"."i7..'.-1'.fO1’I5(), we create a new anon

This document is available on Docket Alarm but you must sign up to view it.


Or .

Accessing this document will incur an additional charge of $.

After purchase, you can access this document again without charge.

Accept $ Charge
throbber

Still Working On It

This document is taking longer than usual to download. This can happen if we need to contact the court directly to obtain the document and their servers are running slowly.

Give it another minute or two to complete, and then try the refresh button.

throbber

A few More Minutes ... Still Working

It can take up to 5 minutes for us to download a document if the court servers are running slowly.

Thank you for your continued patience.

This document could not be displayed.

We could not find this document within its docket. Please go back to the docket page and check the link. If that does not work, go back to the docket and refresh it to pull the newest information.

Your account does not support viewing this document.

You need a Paid Account to view this document. Click here to change your account type.

Your account does not support viewing this document.

Set your membership status to view this document.

With a Docket Alarm membership, you'll get a whole lot more, including:

  • Up-to-date information for this case.
  • Email alerts whenever there is an update.
  • Full text search for other cases.
  • Get email alerts whenever a new case matches your search.

Become a Member

One Moment Please

The filing “” is large (MB) and is being downloaded.

Please refresh this page in a few minutes to see if the filing has been downloaded. The filing will also be emailed to you when the download completes.

Your document is on its way!

If you do not receive the document in five minutes, contact support at support@docketalarm.com.

Sealed Document

We are unable to display this document, it may be under a court ordered seal.

If you have proper credentials to access the file, you may proceed directly to the court's system using your government issued username and password.


Access Government Site

We are redirecting you
to a mobile optimized page.





Document Unreadable or Corrupt

Refresh this Document
Go to the Docket

We are unable to display this document.

Refresh this Document
Go to the Docket