home *** CD-ROM | disk | FTP | other *** search
/ PC World 2000 December / PCWorld_2000-12_cd.bin / Komunikace / Comanche / docs / developer / apacheModule.sgml < prev    next >
SGML Document  |  2000-11-02  |  15KB

  1. <!doctype linuxdoc system>
  2.  
  3. <article>
  4.  
  5. <!-- Title Information -->
  6.  
  7. <title>How to add support for Apache modules under Comanche
  8. <author>Daniel Lopez Ridruejo, <tt/ridruejo@apache.org/
  9. <date>v0.1, 1 March 2000
  10.  
  11. <!-- Abstract -->
  12. <abstract>
  13. This paper is a work in progress that documents the steps necessary to add support for 
  14. configuring additional Apache modules with Comanche
  15. </abstract> 
  16.  
  17.  
  18. <!-- Table of Contents -->
  19. <toc>
  20.  
  21.  
  22. <sect> Introduction     
  23.  
  24. <p>
  25.  
  26. This documents gives detailed information of the steps involved in adding
  27. support for a new Apache module in Comanche (like PHP3, mod_ldap, etc.) or
  28. adding support for new directives.<p>
  29. Comanche is a framework to build management modules (plugins). There are
  30. plugins for Apache, Samba, etc.  Since Apache is a complex program the
  31. plugin for Apache itself is modular and support for directives and modules is done via
  32. an extension mechanism. <p>
  33. The process is relatively simple. For most modules, you only have to write a few XML files
  34. following certain simple rules.
  35.  
  36. <sect> What the Apache plugin needs to know from you
  37. <p>
  38.  
  39. In order to add support for your module or directive the Apache plugin needs
  40. to know a few things. 
  41.  
  42. <itemize>
  43. <item>Where is your module located? :
  44. At plugins/apache/modules you can find current supported modules each one of
  45. them has a subdirectory which contains the necessary files
  46. <item>Which files are necessary to support your module? :
  47. <itemize>
  48. <item>moduleDescription.xml:  Describes the module and gives pointers for the other files
  49. <item>directives.xml: Describes the directives that we are configuring 
  50. <item>propertyPages.xml: Arrange the directives for presentation to the user
  51. <item>specialCases.tcl: For parsing complex directives back and forth between the
  52. XML format and httpd.conf format
  53. </itemize>
  54. </itemize>
  55.  
  56.  
  57. <sect1> moduleDescription.xml
  58. <p>
  59. <itemize>
  60. <item>Description of module: name, where to find directive and property pages
  61. definition, special cases definition and description of the module
  62. <item>Nodes in which we are interested: Which nodes (main server, virtual
  63. hosts, etc) we want our property pages to appear in
  64. <item>Description of special cases: Apache uses httpd.conf format and Comanche
  65. uses XML format. If the directives are simple, the mapping will be
  66. automagically done by Comanche, if not we specify the name of the procedures
  67. here
  68. </itemize>
  69.  
  70. <sect1> specialCases.tcl
  71. <p>
  72. Actual Tcl code used to convert from XML format to httpd.conf
  73.  
  74. <sect1>directives.xml
  75. <p>
  76. Description of the directives that belong to this module
  77.  
  78. <sect1>propertyPages.xml
  79.  
  80. <p>Description of the property pages for this modules. They are presented to
  81. the user during configuration. They arrange the directives on the screen
  82. logically. It is possible to have different versions for beginners and for
  83. advanced users.
  84.  
  85.  
  86. <sect1>messages
  87. <p>
  88. In the subdirectory messages/ the texts corresponding to the messages are
  89. stored there so they can easily be translated by other people. The messages
  90. are stored with a suffix corresponding to the language: messages.en, messages.es, etc.
  91.  
  92.  
  93. <sect> Step by step guide to create a module from scratch
  94. <p>
  95.  
  96. The following is a detailed description of the necessary steps to add
  97. support for a module. We will add support for the PHP scripting language
  98. (<url name="http://www.php.net" url="http://www.php.net">). 
  99.  
  100.  
  101. <sect1>Planning
  102. <p>
  103. We take a look at the configuration information for PHP:
  104. <url name="http://www.php.net/manual/configuration.php3" url="http://www.php.net/manual/configuration.php3">
  105. <p>
  106. As it turns out PHP can be configured in different ways, either inside the
  107. Apache httpd.conf file or in a separate file. The syntax varies too from
  108. PHP3 to PHP4. Since this is just an example, we will configure PHP3 for
  109. httpd.conf syntax. The user interface will remain unchanged among all of
  110. them, so to support the other versions we just need to change the
  111. translating functions since as can reuse the directive and property pages
  112. definitions.
  113. <p>
  114. One thing to remember is that we do not need to support all directives at
  115. once. Directives not known to Comanche are safely ignored and restored when
  116. writing the output configuration file. We can provide support for the most
  117. commonly used directives and then go for the more obscure parameters.
  118. <p>
  119. Before doing any coding we need to plan what the user interface is going to
  120. look like. We plan on having the following property pages:
  121. <p>
  122. <verb>
  123. PHP3   (Enable/disable and tags)
  124.   |
  125.   \__ Resources (Limit use if resources CPU/Time)
  126.   |
  127.   \__ Error Handling (Error logs, display, etc.)
  128.   |
  129.   \__ Data Handling (POST variables, prepend, autopend...)
  130.   |
  131.   \__ Paths (auto include directories)
  132. </verb>  
  133. <sect1>Directive definition
  134. <p>
  135. Next step is to actually define the directives. The XML language used here
  136. is described in the programmer guide. It is really easy so you probably can
  137. pick it up just by taking a look at how the other modules are described.
  138. Most directives have a one to one correspondence, others will need more
  139. elaborated XML directives.
  140.  
  141. <sect2>asp_tags
  142. <p>
  143. In the docs we find
  144.  
  145. <verb>
  146. asp_tags boolean
  147.  
  148. Enables the use of ASP-like <% %> tags in addition to the
  149. usual <?php ?> tags. This includes the variable-value printing shorthand of
  150. <%=$value %>. For more information, see Escaping from HTML.
  151. </verb>
  152. <p>
  153. It is clear that this maps directly into the XML boolean type so we write:
  154. <verb>
  155. <boolean name="php3_asp_tags" label="php_asp_tags">
  156.     <default>0 &etago;default>
  157.  &etago;boolean>       
  158. </verb>
  159. <p>
  160. Name is php3_asp_tags because this is how it will appear on Apache config
  161. files. This way Apache already nows which httpd.conf directives match to
  162. which XML directives.
  163. <p>
  164. Instead of writting the description of the directive directly on the label
  165. we store the description in the messages/ subdirectory. The contents of the
  166. messages.en file:
  167. <verb>
  168. php_asp_tags {Enable ASP (<% %>) style tags?}
  169. </verb>  
  170. If we want an additional Spanish version, we write (lenguage can be later on
  171. selected by the user) 
  172. messages.es:
  173. <verb>
  174. php_asp_tags {Permitir tags como las de ASP (<% %>)?}
  175. </verb>
  176.  
  177. <sect2>max_execution_time
  178. <p>
  179. This one, which accepts a number as an argument gets turned into
  180. <verb>
  181. <number name="php3_max_execution_time" label="php_max_execution_time">
  182. <default>30 &etago;default>
  183.  &etago;number>         
  184. </verb>
  185. with messages.en
  186. <verb>php_max_execution_time {Limit in execution time (seconds)}  </verb>
  187.  
  188.  
  189. <sect2>doc_root
  190. <p>
  191. This one sets the document root for safe mode. This is a string, more
  192. precisely a directory, so the corresponding entry:
  193. <verb>
  194. <string name="php3_doc_root" label="php_doc_root" classes="directory" >
  195. <default> &etago;default>
  196.  &etago;string>
  197. </verb>
  198. (note the classes attribute, it hints the gui to provide a directory selector
  199. button and to write back quoted directories with blank spaces)
  200.  
  201. with messages.en:
  202. <p>
  203. php_doc_root {PHP root directory (for safe mode)}   
  204. </p>
  205.  
  206. <sect2>gpc_order
  207. <p>
  208. This one could have been modeled in a different way, but this ones works
  209. just fine at it is clear
  210. <verb>
  211. <choice name="php3_gpc_order" label="php_gpc_order">
  212.     <syntax>
  213.         <option name="GPC" value="GET/POST/COOKIE" />
  214.         <option name="GCP" value="GET/COOKIE/POST" />
  215.         <option name="PGC" value="POST/GET/COOKIE" />
  216.         <option name="PCG" value="POST/COOKIE/GET" />
  217.         <option name="CPG" value="COOKIE/POST/GET" />
  218.         <option name="CGP" value="COOKIE/GET/POST" />
  219.         <option name="GP" value="GET/POST" />
  220.         <option name="GC" value="GET/COOKIE" />
  221.         <option name="PG" value="POST/GET" />
  222.         <option name="PC" value="POST/COOKIE" />
  223.         <option name="CP" value="COOKIE/POST" />
  224.         <option name="CG" value="COOKIE/GET" />
  225.         <option name="G" value="GET" />
  226.         <option name="P" value="POST" />
  227.         <option name="C" value="COOKIE" />
  228.      &etago;syntax>
  229.     <default>GPC &etago;default>
  230.  &etago;choice>     
  231. </verb>
  232. messages.en:
  233. <verb>
  234. php_gpc_order {Order of GET/POST/COOKIE variable parsing}  
  235. </verb>
  236. So far the mapping between httpd.conf and XML directives has been pretty
  237. straightforward. For the previous entries the conversion is handled
  238. automatically by Comanche and we do not need to do anything else!
  239. <p>
  240. Now comes the interesting part. It requires a little bit more of work but it
  241. pays off in a more easy to use interface for the user. There are some
  242. directives that could be better expressed in some other way.
  243. Take for example the directive auto_append_file (File to always parse
  244. after processing the main file). It can have a special value of 'none' to
  245. disable this feature. Instead of mapping it to a string and have the user
  246. know that piece of information we make it a little bit easier and provide
  247. a pair of radiobuttons. First one is simply 'none' the other is the name of
  248. the file. 
  249. <p> 
  250.  This, translated to XML gets us:
  251. <verb> 
  252.  <alternate name="php3_auto_append_file" label="php_auto_append_file"
  253.             style="normal">
  254.     <syntax>
  255.         <label name="none" label="php_auto_append_file_none" />
  256.         <string name="file" label="php_auto_append_file_file" classes="file" />
  257.      &etago;syntax>
  258.     <default>none &etago;default>
  259.  &etago;alternate>     
  260. </verb>    
  261.  You get the idea. By default the 'none' element is selected.
  262.  
  263. We need a way to convert from httpd.conf to this XML format and the other
  264. way around. This involves a little bit of programming, which is shown below
  265. <verb>
  266. # This procedure is called whenever the php3_auto_append_file is encountered
  267. # in httpd.conf
  268.  
  269. proc ::apache1.3::parse_php3_auto_append_file {text parser dirDef xmlConf currentContainer} {
  270.  
  271.     # Create a new instance of this directive or overwrite the existing one
  272.     
  273.     set xuiObj [apacheparserutils::getOrCreateIfNotExists php3_auto_append_file \
  274.             $dirDef $xmlConf $currentContainer]
  275.         
  276.     # Depending on the value (none or a filename), select the appropriate component and store the value
  277.         
  278.     set value [lindex $text 1]
  279.     switch [string tolower $value] {
  280.        none {
  281.           $xuiObj selectComponentByName none
  282.        } default {
  283.           $xuiObj selectComponentByName file
  284.           $xuiObj.file setValue $value
  285.        }
  286.     }
  287. }
  288.  
  289.  
  290. # Procedure called to dump the contents to httpd.conf
  291.  
  292. proc ::apache1.3::dump_php3_auto_append_file {xuiObj} {
  293.     set value [[$xuiObj getSelectedComponent] getValue]
  294.     return "php3_auto_append_file $value" 
  295. }
  296. </verb> 
  297. Similar goes for php3_auto_prepend directive or php3_error_log
  298.  
  299.  
  300. <sect2>php3_include_path
  301. <p>
  302. This is another directive that would benefit of special treatment is
  303. php3_include_path (and php3_open_basedir)
  304.  
  305. From the PHP docs:
  306. <verb>
  307. include_path string
  308.  
  309. Specifies a list of directories where the require(), include() and
  310. fopen_with_path() functions look for files. The format is like the system's 
  311.  
  312. PATH environment variable: a list of directories separated with a colon in
  313. UNIX or semicolon in Windows. 
  314.  
  315. Example 3-1. UNIX include_path
  316.  
  317. include_path=.:/home/httpd/php-lib
  318.  
  319.  
  320. Example 3-2. Windows include_path
  321.  
  322. include_path=".;c:\www\phplib"
  323.  
  324. The default value for this directive is . (only the current directory).
  325. </verb>
  326.  Now we could map this directive to a string directive and hvae the user
  327. enter a string of directories separated by : or ;  Instead we make it a
  328. little bit easier for them by abstracting it and presenting them with a list
  329. of directories.
  330. <p>
  331. The XML description:
  332. <verb>
  333. <list name="php3_include_path" label="php_include_path">
  334.     <syntax>
  335.         <string name="php3_include_path_file" label="php_include_path_file" classes="directory" />
  336.      &etago;syntax>
  337.     <default>
  338.     <item>. &etago;item>
  339.      &etago;default>
  340.  &etago;list>
  341. </verb>
  342. We need now a couple of functions for converting from : or ; format
  343. (httpd.conf) to XML and viceversa.
  344. <verb>
  345. proc ::apache1.3::parse_php3_include_path {text parser dirDef xmlConf
  346. currentContainer} {
  347.     set xuiObj [apacheparserutils::getOrCreateIfNotExists php3_include_path \
  348.             $dirDef $xmlConf $currentContainer]
  349.     global tcl_platform
  350.     switch $tcl_platform(platform) {
  351.        windows {
  352.            set separator {;}
  353.        } default {
  354.            set separator :
  355.        }
  356.     }
  357.     foreach element [split [lrange $text 1 end] $separator] {
  358.         set child [$xuiObj newChild]
  359.  
  360.         # Split fscks up quoted filenames, so this is required
  361.  
  362.         regsub {\\\"} $element {"} result
  363.         $child setValue $result
  364.         $xuiObj insertChild $child
  365.     }
  366. }
  367.  
  368.  
  369. proc ::apache1.3::dump_php3_include_path {xuiObj} {
  370.    global tcl_platform
  371.    switch $tcl_platform(platform) {
  372.        windows {
  373.            set separator {;}
  374.        } default {
  375.            set separator :
  376.        }
  377.     }
  378.     set values {}
  379.     foreach child [$xuiObj getChildren] {
  380.         lappend values [$child getValue]
  381.     }
  382.     set result [join $values $separator]
  383.     if [llength $result] {
  384.         return "php3_include_path $result"
  385.     }
  386.     return {}
  387. }   
  388. </verb>
  389.  
  390. Once we have described all the directives (take a look at
  391. plugins/apache/modules/php3/directives.xml for a complete listing)
  392. We need to tell Comanche how do we want them organized in property pages
  393. (like in the tree described at the beginning)
  394.  
  395. In plugins/apache/modules/php3/propertyPages.xml
  396.  
  397. As an example, the main page:
  398. <verb>
  399. <propertyPage label="php3_pp_phpEngine" icon="smallWheel" name="pp_phpEngine" align="vertical">
  400.         <directiveInclude name="php3_engine"/>
  401.         <group name="php3_pp_phpEngine_tags"align="vertical"label="php3_pp_phpEngine_tags" style="normal">
  402.             <directiveInclude name="php3_asp_tags"/>
  403.             <directiveInclude name="php3_short_open_tag"/>
  404.          &etago;group>
  405.  &etago;propertyPage>   
  406.  
  407.  
  408. Finally, the moduleDescription.xml puts everything together:
  409.  
  410. <apacheModuleDescription name="php3"
  411.                          directivesXMLDefinition="directives.xml"
  412.                          propertyPagesXMLDefinition="propertyPages.xml"
  413.                          description="PHP3 Apache module." >
  414.     <nodesInterested>
  415.         <node type="mainserver,virtualhost">
  416.              <propertyPage name="pp_phpEngine"  />
  417.  
  418.         [...]
  419.  
  420.              <propertyPage name="pp_phpPaths" hookUnder="pp_phpEngine" />
  421.          &etago;node>
  422.      &etago;nodesInterested>
  423.  <specialCases file="specialCases.tcl">
  424.         <specialCase confDir="php3_open_basedir"
  425.                      xmlDir="php3_open_basedir"
  426.                      parser="apache1.3::parse_php3_open_basedir"
  427.                      dumper="apache1.3::dump_php3_open_basedir" />
  428.      
  429.      [...]
  430.  
  431.  &etago;specialCases>
  432.  &etago;apacheModuleDescription>    
  433. </verb>
  434. </article>