home *** CD-ROM | disk | FTP | other *** search
-
- Introduction
- ------------
-
- 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.
- Comanche is a framework to build management modules (plugins). There are
- plugins for Apache, Samba, etc. Since Apache is a complex program the
- plugin itself is modular and support for directives and modules is done via
- an extension mechanism.
- The process is relatively simple. You have to write a few XML files
- following certain simple rules and that's about it :)
-
- What the Apache plugin needs to know from you
- ---------------------------------------------
-
- In order to add support for your module or directive the Apache plugin needs
- to know a few things.
-
- * 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
-
- * Which files are necessary to support your module?
- moduleDescription.xml: Describes the module and gives pointers for the other files
-
- directives.xml: Describes the directives that we are configuring
-
- propertyPages.xml: Arrange the directives for presentation to the user
-
- specialCases.tcl: For parsing complex directives back and forth between the
- XML format and httpd.conf format
-
-
- moduleDescription.xml
- ---------------------
- * Description of module: name, where to find directive and property pages
- definition, special cases definition and description of the module
- * Nodes in which we are interested: Which nodes (main server, virtual
- hosts, etc) we want our property pages to appear in
- * 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
-
- specialCases.tcl
- ----------------
- * Actual Tcl code used to convert from XML format to httpd.conf
-
- directives.xml
- --------------
- * Description of the directives that belong to this module
-
- propertyPages.xml
- -----------------
- * 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.
-
-
- messages
- --------
- 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.
-
-
- Step by step guide to create a module from scratch
- --------------------------------------------------
-
- 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
- (http://www.php.net).
-
-
- Planning
- --------
- We take a look at the configuration information for PHP:
- http://www.php.net/manual/configuration.php3
-
- 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.
-
- 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.
-
- 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:
-
- 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)
-
-
- 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.
-
- * asp_tags
-
- In the docs we find
-
- "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."
-
- It is clear that this maps directly into the XML boolean type so we write:
- <boolean name="php3_asp_tags" label="php_asp_tags">
- <default>0</default>
- </boolean>
-
- 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.
- 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:
- php_asp_tags {Enable ASP (<% %>) style tags?}
-
- If we want an additional Spanish version, we write (lenguage can be later on
- selected by the user)
- messages.es:
- php_asp_tags {Permitir tags como las de ASP (<% %>)?}
-
-
- * max_execution_time
-
- This one, which accepts a number as an argument gets turned into
-
- <number name="php3_max_execution_time" label="php_max_execution_time">
- <default>30</default>
- </number>
-
- with messages.en
- php_max_execution_time {Limit in execution time (seconds)}
-
-
- * doc_root
-
- This one sets the document root for safe mode. This is a string, more
- precisely a directory, so the corresponding entry:
-
- <string name="php3_doc_root" label="php_doc_root" classes="directory" >
- <default></default>
- </string>
-
- (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:
- php_doc_root {PHP root directory (for safe mode)}
-
- * gpc_order
-
- This one could have been modeled in a different way, but this ones works
- just fine at it is clear
-
- <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" />
- </syntax>
- <default>GPC</default>
- </choice>
-
- messages.en:
- php_gpc_order {Order of GET/POST/COOKIE variable parsing}
-
- 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!
-
- 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.
-
- This, translated to XML gets us:
-
- <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" />
- </syntax>
- <default>none</default>
- </alternate>
-
- 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
-
- # 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"
- }
-
- Similar goes for php3_auto_prepend directive or php3_error_log
-
-
- php3_include_path
- -----------------
- This is another directive that would benefit of special treatment is
- php3_include_path (and php3_open_basedir)
-
- From the PHP docs:
- 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).
-
-
- - 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.
-
- The XML description:
-
- <list name="php3_include_path" label="php_include_path">
- <syntax>
- <string name="php3_include_path_file" label="php_include_path_file" classes="directory" />
- </syntax>
- <default>
- <item>.</item>
- </default>
- </list>
-
- We need now a couple of functions for converting from : or ; format
- (httpd.conf) to XML and viceversa.
-
- 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 {}
- }
-
-
- 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:
-
- <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"/>
- </group>
- </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" />
- </node>
- </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" />
-
- [...]
-
- </specialCases>
- </apacheModuleDescription>
-