home *** CD-ROM | disk | FTP | other *** search
- <!doctype linuxdoc system>
-
- <article>
-
- <!-- Title Information -->
-
- <title>How to add support for Apache modules under Comanche
- <author>Daniel Lopez Ridruejo, <tt/ridruejo@apache.org/
- <date>v0.1, 1 March 2000
-
- <!-- Abstract -->
- <abstract>
- This paper is a work in progress that documents the steps necessary to add support for
- configuring additional Apache modules with Comanche
- </abstract>
-
-
- <!-- Table of Contents -->
- <toc>
-
-
- <sect> Introduction
-
- <p>
-
- This documents gives detailed information of the steps involved in adding
- support for a new Apache module in Comanche (like PHP3, mod_ldap, etc.) or
- adding support for new directives.<p>
- Comanche is a framework to build management modules (plugins). There are
- plugins for Apache, Samba, etc. Since Apache is a complex program the
- plugin for Apache itself is modular and support for directives and modules is done via
- an extension mechanism. <p>
- The process is relatively simple. For most modules, you only have to write a few XML files
- following certain simple rules.
-
- <sect> What the Apache plugin needs to know from you
- <p>
-
- In order to add support for your module or directive the Apache plugin needs
- to know a few things.
-
- <itemize>
- <item>Where is your module located? :
- At plugins/apache/modules you can find current supported modules each one of
- them has a subdirectory which contains the necessary files
- <item>Which files are necessary to support your module? :
- <itemize>
- <item>moduleDescription.xml: Describes the module and gives pointers for the other files
- <item>directives.xml: Describes the directives that we are configuring
- <item>propertyPages.xml: Arrange the directives for presentation to the user
- <item>specialCases.tcl: For parsing complex directives back and forth between the
- XML format and httpd.conf format
- </itemize>
- </itemize>
-
-
- <sect1> moduleDescription.xml
- <p>
- <itemize>
- <item>Description of module: name, where to find directive and property pages
- definition, special cases definition and description of the module
- <item>Nodes in which we are interested: Which nodes (main server, virtual
- hosts, etc) we want our property pages to appear in
- <item>Description of special cases: Apache uses httpd.conf format and Comanche
- uses XML format. If the directives are simple, the mapping will be
- automagically done by Comanche, if not we specify the name of the procedures
- here
- </itemize>
-
- <sect1> specialCases.tcl
- <p>
- Actual Tcl code used to convert from XML format to httpd.conf
-
- <sect1>directives.xml
- <p>
- Description of the directives that belong to this module
-
- <sect1>propertyPages.xml
-
- <p>Description of the property pages for this modules. They are presented to
- the user during configuration. They arrange the directives on the screen
- logically. It is possible to have different versions for beginners and for
- advanced users.
-
-
- <sect1>messages
- <p>
- In the subdirectory messages/ the texts corresponding to the messages are
- stored there so they can easily be translated by other people. The messages
- are stored with a suffix corresponding to the language: messages.en, messages.es, etc.
-
-
- <sect> Step by step guide to create a module from scratch
- <p>
-
- The following is a detailed description of the necessary steps to add
- support for a module. We will add support for the PHP scripting language
- (<url name="http://www.php.net" url="http://www.php.net">).
-
-
- <sect1>Planning
- <p>
- We take a look at the configuration information for PHP:
- <url name="http://www.php.net/manual/configuration.php3" url="http://www.php.net/manual/configuration.php3">
- <p>
- As it turns out PHP can be configured in different ways, either inside the
- Apache httpd.conf file or in a separate file. The syntax varies too from
- PHP3 to PHP4. Since this is just an example, we will configure PHP3 for
- httpd.conf syntax. The user interface will remain unchanged among all of
- them, so to support the other versions we just need to change the
- translating functions since as can reuse the directive and property pages
- definitions.
- <p>
- One thing to remember is that we do not need to support all directives at
- once. Directives not known to Comanche are safely ignored and restored when
- writing the output configuration file. We can provide support for the most
- commonly used directives and then go for the more obscure parameters.
- <p>
- Before doing any coding we need to plan what the user interface is going to
- look like. We plan on having the following property pages:
- <p>
- <verb>
- PHP3 (Enable/disable and tags)
- |
- \__ Resources (Limit use if resources CPU/Time)
- |
- \__ Error Handling (Error logs, display, etc.)
- |
- \__ Data Handling (POST variables, prepend, autopend...)
- |
- \__ Paths (auto include directories)
- </verb>
- <sect1>Directive definition
- <p>
- Next step is to actually define the directives. The XML language used here
- is described in the programmer guide. It is really easy so you probably can
- pick it up just by taking a look at how the other modules are described.
- Most directives have a one to one correspondence, others will need more
- elaborated XML directives.
-
- <sect2>asp_tags
- <p>
- In the docs we find
-
- <verb>
- asp_tags boolean
-
- Enables the use of ASP-like <% %> tags in addition to the
- usual <?php ?> tags. This includes the variable-value printing shorthand of
- <%=$value %>. For more information, see Escaping from HTML.
- </verb>
- <p>
- It is clear that this maps directly into the XML boolean type so we write:
- <verb>
- <boolean name="php3_asp_tags" label="php_asp_tags">
- <default>0 &etago;default>
- &etago;boolean>
- </verb>
- <p>
- Name is php3_asp_tags because this is how it will appear on Apache config
- files. This way Apache already nows which httpd.conf directives match to
- which XML directives.
- <p>
- Instead of writting the description of the directive directly on the label
- we store the description in the messages/ subdirectory. The contents of the
- messages.en file:
- <verb>
- php_asp_tags {Enable ASP (<% %>) style tags?}
- </verb>
- If we want an additional Spanish version, we write (lenguage can be later on
- selected by the user)
- messages.es:
- <verb>
- php_asp_tags {Permitir tags como las de ASP (<% %>)?}
- </verb>
-
- <sect2>max_execution_time
- <p>
- This one, which accepts a number as an argument gets turned into
- <verb>
- <number name="php3_max_execution_time" label="php_max_execution_time">
- <default>30 &etago;default>
- &etago;number>
- </verb>
- with messages.en
- <verb>php_max_execution_time {Limit in execution time (seconds)} </verb>
-
-
- <sect2>doc_root
- <p>
- This one sets the document root for safe mode. This is a string, more
- precisely a directory, so the corresponding entry:
- <verb>
- <string name="php3_doc_root" label="php_doc_root" classes="directory" >
- <default> &etago;default>
- &etago;string>
- </verb>
- (note the classes attribute, it hints the gui to provide a directory selector
- button and to write back quoted directories with blank spaces)
-
- with messages.en:
- <p>
- php_doc_root {PHP root directory (for safe mode)}
- </p>
-
- <sect2>gpc_order
- <p>
- This one could have been modeled in a different way, but this ones works
- just fine at it is clear
- <verb>
- <choice name="php3_gpc_order" label="php_gpc_order">
- <syntax>
- <option name="GPC" value="GET/POST/COOKIE" />
- <option name="GCP" value="GET/COOKIE/POST" />
- <option name="PGC" value="POST/GET/COOKIE" />
- <option name="PCG" value="POST/COOKIE/GET" />
- <option name="CPG" value="COOKIE/POST/GET" />
- <option name="CGP" value="COOKIE/GET/POST" />
- <option name="GP" value="GET/POST" />
- <option name="GC" value="GET/COOKIE" />
- <option name="PG" value="POST/GET" />
- <option name="PC" value="POST/COOKIE" />
- <option name="CP" value="COOKIE/POST" />
- <option name="CG" value="COOKIE/GET" />
- <option name="G" value="GET" />
- <option name="P" value="POST" />
- <option name="C" value="COOKIE" />
- &etago;syntax>
- <default>GPC &etago;default>
- &etago;choice>
- </verb>
- messages.en:
- <verb>
- php_gpc_order {Order of GET/POST/COOKIE variable parsing}
- </verb>
- So far the mapping between httpd.conf and XML directives has been pretty
- straightforward. For the previous entries the conversion is handled
- automatically by Comanche and we do not need to do anything else!
- <p>
- Now comes the interesting part. It requires a little bit more of work but it
- pays off in a more easy to use interface for the user. There are some
- directives that could be better expressed in some other way.
- Take for example the directive auto_append_file (File to always parse
- after processing the main file). It can have a special value of 'none' to
- disable this feature. Instead of mapping it to a string and have the user
- know that piece of information we make it a little bit easier and provide
- a pair of radiobuttons. First one is simply 'none' the other is the name of
- the file.
- <p>
- This, translated to XML gets us:
- <verb>
- <alternate name="php3_auto_append_file" label="php_auto_append_file"
- style="normal">
- <syntax>
- <label name="none" label="php_auto_append_file_none" />
- <string name="file" label="php_auto_append_file_file" classes="file" />
- &etago;syntax>
- <default>none &etago;default>
- &etago;alternate>
- </verb>
- You get the idea. By default the 'none' element is selected.
-
- We need a way to convert from httpd.conf to this XML format and the other
- way around. This involves a little bit of programming, which is shown below
- <verb>
- # This procedure is called whenever the php3_auto_append_file is encountered
- # in httpd.conf
-
- proc ::apache1.3::parse_php3_auto_append_file {text parser dirDef xmlConf currentContainer} {
-
- # Create a new instance of this directive or overwrite the existing one
-
- set xuiObj [apacheparserutils::getOrCreateIfNotExists php3_auto_append_file \
- $dirDef $xmlConf $currentContainer]
-
- # Depending on the value (none or a filename), select the appropriate component and store the value
-
- set value [lindex $text 1]
- switch [string tolower $value] {
- none {
- $xuiObj selectComponentByName none
- } default {
- $xuiObj selectComponentByName file
- $xuiObj.file setValue $value
- }
- }
- }
-
-
- # Procedure called to dump the contents to httpd.conf
-
- proc ::apache1.3::dump_php3_auto_append_file {xuiObj} {
- set value [[$xuiObj getSelectedComponent] getValue]
- return "php3_auto_append_file $value"
- }
- </verb>
- Similar goes for php3_auto_prepend directive or php3_error_log
-
-
- <sect2>php3_include_path
- <p>
- This is another directive that would benefit of special treatment is
- php3_include_path (and php3_open_basedir)
-
- From the PHP docs:
- <verb>
- include_path string
-
- Specifies a list of directories where the require(), include() and
- fopen_with_path() functions look for files. The format is like the system's
-
- PATH environment variable: a list of directories separated with a colon in
- UNIX or semicolon in Windows.
-
- Example 3-1. UNIX include_path
-
- include_path=.:/home/httpd/php-lib
-
-
- Example 3-2. Windows include_path
-
- include_path=".;c:\www\phplib"
-
- The default value for this directive is . (only the current directory).
- </verb>
- Now we could map this directive to a string directive and hvae the user
- enter a string of directories separated by : or ; Instead we make it a
- little bit easier for them by abstracting it and presenting them with a list
- of directories.
- <p>
- The XML description:
- <verb>
- <list name="php3_include_path" label="php_include_path">
- <syntax>
- <string name="php3_include_path_file" label="php_include_path_file" classes="directory" />
- &etago;syntax>
- <default>
- <item>. &etago;item>
- &etago;default>
- &etago;list>
- </verb>
- We need now a couple of functions for converting from : or ; format
- (httpd.conf) to XML and viceversa.
- <verb>
- proc ::apache1.3::parse_php3_include_path {text parser dirDef xmlConf
- currentContainer} {
- set xuiObj [apacheparserutils::getOrCreateIfNotExists php3_include_path \
- $dirDef $xmlConf $currentContainer]
- global tcl_platform
- switch $tcl_platform(platform) {
- windows {
- set separator {;}
- } default {
- set separator :
- }
- }
- foreach element [split [lrange $text 1 end] $separator] {
- set child [$xuiObj newChild]
-
- # Split fscks up quoted filenames, so this is required
-
- regsub {\\\"} $element {"} result
- $child setValue $result
- $xuiObj insertChild $child
- }
- }
-
-
- proc ::apache1.3::dump_php3_include_path {xuiObj} {
- global tcl_platform
- switch $tcl_platform(platform) {
- windows {
- set separator {;}
- } default {
- set separator :
- }
- }
- set values {}
- foreach child [$xuiObj getChildren] {
- lappend values [$child getValue]
- }
- set result [join $values $separator]
- if [llength $result] {
- return "php3_include_path $result"
- }
- return {}
- }
- </verb>
-
- Once we have described all the directives (take a look at
- plugins/apache/modules/php3/directives.xml for a complete listing)
- We need to tell Comanche how do we want them organized in property pages
- (like in the tree described at the beginning)
-
- In plugins/apache/modules/php3/propertyPages.xml
-
- As an example, the main page:
- <verb>
- <propertyPage label="php3_pp_phpEngine" icon="smallWheel" name="pp_phpEngine" align="vertical">
- <directiveInclude name="php3_engine"/>
- <group name="php3_pp_phpEngine_tags"align="vertical"label="php3_pp_phpEngine_tags" style="normal">
- <directiveInclude name="php3_asp_tags"/>
- <directiveInclude name="php3_short_open_tag"/>
- &etago;group>
- &etago;propertyPage>
-
-
- Finally, the moduleDescription.xml puts everything together:
-
- <apacheModuleDescription name="php3"
- directivesXMLDefinition="directives.xml"
- propertyPagesXMLDefinition="propertyPages.xml"
- description="PHP3 Apache module." >
- <nodesInterested>
- <node type="mainserver,virtualhost">
- <propertyPage name="pp_phpEngine" />
-
- [...]
-
- <propertyPage name="pp_phpPaths" hookUnder="pp_phpEngine" />
- &etago;node>
- &etago;nodesInterested>
- <specialCases file="specialCases.tcl">
- <specialCase confDir="php3_open_basedir"
- xmlDir="php3_open_basedir"
- parser="apache1.3::parse_php3_open_basedir"
- dumper="apache1.3::dump_php3_open_basedir" />
-
- [...]
-
- &etago;specialCases>
- &etago;apacheModuleDescription>
- </verb>
- </article>