.\" Automatically generated by Pod::Man 4.14 (Pod::Simple 3.40) .\" .\" Standard preamble: .\" ======================================================================== .de Sp \" Vertical space (when we can't use .PP) .if t .sp .5v .if n .sp .. .de Vb \" Begin verbatim text .ft CW .nf .ne \\$1 .. .de Ve \" End verbatim text .ft R .fi .. .\" Set up some character translations and predefined strings. \*(-- will .\" give an unbreakable dash, \*(PI will give pi, \*(L" will give a left .\" double quote, and \*(R" will give a right double quote. \*(C+ will .\" give a nicer C++. Capital omega is used to do unbreakable dashes and .\" therefore won't be available. \*(C` and \*(C' expand to `' in nroff, .\" nothing in troff, for use with C<>. .tr \(*W- .ds C+ C\v'-.1v'\h'-1p'\s-2+\h'-1p'+\s0\v'.1v'\h'-1p' .ie n \{\ . ds -- \(*W- . ds PI pi . if (\n(.H=4u)&(1m=24u) .ds -- \(*W\h'-12u'\(*W\h'-12u'-\" diablo 10 pitch . if (\n(.H=4u)&(1m=20u) .ds -- \(*W\h'-12u'\(*W\h'-8u'-\" diablo 12 pitch . ds L" "" . ds R" "" . ds C` "" . ds C' "" 'br\} .el\{\ . ds -- \|\(em\| . ds PI \(*p . ds L" `` . ds R" '' . ds C` . ds C' 'br\} .\" .\" Escape single quotes in literal strings from groff's Unicode transform. .ie \n(.g .ds Aq \(aq .el .ds Aq ' .\" .\" If the F register is >0, we'll generate index entries on stderr for .\" titles (.TH), headers (.SH), subsections (.SS), items (.Ip), and index .\" entries marked with X<> in POD. Of course, you'll have to process the .\" output yourself in some meaningful fashion. .\" .\" Avoid warning from groff about undefined register 'F'. .de IX .. .nr rF 0 .if \n(.g .if rF .nr rF 1 .if (\n(rF:(\n(.g==0)) \{\ . if \nF \{\ . de IX . tm Index:\\$1\t\\n%\t"\\$2" .. . if !\nF==2 \{\ . nr % 0 . nr F 2 . \} . \} .\} .rr rF .\" .\" Accent mark definitions (@(#)ms.acc 1.5 88/02/08 SMI; from UCB 4.2). .\" Fear. Run. Save yourself. No user-serviceable parts. . \" fudge factors for nroff and troff .if n \{\ . ds #H 0 . ds #V .8m . ds #F .3m . ds #[ \f1 . ds #] \fP .\} .if t \{\ . ds #H ((1u-(\\\\n(.fu%2u))*.13m) . ds #V .6m . ds #F 0 . ds #[ \& . ds #] \& .\} . \" simple accents for nroff and troff .if n \{\ . ds ' \& . ds ` \& . ds ^ \& . ds , \& . ds ~ ~ . ds / .\} .if t \{\ . ds ' \\k:\h'-(\\n(.wu*8/10-\*(#H)'\'\h"|\\n:u" . ds ` \\k:\h'-(\\n(.wu*8/10-\*(#H)'\`\h'|\\n:u' . ds ^ \\k:\h'-(\\n(.wu*10/11-\*(#H)'^\h'|\\n:u' . ds , \\k:\h'-(\\n(.wu*8/10)',\h'|\\n:u' . ds ~ \\k:\h'-(\\n(.wu-\*(#H-.1m)'~\h'|\\n:u' . ds / \\k:\h'-(\\n(.wu*8/10-\*(#H)'\z\(sl\h'|\\n:u' .\} . \" troff and (daisy-wheel) nroff accents .ds : \\k:\h'-(\\n(.wu*8/10-\*(#H+.1m+\*(#F)'\v'-\*(#V'\z.\h'.2m+\*(#F'.\h'|\\n:u'\v'\*(#V' .ds 8 \h'\*(#H'\(*b\h'-\*(#H' .ds o \\k:\h'-(\\n(.wu+\w'\(de'u-\*(#H)/2u'\v'-.3n'\*(#[\z\(de\v'.3n'\h'|\\n:u'\*(#] .ds d- \h'\*(#H'\(pd\h'-\w'~'u'\v'-.25m'\f2\(hy\fP\v'.25m'\h'-\*(#H' .ds D- D\\k:\h'-\w'D'u'\v'-.11m'\z\(hy\v'.11m'\h'|\\n:u' .ds th \*(#[\v'.3m'\s+1I\s-1\v'-.3m'\h'-(\w'I'u*2/3)'\s-1o\s+1\*(#] .ds Th \*(#[\s+2I\s-2\h'-\w'I'u*3/5'\v'-.3m'o\v'.3m'\*(#] .ds ae a\h'-(\w'a'u*4/10)'e .ds Ae A\h'-(\w'A'u*4/10)'E . \" corrections for vroff .if v .ds ~ \\k:\h'-(\\n(.wu*9/10-\*(#H)'\s-2\u~\d\s+2\h'|\\n:u' .if v .ds ^ \\k:\h'-(\\n(.wu*10/11-\*(#H)'\v'-.4m'^\v'.4m'\h'|\\n:u' . \" for low resolution devices (crt and lpr) .if \n(.H>23 .if \n(.V>19 \ \{\ . ds : e . ds 8 ss . ds o a . ds d- d\h'-1'\(ga . ds D- D\h'-1'\(hy . ds th \o'bp' . ds Th \o'LP' . ds ae ae . ds Ae AE .\} .rm #[ #] #H #V #F C .\" ======================================================================== .\" .IX Title "OpenGuides 3pm" .TH OpenGuides 3pm "2021-01-30" "perl v5.32.0" "User Contributed Perl Documentation" .\" For nroff, turn off justification. Always turn off hyphenation; it makes .\" way too many mistakes in technical documents. .if n .ad l .nh .SH "NAME" OpenGuides \- A complete web application for managing a collaboratively\-written guide to a city or town. .SH "DESCRIPTION" .IX Header "DESCRIPTION" The OpenGuides software provides the framework for a collaboratively-written city guide. It is similar to a wiki but provides somewhat more structured data storage allowing you to annotate wiki pages with information such as category, location, and much more. It provides searching facilities including \*(L"find me everything within a certain distance of this place\*(R". Every page includes a link to a machine-readable (\s-1RDF\s0) version of the page. .SH "METHODS" .IX Header "METHODS" .IP "\fBnew\fR" 4 .IX Item "new" .Vb 2 \& my $config = OpenGuides::Config\->new( file => "wiki.conf" ); \& my $guide = OpenGuides\->new( config => $config ); .Ve .IP "\fBwiki\fR" 4 .IX Item "wiki" An accessor, returns the underlying Wiki::Toolkit object. .IP "\fBconfig\fR" 4 .IX Item "config" An accessor, returns the underlying OpenGuides::Config object. .IP "\fBlocator\fR" 4 .IX Item "locator" An accessor, returns the underlying Wiki::Toolkit::Plugin::Locator::UK object. .IP "\fBdiffer\fR" 4 .IX Item "differ" An accessor, returns the underlying Wiki::Toolkit::Plugin::Diff object. .IP "\fBdisplay_node\fR" 4 .IX Item "display_node" .Vb 5 \& # Print node to STDOUT. \& $guide\->display_node( \& id => "Calthorpe Arms", \& version => 2, \& ); \& \& # Or return output as a string (useful for writing tests). \& $guide\->display_node( \& id => "Calthorpe Arms", \& return_output => 1, \& ); \& \& # Return output as a string with HTTP headers omitted (for tests). \& $guide\->display_node( \& id => "Calthorpe Arms", \& return_output => 1, \& noheaders => 1, \& ); \& \& # Or return the hash of variables that will be passed to the template \& # (not including those set additionally by OpenGuides::Template). \& $guide\->display_node( \& id => "Calthorpe Arms", \& return_tt_vars => 1, \& ); .Ve .Sp If \f(CW\*(C`version\*(C'\fR is omitted then it will assume you want the latest version. .Sp Note that if you pass the \f(CW\*(C`return_output\*(C'\fR parameter, and your node is a redirecting node, this method will fake the redirect and return the output that will actually end up in the user's browser. If instead you want to see the \s-1HTTP\s0 headers that will be printed in order to perform the redirect, pass the \f(CW\*(C`intercept_redirect\*(C'\fR parameter as well. The \f(CW\*(C`intercept_redirect\*(C'\fR parameter has no effect if the node isn't a redirect, or if the \&\f(CW\*(C`return_output\*(C'\fR parameter is omitted. .Sp (At the moment, \f(CW\*(C`return_tt_vars\*(C'\fR acts as if the \f(CW\*(C`intercept_redirect\*(C'\fR parameter was passed.) .Sp The \f(CW\*(C`noheaders\*(C'\fR parameter only takes effect if \f(CW\*(C`return_output\*(C'\fR is true and \f(CW\*(C`intercept_redirect\*(C'\fR is false or omitted. .Sp If you have specified the \f(CW\*(C`host_checker_module\*(C'\fR option in your \&\f(CW\*(C`wiki.conf\*(C'\fR, this method will attempt to call the method of that module to determine whether the host requesting the node has been blacklisted. If this method returns true, then the \&\f(CW\*(C`blacklisted_host.tt\*(C'\fR template will be used to display an error message. .Sp The \f(CW\*(C`blacklisted_host\*(C'\fR method will be passed a scalar containing the host's \&\s-1IP\s0 address. .IP "\fBdisplay_random_page\fR" 4 .IX Item "display_random_page" .Vb 1 \& $guide\->display_random_page; .Ve .Sp Display a random page. As with other methods, the \f(CW\*(C`return_output\*(C'\fR parameter can be used to return the output instead of printing it to \s-1STDOUT.\s0 You can also restrict it to a given category and/or locale by supplying appropriate parameters: .Sp .Vb 4 \& $guide\->display_random_page( \& category => "pubs", \& locale => "bermondsey", \& ); .Ve .Sp The values of these parameters are case-insensitive. .Sp You can make sure this method never returns pages that are themselves categories and/or locales by setting \f(CW\*(C`random_page_omits_categories\*(C'\fR and/or \f(CW\*(C`random_page_omits_locales\*(C'\fR in your wiki.conf. .IP "\fBdisplay_edit_form\fR" 4 .IX Item "display_edit_form" .Vb 7 \& $guide\->display_edit_form( \& id => "Vivat Bacchus", \& vars => \e%vars, \& content => $content, \& metadata => \e%metadata, \& checksum => $checksum \& ); .Ve .Sp Display an edit form for the specified node. As with other methods, the \&\f(CW\*(C`return_output\*(C'\fR parameter can be used to return the output instead of printing it to \s-1STDOUT.\s0 .Sp If this is to redisplay an existing edit, the content, metadata and checksum may be supplied in those arguments .Sp Extra template variables may be supplied in the vars argument .IP "\fBpreview_edit\fR" 4 .IX Item "preview_edit" .Vb 4 \& $guide\->preview_edit( \& id => "Vivat Bacchus", \& cgi_obj => $q, \& ); .Ve .Sp Preview the edited version of the specified node. As with other methods, the \&\f(CW\*(C`return_output\*(C'\fR parameter can be used to return the output instead of printing it to \s-1STDOUT.\s0 .IP "\fBdisplay_prefs_form\fR" 4 .IX Item "display_prefs_form" .Vb 1 \& $guide\->display_prefs_form; .Ve .Sp Displays a form that lets the user view and set their preferences. The \&\f(CW\*(C`return_output\*(C'\fR and \f(CW\*(C`return_tt_vars\*(C'\fR parameters can be used to return the output or template variables, instead of printing the output to \s-1STDOUT.\s0 The \f(CW\*(C`noheaders\*(C'\fR parameter can also be used in conjunction with \&\f(CW\*(C`return_output\*(C'\fR, if you wish to omit all \s-1HTTP\s0 headers. .IP "\fBdisplay_recent_changes\fR" 4 .IX Item "display_recent_changes" .Vb 1 \& $guide\->display_recent_changes; .Ve .Sp As with other methods, the \f(CW\*(C`return_output\*(C'\fR parameter can be used to return the output instead of printing it to \s-1STDOUT.\s0 .IP "\fBdisplay_diffs\fR" 4 .IX Item "display_diffs" .Vb 5 \& $guide\->display_diffs( \& id => "Home Page", \& version => 6, \& other_version => 5, \& ); \& \& # Or return output as a string (useful for writing tests). \& my $output = $guide\->display_diffs( \& id => "Home Page", \& version => 6, \& other_version => 5, \& return_output => 1, \& ); \& \& # Or return the hash of variables that will be passed to the template \& # (not including those set additionally by OpenGuides::Template). \& my %vars = $guide\->display_diffs( \& id => "Home Page", \& version => 6, \& other_version => 5, \& return_tt_vars => 1, \& ); .Ve .IP "\fBfind_within_distance\fR" 4 .IX Item "find_within_distance" .Vb 4 \& $guide\->find_within_distance( \& id => $node, \& metres => $q\->param("distance_in_metres") \& ); .Ve .IP "\fBshow_backlinks\fR" 4 .IX Item "show_backlinks" .Vb 1 \& $guide\->show_backlinks( id => "Calthorpe Arms" ); .Ve .Sp As with other methods, parameters \f(CW\*(C`return_tt_vars\*(C'\fR and \&\f(CW\*(C`return_output\*(C'\fR can be used to return these things instead of printing the output to \s-1STDOUT.\s0 .IP "\fBshow_index\fR" 4 .IX Item "show_index" .Vb 4 \& # Show everything in Category: Pubs. \& $guide\->show_index( \& cat => "pubs", \& ); \& \& # Show all pubs in Holborn. \& $guide\->show_index( \& cat => "pubs", \& loc => "holborn", \& ); \& \& # RDF version of things in Locale: Holborn. \& $guide\->show_index( \& loc => "Holborn", \& format => "rdf", \& ); \& \& # RSS / Atom version (recent changes style). \& $guide\->show_index( \& loc => "Holborn", \& format => "rss", \& ); \& \& # Or return output as a string (useful for writing tests). \& $guide\->show_index( \& cat => "pubs", \& return_output => 1, \& ); \& \& # Return output as a string with HTTP headers omitted (for tests). \& $guide\->show_index( \& cat => "pubs", \& return_output => 1, \& noheaders => 1, \& ); \& \& # Or return the template variables (again, useful for writing tests). \& $guide\->show_index( \& cat => "pubs", \& format => "map" \& return_tt_vars => 1, \& ); .Ve .Sp If neither \f(CW\*(C`cat\*(C'\fR or \f(CW\*(C`loc\*(C'\fR is supplied, then all pages will be returned. .Sp The recommended format of parameters to this method changed to the above in version 0.67 of OpenGuides, though older invocations are still supported and will redirect to the new \s-1URL\s0 format. .Sp If you pass the \f(CW\*(C`return_output\*(C'\fR or \f(CW\*(C`return_tt_vars\*(C'\fR parameters, and a redirect is required, this method will fake the redirect and return the output/variables that will actually end up being viewed by the user. If instead you want to see the \s-1HTTP\s0 headers that will be printed in order to perform the redirect, pass the \f(CW\*(C`intercept_redirect\*(C'\fR parameter as well. .Sp The \f(CW\*(C`intercept_redirect\*(C'\fR parameter has no effect if no redirect is required, or if the \f(CW\*(C`return_output\*(C'\fR/\f(CW\*(C`return_tt_vars\*(C'\fR parameter is omitted. .Sp The \f(CW\*(C`noheaders\*(C'\fR parameter only takes effect if \f(CW\*(C`return_output\*(C'\fR is true and \f(CW\*(C`intercept_redirect\*(C'\fR is false or omitted. .IP "\fBshow_metadata\fR" 4 .IX Item "show_metadata" .Vb 3 \& $guide\->show_metadata(); \& $guide\->show_metadata(type => "category"); \& $guide\->show_metadata(type => "category", format => "json"); .Ve .Sp Lists all metadata types, or all metadata values of a given type. Useful for programatically discovering a guide. .Sp As with other methods, parameters \f(CW\*(C`return_tt_vars\*(C'\fR and \&\f(CW\*(C`return_output\*(C'\fR can be used to return these things instead of printing the output to \s-1STDOUT.\s0 .IP "\fBlist_all_versions\fR" 4 .IX Item "list_all_versions" .Vb 1 \& $guide\->list_all_versions ( id => "Home Page" ); \& \& # Or return output as a string (useful for writing tests). \& $guide\->list_all_versions ( \& id => "Home Page", \& return_output => 1, \& ); \& \& # Or return the hash of variables that will be passed to the template \& # (not including those set additionally by OpenGuides::Template). \& $guide\->list_all_versions ( \& id => "Home Page", \& return_tt_vars => 1, \& ); .Ve .IP "\fBget_feed_and_content_type\fR" 4 .IX Item "get_feed_and_content_type" Fetch the OpenGuides feed object, and the output content type, for the supplied feed type. .Sp Handles all the setup for the OpenGuides feed object. .IP "\fBdisplay_feed\fR" 4 .IX Item "display_feed" .Vb 8 \& # Last ten non\-minor edits to Hammersmith pages in RSS 1.0 format \& $guide\->display_feed( \& feed_type => \*(Aqrss\*(Aq, \& feed_listing => \*(Aqrecent_changes\*(Aq, \& items => 10, \& ignore_minor_edits => 1, \& locale => "Hammersmith", \& ); \& \& # All edits bob has made to pub pages in the last week in Atom format \& $guide\->display_feed( \& feed_type => \*(Aqatom\*(Aq, \& feed_listing => \*(Aqrecent_changes\*(Aq, \& days => 7, \& username => "bob", \& category => "Pubs", \& ); .Ve .Sp \&\f(CW\*(C`feed_type\*(C'\fR is a mandatory parameter. Supported values at present are \&\*(L"rss\*(R" and \*(L"atom\*(R". .Sp \&\f(CW\*(C`feed_listing\*(C'\fR is a mandatory parameter. Supported values at present are \*(L"recent_changes\*(R". (More values are coming soon though!) .Sp As with other methods, the \f(CW\*(C`return_output\*(C'\fR parameter can be used to return the output instead of printing it to \s-1STDOUT.\s0 .IP "\fBdisplay_about\fR" 4 .IX Item "display_about" .Vb 1 \& print $guide\->display_about(format => "rdf"); .Ve .Sp Displays static 'about' information in various format. Defaults to \s-1HTML.\s0 .IP "\fBcommit_node\fR" 4 .IX Item "commit_node" .Vb 4 \& $guide\->commit_node( \& id => $node, \& cgi_obj => $q, \& ); .Ve .Sp As with other methods, parameters \f(CW\*(C`return_tt_vars\*(C'\fR and \&\f(CW\*(C`return_output\*(C'\fR can be used to return these things instead of printing the output to \s-1STDOUT.\s0 .Sp If you have specified the \f(CW\*(C`spam_detector_module\*(C'\fR option in your \&\f(CW\*(C`wiki.conf\*(C'\fR, this method will attempt to call the method of that module to determine whether the edit is spam. If this method returns true, then the \f(CW\*(C`spam_detected.tt\*(C'\fR template will be used to display an error message. .Sp The \f(CW\*(C`looks_like_spam\*(C'\fR method will be passed a datastructure containing content and metadata. .Sp The geographical data that you should provide in the \s-1CGI\s0 object depends on the handler you chose in \f(CW\*(C`wiki.conf\*(C'\fR. .RS 4 .IP "\(bu" 4 \&\fBBritish National Grid\fR \- provide either \f(CW\*(C`os_x\*(C'\fR and \f(CW\*(C`os_y\*(C'\fR or \&\f(CW\*(C`latitude\*(C'\fR and \f(CW\*(C`longitude\*(C'\fR; whichever set of data you give, it will be converted to the other and both sets will be stored. .IP "\(bu" 4 \&\fBIrish National Grid\fR \- provide either \f(CW\*(C`osie_x\*(C'\fR and \f(CW\*(C`osie_y\*(C'\fR or \&\f(CW\*(C`latitude\*(C'\fR and \f(CW\*(C`longitude\*(C'\fR; whichever set of data you give, it will be converted to the other and both sets will be stored. .IP "\(bu" 4 \&\fB\s-1UTM\s0 ellipsoid\fR \- provide \f(CW\*(C`latitude\*(C'\fR and \f(CW\*(C`longitude\*(C'\fR; these will be converted to easting and northing and both sets of data will be stored. .RE .RS 4 .RE .IP "\fB_autoCreateCategoryLocale\fR" 4 .IX Item "_autoCreateCategoryLocale" .Vb 4 \& $guide\->_autoCreateCategoryLocale( \& id => "FAQ", \& metadata => \e%metadata, \& ); .Ve .Sp When a new node is added, or a previously un-moderated node is moderated, identifies if any of its Categories or Locales are missing, and creates them. .Sp Guide admins can control the text that gets put into the content field of the autocreated node by putting it in custom_autocreate_content.tt in their custom templates directory. The following \s-1TT\s0 variables will be available to the template: .RS 4 .IP "\(bu" 4 index_type (e.g. \f(CW\*(C`Category\*(C'\fR) .IP "\(bu" 4 index_value (e.g. \f(CW\*(C`Vegan\-friendly\*(C'\fR) .IP "\(bu" 4 node_name (e.g. \f(CW\*(C`Category Vegan\-Friendly\*(C'\fR) .RE .RS 4 .Sp (Note capitalisation \- index_value is what they typed in to the form, and node_name is the fully free-upper-ed name of the autocreated node.) .Sp For nodes not requiring moderation, should be called on writing the node For nodes requiring moderation, should only be called on moderation .RE .IP "\fBdelete_node\fR" 4 .IX Item "delete_node" .Vb 5 \& $guide\->delete_node( \& id => "FAQ", \& version => 15, \& password => "beer", \& ); .Ve .Sp \&\f(CW\*(C`version\*(C'\fR is optional \- if it isn't supplied then all versions of the node will be deleted; in other words the node will be entirely removed. .Sp If \f(CW\*(C`password\*(C'\fR is not supplied then a form for entering the password will be displayed. .Sp As with other methods, parameters \f(CW\*(C`return_tt_vars\*(C'\fR and \&\f(CW\*(C`return_output\*(C'\fR can be used to return these things instead of printing the output to \s-1STDOUT.\s0 .IP "\fBset_node_moderation\fR" 4 .IX Item "set_node_moderation" .Vb 5 \& $guide\->set_node_moderation( \& id => "FAQ", \& password => "beer", \& moderation_flag => 1, \& ); .Ve .Sp Sets the moderation needed flag on a node, either on or off. .Sp If \f(CW\*(C`password\*(C'\fR is not supplied then a form for entering the password will be displayed. .IP "\fBmoderate_node\fR" 4 .IX Item "moderate_node" .Vb 5 \& $guide\->moderate_node( \& id => "FAQ", \& version => 12, \& password => "beer", \& ); .Ve .Sp Marks a version of a node as moderated. Will also auto-create and Locales and Categories for the newly moderated version. .Sp If \f(CW\*(C`password\*(C'\fR is not supplied then a form for entering the password will be displayed. .IP "\fBshow_missing_metadata\fR" 4 .IX Item "show_missing_metadata" Search for nodes which don't have a certain kind of metadata. Excludes nodes which are pure redirects, and optionally also excludes locales and categories. .IP "\fBrevert_user_interface\fR" 4 .IX Item "revert_user_interface" If \f(CW\*(C`password\*(C'\fR is not supplied then a form for entering the password will be displayed, along with a list of all the edits the user made. .Sp If the password is given, will delete all of these versions. .IP "\fBdisplay_admin_interface\fR" 4 .IX Item "display_admin_interface" Fetch everything we need to display the admin interface, and passes it off to the template .SH "BUGS AND CAVEATS" .IX Header "BUGS AND CAVEATS" \&\s-1UTF8\s0 data are currently not handled correctly throughout. .PP Other bugs are documented at .SH "SEE ALSO" .IX Header "SEE ALSO" .IP "\(bu" 4 The Randomness Guide to London, at , the largest OpenGuides site. .IP "\(bu" 4 The list of live OpenGuides installs at . .IP "\(bu" 4 Wiki::Toolkit, the Wiki toolkit which does the heavy lifting for OpenGuides. .SH "FEEDBACK" .IX Header "FEEDBACK" If you have a question, a bug report, or a patch, or you're interested in joining the development team, please contact openguides\-dev@lists.openguides.org (moderated mailing list, will reach all current developers but you'll have to wait for your post to be approved) or file a bug report at .SH "AUTHOR" .IX Header "AUTHOR" The OpenGuides Project (openguides\-dev@lists.openguides.org) .SH "COPYRIGHT" .IX Header "COPYRIGHT" .Vb 1 \& Copyright (C) 2003\-2020 The OpenGuides Project. All Rights Reserved. .Ve .PP The OpenGuides distribution is free software; you can redistribute it and/or modify it under the same terms as Perl itself. .SH "CREDITS" .IX Header "CREDITS" Programming by Dominic Hargreaves, Earle Martin, Kake Pugh, and Ivor Williams. Testing and bug reporting by Billy Abbott, Jody Belka, Kerry Bosworth, Simon Cozens, Cal Henderson, Steve Jolly, and Bob Walker (among others). Much of the Module::Build stuff copied from the Siesta project