<?xml version="1.0"?>
<feed xmlns="http://www.w3.org/2005/Atom" xml:lang="en">
		<id>http://gwiki3.thatlinuxbox.com/api.php?action=feedcontributions&amp;feedformat=atom&amp;user=LWC</id>
		<title>GeeklogWiki - User contributions [en]</title>
		<link rel="self" type="application/atom+xml" href="http://gwiki3.thatlinuxbox.com/api.php?action=feedcontributions&amp;feedformat=atom&amp;user=LWC"/>
		<link rel="alternate" type="text/html" href="http://gwiki3.thatlinuxbox.com/Special:Contributions/LWC"/>
		<updated>2026-04-06T09:22:02Z</updated>
		<subtitle>User contributions</subtitle>
		<generator>MediaWiki 1.27.5</generator>

	<entry>
		<id>http://gwiki3.thatlinuxbox.com/index.php?title=Scripts_Class&amp;diff=6278</id>
		<title>Scripts Class</title>
		<link rel="alternate" type="text/html" href="http://gwiki3.thatlinuxbox.com/index.php?title=Scripts_Class&amp;diff=6278"/>
				<updated>2013-04-21T13:58:14Z</updated>
		
		<summary type="html">&lt;p&gt;LWC: /* Setting a JavaScript Library */ Fixed line&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Introduction ==&lt;br /&gt;
&lt;br /&gt;
As of version 1.8.0, Geeklog introduced the Scripts class. The Scripts Class has been designed to allow themes and plugins to easily add JavaScript, JavaScript files and CSS files to the header and/or footer of a page. It also allows plugins and themes to enable the use of jQuery and the jQuery UI plugin. By default Geeklog will place all JavaScript in the footer unless told otherwise.&lt;br /&gt;
&lt;br /&gt;
In previous versions of Geeklog, JavaScript and the CSS files were handled solely by the plugin usually by including the functions plugin_getheadercode_foo or plugin_getfootercode_foo.&lt;br /&gt;
&lt;br /&gt;
The advantages of using the Scripts class over having a plugin or theme manage things are many. You have easy access to jQuery and the jQuery UI plugin, no more inline scripting, and you can setup things to have files only load when needed. Plus, in the future it will automatically support caching and compression of the CSS and JavaScript files.&lt;br /&gt;
&lt;br /&gt;
== Usage ==&lt;br /&gt;
&lt;br /&gt;
The Scripts class is set near the beginning of lib-common.php as $_SCRIPTS. It uses the template variable plg_headercode (which is set in the function COM_SiteHeader) to put information in the header and the template variable plg_footercode (which is set in the function COM_SiteFooter) to put JavaScript in the footer. All of your JavaScript code and CSS files for the header needs to be set in the class before COM_SiteHeader is run or, for plugins, in your plugin_getheadercode_xxxx function, and themes, in the functions.php file. All JavaScript for the footer must be set by the time you call COM_SiteFooter (this shouldn't be a problem since this is one of the last functions you should be calling anyways on a page).&lt;br /&gt;
&lt;br /&gt;
All JavaScript in the footer will also have access to the GeeklogConfig object. This object contains commonly used attributes taken right from Geeklogs configuration array ($_CONF) and uses the same keys.&lt;br /&gt;
&lt;br /&gt;
=== Setting a CSS File ===&lt;br /&gt;
&lt;br /&gt;
To set a CSS file for your plugin you would point the Scripts class to the file like so:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;global $_SCRIPTS;&lt;br /&gt;
    &lt;br /&gt;
$_SCRIPTS-&amp;gt;setCSSFile('polls', '/polls/style.css');&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This tells the Scripts class to include the style sheet called polls. It is also telling the class that you plan to always include this CSS file. The reason you want to tell Geeklog that you plan to always include this CSS file is that it will then be marked for caching and compressing (future feature). If you plan to only include this CSS file on pages that the plugin displays you may want to include an extra parameter in the call to the class:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;global $_SCRIPTS;&lt;br /&gt;
    &lt;br /&gt;
$_SCRIPTS-&amp;gt;setCSSFile('polls', '/polls/style.css', false);&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
As stated before this needs to be done before you run the function COM_SiteHeader or in your plugins plugin_getheadercode_foo function. If your plugin has a block or uses Autotags that need the CSS file then you should always make sure it is included since Geeklog has no way of knowing if a block or Autotag will be displayed before the header is written.&lt;br /&gt;
&lt;br /&gt;
=== Setting JavaScript ===&lt;br /&gt;
&lt;br /&gt;
To set JavaScript for your plugin or theme you would do the following:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;global $_SCRIPTS;&lt;br /&gt;
    &lt;br /&gt;
$js = 'some JavaScript';&lt;br /&gt;
$_SCRIPTS-&amp;gt;setJavaScript($js, true);&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This will automatically wrap the code in the html script tag. If you want to include your own script tag then just remove the &amp;quot;true&amp;quot; from the function call. There are several other attributes to this function that you may need to use from time to time (i.e. specifying the JavaScript to appear in the header and if it is constant). For more information on these take a look at the Scripts class found in the &amp;quot;/system/classes/&amp;quot; directory of your Geeklog install.&lt;br /&gt;
&lt;br /&gt;
=== Setting a JavaScript File ===&lt;br /&gt;
&lt;br /&gt;
To set a JavaScript file for your plugin or theme you would do the following:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;global $_SCRIPTS;&lt;br /&gt;
    &lt;br /&gt;
$_SCRIPTS-&amp;gt;setJavaScriptFile('pluginname', '/pluginname/javascript/yourfile.js');&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The first attribute of the function is the internal name of the file. Make sure this is unique as you can overwrite previous entries. To standardize this, the name should be your plugin name (for themes use &amp;quot;theme.themename&amp;quot;). If you have more than one JavaScript file then you could use a name like &amp;quot;pluginname.subname&amp;quot;. The second attribute of the function is obviously the location and file name of your JavaScript file. The backslash needs to be included at the beginning of this and you only include the part of the path after the public_html directory.&lt;br /&gt;
&lt;br /&gt;
=== Setting a JavaScript Library ===&lt;br /&gt;
&lt;br /&gt;
To load the jQuery libray included with Geeklog all you need to do is add the following code:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;global $_SCRIPTS;&lt;br /&gt;
$_SCRIPTS-&amp;gt;setJavaScriptLibrary('jquery');&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
To load a jQuery UI widget all you need to do add the following code:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;global $_SCRIPTS;&lt;br /&gt;
$_SCRIPTS-&amp;gt;setJavaScriptLibrary('jquery.ui.tabs');&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
To load a jQuery UI effect all you need to do add the following code:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;global $_SCRIPTS;&lt;br /&gt;
$_SCRIPTS-&amp;gt;setJavaScriptLibrary('jquery.ui.effects-highlight');&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
When loading an effect or widget you do not need to load the jQuery library first. When loading an effect or widget all the required files will be automatically set to load.&lt;br /&gt;
&lt;br /&gt;
If a jQuery file is missing then the Google CDN-hosted copy will be substituted. There is also an option in the Geeklog Configuration under the Site tab to always use a CDN-hosted version of jQuery.&lt;br /&gt;
&lt;br /&gt;
When loading one of the widgets or effects for jQuery UI you need to make sure to set it before COM_SiteHeader is executed or in your plugins plugin_getheadercode_foo function.  The reason for this is the css files are set in COM_SiteHeader and we need to make sure that the CSS files for the UI plugin get set.&lt;/div&gt;</summary>
		<author><name>LWC</name></author>	</entry>

	<entry>
		<id>http://gwiki3.thatlinuxbox.com/index.php?title=Stories&amp;diff=5943</id>
		<title>Stories</title>
		<link rel="alternate" type="text/html" href="http://gwiki3.thatlinuxbox.com/index.php?title=Stories&amp;diff=5943"/>
				<updated>2011-01-04T20:25:45Z</updated>
		
		<summary type="html">&lt;p&gt;LWC: /* Adding Images */ Sub-categories&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== What Is A Story? ==&lt;br /&gt;
&lt;br /&gt;
A Story is a dated entry which is added to your website. The stories are sorted by date, and have many features associated with them. There are two main components to a story: the topic and the actual story.&lt;br /&gt;
&lt;br /&gt;
[[Topics]] allow you to categorize your stories and virtually create sections within your website. The default installation of Geeklog includes the topics &amp;quot;General News&amp;quot; and &amp;quot;Geeklog&amp;quot;. These topics can be renamed or deleted, and new ones can be added.&lt;br /&gt;
&lt;br /&gt;
Stories are the main way you can add new content to your Geeklog-powered website. Traditionally, they are used much like news-articles and are used to provide new and ongoing information to visitors of a Geeklog-powered website. Please read the [[Administration]] section for other content options.&lt;br /&gt;
&lt;br /&gt;
The following instructions are for administrators' use with the [http://www.geeklog.net/article.php?story=advanced-editor Advanced Editor] which comes with Geeklog 1.4 and is integrated into the Professional theme. You must be a member of Root or Story Admin to be able to add a story this way.&lt;br /&gt;
&lt;br /&gt;
=== Adding A Story ===&lt;br /&gt;
&lt;br /&gt;
# Log into your site.&lt;br /&gt;
# In the [[Admins Block|Admins Only]] section on the left, click the &amp;quot;Stories&amp;quot; link.&lt;br /&gt;
# Click the &amp;quot;Create New&amp;quot; link near the top of the page.&lt;br /&gt;
# Wait for the page to load the toolbar for editing.&lt;br /&gt;
# Complete the &amp;quot;Title&amp;quot; field&lt;br /&gt;
# Select a Topic.&lt;br /&gt;
# You may change the text in the &amp;quot;ID&amp;quot; field if desired (it defaults to the date and time).&lt;br /&gt;
# By default (i.e. unless you have changed the setting in the [[ConfigFile14|configuration file]]) the &amp;quot;Show Topic&amp;quot; icon is selected. Change this if you do not want the topic icon to show.&lt;br /&gt;
# Select the &amp;quot;Draft&amp;quot; box if you are creating a draft only.&lt;br /&gt;
# Complete the &amp;quot;Intro Text&amp;quot; and &amp;quot;Body Text&amp;quot; fields. The text in the &amp;quot;Intro Text&amp;quot; field will show on your main page. The text in the &amp;quot;Body Text&amp;quot; field will show with the intro text after someone clicks on the &amp;quot;read more&amp;quot; link under a story.&lt;br /&gt;
# If you are using the advanced editor and want to preview your story, you must click the &amp;quot;Preview&amp;quot; button at the bottom to save a temporary copy of the story on the server, then click the &amp;quot;Preview&amp;quot; button at the top to view the preview.&lt;br /&gt;
# When you are happy with your changes, click the &amp;quot;Save&amp;quot; button.&lt;br /&gt;
&lt;br /&gt;
=== Publishing Options ===&lt;br /&gt;
&lt;br /&gt;
When editing your story, you can access the publishing options by clicking the &amp;quot;Publishing Options&amp;quot; link at the top of the screen. Your options are to change:&lt;br /&gt;
* the publishing date (future-dated stories will not be published until that date)&lt;br /&gt;
* whether the story is &amp;quot;featured&amp;quot; (the default is &amp;quot;not featured&amp;quot;; a featured story will show at the top of the list of stories, even if a newer story is added, until another story is flagged as &amp;quot;featured&amp;quot;)&lt;br /&gt;
* whether the story will show on the &amp;quot;front page&amp;quot; (i.e. home page) of your site, or whether it will only show in the topic subsection&lt;br /&gt;
* whether comments are allowed&lt;br /&gt;
* whether trackbacks are allowed (this is defaulted to &amp;quot;disabled&amp;quot;; [http://en.wikipedia.org/wiki/Trackback trackbacks] are links to sites which link to yours; use trackbacks with caution, because much trackback is now found to be spam)&lt;br /&gt;
&lt;br /&gt;
=== Adding Images ===&lt;br /&gt;
&lt;br /&gt;
====Internally====&lt;br /&gt;
Click on the &amp;quot;Images&amp;quot; link at the top of the story editor screen. Use the &amp;quot;Browse&amp;quot; buttons to look for the images on your computer for uploading. The &amp;quot;Images&amp;quot; section of the story editor has more notes on how to integrate the images in your post. You will need to insert the [image1] etc tags into the story manually.&lt;br /&gt;
=====Extra images=====&lt;br /&gt;
* To increase the number of images you can upload (available only if you have access to uploading files directly to the webserver):&lt;br /&gt;
*# log out of your site&lt;br /&gt;
*# open your config.php file in a text editor&lt;br /&gt;
*# search for &amp;lt;i&amp;gt;$_CONF['maximagesperarticle']&amp;lt;/i&amp;gt;&lt;br /&gt;
*# change the number &amp;quot;5&amp;quot; to the maximum number of images you want to be allowed for a story&lt;br /&gt;
*# save your changes&lt;br /&gt;
*# upload the changed config.php file (overwrite the existing file) onto your web server&lt;br /&gt;
&lt;br /&gt;
====Externally====&lt;br /&gt;
# Stay in the &amp;quot;Editor&amp;quot; screen (if you have left it, simply click the &amp;quot;Editor&amp;quot; link at the top of the screen).&lt;br /&gt;
# Click the arrow button in your editor toolbar [[image:expand-arrow.jpg]]. This will open the editor in a new window.&lt;br /&gt;
# Click on the image icon [[image:image.jpg]]. A new window will open.&lt;br /&gt;
# Click on the &amp;quot;Browse Server&amp;quot; button. The window will change to the Resource Browser window.&lt;br /&gt;
# To upload a new photo:&lt;br /&gt;
#* click the &amp;quot;Browse&amp;quot; button at the bottom&lt;br /&gt;
#* find the image on your computer, and double-click it to select the image&lt;br /&gt;
#* click the &amp;quot;Upload&amp;quot; button and wait for the upload to complete&lt;br /&gt;
#* if the window goes blank, right-click in the window and select &amp;quot;Reload&amp;quot; or &amp;quot;Refresh&amp;quot; to update the list of photos.&lt;br /&gt;
# If you have already uploaded your photo, you can click on it to select the photo.&lt;br /&gt;
# Other options (changes will show in the preview area):&lt;br /&gt;
#* Type a number in the &amp;quot;Border&amp;quot; field if you want a border (0=no border; 1=thin border; 2 and up correspond with the thickness of the border)&lt;br /&gt;
#* HSpace is the space on the left and right of the image&lt;br /&gt;
#* VSpace is the space above and below the image&lt;br /&gt;
#* The Alternate Text is what will show if you &amp;quot;hover&amp;quot; your mouse above the image, or if your visitor's web browser is set to block images&lt;br /&gt;
#* The &amp;quot;Link&amp;quot; tab allows you to make the image a link. You can either type the web address in the &amp;quot;URL&amp;quot; or click the &amp;quot;Browse Server&amp;quot; button to activate the Resource Browser window (this works the same way as it does in the &amp;quot;To upload a new photo&amp;quot; instructions above). The &amp;quot;Target&amp;quot; drop-down allows you to change the target window of the link.&lt;br /&gt;
#* Advanced Features - ? (please edit this page and add info on the Advanced Features tab if you have used it)&lt;br /&gt;
# When you are happy with your changes, click the &amp;quot;OK&amp;quot; button. This will close the small window.&lt;br /&gt;
# You can continue to edit your story here, or return to the main editing window. To close the large editing window, click the arrow button [[image:minimize-arrow.jpg]]&lt;br /&gt;
&lt;br /&gt;
=== Archive Options ===&lt;br /&gt;
&lt;br /&gt;
The archive options allow you to set whether the story will be [[Archive Topic|archived]] or deleted on a particular date. The default is for no archiving or deleting. To change the setting, click on the &amp;quot;Archive Options&amp;quot; link and make the desired changes.&lt;br /&gt;
&lt;br /&gt;
=== Permissions ===&lt;br /&gt;
&lt;br /&gt;
Permissions indicate who is allowed to read and edit the story. The default is that anyone can read the story, and only the owner can edit it.&lt;br /&gt;
&lt;br /&gt;
The possible permission options are:&lt;br /&gt;
* Anonymous visitors (not logged-in) - read-access on or off&lt;br /&gt;
* Members (logged-in) - read-access on or off&lt;br /&gt;
* Group members (must be logged-in) - read-access on or off; edit-access on or off&lt;br /&gt;
* Owner (must be logged-in) - read-access on or off; edit-access on or off&lt;br /&gt;
&lt;br /&gt;
To allow only members to read the story, de-select the check-box under &amp;quot;Anonymous&amp;quot;. Members must log into the site before they can read the article.&lt;br /&gt;
&lt;br /&gt;
To prevent members from reading the story (e.g. if you have a story about creating a user-account and don't want it to show once they have logged in), de-select the check-box under &amp;quot;Members&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
Geeklog also has permissions set by groups. By default, the Admin account and any account with Root access is a member of all groups except Remote Users. Members can also be assigned selectively to individual groups (e.g. &amp;quot;Story Admin&amp;quot;). By changing the group showing in the drop-down box and selecting the check-box &amp;quot;E&amp;quot; under &amp;quot;Groups&amp;quot;, you will allow anyone in the selected group to be able to edit the story.&lt;br /&gt;
&lt;br /&gt;
You will want to retain read- and edit-access to your story. De-selecting those options does not seem to remove your read- and edit-access, but you are advised against changing that because you may lock yourself out of the story.&lt;br /&gt;
&lt;br /&gt;
=== Show All ===&lt;br /&gt;
&lt;br /&gt;
The &amp;quot;Show All&amp;quot; link allows you to see and edit the story, publish options, images, archive options and permissions on one page.&lt;/div&gt;</summary>
		<author><name>LWC</name></author>	</entry>

	<entry>
		<id>http://gwiki3.thatlinuxbox.com/index.php?title=Submitting_Patches&amp;diff=5797</id>
		<title>Submitting Patches</title>
		<link rel="alternate" type="text/html" href="http://gwiki3.thatlinuxbox.com/index.php?title=Submitting_Patches&amp;diff=5797"/>
				<updated>2010-04-05T10:32:34Z</updated>
		
		<summary type="html">&lt;p&gt;LWC: Added title and fixed typo&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;If you want to submit a patch for Geeklog, please check out the current development version from our [[Using Mercurial|Mercurial]] repository. You can also submit patches against released versions by checking out that version's code using the &amp;lt;tt&amp;gt;..._stable&amp;lt;/tt&amp;gt; [[Tags and Branches|tag]].&lt;br /&gt;
&lt;br /&gt;
==Checklist==&lt;br /&gt;
* check out the source code&lt;br /&gt;
* make the necessary changes to the source&lt;br /&gt;
* commit changes into your local repository&lt;br /&gt;
* Exporting:&lt;br /&gt;
** export the changeset using &amp;lt;tt&amp;gt;hg export REV&amp;lt;/tt&amp;gt; where &amp;lt;tt&amp;gt;REV&amp;lt;/tt&amp;gt; is the revision number of the changeset&lt;br /&gt;
*** to export the latest changeset from your repository, simply use &amp;lt;pre&amp;gt;hg export tip&amp;lt;/pre&amp;gt;&lt;br /&gt;
*** The TortoiseHg GUI equivalence is: '''Hg Repository Explorer=&amp;gt;choose Changeset=&amp;gt;Export Patch'''&lt;br /&gt;
* if your patch consists of more than one changeset, please export them individually into separate files with consecutive numbers so we know in which order they need to be applied (Note: while &amp;lt;tt&amp;gt;hg export&amp;lt;/tt&amp;gt; can export multiple changesets into one file, the equivalent &amp;lt;tt&amp;gt;hg import&amp;lt;/tt&amp;gt; currently only accepts one changeset per file, so we're asking for separate files.)&lt;br /&gt;
* Diff files:&lt;br /&gt;
** if you are '''not''' using &amp;lt;tt&amp;gt;hg export&amp;lt;/tt&amp;gt; please send ''unified'' diff files and make sure you list the files in the correct order, i.e. &amp;lt;pre&amp;gt;diff -u original-file modified-file &amp;gt; patch.diff&amp;lt;/pre&amp;gt;&lt;br /&gt;
** The TortoiseHg GUI equivalence is: '''Hg Commit=&amp;gt;Diff''' ''(?)''&lt;br /&gt;
* add the patch (or zipped/gzipped set of patches) as an attachment to the bug or feature request in question on our [http://project.geeklog.net/tracking/ bugtracker]&lt;br /&gt;
** if there is no bug or feature request for your patch, send the patch (with an explanation) to the [http://eight.pairlist.net/mailman/admindb/geeklog-devel geeklog-devel] mailing list (if the patch is really huge, you may want to upload it somewhere and only send the URL)&lt;br /&gt;
&lt;br /&gt;
Thank you!&lt;br /&gt;
&lt;br /&gt;
== diff vs. hg export ==&lt;br /&gt;
&lt;br /&gt;
You may be wondering why we're asking you to use &amp;lt;tt&amp;gt;hg export&amp;lt;/tt&amp;gt; instead of the more common &amp;lt;tt&amp;gt;diff&amp;lt;/tt&amp;gt; files. That is because export files&lt;br /&gt;
* include the checkin comment&lt;br /&gt;
* give proper attribution to the person who created the patch (i.e. '''you''')&lt;br /&gt;
&lt;br /&gt;
[[Category:Development]]&lt;/div&gt;</summary>
		<author><name>LWC</name></author>	</entry>

	<entry>
		<id>http://gwiki3.thatlinuxbox.com/index.php?title=Submitting_Patches&amp;diff=5796</id>
		<title>Submitting Patches</title>
		<link rel="alternate" type="text/html" href="http://gwiki3.thatlinuxbox.com/index.php?title=Submitting_Patches&amp;diff=5796"/>
				<updated>2010-04-05T10:31:54Z</updated>
		
		<summary type="html">&lt;p&gt;LWC: GUI equivalence&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;If you want to submit a patch for Geeklog, please check out the current development version from our [[Using Mercurial|Mercurial]] repository. You can also submit patches against released versions by checking out that version's code using the &amp;lt;tt&amp;gt;..._stable&amp;lt;/tt&amp;gt; [[Tags and Branches|tag]].&lt;br /&gt;
&lt;br /&gt;
* check out the source code&lt;br /&gt;
* make the necessary changes to the source&lt;br /&gt;
* commit changes into your local repository&lt;br /&gt;
* Exporting:&lt;br /&gt;
** export the changeset using &amp;lt;tt&amp;gt;hg export REV&amp;lt;/tt&amp;gt; where &amp;lt;tt&amp;gt;REV&amp;lt;/tt&amp;gt; is the revision number of the changeset&lt;br /&gt;
*** to export the latest changeset from your repository, simply use &amp;lt;pre&amp;gt;hg export tip&amp;lt;/pre&amp;gt;&lt;br /&gt;
*** The TortoiseHg GUI equivalence is: '''Hd Repository Explorer=&amp;gt;choose Changeset=&amp;gt;Export Patch'''&lt;br /&gt;
* if your patch consists of more than one changeset, please export them individually into separate files with consecutive numbers so we know in which order they need to be applied (Note: while &amp;lt;tt&amp;gt;hg export&amp;lt;/tt&amp;gt; can export multiple changesets into one file, the equivalent &amp;lt;tt&amp;gt;hg import&amp;lt;/tt&amp;gt; currently only accepts one changeset per file, so we're asking for separate files.)&lt;br /&gt;
* Diff files:&lt;br /&gt;
** if you are '''not''' using &amp;lt;tt&amp;gt;hg export&amp;lt;/tt&amp;gt; please send ''unified'' diff files and make sure you list the files in the correct order, i.e. &amp;lt;pre&amp;gt;diff -u original-file modified-file &amp;gt; patch.diff&amp;lt;/pre&amp;gt;&lt;br /&gt;
** The TortoiseHg GUI equivalence is: '''Hg Commit=&amp;gt;Diff''' ''(?)''&lt;br /&gt;
* add the patch (or zipped/gzipped set of patches) as an attachment to the bug or feature request in question on our [http://project.geeklog.net/tracking/ bugtracker]&lt;br /&gt;
** if there is no bug or feature request for your patch, send the patch (with an explanation) to the [http://eight.pairlist.net/mailman/admindb/geeklog-devel geeklog-devel] mailing list (if the patch is really huge, you may want to upload it somewhere and only send the URL)&lt;br /&gt;
&lt;br /&gt;
Thank you!&lt;br /&gt;
&lt;br /&gt;
== diff vs. hg export ==&lt;br /&gt;
&lt;br /&gt;
You may be wondering why we're asking you to use &amp;lt;tt&amp;gt;hg export&amp;lt;/tt&amp;gt; instead of the more common &amp;lt;tt&amp;gt;diff&amp;lt;/tt&amp;gt; files. That is because export files&lt;br /&gt;
* include the checkin comment&lt;br /&gt;
* give proper attribution to the person who created the patch (i.e. '''you''')&lt;br /&gt;
&lt;br /&gt;
[[Category:Development]]&lt;/div&gt;</summary>
		<author><name>LWC</name></author>	</entry>

	<entry>
		<id>http://gwiki3.thatlinuxbox.com/index.php?title=InstallFaq&amp;diff=5789</id>
		<title>InstallFaq</title>
		<link rel="alternate" type="text/html" href="http://gwiki3.thatlinuxbox.com/index.php?title=InstallFaq&amp;diff=5789"/>
				<updated>2010-03-25T20:39:32Z</updated>
		
		<summary type="html">&lt;p&gt;LWC: /* What are the System Requirments for Geeklog? */ LightTPD&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;'''Note:''' You may also want to check [http://www.geeklog.net/faqman/ the FAQs on geeklog.net] as some of the information here may be out of date or incomplete.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Configuring Email (Geeklog 1.3.9 and newer versions) ==&lt;br /&gt;
&lt;br /&gt;
Starting with version 1.3.9, Geeklog uses the PEAR::Mail class to send all emails, offering you the following methods to send emails:&lt;br /&gt;
*'smtp', i.e. using an SMTP server&lt;br /&gt;
*'mail', i.e. using PHP's built-in mail function&lt;br /&gt;
*'sendmail', i.e. using the Unix sendmail application&lt;br /&gt;
&lt;br /&gt;
All the following settings can be found in your config.php.&lt;br /&gt;
&lt;br /&gt;
=== SMTP ===&lt;br /&gt;
&lt;br /&gt;
To configure Geeklog to send all emails using an SMTP server, set 'backend' to 'smtp' and enter the information to contact your SMTP server as follows:&lt;br /&gt;
&lt;br /&gt;
:'host'     =&amp;gt; 'name of your smtp server',    &lt;br /&gt;
:'port'     =&amp;gt; '25',     &lt;br /&gt;
:'auth'     =&amp;gt; false,    &lt;br /&gt;
:'username' =&amp;gt; 'your smtp username',    &lt;br /&gt;
:'password' =&amp;gt; 'your smtp password'&lt;br /&gt;
&lt;br /&gt;
You should have gotten these settings from your ISP. The name of the smtp server is usually something like 'smtp.your-domain.com' but in some cases it's simply 'localhost'. The port number is usually 25. The 'auth' option tells Geeklog whether to use authentication or not (set to true for authentication).&lt;br /&gt;
&lt;br /&gt;
=== mail ===&lt;br /&gt;
&lt;br /&gt;
When setting 'backend' to 'mail' (which is also the default) Geeklog will use PHP's built-in mail() function. None of the other $_CONF['mail_settings'] options have to be changed for this.&lt;br /&gt;
&lt;br /&gt;
This is almost like what Geeklog used in versions prior to 1.3.9. There is, however, a difference in how PEAR::Mail implements this option so that 'mail' can not be used when safe_mode is activate on your webserver. You will have to use one of the other options if that is the case for you.&lt;br /&gt;
&lt;br /&gt;
=== sendmail ===&lt;br /&gt;
&lt;br /&gt;
On most setups, there isn't any benefit in using this option - it's mainly provided for completeness. You can set the path to the sendmail binary ('sendmail_path') and pass additional arguments to sendmail by setting 'sendmail_args' accordingly.&lt;br /&gt;
&lt;br /&gt;
=== Which method should I use? ===&lt;br /&gt;
&lt;br /&gt;
If you can, SMTP is probably the best method to use. It ensures that the email is sent through your SMTP server which reduces the chances that emails are regarded as spam by some of the more strict mail filters.&lt;br /&gt;
&lt;br /&gt;
'mail' is the second-best option but, as noted above, won't work when safe_mode is on.&lt;br /&gt;
&lt;br /&gt;
=== A fourth option ===&lt;br /&gt;
&lt;br /&gt;
If none of the above methods work for you, there is a fourth option: You can implement your own function to send email. This may be necessary on some free hosting services that disable PHP's mail function.&lt;br /&gt;
&lt;br /&gt;
The function must be called CUSTOM_mail. A sample implementation is included in the lib-custom.php file that ships with Geeklog. This sample code is a re-implementation of the way Geeklog sent emails prior to 1.3.9. It also uses PHP's mail function, but in such a way that it will work when safe_mode is on.&lt;br /&gt;
&lt;br /&gt;
Please note that the function is commented out by default - you will have to remove the comments around the function before it will be used.&lt;br /&gt;
&lt;br /&gt;
== Geeklog on PHP 5 ==&lt;br /&gt;
&lt;br /&gt;
Here are some initial observations, a few days after the official release of PHP 5.0.0:&lt;br /&gt;
&lt;br /&gt;
*The links to plugins don't show up properly in the Admin and User Functions blocks, as well as in the &amp;quot;Command and Control&amp;quot; block. The problem is in lib-plugins.php and a fix (for Geeklog 1.3.9sr1) is available from CVS.&lt;br /&gt;
*Make sure you have register_long_arrays = On in your php.ini. For compatibility with old versions of PHP 4, Geeklog relies on the &amp;quot;old-style&amp;quot; input arrays, $HTTP_POST_VARS and $HTTP_GET_VARS.&lt;br /&gt;
*Don't forget to switch register_globals = On&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== How can I upgrade from a version of Geeklog older than 1.2.5-1? ==&lt;br /&gt;
&lt;br /&gt;
If you are running a version of Geeklog older than 1.2.5-1 you will need to upgrade your database from your current version to 1.2.5-1 using the SQL scripts in the sql/updates directory. Once you have the database upgraded to 1.2.5-1 you can run the installation script to upgrade to the current version.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== How do I find out my paths? ==&lt;br /&gt;
&lt;br /&gt;
Just call up the install script &amp;lt;b&amp;gt;&amp;lt;nowiki&amp;gt;http://yourgeeklogsite/admin/install/install.php&amp;lt;/nowiki&amp;gt;&amp;lt;/b&amp;gt;. At the bottom of the page, it will give you a hint what the complete path to the install script is and, depending on your configuration, it may also tell you what you need to set as your &amp;quot;path to geeklog&amp;quot;. You should be able to figure the paths out from these hints.&lt;br /&gt;
&lt;br /&gt;
If you have shell access to your webserver, another way to find out the proper paths is to change to the directories in question (e.g. the one where the config.php resides) and enter the Unix pwd command, which will print out the current path.&lt;br /&gt;
&lt;br /&gt;
== How do I setup PHP mail for Windows? ==&lt;br /&gt;
&lt;br /&gt;
Geeklog prior to version 1.3.9 uses the built-in mail function in PHP. In your php.ini file find the following section header: [mail function]&lt;br /&gt;
&lt;br /&gt;
Setup the smtp directive to either you local server or your ISP. Also setup the sendmail_from directive. That should do it. &lt;br /&gt;
&lt;br /&gt;
[mail function]&lt;br /&gt;
; For Win32 only.&lt;br /&gt;
SMTP = mail.mw.centurytel.net&lt;br /&gt;
&lt;br /&gt;
; For Win32 only.&lt;br /&gt;
sendmail_from = admim@somegeeklogsite.com&lt;br /&gt;
&lt;br /&gt;
; For Unix only. You may supply arguments as well (default: &amp;quot;sendmail -t -i&amp;quot;).&lt;br /&gt;
;sendmail_path =&lt;br /&gt;
&lt;br /&gt;
Starting with Geeklog 1.3.9, you can make those settings in Geeklog's config.php instead. See this FAQ for details.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Migrating a Geeklog Site ==&lt;br /&gt;
&lt;br /&gt;
Sooner or later, you'll be facing the problem of having to move your Geeklog site from one server to another, e.g. when changing hosting services. Here are a few tips to successfully make that transition:&lt;br /&gt;
&lt;br /&gt;
#Create a '''backup''' of your Geeklog database on your old server&lt;br /&gt;
#Make backups of the story images in the images/articles and the userphotos in the images/userphoto directories&lt;br /&gt;
#Make a backup of your config.php for reference&lt;br /&gt;
#Make a backup of your theme&lt;br /&gt;
&lt;br /&gt;
We'd suggest that you start with a fresh install on your new site. Moving your site is also the perfect opportunity to upgrade if you haven't been running the latest version of Geeklog anyway (use the &amp;quot;GL Version Test&amp;quot; link on your old site to check if you are running the current version).&lt;br /&gt;
&lt;br /&gt;
Once you have Geeklog up and running on the new server, you can drop the database, create an empty database again, and then import the database backup from your old site (see Restoring a database backup).&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
*If you had any plugins installed (besides the Static Pages plugin), you should now upload their files on the new server as well (don't run any install scripts for those plugins, though).&lt;br /&gt;
*Upload your story images and userphotos into their new locations.&lt;br /&gt;
*If you're upgrading to a new Geeklog version in the process, then don't upload your theme just yet. New Geeklog versions usually include changes in the theme files and you should use one of the included default themes until you can be sure your migrated site works properly.&lt;br /&gt;
*If you're upgrading your Geeklog site, run the install script in upgrade mode now.&lt;br /&gt;
*If you've updated any of your plugins, run their upgrade scripts now, if necessary (please refer to the documentation of your plugins to see if that is necessary).&lt;br /&gt;
*Make sure everything works properly. See if you can edit stories, for example.&lt;br /&gt;
*Update your theme, if necessary. Refer to Geeklog's theme documentation for a list of changes in the themes.&lt;br /&gt;
&lt;br /&gt;
That's it. You've successfully migrated your Geeklog site.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Common problems ===&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
*Make sure register_globals=on on your new server.&lt;br /&gt;
: You can check this by creating a file (in a text editor) with the following line:&lt;br /&gt;
&amp;lt;pre&amp;gt;&amp;lt;?php phpinfo(); ?&amp;gt;&amp;lt;/pre&amp;gt;&lt;br /&gt;
: Save this file somewhere on your server as &amp;quot;phpinfo.php&amp;quot; and load it up in your browser.  This will generate a nice table with all the current settings of your php installation.  If register_globals is OFF, [[#Will Geeklog work with register_globals off?|see the tip below]].&lt;br /&gt;
&lt;br /&gt;
*If the URL of your site changed, then the URLs to any uploaded images in your stories will still point to your old site. There is, unfortunately, no easy solution for this yet, so you'll have to edit those image URLs in the database directly (using phpMyAdmin). This is currently listed as a bug and will be addressed in a future version of Geeklog.&lt;br /&gt;
&lt;br /&gt;
== What are the System Requirments for Geeklog? ==&lt;br /&gt;
&lt;br /&gt;
Geeklog requires [http://www.php.net PHP], [http://www.mysql.com MySQL] and a webserver that works with these.&lt;br /&gt;
&lt;br /&gt;
'''PHP''': The minimum PHP version required is '''PHP 4.0.4'''. However, that version is very much out of date (and has security issues), so we suggest you use PHP 4.1.2 at the very least. Or, better yet, use the most up to date version available at the time you're reading this.&lt;br /&gt;
&lt;br /&gt;
At the time of this writing, PHP 5 is still in Beta. As one of the main goals of PHP 5 development was to keep compatibility with PHP 4, we do not expect any serious problems with PHP 5. We plan to be fully compatible with PHP 5 when it is released.&lt;br /&gt;
&lt;br /&gt;
'''MS SQL''': Microsoft SQL Server 2000 or above.&lt;br /&gt;
&lt;br /&gt;
'''MySQL''': While we try to be compatible with MySQL down to version 3.22, we recommend using the most up to date version of the 3.23 or 4.0 variety available at the time you're reading this.&lt;br /&gt;
&lt;br /&gt;
Please note that because of possible SQL injection problems, we do not recommend using Geeklog on MySQL 4.1 (which is still in Alpha state at the time of this writing). We plan to resolve any outstanding issues with the release of Geeklog 1.3.9 in early 2004.&lt;br /&gt;
&lt;br /&gt;
'''Webserver''': Geeklog is known to work with the Apache, Zeus, Microsoft IIS and LightTPD webservers. As with the other components, it is suggested to use the most up to date version available at the time you're reading this.&lt;br /&gt;
&lt;br /&gt;
A note about Apache 2 compatibility: At the time of this writing, there was still no official word from the PHP developers regarding compatibility of PHP 4 and Apache 2. There are, however, several sites running without any problems on this combination. Again, it is suggested to use the most up to date version of both Apache and PHP.&lt;br /&gt;
&lt;br /&gt;
== Where Do I enter the mail server configuration? ==&lt;br /&gt;
&lt;br /&gt;
For Geeklog 1.3.9 and newer versions, please see [[#Configuring_Email_(Geeklog_1.3.9_and_newer_versions)|this FAQ entry]].&lt;br /&gt;
&lt;br /&gt;
Older Geeklog versions simply use PHP's mail() function to send all email. To make that function work, you will need to edit your php.ini file.&lt;br /&gt;
&lt;br /&gt;
The [http://www.php.net/manual/en/ref.mail.php PHP manual] has all the information you need.&lt;br /&gt;
&lt;br /&gt;
In case your site is running on Windows, [[#How do I setup PHP mail for Windows?|this FAQ entry]] has additional information.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Will you install Geeklog for me? ==&lt;br /&gt;
&lt;br /&gt;
Sure. The people listed in [http://www.geeklog.net/article.php?story=20030818224145271 this story] will be more than willing to install it for you.&lt;br /&gt;
&lt;br /&gt;
== Will Geeklog work with register_globals off? ==&lt;br /&gt;
&lt;br /&gt;
Only Geeklog 1.4.0 and later versions will work with &amp;lt;code&amp;gt;register_globals = off&amp;lt;/code&amp;gt;. Older versions as well as some plugins and other add-ons still require it to be &amp;quot;on&amp;quot;. &lt;br /&gt;
&lt;br /&gt;
[[#Common problems|How to tell if it's on or off]]&lt;br /&gt;
&lt;br /&gt;
If you can't set &amp;lt;code&amp;gt;register_globals = on&amp;lt;/code&amp;gt; in &amp;lt;tt&amp;gt;php.ini&amp;lt;/tt&amp;gt; (e.g. because you don't have access to it) you can try to create a &amp;lt;tt&amp;gt;.htaccess&amp;lt;/tt&amp;gt; file in your document root that has this line in it:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;php_flag register_globals on&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This will only work when your webserver is Apache (does a similar option exist for IIS?) and when it's configured such that it lets you override the &amp;lt;code&amp;gt;register_globals&amp;lt;/code&amp;gt; setting.&lt;br /&gt;
&lt;br /&gt;
See also: Isn't it a security risk to have register_globals=on?&lt;/div&gt;</summary>
		<author><name>LWC</name></author>	</entry>

	<entry>
		<id>http://gwiki3.thatlinuxbox.com/index.php?title=InstallFaq&amp;diff=5788</id>
		<title>InstallFaq</title>
		<link rel="alternate" type="text/html" href="http://gwiki3.thatlinuxbox.com/index.php?title=InstallFaq&amp;diff=5788"/>
				<updated>2010-03-25T20:38:35Z</updated>
		
		<summary type="html">&lt;p&gt;LWC: /* What are the System Requirments for Geeklog? */ MS SQL is supported too&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;'''Note:''' You may also want to check [http://www.geeklog.net/faqman/ the FAQs on geeklog.net] as some of the information here may be out of date or incomplete.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Configuring Email (Geeklog 1.3.9 and newer versions) ==&lt;br /&gt;
&lt;br /&gt;
Starting with version 1.3.9, Geeklog uses the PEAR::Mail class to send all emails, offering you the following methods to send emails:&lt;br /&gt;
*'smtp', i.e. using an SMTP server&lt;br /&gt;
*'mail', i.e. using PHP's built-in mail function&lt;br /&gt;
*'sendmail', i.e. using the Unix sendmail application&lt;br /&gt;
&lt;br /&gt;
All the following settings can be found in your config.php.&lt;br /&gt;
&lt;br /&gt;
=== SMTP ===&lt;br /&gt;
&lt;br /&gt;
To configure Geeklog to send all emails using an SMTP server, set 'backend' to 'smtp' and enter the information to contact your SMTP server as follows:&lt;br /&gt;
&lt;br /&gt;
:'host'     =&amp;gt; 'name of your smtp server',    &lt;br /&gt;
:'port'     =&amp;gt; '25',     &lt;br /&gt;
:'auth'     =&amp;gt; false,    &lt;br /&gt;
:'username' =&amp;gt; 'your smtp username',    &lt;br /&gt;
:'password' =&amp;gt; 'your smtp password'&lt;br /&gt;
&lt;br /&gt;
You should have gotten these settings from your ISP. The name of the smtp server is usually something like 'smtp.your-domain.com' but in some cases it's simply 'localhost'. The port number is usually 25. The 'auth' option tells Geeklog whether to use authentication or not (set to true for authentication).&lt;br /&gt;
&lt;br /&gt;
=== mail ===&lt;br /&gt;
&lt;br /&gt;
When setting 'backend' to 'mail' (which is also the default) Geeklog will use PHP's built-in mail() function. None of the other $_CONF['mail_settings'] options have to be changed for this.&lt;br /&gt;
&lt;br /&gt;
This is almost like what Geeklog used in versions prior to 1.3.9. There is, however, a difference in how PEAR::Mail implements this option so that 'mail' can not be used when safe_mode is activate on your webserver. You will have to use one of the other options if that is the case for you.&lt;br /&gt;
&lt;br /&gt;
=== sendmail ===&lt;br /&gt;
&lt;br /&gt;
On most setups, there isn't any benefit in using this option - it's mainly provided for completeness. You can set the path to the sendmail binary ('sendmail_path') and pass additional arguments to sendmail by setting 'sendmail_args' accordingly.&lt;br /&gt;
&lt;br /&gt;
=== Which method should I use? ===&lt;br /&gt;
&lt;br /&gt;
If you can, SMTP is probably the best method to use. It ensures that the email is sent through your SMTP server which reduces the chances that emails are regarded as spam by some of the more strict mail filters.&lt;br /&gt;
&lt;br /&gt;
'mail' is the second-best option but, as noted above, won't work when safe_mode is on.&lt;br /&gt;
&lt;br /&gt;
=== A fourth option ===&lt;br /&gt;
&lt;br /&gt;
If none of the above methods work for you, there is a fourth option: You can implement your own function to send email. This may be necessary on some free hosting services that disable PHP's mail function.&lt;br /&gt;
&lt;br /&gt;
The function must be called CUSTOM_mail. A sample implementation is included in the lib-custom.php file that ships with Geeklog. This sample code is a re-implementation of the way Geeklog sent emails prior to 1.3.9. It also uses PHP's mail function, but in such a way that it will work when safe_mode is on.&lt;br /&gt;
&lt;br /&gt;
Please note that the function is commented out by default - you will have to remove the comments around the function before it will be used.&lt;br /&gt;
&lt;br /&gt;
== Geeklog on PHP 5 ==&lt;br /&gt;
&lt;br /&gt;
Here are some initial observations, a few days after the official release of PHP 5.0.0:&lt;br /&gt;
&lt;br /&gt;
*The links to plugins don't show up properly in the Admin and User Functions blocks, as well as in the &amp;quot;Command and Control&amp;quot; block. The problem is in lib-plugins.php and a fix (for Geeklog 1.3.9sr1) is available from CVS.&lt;br /&gt;
*Make sure you have register_long_arrays = On in your php.ini. For compatibility with old versions of PHP 4, Geeklog relies on the &amp;quot;old-style&amp;quot; input arrays, $HTTP_POST_VARS and $HTTP_GET_VARS.&lt;br /&gt;
*Don't forget to switch register_globals = On&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== How can I upgrade from a version of Geeklog older than 1.2.5-1? ==&lt;br /&gt;
&lt;br /&gt;
If you are running a version of Geeklog older than 1.2.5-1 you will need to upgrade your database from your current version to 1.2.5-1 using the SQL scripts in the sql/updates directory. Once you have the database upgraded to 1.2.5-1 you can run the installation script to upgrade to the current version.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== How do I find out my paths? ==&lt;br /&gt;
&lt;br /&gt;
Just call up the install script &amp;lt;b&amp;gt;&amp;lt;nowiki&amp;gt;http://yourgeeklogsite/admin/install/install.php&amp;lt;/nowiki&amp;gt;&amp;lt;/b&amp;gt;. At the bottom of the page, it will give you a hint what the complete path to the install script is and, depending on your configuration, it may also tell you what you need to set as your &amp;quot;path to geeklog&amp;quot;. You should be able to figure the paths out from these hints.&lt;br /&gt;
&lt;br /&gt;
If you have shell access to your webserver, another way to find out the proper paths is to change to the directories in question (e.g. the one where the config.php resides) and enter the Unix pwd command, which will print out the current path.&lt;br /&gt;
&lt;br /&gt;
== How do I setup PHP mail for Windows? ==&lt;br /&gt;
&lt;br /&gt;
Geeklog prior to version 1.3.9 uses the built-in mail function in PHP. In your php.ini file find the following section header: [mail function]&lt;br /&gt;
&lt;br /&gt;
Setup the smtp directive to either you local server or your ISP. Also setup the sendmail_from directive. That should do it. &lt;br /&gt;
&lt;br /&gt;
[mail function]&lt;br /&gt;
; For Win32 only.&lt;br /&gt;
SMTP = mail.mw.centurytel.net&lt;br /&gt;
&lt;br /&gt;
; For Win32 only.&lt;br /&gt;
sendmail_from = admim@somegeeklogsite.com&lt;br /&gt;
&lt;br /&gt;
; For Unix only. You may supply arguments as well (default: &amp;quot;sendmail -t -i&amp;quot;).&lt;br /&gt;
;sendmail_path =&lt;br /&gt;
&lt;br /&gt;
Starting with Geeklog 1.3.9, you can make those settings in Geeklog's config.php instead. See this FAQ for details.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Migrating a Geeklog Site ==&lt;br /&gt;
&lt;br /&gt;
Sooner or later, you'll be facing the problem of having to move your Geeklog site from one server to another, e.g. when changing hosting services. Here are a few tips to successfully make that transition:&lt;br /&gt;
&lt;br /&gt;
#Create a '''backup''' of your Geeklog database on your old server&lt;br /&gt;
#Make backups of the story images in the images/articles and the userphotos in the images/userphoto directories&lt;br /&gt;
#Make a backup of your config.php for reference&lt;br /&gt;
#Make a backup of your theme&lt;br /&gt;
&lt;br /&gt;
We'd suggest that you start with a fresh install on your new site. Moving your site is also the perfect opportunity to upgrade if you haven't been running the latest version of Geeklog anyway (use the &amp;quot;GL Version Test&amp;quot; link on your old site to check if you are running the current version).&lt;br /&gt;
&lt;br /&gt;
Once you have Geeklog up and running on the new server, you can drop the database, create an empty database again, and then import the database backup from your old site (see Restoring a database backup).&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
*If you had any plugins installed (besides the Static Pages plugin), you should now upload their files on the new server as well (don't run any install scripts for those plugins, though).&lt;br /&gt;
*Upload your story images and userphotos into their new locations.&lt;br /&gt;
*If you're upgrading to a new Geeklog version in the process, then don't upload your theme just yet. New Geeklog versions usually include changes in the theme files and you should use one of the included default themes until you can be sure your migrated site works properly.&lt;br /&gt;
*If you're upgrading your Geeklog site, run the install script in upgrade mode now.&lt;br /&gt;
*If you've updated any of your plugins, run their upgrade scripts now, if necessary (please refer to the documentation of your plugins to see if that is necessary).&lt;br /&gt;
*Make sure everything works properly. See if you can edit stories, for example.&lt;br /&gt;
*Update your theme, if necessary. Refer to Geeklog's theme documentation for a list of changes in the themes.&lt;br /&gt;
&lt;br /&gt;
That's it. You've successfully migrated your Geeklog site.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Common problems ===&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
*Make sure register_globals=on on your new server.&lt;br /&gt;
: You can check this by creating a file (in a text editor) with the following line:&lt;br /&gt;
&amp;lt;pre&amp;gt;&amp;lt;?php phpinfo(); ?&amp;gt;&amp;lt;/pre&amp;gt;&lt;br /&gt;
: Save this file somewhere on your server as &amp;quot;phpinfo.php&amp;quot; and load it up in your browser.  This will generate a nice table with all the current settings of your php installation.  If register_globals is OFF, [[#Will Geeklog work with register_globals off?|see the tip below]].&lt;br /&gt;
&lt;br /&gt;
*If the URL of your site changed, then the URLs to any uploaded images in your stories will still point to your old site. There is, unfortunately, no easy solution for this yet, so you'll have to edit those image URLs in the database directly (using phpMyAdmin). This is currently listed as a bug and will be addressed in a future version of Geeklog.&lt;br /&gt;
&lt;br /&gt;
== What are the System Requirments for Geeklog? ==&lt;br /&gt;
&lt;br /&gt;
Geeklog requires [http://www.php.net PHP], [http://www.mysql.com MySQL] and a webserver that works with these.&lt;br /&gt;
&lt;br /&gt;
'''PHP''': The minimum PHP version required is '''PHP 4.0.4'''. However, that version is very much out of date (and has security issues), so we suggest you use PHP 4.1.2 at the very least. Or, better yet, use the most up to date version available at the time you're reading this.&lt;br /&gt;
&lt;br /&gt;
At the time of this writing, PHP 5 is still in Beta. As one of the main goals of PHP 5 development was to keep compatibility with PHP 4, we do not expect any serious problems with PHP 5. We plan to be fully compatible with PHP 5 when it is released.&lt;br /&gt;
&lt;br /&gt;
'''MS SQL''': Microsoft SQL Server 2000 or above.&lt;br /&gt;
&lt;br /&gt;
'''MySQL''': While we try to be compatible with MySQL down to version 3.22, we recommend using the most up to date version of the 3.23 or 4.0 variety available at the time you're reading this.&lt;br /&gt;
&lt;br /&gt;
Please note that because of possible SQL injection problems, we do not recommend using Geeklog on MySQL 4.1 (which is still in Alpha state at the time of this writing). We plan to resolve any outstanding issues with the release of Geeklog 1.3.9 in early 2004.&lt;br /&gt;
&lt;br /&gt;
'''Webserver''': Geeklog is known to work with the Apache, Zeus, and Microsoft IIS webservers. As with the other components, it is suggested to use the most up to date version available at the time you're reading this.&lt;br /&gt;
&lt;br /&gt;
A note about Apache 2 compatibility: At the time of this writing, there was still no official word from the PHP developers regarding compatibility of PHP 4 and Apache 2. There are, however, several sites running without any problems on this combination. Again, it is suggested to use the most up to date version of both Apache and PHP.&lt;br /&gt;
&lt;br /&gt;
== Where Do I enter the mail server configuration? ==&lt;br /&gt;
&lt;br /&gt;
For Geeklog 1.3.9 and newer versions, please see [[#Configuring_Email_(Geeklog_1.3.9_and_newer_versions)|this FAQ entry]].&lt;br /&gt;
&lt;br /&gt;
Older Geeklog versions simply use PHP's mail() function to send all email. To make that function work, you will need to edit your php.ini file.&lt;br /&gt;
&lt;br /&gt;
The [http://www.php.net/manual/en/ref.mail.php PHP manual] has all the information you need.&lt;br /&gt;
&lt;br /&gt;
In case your site is running on Windows, [[#How do I setup PHP mail for Windows?|this FAQ entry]] has additional information.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Will you install Geeklog for me? ==&lt;br /&gt;
&lt;br /&gt;
Sure. The people listed in [http://www.geeklog.net/article.php?story=20030818224145271 this story] will be more than willing to install it for you.&lt;br /&gt;
&lt;br /&gt;
== Will Geeklog work with register_globals off? ==&lt;br /&gt;
&lt;br /&gt;
Only Geeklog 1.4.0 and later versions will work with &amp;lt;code&amp;gt;register_globals = off&amp;lt;/code&amp;gt;. Older versions as well as some plugins and other add-ons still require it to be &amp;quot;on&amp;quot;. &lt;br /&gt;
&lt;br /&gt;
[[#Common problems|How to tell if it's on or off]]&lt;br /&gt;
&lt;br /&gt;
If you can't set &amp;lt;code&amp;gt;register_globals = on&amp;lt;/code&amp;gt; in &amp;lt;tt&amp;gt;php.ini&amp;lt;/tt&amp;gt; (e.g. because you don't have access to it) you can try to create a &amp;lt;tt&amp;gt;.htaccess&amp;lt;/tt&amp;gt; file in your document root that has this line in it:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;php_flag register_globals on&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This will only work when your webserver is Apache (does a similar option exist for IIS?) and when it's configured such that it lets you override the &amp;lt;code&amp;gt;register_globals&amp;lt;/code&amp;gt; setting.&lt;br /&gt;
&lt;br /&gt;
See also: Isn't it a security risk to have register_globals=on?&lt;/div&gt;</summary>
		<author><name>LWC</name></author>	</entry>

	<entry>
		<id>http://gwiki3.thatlinuxbox.com/index.php?title=User_talk:LWC&amp;diff=5771</id>
		<title>User talk:LWC</title>
		<link rel="alternate" type="text/html" href="http://gwiki3.thatlinuxbox.com/index.php?title=User_talk:LWC&amp;diff=5771"/>
				<updated>2010-03-07T19:10:14Z</updated>
		
		<summary type="html">&lt;p&gt;LWC: /* Templates */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;==Templates==&lt;br /&gt;
LWC, I'm not sure if your use of templates for links really improves things. IMHO, it only makes things harder to read. As in &amp;quot;... we will be adopting jQuery as our ...&amp;quot;. What's wrong with having &amp;quot;jQuery&amp;quot; as a link? I can guess where the link goes to and if I don't want to follow it, I can easily ignore it. But with your template, it now reads &amp;quot;... jQuery (Wikipedia entry) as our ...&amp;quot;, which is much harder to read and clutters the sentence with information that I don't need. -- [[User:Dirk|Dirk]] 19:06, 7 March 2010 (UTC)&lt;br /&gt;
: Actually, that one is not a template but just a regular wiki-link. As for the templates, you can just change them to look like what you want. But the bottom line is that I think users deserve to know where they'll be going before clicking external links. This full disclosure is a matter of taste, I guess. If it was Wikipedia, we could do a vote. :-) -[[User:LWC|LWC]] 19:10, 7 March 2010 (UTC)&lt;/div&gt;</summary>
		<author><name>LWC</name></author>	</entry>

	<entry>
		<id>http://gwiki3.thatlinuxbox.com/index.php?title=SoC_improve_configuration_gui&amp;diff=5769</id>
		<title>SoC improve configuration gui</title>
		<link rel="alternate" type="text/html" href="http://gwiki3.thatlinuxbox.com/index.php?title=SoC_improve_configuration_gui&amp;diff=5769"/>
				<updated>2010-03-07T18:53:32Z</updated>
		
		<summary type="html">&lt;p&gt;LWC: Improved links&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&amp;lt;center&amp;gt;(This is an idea page for the [[Google Summer of Code]])&amp;lt;/center&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Incentive ==&lt;br /&gt;
&lt;br /&gt;
This is a continuation of the [[SoC config.php GUI|2007 GSoC project]] that resulted in the current Configuration GUI. This follow-up project is aimed at implementing some of the ideas that didn't make it into the initial version. This is also a good opportunity to do a reality check of the existing GUI and see what's missing and what could be improved.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Details ==&lt;br /&gt;
&lt;br /&gt;
=== More Fine Grained Access Control ===&lt;br /&gt;
&lt;br /&gt;
Currently, only users in Geeklog's &amp;quot;Root&amp;quot; group have access to the Configuration. The idea has always been, however, to make this more fine grained so that, for example, Story Admins could - optionally - have access to configuration options related to stories and story submissions.&lt;br /&gt;
&lt;br /&gt;
==== Define Config Groups ====&lt;br /&gt;
&lt;br /&gt;
As a first step, the existing config options will have to be reviewed and grouped to get an idea which options belong together and to which access can be granted. There will certainly be options for which Root access is still required. Plugins should also be allowed to control access to their config options.&lt;br /&gt;
&lt;br /&gt;
==== Access Control ====&lt;br /&gt;
&lt;br /&gt;
Access control should be implemented on a per-option basis. There are various ways how this could be implemented. One obvious solution could be to introduce &amp;lt;tt&amp;gt;config.*&amp;lt;/tt&amp;gt; permissions, e.g. having &amp;lt;tt&amp;gt;config.story&amp;lt;/tt&amp;gt; permissions would give access to config options related to stories (actually, that's probably too broad and should be more fine grained). But there may be other (better) ways to implement this.&lt;br /&gt;
&lt;br /&gt;
Options for which the current user does not have access should not be displayed. Root users should have access to everything, as usual.&lt;br /&gt;
&lt;br /&gt;
=== JavaScript ===&lt;br /&gt;
&lt;br /&gt;
==== jQuery ====&lt;br /&gt;
The current GUI uses some custom JavaScript code to operate. For future versions of Geeklog, we will be adopting jQuery ([[wikipedia:en:jQuery|Wikipedia entry]]) as our standard JavaScript library. This would be a good opportunity to use jQuery for some non-trivial application, i.e. rewrite the existing JavaScript code for jQuery.&lt;br /&gt;
&lt;br /&gt;
==== UI improvements ====&lt;br /&gt;
&lt;br /&gt;
Other areas where JavaScript could help improve the UI:&lt;br /&gt;
* Some config options depend on each other (e.g. 'language_files' and 'languages'). Some JavaScript code could help prevent setting these options to illegal states that could prevent the site from working properly.&lt;br /&gt;
* Real-time bounds checks: Some config options are displayed as free-form input fields but really only accept numerical values or a certain range of values.&lt;br /&gt;
&lt;br /&gt;
=== Search ===&lt;br /&gt;
&lt;br /&gt;
With over 200 configuration options for the Geeklog core alone, it is sometimes hard to find the config option you're looking for. Being able to search for an option would come in handy.&lt;br /&gt;
&lt;br /&gt;
While this could be implemented as a &amp;quot;traditional&amp;quot; search, something more interactive could make this a really useful feature. This would also be another case that could benefit from the adoption of jQuery.&lt;br /&gt;
&lt;br /&gt;
=== New UI Elements ===&lt;br /&gt;
&lt;br /&gt;
Currently, the Configuration GUI supports dropdowns, input fields (one-line and multi-line) and array-type fields.&lt;br /&gt;
&lt;br /&gt;
Many of the dropdowns, however, only offer true/false options and may be better represented as radio buttons or checkboxes. Review the existing options and implement support for the additional types where required.&lt;br /&gt;
&lt;br /&gt;
There may be other new UI elements that we may want to implement to better represent some of the available options. A pair of fresh eyes (belonging to someone who doesn't know about the $_CONF heritage of the Configuration) could help identify those ...&lt;br /&gt;
&lt;br /&gt;
=== Miscellaneous ===&lt;br /&gt;
&lt;br /&gt;
And then there are a couple of minor details that should be looked into, e.g.&lt;br /&gt;
&lt;br /&gt;
* re-grouping / re-arranging / re-wording options&lt;br /&gt;
* provide direct links to config sections, e.g. {{forum|89704|for plugins}}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Level of Difficulty ==&lt;br /&gt;
&lt;br /&gt;
''medium''&lt;br /&gt;
&lt;br /&gt;
This project involves understanding the existing code and learning how to modify and extend it. Knowledge of JavaScript is required.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Further Reading ==&lt;br /&gt;
&lt;br /&gt;
* [[Configuration Class|Implementation details of the Configuration Class]]&lt;br /&gt;
* {{tracker|950|Feature Request #0000950}}: Only root admins can see and use Site Configuration &lt;br /&gt;
&lt;br /&gt;
[[Category:Summer of Code]] [[Category:Development]]&lt;/div&gt;</summary>
		<author><name>LWC</name></author>	</entry>

	<entry>
		<id>http://gwiki3.thatlinuxbox.com/index.php?title=Template:Tracker&amp;diff=5768</id>
		<title>Template:Tracker</title>
		<link rel="alternate" type="text/html" href="http://gwiki3.thatlinuxbox.com/index.php?title=Template:Tracker&amp;diff=5768"/>
				<updated>2010-03-07T18:52:24Z</updated>
		
		<summary type="html">&lt;p&gt;LWC: New page: &amp;lt;includeonly&amp;gt;'''{{{2}}}''' ([http://project.geeklog.net/tracking/view.php?id={{{1}}} tracker link])&amp;lt;/includeonly&amp;gt;&amp;lt;noinclude&amp;gt;Supply tracker parameters and get a link.  ==Usage== &amp;lt;pre&amp;gt;&amp;lt;nowik...&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&amp;lt;includeonly&amp;gt;'''{{{2}}}''' ([http://project.geeklog.net/tracking/view.php?id={{{1}}} tracker link])&amp;lt;/includeonly&amp;gt;&amp;lt;noinclude&amp;gt;Supply tracker parameters and get a link.&lt;br /&gt;
&lt;br /&gt;
==Usage==&lt;br /&gt;
&amp;lt;pre&amp;gt;&amp;lt;nowiki&amp;gt;{{tracker|ticketID|Title}}&amp;lt;/nowiki&amp;gt;&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
For example, &amp;lt;nowiki&amp;gt;{{tracker|200|Test}}&amp;lt;/nowiki&amp;gt; would display as:&lt;br /&gt;
&lt;br /&gt;
{{tracker|200|Test}}&lt;br /&gt;
&amp;lt;/noinclude&amp;gt;&lt;/div&gt;</summary>
		<author><name>LWC</name></author>	</entry>

	<entry>
		<id>http://gwiki3.thatlinuxbox.com/index.php?title=Themes_and_XHTML&amp;diff=5665</id>
		<title>Themes and XHTML</title>
		<link rel="alternate" type="text/html" href="http://gwiki3.thatlinuxbox.com/index.php?title=Themes_and_XHTML&amp;diff=5665"/>
				<updated>2010-01-24T23:00:47Z</updated>
		
		<summary type="html">&lt;p&gt;LWC: /* XHTML Constant */ Fixed spelling&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Since version 1.5.0, Geeklog supports [http://en.wikipedia.org/wiki/XHTML XHTML] compliant themes. This means that Geeklog will automatically create XHTML compliant tags when required.&lt;br /&gt;
&lt;br /&gt;
== Switching to XHTML ==&lt;br /&gt;
&lt;br /&gt;
Whether Geeklog will switch to XHTML compliant mode or not depends on the definition of an &amp;lt;tt&amp;gt;XHTML&amp;lt;/tt&amp;gt; variable in the PHP code. This variable can either be defined by the theme (in the theme's &amp;lt;tt&amp;gt;functions.php&amp;lt;/tt&amp;gt; file) or by selecting an XHTML DOCTYPE from the Configuation (since Geeklog 1.6.0):&lt;br /&gt;
&lt;br /&gt;
: Configuration &amp;gt; Geeklog &amp;gt; Theme &amp;gt; Theme &amp;gt; [http://www.geeklog.net/docs/english/config.html#desc_doctype DOCTYPE Declaration]&lt;br /&gt;
&lt;br /&gt;
Selecting an XHTML DOCTYPE will automatically set the &amp;lt;tt&amp;gt;XHTML&amp;lt;/tt&amp;gt; constant properly (any definition made by the theme still takes precedence, though, so make sure the two don't conflict).&lt;br /&gt;
&lt;br /&gt;
== XHTML Constant ==&lt;br /&gt;
&lt;br /&gt;
For an XHTML compliant theme, the &amp;lt;tt&amp;gt;XHTML&amp;lt;/tt&amp;gt; constant should be defined like so:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;define('XHTML', ' /');&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Otherwise, the constant will be defined as an empty string:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;define('XHTML', '');&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Plugins can simply use the &amp;lt;tt&amp;gt;XHTML&amp;lt;/tt&amp;gt; constant - Geeklog will take care that is always defined. The same is true for code in &amp;lt;tt&amp;gt;lib-custom.php&amp;lt;/tt&amp;gt;, with the exception of code that is not located in a function (since &amp;lt;tt&amp;gt;lib-custom.php&amp;lt;/tt&amp;gt; will be included before the theme, and any global code in &amp;lt;tt&amp;gt;lib-custom.php&amp;lt;/tt&amp;gt; would therefore be executed before the constant is defined).&lt;br /&gt;
&lt;br /&gt;
== Template Variables ==&lt;br /&gt;
&lt;br /&gt;
The definition of the &amp;lt;tt&amp;gt;XHTML&amp;lt;/tt&amp;gt; constant is also available as a &amp;lt;tt&amp;gt;{xhtml}&amp;lt;/tt&amp;gt; template variable in all template files used by Geeklog. This way, it is possible to create themes that will work both as XHTML and &amp;quot;plain&amp;quot; HTML by using the template variable for tags that have to be closed in XHTML, e.g.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&amp;lt;br{xhtml}&amp;gt;&lt;br /&gt;
&amp;lt;input type=&amp;quot;submit&amp;quot; name=&amp;quot;test&amp;quot;{xhtml}&amp;gt;&lt;br /&gt;
&amp;lt;img src=&amp;quot;image.png&amp;quot; alt=&amp;quot;&amp;quot;{xhtml}&amp;gt;&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Other Template Variables ===&lt;br /&gt;
&lt;br /&gt;
Themes that are written to be both valid HTML and XHTML (as described above) should use the &amp;lt;tt&amp;gt;{doctype}&amp;lt;/tt&amp;gt; variable as the first line in &amp;lt;tt&amp;gt;header.thtml&amp;lt;/tt&amp;gt; instead of hard-coding the DOCTYPE.&lt;br /&gt;
&lt;br /&gt;
In XHTML mode, Geeklog will also provide a &amp;lt;tt&amp;gt;{xmlns}&amp;lt;/tt&amp;gt; variable that will contain the &amp;lt;tt&amp;gt;xmlns&amp;lt;/tt&amp;gt; attribute for the &amp;lt;tt&amp;gt;html&amp;lt;/tt&amp;gt; element.&lt;br /&gt;
&lt;br /&gt;
Putting it all together, the first 3 lines of your theme's &amp;lt;tt&amp;gt;header.thtml&amp;lt;/tt&amp;gt; should look like this:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;{doctype}&lt;br /&gt;
&amp;lt;html{lang_attribute}{xmlns}&amp;gt;&lt;br /&gt;
&amp;lt;head&amp;gt;&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The &amp;lt;tt&amp;gt;{lang_attribute}&amp;lt;/tt&amp;gt; will set a &amp;lt;tt&amp;gt;lang&amp;lt;/tt&amp;gt; attribute in [[Multilingual Support|multi-language setups]].&lt;br /&gt;
&lt;br /&gt;
The Professional theme that ships with Geeklog uses the &amp;lt;tt&amp;gt;{doctype}&amp;lt;/tt&amp;gt; template variable and is both HTML and XHTML compliant, depending on the DOCTYPE selected in the Configuration.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Category:Themes]]&lt;/div&gt;</summary>
		<author><name>LWC</name></author>	</entry>

	<entry>
		<id>http://gwiki3.thatlinuxbox.com/index.php?title=Dynamic_Blocks&amp;diff=5659</id>
		<title>Dynamic Blocks</title>
		<link rel="alternate" type="text/html" href="http://gwiki3.thatlinuxbox.com/index.php?title=Dynamic_Blocks&amp;diff=5659"/>
				<updated>2010-01-24T15:42:31Z</updated>
		
		<summary type="html">&lt;p&gt;LWC: /* Dynamic Block API */ Fixed spelling&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Dynamic Block Plugin API in Geeklog 1.4 ==&lt;br /&gt;
&lt;br /&gt;
The dynamic block plugin API is a new feature of Geeklog 1.4. This new API function allows plugin developers to create left and right blocks in Geeklog on the fly without adding a block to the blocks table. This is accomplished by inserting the block data directly into the array of blocks that is created from a SQL call to the blocks table before it is used to create what is displayed. What follows is an description of the API call and its use in a plugin.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Dynamic Block API ===&lt;br /&gt;
&lt;br /&gt;
This section will describe and document how to enable your plugin to use the Geeklog dynamic block API. This will be a useful feature of plugin functionality for many developers and it has been designed to be easy to integrate into your plugin. We have done our best to make this straightforward.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;b&amp;gt;NOTE:&amp;lt;/b&amp;gt; You will need to be using Geeklog version 1.4 or later to successfully use the Dynamic Block API. This plugin API is only available in Geeklog 1.4 and is not present in previous versions of Geeklog.&lt;br /&gt;
&lt;br /&gt;
There is only one plugin function that is required to support dynamic blocks in a plugin. The example function that is included in this explanation are very complete. You should only need to edit them for your plugin name name. The following table summarizes the functions:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div align=&amp;quot;center&amp;quot;&amp;gt;&lt;br /&gt;
  &amp;lt;table cellpadding=&amp;quot;2&amp;quot; width=&amp;quot;100%&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
style=&amp;quot;border-collapse: collapse&amp;quot; bordercolor=&amp;quot;#111111&amp;quot;&lt;br /&gt;
cellspacing=&amp;quot;0&amp;quot;&amp;gt;&lt;br /&gt;
    &amp;lt;tr&amp;gt;&lt;br /&gt;
      &amp;lt;th vAlign=&amp;quot;top&amp;quot; width=&amp;quot;4%&amp;quot;&amp;gt;&amp;amp;nbsp;&amp;lt;/th&amp;gt;&lt;br /&gt;
      &amp;lt;th vAlign=&amp;quot;top&amp;quot; width=&amp;quot;31%&amp;quot;&amp;gt;Function&amp;lt;/th&amp;gt;&lt;br /&gt;
      &amp;lt;th vAlign=&amp;quot;top&amp;quot; width=&amp;quot;95%&amp;quot;&amp;gt;Description of Function&amp;lt;/th&amp;gt;&lt;br /&gt;
&lt;br /&gt;
    &amp;lt;/tr&amp;gt;&lt;br /&gt;
    &amp;lt;tr&amp;gt;&lt;br /&gt;
	  &amp;lt;td class=&amp;quot;codeheader&amp;quot; valign=&amp;quot;top&amp;quot; width=&amp;quot;5%&amp;quot; align=&amp;quot;center&amp;quot;&amp;gt;&amp;lt;font&lt;br /&gt;
size=&amp;quot;2&amp;quot;&amp;gt;1&amp;lt;/font&amp;gt;&amp;lt;/td&amp;gt;&lt;br /&gt;
	  &amp;lt;td class=&amp;quot;codeheader&amp;quot; valign=&amp;quot;top&amp;quot; width=&amp;quot;10%&amp;quot;&amp;gt;&amp;lt;font&lt;br /&gt;
size=&amp;quot;2&amp;quot;&amp;gt;plugin_getBlocks_&amp;amp;lt;plugin name&amp;amp;gt;&amp;lt;/font&amp;gt;&amp;lt;/td&amp;gt;&lt;br /&gt;
	  &amp;lt;td class=&amp;quot;code&amp;quot; valign=&amp;quot;top&amp;quot; width=&amp;quot;85%&amp;quot;&amp;gt;&amp;lt;font size=&amp;quot;2&amp;quot;&amp;gt;This&lt;br /&gt;
function expects two parameters:  side and topic. This function is called when a left and right blocks are created with COM_showBlocks in lib-common.php. It is up to the plugin to make sure that the requesting user has sufficient permissions to view any blocks that are returned. It should return an array of block data containing the dynamically generated blocks that you wish the user to see.&amp;lt;/font&amp;gt;&amp;lt;/td&amp;gt;&lt;br /&gt;
    &amp;lt;/tr&amp;gt;&lt;br /&gt;
  &amp;lt;/table&amp;gt;&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Function Details and Examples ===&lt;br /&gt;
&lt;br /&gt;
Examples provided here have been provided from an initial example created by the developer of the Dynamic Block API for a plugin currently in development&lt;br /&gt;
&lt;br /&gt;
This function expects two parameters:  side and topic. This function is called when a left and right blocks are created with COM_showBlocks in lib-common.php. It is up to the plugin to make sure that the requesting user has sufficient permissions to view any blocks that are returned. It should return an array of block data containing the dynamically generated blocks that you wish the user to see.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div style=&amp;quot;white-space:pre; border: solid; border-color: black;&lt;br /&gt;
border-width: 1; background-color: #DDDDDD; padding: 6px 6px 6px 6px;&lt;br /&gt;
font-size: x-small&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
/**&lt;br /&gt;
* Returns blocks for this plugin that should appear when COM_showBlocks is run&lt;br /&gt;
*&lt;br /&gt;
* NOTE: this MUST return the label/value pairs in the following format&lt;br /&gt;
* &amp;amp;#36;items[] = array('label1' =&amp;gt; 'value', 'label2' =&amp;gt; 'value')&lt;br /&gt;
* Basic available labels are..&lt;br /&gt;
*   name     Name of block (BLOCK_ID)&lt;br /&gt;
*   type       Must always be set 'dynamic' unless you use advanced API labels&lt;br /&gt;
*                Advanced API means you set all fields that COM_showBlocks &lt;br /&gt;
*                expects to see from the blocks table. All labels are column names&lt;br /&gt;
*   title        Title of block&lt;br /&gt;
*   blockorder     Block order number&lt;br /&gt;
*   content         Body of the block (the html output)&lt;br /&gt;
*   help            Optional url to a help page&lt;br /&gt;
*&lt;br /&gt;
*  You must only return left or right blocks based on &amp;amp;#36;side and&lt;br /&gt;
*  you must also do your own security checks. Everything you send &lt;br /&gt;
*  will show up on a page load&lt;br /&gt;
* &lt;br /&gt;
*&lt;br /&gt;
* &lt;br /&gt;
*/&lt;br /&gt;
function plugin_getBlocks_glcommerce(&amp;amp;#36;side, &amp;amp;#36;topic='' )&lt;br /&gt;
&amp;amp;#123;&lt;br /&gt;
    global &amp;amp;#36;_CONF, &amp;amp;#36;_USER, &amp;amp;#36;HTTP_SERVER_VARS, &amp;amp;#36;REQUEST_URI, &amp;amp;#36;sess, &amp;amp;#36;db;&lt;br /&gt;
    // only show on a page in the plugin's dir&lt;br /&gt;
    If (in_string('glcommerce', &amp;amp;#36;REQUEST_URI))&lt;br /&gt;
   &amp;amp;#123;&lt;br /&gt;
        // generate left blocks&lt;br /&gt;
        if (&amp;amp;#36;side=='left')&lt;br /&gt;
        &amp;amp;#123;&lt;br /&gt;
&lt;br /&gt;
            &amp;amp;#36;display1 = glc_makemenu();&lt;br /&gt;
            &amp;amp;#36;display2 = glc_latestprod();&lt;br /&gt;
&lt;br /&gt;
            &amp;amp;#36;items[] = array('name' =&amp;gt; 'glcommerce_1',&lt;br /&gt;
                                           'type' =&amp;gt; 'dynamic',&lt;br /&gt;
                                           'onleft' =&amp;gt; 1,&lt;br /&gt;
                                           'title' =&amp;gt; 'Shop Menu', &lt;br /&gt;
                                           'blockorder' =&amp;gt; 1,&lt;br /&gt;
                                           'content' =&amp;gt; &amp;amp;#36;display1, &lt;br /&gt;
                                           'help' =&amp;gt; '/glcommerce/help.html');&lt;br /&gt;
&lt;br /&gt;
            &amp;amp;#36;items[] = array('name' =&amp;gt; 'glcommerce_2',&lt;br /&gt;
                                           'type' =&amp;gt; 'dynamic',&lt;br /&gt;
                                           'onleft' =&amp;gt; 1,&lt;br /&gt;
                                           'title' =&amp;gt; 'Latest Products ',&lt;br /&gt;
                                           'blockorder' =&amp;gt; 1,&lt;br /&gt;
                                           'content' =&amp;gt; &amp;amp;#36;display2,&lt;br /&gt;
                                           'help' =&amp;gt; '/glcommerce/help.html');&lt;br /&gt;
&lt;br /&gt;
        &amp;amp;#125; else &amp;amp;#123;&lt;br /&gt;
        // else generate right blocks&lt;br /&gt;
            &amp;amp;#36;display3 = glc_featuredprod()'&lt;br /&gt;
            &amp;amp;#36;display4 = glc_minicart();&lt;br /&gt;
&lt;br /&gt;
            &amp;amp;#36;items[] = array('name' =&amp;gt; 'glcommerce_3', &lt;br /&gt;
                                           'type' =&amp;gt; 'dynamic',&lt;br /&gt;
                                           'onleft' =&amp;gt; 0,&lt;br /&gt;
                                           'title' =&amp;gt; 'Featured Stuff',&lt;br /&gt;
                                           'blockorder' =&amp;gt; 1,&lt;br /&gt;
                                           'content' =&amp;gt; &amp;amp;#36;display3, &lt;br /&gt;
                                           'help' =&amp;gt; '/glcommerce/help.html'); &lt;br /&gt;
&lt;br /&gt;
            &amp;amp;#36;items[] = array('name' =&amp;gt; 'glcommerce_4',&lt;br /&gt;
                                           'type' =&amp;gt; 'dynamic',&lt;br /&gt;
                                           'onleft' =&amp;gt; 0,&lt;br /&gt;
                                           'title' =&amp;gt; 'My Cart', &lt;br /&gt;
                                           'blockorder' =&amp;gt; 1, &lt;br /&gt;
                                           'content' =&amp;gt; &amp;amp;#36;display4, &lt;br /&gt;
                                           'help' =&amp;gt; '/glcommerce/help.html'); &lt;br /&gt;
&lt;br /&gt;
       &amp;amp;#125;&lt;br /&gt;
&lt;br /&gt;
   &amp;amp;#125;&lt;br /&gt;
   return &amp;amp;#36;items;&lt;br /&gt;
&amp;amp;#125;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Function PLG_getBlocks() for reference ===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div style=&amp;quot;white-space:pre; border: solid; border-color: black;&lt;br /&gt;
border-width: 1; background-color: #DDDDDD; padding: 6px 6px 6px 6px;&lt;br /&gt;
font-size: x-small&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
/**&lt;br /&gt;
* gets Geeklog blocks from plugin's&lt;br /&gt;
*&lt;br /&gt;
* Returns data for blocks on a given side and, potentially, for&lt;br /&gt;
* a given topic.&lt;br /&gt;
*&lt;br /&gt;
* @param        string      &amp;amp;#36;side       Side to get blocks for (right or left for now)&lt;br /&gt;
* @param        string      &amp;amp;#36;topic      Only get blocks for this topic&lt;br /&gt;
* @return   array of block data&lt;br /&gt;
*&lt;br /&gt;
*/&lt;br /&gt;
function PLG_getBlocks( &amp;amp;#36;side, &amp;amp;#36;topic='')&lt;br /&gt;
&amp;amp;#123;&lt;br /&gt;
    global &amp;amp;#36;_PLUGINS;&lt;br /&gt;
&lt;br /&gt;
    &amp;amp;#36;ret = array();&lt;br /&gt;
    foreach (&amp;amp;#36;_PLUGINS as &amp;amp;#36;pi_name)&lt;br /&gt;
    &amp;amp;#123;&lt;br /&gt;
        &amp;amp;#36;function = 'plugin_getBlocks_' . &amp;amp;#36;pi_name;&lt;br /&gt;
        if (function_exists(&amp;amp;#36;function))&lt;br /&gt;
        &amp;amp;#123;&lt;br /&gt;
            &amp;amp;#36;items = &amp;amp;#36;function(&amp;amp;#36;side, &amp;amp;#36;topic='');&lt;br /&gt;
            if (is_array (&amp;amp;#36;items))&lt;br /&gt;
            &amp;amp;#123;&lt;br /&gt;
                &amp;amp;#36;ret = array_merge (&amp;amp;#36;ret, &amp;amp;#36;items);&lt;br /&gt;
            &amp;amp;#125;&lt;br /&gt;
        &amp;amp;#125;&lt;br /&gt;
    &amp;amp;#125;&lt;br /&gt;
&lt;br /&gt;
    // future code to do a lib-custom function&lt;br /&gt;
    /*&lt;br /&gt;
    if (function_exists('CUSTOM_getBlocks')) &amp;amp;#123;&lt;br /&gt;
       &amp;amp;#36;cust_items .= CUSTOM_getBlocks(&amp;amp;#36;side, &amp;amp;#36;topic='');&lt;br /&gt;
       if (is_array (&amp;amp;#36;cust_items)) &amp;amp;#123;&lt;br /&gt;
          &amp;amp;#36;ret = array_merge (&amp;amp;#36;ret, &amp;amp;#36;cust_items)&lt;br /&gt;
       &amp;amp;#125;&lt;br /&gt;
    &amp;amp;#125;&lt;br /&gt;
    */&lt;br /&gt;
    return &amp;amp;#36;ret;&lt;br /&gt;
&amp;amp;#125;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Geeklog Documentation|Main Table of Contents]]&amp;lt;br/&amp;gt;&lt;br /&gt;
[[Complete Table of Contents]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Category:Development]] [[Category:Plugin Development]] [[Category:Blocks]]&lt;/div&gt;</summary>
		<author><name>LWC</name></author>	</entry>

	<entry>
		<id>http://gwiki3.thatlinuxbox.com/index.php?title=Multilingual_Support&amp;diff=5638</id>
		<title>Multilingual Support</title>
		<link rel="alternate" type="text/html" href="http://gwiki3.thatlinuxbox.com/index.php?title=Multilingual_Support&amp;diff=5638"/>
				<updated>2009-12-15T16:19:09Z</updated>
		
		<summary type="html">&lt;p&gt;LWC: /* Blocks */ Stressed what's disabled&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Background ==&lt;br /&gt;
&lt;br /&gt;
The Geeklog language files have been translated into more than 25 languages - but that only means that you can have the user interface in one of those languages. For the actual site content (articles, static pages, ...), there was no support for multiple languages, which means that you either had to have everything in one language only or you ended up with all the different language versions of, e.g. an article, being displayed to anyone.&lt;br /&gt;
&lt;br /&gt;
Euan McKay then came up with a [http://heatherengineering.com/staticpages/index.php/multilingual-en first multilingual hack], which was later [http://www.geeklog.net/forum/viewtopic.php?showtopic=61999 built upon and generalized] by LWC.&lt;br /&gt;
&lt;br /&gt;
The multilingual support in Geeklog (as of version 1.4.1) is based on this earlier work by Euan and LWC.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== How it works ==&lt;br /&gt;
&lt;br /&gt;
The basic idea behind the multilingual support is to encode the language of an object into its ID. For example, for a story to encode it into the story ID, like so:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;http://www.example.com/article.php/introduction_en -- English version&lt;br /&gt;
http://www.example.com/article.php/introduction_de -- German version&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Now there is a way to identify the language of an object (article, topic, static page, ...) and it can be displayed (or not), based on the user's language preferences. It's also possible then to switch between the various languages in which an object exists in the database.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Setting it up ==&lt;br /&gt;
&lt;br /&gt;
=== Geeklog 1.4.1 ===&lt;br /&gt;
&lt;br /&gt;
In config.php, there is a new section to enable multilingual support and to define the list of supported languages:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;// Multilingual support&lt;br /&gt;
// (note that this section is commented out - remove the '/*' and '*/' lines&lt;br /&gt;
//  below to activate it and make sure you understand what it does)&lt;br /&gt;
/*&lt;br /&gt;
&lt;br /&gt;
// IMPORTANT!&lt;br /&gt;
// 1) Both the $_CONF['language_files'] and the $_CONF['languages'] arrays&lt;br /&gt;
//    (see below) must have the same number of elements.&lt;br /&gt;
// 2) The shortcuts used must be the same in both arrays.&lt;br /&gt;
// 3) All shortcuts must have the same length, e.g. 2 characters.&lt;br /&gt;
&lt;br /&gt;
// The shortcuts are to be used in IDs of objects that are multilingual&lt;br /&gt;
// aware, e.g. /article.php/introduction_en and /article.php/introduction_de&lt;br /&gt;
// for the English and German version of an introductory article.&lt;br /&gt;
&lt;br /&gt;
// Supported languages&lt;br /&gt;
// Maps a shortcut to a Geeklog language file (without the '.php' extension)&lt;br /&gt;
$_CONF['language_files'] = array (&lt;br /&gt;
    'en' =&amp;gt; 'english',&lt;br /&gt;
    'de' =&amp;gt; 'german_formal'&lt;br /&gt;
);&lt;br /&gt;
&lt;br /&gt;
// Display names of supported languages&lt;br /&gt;
// Maps the same shortcuts as above to a language name. The language names&lt;br /&gt;
// are used to let users switch languages, e.g. in a drop-down menu.&lt;br /&gt;
$_CONF['languages'] = array (&lt;br /&gt;
    'en' =&amp;gt; 'English',&lt;br /&gt;
    'de' =&amp;gt; 'Deutsch'&lt;br /&gt;
);&lt;br /&gt;
&lt;br /&gt;
*/&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
To enable multilingual support, the two arrays $_CONF['language_files'] and $_CONF['languages'] have to be defined. In the default config.php, they are commented out and, therefore, not defined.&lt;br /&gt;
&lt;br /&gt;
=== Geeklog 1.5.0 and later ===&lt;br /&gt;
&lt;br /&gt;
As of Geeklog 1.5.0, the &amp;lt;tt&amp;gt;config.php&amp;lt;/tt&amp;gt; file has been replaced with a web-based configuration that can be found under &amp;quot;Configuration&amp;quot; in the Admin's block. Under the &amp;quot;Languages and Locale&amp;quot; heading, you'll find two options:&lt;br /&gt;
* Language Files&lt;br /&gt;
* Languages&lt;br /&gt;
These two options are the equivalents of the &amp;lt;code&amp;gt;$_CONF['language_files']&amp;lt;/code&amp;gt; and &amp;lt;code&amp;gt;$_CONF['languages']&amp;lt;/code&amp;gt; arrays, as explained above. To use the multilingual feature, '''both''' of these options have to be enabled. Other than that, the two options work as described above.&lt;br /&gt;
&lt;br /&gt;
Note that in Geeklog 1.5.0, you can not easily disable multilingual support again (for a workaround, see [http://www.geeklog.net/forum/viewtopic.php?showtopic=83327 here]). As of Geeklog 1.5.1, there is a litte &amp;lt;tt&amp;gt;(X)&amp;lt;/tt&amp;gt; next to the options (once they're enabled). Click on the &amp;lt;tt&amp;gt;(X)&amp;lt;/tt&amp;gt; to disable the options again (remember that you need to disable both of them).&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== The shortcuts ===&lt;br /&gt;
&lt;br /&gt;
For each of the languages you intend to support, you will have to define a shortcut that will then be used in the IDs of the multilingual objects, as explained above.&lt;br /&gt;
&lt;br /&gt;
You can freely define these shortcuts, but it would make sense to set them in some relation to the language which they represent. From Geeklog's point of view, though, it doesn't matter whether the English language is represented by a shortcut 'en' or by 'peter'.&lt;br /&gt;
&lt;br /&gt;
Please note:&lt;br /&gt;
* All the shortcuts in both of the arrays have to be of the same length.&lt;br /&gt;
* The shortcut must be appended to the ''end'' of an object's ID and it must be preceded by an underscore '_' character.&lt;br /&gt;
* It's recommended that you use a language's ISO abbreviation ('en' for English, 'de' for German, etc.), either with or without the country appendix ('en-US'), as Geeklog will also try to determine a user's preferred language from their browser setting.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== The language files ===&lt;br /&gt;
&lt;br /&gt;
The $_CONF['language_files'] array defines which language files should represent which language. Note that Geeklog also uses the language file name for a user's language setting (in their preferences).&lt;br /&gt;
&lt;br /&gt;
It's recommended that you remove all the other language files, i.e. those for which you do not intend to have content in that particular language on your site.&lt;br /&gt;
&lt;br /&gt;
'''Note:''' Be careful when mixing languages that use different character sets (e.g. Russian and Japanese). You may want to switch to the UTF-8 versions of ''all'' language files for such a setup.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== The language names ===&lt;br /&gt;
&lt;br /&gt;
The $_CONF['languages'] array defines a set of display names for the supported languages. These names are used to let the user switch between the supported languages, e.g. from a drop-down menu.&lt;br /&gt;
&lt;br /&gt;
Most of the time, you'll want to use the native names of the languages, e.g. &amp;quot;Deutsch&amp;quot; instead of &amp;quot;German&amp;quot;, but that's only a convention.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Blocks ==&lt;br /&gt;
&lt;br /&gt;
Multilingual blocks are only supported as of Geeklog 1.5.1. The setup differs slightly from the setup for stories, topics, etc.&lt;br /&gt;
&lt;br /&gt;
Let's assume you want to create a multilingual &amp;quot;about this site&amp;quot; block and that your site is configured for two languages (say, English and German). For this setup you would then need ''three''(!) blocks. The block name serves as the ID and you would create blocks with the following names:&lt;br /&gt;
* about_en (disabled)&lt;br /&gt;
* about_de (disabled)&lt;br /&gt;
* about&lt;br /&gt;
The first two blocks would simply contain your content in English and German, respectively. Both blocks should be ''disabled''. The third block then serves as a placeholder for the actual block for the current language. Therefore, only this block (&amp;quot;about&amp;quot;, in our example) should be enabled. When the multilingual support is enabled, you will never see the contents of that block, as it will be replaced with the proper block for the current language, e.g. &amp;quot;about_en&amp;quot; for English.&lt;br /&gt;
&lt;br /&gt;
== Switching languages ==&lt;br /&gt;
&lt;br /&gt;
Registered users can always switch their preferred language by selecting another language in their preferences.&lt;br /&gt;
&lt;br /&gt;
To make things more convenient (and also allow anonymous users to switch the language), you can put a PHP block on your site. Geeklog provides a function phpblock_switch_language that will display a drop-down menu of all available languages (if you only have two languages defined, it will display a simple link to the other language instead).&lt;br /&gt;
&lt;br /&gt;
This function can also be called from the header.thtml template file of your theme, so that you can put it into your site's menu:&lt;br /&gt;
&amp;lt;pre&amp;gt;&amp;lt;?php print phpblock_switch_language(); ?&amp;gt;&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Technically, switching the language will set a cookie (with the selected language) and also update a user's language preference, if they're registered with the site.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Detecting the language ==&lt;br /&gt;
&lt;br /&gt;
When a user comes to a multilingual enabled site, Geeklog will check for the user's preference setting first (if it's a registered user), then for the language cookie, and if that couldn't be found, it tries to get the language from the browser's 'Accept-Language' header (which only works if you chose to use the ISO shortcuts, as explained above). If all else fails, content will be presented in the site's default language, i.e. $_CONF['language'].&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Supporting multiple languages ==&lt;br /&gt;
&lt;br /&gt;
Developers of plugins and other add-ons don't have to do much to support multiple languages. Mainly, the objects under your plugin's control will have to have an editable, non-numerical ID (like Geeklog's stories have), so that the language shortcut can be appended to the ID.&lt;br /&gt;
&lt;br /&gt;
If you have a list of objects under your plugin's control and only want to show the objects in the current language, you can use the COM_getLangSQL() function when building your SQL request. It will provide the part of an SQL request to only return the objects in the current language (see the function's description in lib-common.php for details).&lt;br /&gt;
&lt;br /&gt;
COM_getLangSQL() will return an empty string when multilingual support is disabled, so you don't need to check for that yourself.&lt;br /&gt;
&lt;br /&gt;
Most of the time, that should be all that you need to know about supporting multiple languages in a plugin. In some scenarios, the following functions may also come in handy:&lt;br /&gt;
* COM_getLanguageId returns the shortcut of the current user's language&lt;br /&gt;
* COM_getLanguage returns the full name of the current user's language, i.e. the name of the Geeklog language file (without the .php extension)&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Switching locale settings ==&lt;br /&gt;
&lt;br /&gt;
Switching the language will often also require different formatting of the date, time, and other locale settings. For this, you can define alternative settings for each language in your site's config.php.&lt;br /&gt;
&lt;br /&gt;
For example, the default date formatting in Geeklog's config.php is&lt;br /&gt;
&amp;lt;pre&amp;gt;$_CONF['date'] = '%A, %B %d %Y @ %I:%M %p %Z';&amp;lt;/pre&amp;gt;&lt;br /&gt;
which, amongst other things, includes a time format using am/pm. If your site switches between, say, English and German, then your typical German visitor will expect the time to use a 24-hour format, e.g.&lt;br /&gt;
&amp;lt;pre&amp;gt;$_CONF['date'] = '%A, %d. %B %Y, %R Uhr';&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
If you're using the ISO abbreviation 'de' for German, then you could have the following in your site's config.php:&lt;br /&gt;
&amp;lt;pre&amp;gt;$_CONF['date'] = '%A, %B %d %Y @ %I:%M %p %Z';&lt;br /&gt;
$_CONF['date_de'] = '%A, %d. %B %Y, %R Uhr';&amp;lt;/pre&amp;gt;&lt;br /&gt;
With these two lines, Geeklog would use the 'date_de' formatting when displaying content in German, and the 'date' formatting for all the other languages.&lt;br /&gt;
&lt;br /&gt;
Actually, for this to work properly, you will also have to set &amp;lt;code&amp;gt;$_CONF['locale']&amp;lt;/code&amp;gt; and &amp;lt;code&amp;gt;$_CONF['locale_de']&amp;lt;/code&amp;gt; accordingly, since some of the date formatting (localized day and month names) requires the correct locale to be set:&lt;br /&gt;
&amp;lt;pre&amp;gt;$_CONF['locale'] = 'en_GB';&lt;br /&gt;
$_CONF['locale_de'] = 'de_DE';&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
You can switch all of the following [http://www.geeklog.net/docs/english/config.html#languages_locale locale settings] as described above:&lt;br /&gt;
* &amp;lt;code&amp;gt;$_CONF['locale']&amp;lt;/code&amp;gt;&lt;br /&gt;
* &amp;lt;code&amp;gt;$_CONF['date']&amp;lt;/code&amp;gt;&lt;br /&gt;
* &amp;lt;code&amp;gt;$_CONF['daytime']&amp;lt;/code&amp;gt;&lt;br /&gt;
* &amp;lt;code&amp;gt;$_CONF['shortdate']&amp;lt;/code&amp;gt;&lt;br /&gt;
* &amp;lt;code&amp;gt;$_CONF['dateonly']&amp;lt;/code&amp;gt;&lt;br /&gt;
* &amp;lt;code&amp;gt;$_CONF['timeonly']&amp;lt;/code&amp;gt;&lt;br /&gt;
* &amp;lt;code&amp;gt;$_CONF['week_start']&amp;lt;/code&amp;gt;&lt;br /&gt;
* &amp;lt;code&amp;gt;$_CONF['hour_mode']&amp;lt;/code&amp;gt;&lt;br /&gt;
* &amp;lt;code&amp;gt;$_CONF['thousand_separator']&amp;lt;/code&amp;gt;&lt;br /&gt;
* &amp;lt;code&amp;gt;$_CONF['decimal_separator']&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
'''Note:''' In Geeklog 1.5.0 and later, you will have to add the language-specific entries ($_CONF['date_de'], etc.) to the &amp;lt;tt&amp;gt;siteconfig.php&amp;lt;/tt&amp;gt; file. The settings for the default language can be found in the Configuration admin panel:&lt;br /&gt;
&lt;br /&gt;
: Configuration &amp;gt; Geeklog &amp;gt; Languages and Locale&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Notes and ideas ==&lt;br /&gt;
&lt;br /&gt;
* To make things nicer for the user, the language could be hidden from the ID when editing objects. Instead, the user could be presented with a drop-down menu of the available languages. The shortcut could then be silently added to the ID when the object is saved.&lt;br /&gt;
* [[SoC improve multilingual feature|More ideas]]&lt;/div&gt;</summary>
		<author><name>LWC</name></author>	</entry>

	<entry>
		<id>http://gwiki3.thatlinuxbox.com/index.php?title=Timezone_Support&amp;diff=5626</id>
		<title>Timezone Support</title>
		<link rel="alternate" type="text/html" href="http://gwiki3.thatlinuxbox.com/index.php?title=Timezone_Support&amp;diff=5626"/>
				<updated>2009-11-02T09:23:14Z</updated>
		
		<summary type="html">&lt;p&gt;LWC: /* Prerequisites */ Used template&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;By default, Geeklog uses the timezone that is configured for your webserver. To change the timezone for your website, you need to enable timezone support in the Configuration. Go to&lt;br /&gt;
&lt;br /&gt;
: Configuration &amp;gt; Geeklog &amp;gt; Languages and Locale &amp;gt; Locale&lt;br /&gt;
&lt;br /&gt;
and enable the &amp;quot;Timezone&amp;quot; option. It will display a dropdown of the available timezones (in Geeklog versions prior to 1.6.1, you'll see a text entry field, i.e. you have to type in the timezone to use).&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Prerequisites ==&lt;br /&gt;
&lt;br /&gt;
For timezone support to work, one of the following requirements must be met, i.e. you need either&lt;br /&gt;
&lt;br /&gt;
* PHP 5.1.0 (or later) ''or''&lt;br /&gt;
* an Apache webserver and PHP with &amp;quot;safe_mode&amp;quot; turned off&lt;br /&gt;
&lt;br /&gt;
The latter option is known as the {{forum|21232|Timezone Hack}} and has been integrated into Geeklog since version 1.3.10. Geeklog 1.6.1 added the former option (requirement for PHP 5.1.0), which usually works more smoothly.&lt;br /&gt;
&lt;br /&gt;
== User Timezone ==&lt;br /&gt;
&lt;br /&gt;
As of Geeklog 1.6.1, users can change their timezone, if the timezone support has been enabled for the site. Go to&lt;br /&gt;
&lt;br /&gt;
: My Account &amp;gt; Layout &amp;amp; Language &amp;gt; Misc Settings&lt;br /&gt;
&lt;br /&gt;
and select your preferred timezone from the dropdown.&lt;br /&gt;
&lt;br /&gt;
Note: This dropdown has been present in earlier Geeklog versions but wasn't used.&lt;br /&gt;
&lt;br /&gt;
=== Timezone Cookie ===&lt;br /&gt;
&lt;br /&gt;
Selecting a timezone for the account will also set a timezone cookie. Please note that this cookie is also used when you are not logged into the site. The same is true for the theme cookie, so that you can see the site with your preferred theme and timezone, even when you are not logged in.&lt;/div&gt;</summary>
		<author><name>LWC</name></author>	</entry>

	<entry>
		<id>http://gwiki3.thatlinuxbox.com/index.php?title=Template:Forum&amp;diff=5625</id>
		<title>Template:Forum</title>
		<link rel="alternate" type="text/html" href="http://gwiki3.thatlinuxbox.com/index.php?title=Template:Forum&amp;diff=5625"/>
				<updated>2009-11-02T09:22:27Z</updated>
		
		<summary type="html">&lt;p&gt;LWC: Improved description&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&amp;lt;includeonly&amp;gt;'''{{{2}}}''' ([http://www.geeklog.net/forum/viewtopic.php?showtopic={{{1}}} forum link])&amp;lt;/includeonly&amp;gt;&amp;lt;noinclude&amp;gt;Supply forum parameters and get a link.&lt;br /&gt;
&lt;br /&gt;
==Usage==&lt;br /&gt;
&amp;lt;pre&amp;gt;&amp;lt;nowiki&amp;gt;{{forum|forumID|Title}}&amp;lt;/nowiki&amp;gt;&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
For example, &amp;lt;nowiki&amp;gt;{{forum|9778|Test}}&amp;lt;/nowiki&amp;gt; would display as:&lt;br /&gt;
&lt;br /&gt;
{{forum|9778|Test}}&lt;br /&gt;
&amp;lt;/noinclude&amp;gt;&lt;/div&gt;</summary>
		<author><name>LWC</name></author>	</entry>

	<entry>
		<id>http://gwiki3.thatlinuxbox.com/index.php?title=Template:Forum&amp;diff=5624</id>
		<title>Template:Forum</title>
		<link rel="alternate" type="text/html" href="http://gwiki3.thatlinuxbox.com/index.php?title=Template:Forum&amp;diff=5624"/>
				<updated>2009-11-02T09:21:31Z</updated>
		
		<summary type="html">&lt;p&gt;LWC: Added title&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&amp;lt;includeonly&amp;gt;'''{{{2}}}''' ([http://www.geeklog.net/forum/viewtopic.php?showtopic={{{1}}} forum link])&amp;lt;/includeonly&amp;gt;&amp;lt;noinclude&amp;gt;Supply an forum ID from the main site and get a link for it.&lt;br /&gt;
&lt;br /&gt;
==Usage==&lt;br /&gt;
&amp;lt;pre&amp;gt;&amp;lt;nowiki&amp;gt;{{forum|forumID|Title}}&amp;lt;/nowiki&amp;gt;&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
For example, &amp;lt;nowiki&amp;gt;{{forum|9778|Test}}&amp;lt;/nowiki&amp;gt; would display as:&lt;br /&gt;
&lt;br /&gt;
{{forum|9778|Test}}&lt;br /&gt;
&amp;lt;/noinclude&amp;gt;&lt;/div&gt;</summary>
		<author><name>LWC</name></author>	</entry>

	<entry>
		<id>http://gwiki3.thatlinuxbox.com/index.php?title=Language_Tips_And_Tricks&amp;diff=5621</id>
		<title>Language Tips And Tricks</title>
		<link rel="alternate" type="text/html" href="http://gwiki3.thatlinuxbox.com/index.php?title=Language_Tips_And_Tricks&amp;diff=5621"/>
				<updated>2009-10-31T00:33:42Z</updated>
		
		<summary type="html">&lt;p&gt;LWC: /* How to convert your complete Geeklog to Unicode/UTF-8 in 11 steps. */ Fixed English&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== General Things ==&lt;br /&gt;
&lt;br /&gt;
When you switch to another language in Geeklog, not only the menu text changes, but also the character set might change. This means that certain international characters might not be readable anymore. So if your site has German, Japanese or eastern European content, switching the language might turn your complete content unreadable.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Multilingual Sites ==&lt;br /&gt;
&lt;br /&gt;
If you plan to run a site where the content will be [[Multilingual Support|in several languages]], it is better to stick to languages that support UTF-8. Since they all use the same code, you will be able to display German Umlaut next to Japanese Characters for example. Otherwise, readers will always see unreadable characters next to readables, and will have to switch languages in order to read everything. Read below how to convert your favorite language to UTF-8.&lt;br /&gt;
&lt;br /&gt;
Further, to support proper search and other functions, you should enable --with-mb_string functions in your PHP. In Linux, this might mean that you have to recompile linux! If you do this remember also to set your php.ini to have &amp;quot;mbstring.func_overload = 7&amp;quot;. This makes php use multibyte-functions by default whenever a single-byte function is called.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Unwanted Languages ==&lt;br /&gt;
&lt;br /&gt;
You can remove unwanted languages by simply deleting the unwanted files from the &amp;lt;tt&amp;gt;/language/&amp;lt;/tt&amp;gt; directory. Or you might want to create a subfolder there and move the unwanted files into it. Like this you can avoid that users choose Languages with character sets that will turn content unreadable.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== How to convert Language file Character Sets ==&lt;br /&gt;
&lt;br /&gt;
First check in the download section of geeklog.net if nobody already converted the language file after the last release of Geeklog!&lt;br /&gt;
&lt;br /&gt;
If you have Windows &amp;amp; MS Word, there is a very easy way to convert your language files to UTF-8 or other formats: Simply open the language-file with Word (rename it .doc and double-click for example). Then you will be asked what Character set the Source has. Choose the one that allows you to read the characters properly in the preview. Then save the file again as &amp;quot;Text Only&amp;quot;-Format. You will be asked again what Character Set you want to use. Choose your preferred (&amp;quot;Unicode UTF-8&amp;quot; for example). Make sure you also correct the line 32 of the file so that it represents the format you want:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;$LANG_CHARSET = &amp;quot;utf-8&amp;quot;;&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Then, rename the file to &amp;quot;language_utf-8.php&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
If you have done so, you might want to publish the file also on the geeklog.net website.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== How to convert your complete Geeklog to Unicode/UTF-8 in 11 steps. ==&lt;br /&gt;
&lt;br /&gt;
If you started your server with one language, and want to move to a multilingual system later on, it can be quite difficult if you need different character sets for the different languages. With UTF-8 you can display all languages and letters at the same time in the same page without any problems. The best solution therefore would be to convert your ''complete'' data into Unicode in one go. You don't want to go through each story and comment and edit letters by hand after you switched the encoding of the page.&lt;br /&gt;
&lt;br /&gt;
For this procedure to work you need (1) a text editor like notepad that can save raw text data while choosing the encoding (Notepad unter windows for example), (2) direct access to you MySQL executable (Windows cmd or Linux Shell) and (3) a NON-Unicode-Capable Editor (!) such as PHPEdit (or linux shell editors AFAIK). You can find out which editor cannot handle Unicode by saving a small text containing a &amp;quot;xxöxx&amp;quot; or similar with notepad as UTF-8 (See step 3) and opening it with the other editor. If you the letter &amp;quot;ö&amp;quot; appears now as &amp;quot;Ã¶&amp;quot; you have the right one.&lt;br /&gt;
&lt;br /&gt;
Now let's start.&lt;br /&gt;
&lt;br /&gt;
# Make a Backup of your database using the Geeklog Backup function.&lt;br /&gt;
# Download the created file from your server, zip it, burn it on a CD and send it to your lawyer. He should keep it as a backup in case you need it later to go back to step one.&lt;br /&gt;
# Open the file in Notepad/unicode-able editor (Notepad.exe). If your database is large, this will take some time, but its worth waiting for. Save the file again under a different (!) filename. Before you press the save-button, you have a field called &amp;quot;Encoding&amp;quot; below the field where you entered the filename. Choose &amp;quot;UTF-8&amp;quot;.&lt;br /&gt;
# Now open the file in the non-Unicode-capable editor. You will see three strange letters &amp;quot;ï»¿&amp;quot; in the beginning of the file. Remove them. They cause error messages in the SQL later. Save the file again.&lt;br /&gt;
# Upload the file to your server. You might want to zip it first (also before downloading) to reduce transfer time.&lt;br /&gt;
# Create a new database if you can. If not delete all tables from your old one (call your lawyer to have your backup ready in an envelope).&lt;br /&gt;
# Write the data back into the database. Do this by typing &amp;lt;pre&amp;gt;mysql --user=root --password databasename file.txt&amp;lt;/pre&amp;gt; replace &amp;quot;databasename&amp;quot; with the name of the newly created or empty database, and file.txt with the name of the file that you saved with notepad. The file has to be in the same directory as you are, if not move the file there. In Windows, it has to be in the /Mysql/bin-directory, where your MySQL.exe resides. If you do not want to move the files, prepend the path to the mysql.exe and/or the filename path.&amp;lt;br&amp;gt;If you do not have root access to the database, exchange &amp;quot;root&amp;quot; with the username that you use to access your MySQL server.&lt;br /&gt;
# Hit enter. You will be prompted for the user's password. Enter it, and press return again. Now the database will be parsed back into the server.&lt;br /&gt;
# If you created a second database, edit your Geeklog's config.php so that it accesses the new one.&lt;br /&gt;
# Switch your Geeklog language to one of the _UTF-8 sets. If you want to reduce hassle with your users that have been using non-UTF-8 languages, convert all the language-files you have to UTF-8 with notepad (You don't need to remove the first three letter there) and change the encoding string in each file (Line 30) to &amp;lt;pre&amp;gt;$LANG_CHARSET = &amp;quot;utf-8&amp;quot;;&amp;lt;/pre&amp;gt;&lt;br /&gt;
# Change config.php so that the standard language file will be one of the UTF-8 sets also (somehwere line 239), &amp;lt;pre&amp;gt;$_CONF['language'] = &amp;quot;english_utf-8&amp;quot;;&amp;lt;/pre&amp;gt;&lt;br /&gt;
# You might want to delete all non-UTF-8 languages from your language folders.&lt;br /&gt;
&lt;br /&gt;
That's all. Good luck &amp;lt;tt&amp;gt;:-)&amp;lt;/tt&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Switching back to one language (1.3.9sr1 and before) ==&lt;br /&gt;
&lt;br /&gt;
If you set your config.php so that you use only one language, you might run into trouble if you have users that already registered and selected another language. These users will continue to use their pre-set language. Even if you set their language manually to the standard or NULL (with a tool such as [http://www.phpmyadmin.net/ phpMyAdmin]), the cookies on the user's computers will still call up the old one.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Links and Further Reading ==&lt;br /&gt;
&lt;br /&gt;
* [http://lists.geeklog.net/mailman/listinfo/geeklog-translations geeklog-translations mailing list]&lt;br /&gt;
* [[Multilingual Support]] (as of Geeklog 1.4.1)&lt;/div&gt;</summary>
		<author><name>LWC</name></author>	</entry>

	<entry>
		<id>http://gwiki3.thatlinuxbox.com/index.php?title=Building_a_View&amp;diff=5620</id>
		<title>Building a View</title>
		<link rel="alternate" type="text/html" href="http://gwiki3.thatlinuxbox.com/index.php?title=Building_a_View&amp;diff=5620"/>
				<updated>2009-10-31T00:33:00Z</updated>
		
		<summary type="html">&lt;p&gt;LWC: /* Why Flexy? */ Fixed English&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Building a View ==&lt;br /&gt;
&lt;br /&gt;
Views are the visual components shown to your users.  They often display information from one or more models.  It is important to note that your views are to contain no business logic.  It just displays a page to a user.  The Geeklog 2 Framework has consciously chose to use [http://pear.php.net/package/HTML_Template_Flexy Flexy] for a variety of reasons but know now that you can very quickly retrofit any of what you see to use any other templating engine (such as [http://smarty.php.net/ Smarty]).&lt;br /&gt;
&lt;br /&gt;
== Why Flexy? ==&lt;br /&gt;
&lt;br /&gt;
One of the more annoying questions I get from PHP developers is why Flexy?  Why Flexy?  Why Flexy?  First, keep in mind the Geeklog 2 Framework has been around in various forms since 2003 and back then one of the more annoying things about other template engines out there is their blatant desire to allow rendering of HTML and JavaScript by default.  Flexy, rightfully so, hates these things and will always escape them unless you explicitly tell it to allow them.  After that, Flexy is full of the sorts of features you'd like to see from a modern PHP template eninge.  Things like compiling of templates, support for control structures (IF's, FOR loops, etc), object-oriented design and out-of-the-box multilingual support via [http://pear.php.net/package/Translation2 PEAR::Translation2].&lt;br /&gt;
&lt;br /&gt;
Are there other good alternatives out there?  Absolutely, and let me remind you that just because the Geeklog 2 Framework uses Flexy that doesn't mean you couldn't retrofit your projects to use another engine.  That's the beauty of object-oriented code.&lt;br /&gt;
&lt;br /&gt;
== Your First View ==&lt;br /&gt;
&lt;br /&gt;
OK, enough talk...let's see an MVCnPHP view first hand.  Every view is comprised of two parts.  The first part is the MVCnPHP view which is responsible for pulling all data needed to be displayed on the page.  The second part is the Flexy template.  Let's first build the Flexy template by creating a page called Home.thtml.  Note that Geeklog 2 Coding Standards require that all HTML templates use the .thtml extension.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&amp;lt;pre&amp;gt;&lt;br /&gt;
&amp;lt;html&amp;gt;&lt;br /&gt;
    &amp;lt;head&amp;gt;&lt;br /&gt;
        &amp;lt;title&amp;gt;{pageTitle}&amp;lt;/title&amp;gt;&lt;br /&gt;
    &amp;lt;/head&amp;gt;&lt;br /&gt;
    &amp;lt;body&amp;gt;&lt;br /&gt;
    &amp;lt;p&amp;gt;&lt;br /&gt;
    This is a page created using the Geeklog 2 Framework.  You are viewing this page on {getDateTime()}.&lt;br /&gt;
    &amp;lt;/p&amp;gt;&lt;br /&gt;
    &amp;lt;/body&amp;gt;&lt;br /&gt;
&amp;lt;/html&amp;gt;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
As you would expect from a PHP template engine, the template file itself is mostly HTML.  The template above excercises a couple tasks such as showing data in a variable and calling a method.  Those familir with other template engines might notice the variable and method call noted by {} above. In the TITLE tag, there is the pageTitle variable and in the body there is a method call to getDateTime().  Where does that variable and method exist?  On the MVCnPHP view!&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&amp;lt;pre&amp;gt;&lt;br /&gt;
/**&lt;br /&gt;
 * MVCnPHP Abstract BaseView object&lt;br /&gt;
 */&lt;br /&gt;
require 'Geeklog/MVCnPHP/BaseView.php';&lt;br /&gt;
&lt;br /&gt;
/**&lt;br /&gt;
 * PEAR::HTML_Template_Flexy&lt;br /&gt;
 */&lt;br /&gt;
require 'Flexy.php';&lt;br /&gt;
&lt;br /&gt;
class SAMPLE_HomeView extend MVCnPHP_BaseView  {   &lt;br /&gt;
    /**&lt;br /&gt;
     * Handle to instance of a flexy object&lt;br /&gt;
     *&lt;br /&gt;
     * @access protected&lt;br /&gt;
     * @var object&lt;br /&gt;
     */&lt;br /&gt;
     protected $flexyHandle = null;&lt;br /&gt;
&lt;br /&gt;
    /**&lt;br /&gt;
     * Page title&lt;br /&gt;
     * @var string&lt;br /&gt;
     * @access protected&lt;br /&gt;
     */&lt;br /&gt;
    protected $pageTitle = null;&lt;br /&gt;
&lt;br /&gt;
    /**&lt;br /&gt;
     * Constructor&lt;br /&gt;
     *&lt;br /&gt;
     * @access public&lt;br /&gt;
     */&lt;br /&gt;
    public function __construct()&lt;br /&gt;
    {&lt;br /&gt;
        $this-&amp;gt;pageTitle = 'Your first MVCnPHP View';&lt;br /&gt;
        $this-&amp;gt;initializeFlexy();&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    /**&lt;br /&gt;
     * Instantiates Flexy&lt;br /&gt;
     *&lt;br /&gt;
     * @access protected&lt;br /&gt;
     *&lt;br /&gt;
     */&lt;br /&gt;
    protected function initializeFlexy()&lt;br /&gt;
    {&lt;br /&gt;
        $options = array(&lt;br /&gt;
            'templateDir'   =&amp;gt; '/path/to/templates',&lt;br /&gt;
            'compileDir'    =&amp;gt; '/path/to/templates/compiled_templates',&lt;br /&gt;
            'forceCompile'  =&amp;gt; 0,&lt;br /&gt;
            'debug'         =&amp;gt; 0,&lt;br /&gt;
            'locale'        =&amp;gt; 'en'       &lt;br /&gt;
        );&lt;br /&gt;
        &lt;br /&gt;
        $this-&amp;gt;flexyHandle = new FARMS_HTML_Template_Flexy($options);&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    /**&lt;br /&gt;
     * Gets current date and time&lt;br /&gt;
     *&lt;br /&gt;
     * @access public&lt;br /&gt;
     * @return string Current date and time&lt;br /&gt;
     *&lt;br /&gt;
     */&lt;br /&gt;
    public function getDateTime()&lt;br /&gt;
    {&lt;br /&gt;
        return strftime('%D %T');&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    /**&lt;br /&gt;
     * Shows the page.&lt;br /&gt;
     *&lt;br /&gt;
     * @access public&lt;br /&gt;
     */&lt;br /&gt;
    public function getView() {&lt;br /&gt;
        &lt;br /&gt;
        $this-&amp;gt;setPageTitle('Your first MVCnPHP View');&lt;br /&gt;
    	$this-&amp;gt;flexyHandle-&amp;gt;compile('Home.thtml');&lt;br /&gt;
        $this-&amp;gt;flexyHandle-&amp;gt;outputObject($this);       &lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
So how does all the above work?  Let's run down the notable bits of code.  First of all, if you go back and look at the Flexy template we created, we had a variable called pageTitle.  It is no mistake that on our MVCnPHP view we have a public class member called pageTitle.  Similarly, the Flexy template had a call to a method getDateTime() which can be seen above as a public method on our MVCnPHP view.  The magic to all this is in the getView() method:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&amp;lt;pre&amp;gt;&lt;br /&gt;
$this-&amp;gt;flexyHandle-&amp;gt;compile('Home.thtml');&lt;br /&gt;
$this-&amp;gt;flexyHandle-&amp;gt;outputObject($this);       &lt;br /&gt;
&amp;lt;/pre&amp;gt;&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The first line above compiles our Flexy template Home.thtml into executable PHP code.  It's worth noting that Flexy is smart enough to only compile the template if the template hasn't be compiled yet or if the template itself has changed since the last compile.  This works exactly like JSP's in the Java world.&lt;br /&gt;
&lt;br /&gt;
The outputObject() call tell Flexy to now run the compiled template and that it should use our MVCnPHP view ($this) as the class that holds all the data and methods needed to render the page.&lt;br /&gt;
&lt;br /&gt;
Now you may be wondering how the getView() method even gets called.  That is done by the MVCnPHP Controller and it knows how to call our view based on it's [[MVCnPHPConfig|configuration file]].&lt;br /&gt;
&lt;br /&gt;
== Note on Namespacing ==&lt;br /&gt;
&lt;br /&gt;
PHP5 has no notion of namespaces.  Thus if you have a class called User and you are trying to integrate your code with third party code that also has a class called User then you will be in trouble because of the name conflict.  Your only option is ensure the class names are entirely different.  The Geeklog 2 Framework, uses the [http://pear.php.net PEAR] approach to solving this by qualifying each class name with a prefix.  That prefix is typically the package name you'd like to give the class had you had namespace support.  If you agree this is all messy, feel free to follow the history of attempts made at getting namespace support in PHP5 [http://phpnamespaces.org/wiki/ here].  In the meantime, if you notice class names with prefixs like SAMPLE_ or GEEKLOG_ or MVCnPHP_ you know why.&lt;/div&gt;</summary>
		<author><name>LWC</name></author>	</entry>

	<entry>
		<id>http://gwiki3.thatlinuxbox.com/index.php?title=ConfigFile14&amp;diff=5619</id>
		<title>ConfigFile14</title>
		<link rel="alternate" type="text/html" href="http://gwiki3.thatlinuxbox.com/index.php?title=ConfigFile14&amp;diff=5619"/>
				<updated>2009-10-31T00:31:55Z</updated>
		
		<summary type="html">&lt;p&gt;LWC: Fixed link&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&amp;lt;h1&amp;gt;GeekLog Configuration File&amp;lt;/h1&amp;gt;&lt;br /&gt;
&amp;lt;h2&amp;gt;Setting up config.php&amp;lt;/h2&amp;gt;&lt;br /&gt;
&amp;lt;p&amp;gt;The Geeklog Configuration file (along with the languages file) is the place to make changes to system-wide settings such as the name of the site, user settings, and more.&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
Tip: Make changes to a copy of your file so you can always revert back to a configuration file that you know works.&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
Tip: Until you are familiar with what is going on, make a single change then upload it to see what happened. Once you get the hang of it you can make more substantial edits at a time.&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;/p&amp;gt;&lt;br /&gt;
&amp;lt;p&amp;gt;Most of Geeklog's &amp;amp;quot;static&amp;amp;quot; settings (i.e. those that you aren't&lt;br /&gt;
going to change often) are set in a text file called &amp;lt;tt&amp;gt;config.php&amp;lt;/tt&amp;gt;. It is&lt;br /&gt;
necessary to edit this file to get your system running as well as configuring it&lt;br /&gt;
to your preferences. This file contains a set of variables as defined below:&amp;lt;/p&amp;gt;&lt;br /&gt;
&amp;lt;ul&amp;gt;&lt;br /&gt;
  &amp;lt;li&amp;gt;&amp;lt;a href=&amp;quot;http://www.geeklog.net/docs/config.html#database&amp;quot;&amp;gt;Database&lt;br /&gt;
    Settings&amp;lt;/a&amp;gt;&amp;lt;/li&amp;gt;&lt;br /&gt;
  &amp;lt;li&amp;gt;&amp;lt;a href=&amp;quot;http://www.geeklog.net/docs/config.html#server&amp;quot;&amp;gt;Server Settings&amp;lt;/a&amp;gt;&amp;lt;/li&amp;gt;&lt;br /&gt;
  &amp;lt;li&amp;gt;&amp;lt;a href=&amp;quot;http://www.geeklog.net/docs/config.html#site&amp;quot;&amp;gt;Site Settings&amp;lt;/a&amp;gt;&amp;lt;/li&amp;gt;&lt;br /&gt;
  &amp;lt;li&amp;gt;&amp;lt;a href=&amp;quot;http://www.geeklog.net/docs/config.html#locale&amp;quot;&amp;gt;Locale Settings&amp;lt;/a&amp;gt;&amp;lt;/li&amp;gt;&lt;br /&gt;
  &amp;lt;li&amp;gt;&amp;lt;a href=&amp;quot;http://www.geeklog.net/docs/config.html#session&amp;quot;&amp;gt;Session Settings&amp;lt;/a&amp;gt;&amp;lt;/li&amp;gt;&lt;br /&gt;
  &amp;lt;li&amp;gt;&amp;lt;a href=&amp;quot;http://www.geeklog.net/docs/config.html#cookie&amp;quot;&amp;gt;Cookie Names&amp;lt;/a&amp;gt;&amp;lt;/li&amp;gt;&lt;br /&gt;
  &amp;lt;li&amp;gt;&amp;lt;a href=&amp;quot;http://www.geeklog.net/docs/config.html#desc_mail_settings&amp;quot;&amp;gt;E-Mail&lt;br /&gt;
    Settings&amp;lt;/a&amp;gt;&amp;lt;/li&amp;gt;&lt;br /&gt;
  &amp;lt;li&amp;gt;&amp;lt;a href=&amp;quot;http://www.geeklog.net/docs/config.html#login&amp;quot;&amp;gt;Login Settings&amp;lt;/a&amp;gt;&amp;lt;/li&amp;gt;&lt;br /&gt;
  &amp;lt;li&amp;gt;&amp;lt;a href=&amp;quot;http://www.geeklog.net/docs/config.html#submission&amp;quot;&amp;gt;Submission&lt;br /&gt;
    Settings&amp;lt;/a&amp;gt;&amp;lt;/li&amp;gt;&lt;br /&gt;
  &amp;lt;li&amp;gt;&amp;lt;a href=&amp;quot;http://www.geeklog.net/docs/config.html#trackback&amp;quot;&amp;gt;Trackback,&lt;br /&gt;
    Pingback, and Ping Settings&amp;lt;/a&amp;gt;&amp;lt;/li&amp;gt;&lt;br /&gt;
  &amp;lt;li&amp;gt;&amp;lt;a href=&amp;quot;http://www.geeklog.net/docs/config.html#misc&amp;quot;&amp;gt;Topic, What's New,&lt;br /&gt;
    and Daily Digest Settings&amp;lt;/a&amp;gt;&amp;lt;/li&amp;gt;&lt;br /&gt;
  &amp;lt;li&amp;gt;&amp;lt;a href=&amp;quot;http://www.geeklog.net/docs/config.html#story&amp;quot;&amp;gt;Story Settings&amp;lt;/a&amp;gt;&amp;lt;/li&amp;gt;&lt;br /&gt;
  &amp;lt;li&amp;gt;&amp;lt;a href=&amp;quot;http://www.geeklog.net/docs/config.html#comment&amp;quot;&amp;gt;Comment Settings&amp;lt;/a&amp;gt;&amp;lt;/li&amp;gt;&lt;br /&gt;
  &amp;lt;li&amp;gt;&amp;lt;a href=&amp;quot;http://www.geeklog.net/docs/config.html#image&amp;quot;&amp;gt;Image Settings&amp;lt;/a&amp;gt;&lt;br /&gt;
    &amp;lt;ul&amp;gt;&lt;br /&gt;
      &amp;lt;li&amp;gt;&amp;lt;a href=&amp;quot;http://www.geeklog.net/docs/config.html#userphoto&amp;quot;&amp;gt;User photo&amp;lt;/a&amp;gt;&amp;lt;/li&amp;gt;&lt;br /&gt;
    &amp;lt;/ul&amp;gt;&lt;br /&gt;
  &amp;lt;/li&amp;gt;&lt;br /&gt;
  &amp;lt;li&amp;gt;&amp;lt;a href=&amp;quot;http://www.geeklog.net/docs/config.html#rdf&amp;quot;&amp;gt;Syndication Settings&amp;lt;/a&amp;gt;&amp;lt;/li&amp;gt;&lt;br /&gt;
  &amp;lt;li&amp;gt;&amp;lt;a href=&amp;quot;http://www.geeklog.net/docs/config.html#content&amp;quot;&amp;gt;Content Control&lt;br /&gt;
    Settings&amp;lt;/a&amp;gt;&amp;lt;/li&amp;gt;&lt;br /&gt;
  &amp;lt;li&amp;gt;&amp;lt;a href=&amp;quot;http://www.geeklog.net/docs/config.html#url-rewrite&amp;quot;&amp;gt;URL&lt;br /&gt;
    Rewriting&amp;lt;/a&amp;gt;&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;/ul&amp;gt;&lt;br /&gt;
&amp;lt;h3&amp;gt;&amp;lt;a name=&amp;quot;database&amp;quot;&amp;gt;Database Settings&amp;lt;/a&amp;gt;&amp;lt;/h3&amp;gt;&lt;br /&gt;
&amp;lt;table border=&amp;quot;1&amp;quot; width=&amp;quot;100%&amp;quot;&amp;gt;&lt;br /&gt;
  &amp;lt;tbody&amp;gt;&lt;br /&gt;
    &amp;lt;tr&amp;gt;&lt;br /&gt;
      &amp;lt;th width=&amp;quot;8%&amp;quot;&amp;gt;Variable&amp;lt;/th&amp;gt;&lt;br /&gt;
      &amp;lt;th width=&amp;quot;29%&amp;quot;&amp;gt;Default Value&amp;lt;/th&amp;gt;&lt;br /&gt;
      &amp;lt;th width=&amp;quot;63%&amp;quot;&amp;gt;Description&amp;lt;/th&amp;gt;&lt;br /&gt;
    &amp;lt;/tr&amp;gt;&lt;br /&gt;
    &amp;lt;tr&amp;gt;&lt;br /&gt;
      &amp;lt;td valign=&amp;quot;top&amp;quot;&amp;gt;_DB_dbms&amp;lt;/td&amp;gt;&lt;br /&gt;
      &amp;lt;td valign=&amp;quot;top&amp;quot;&amp;gt;mysql&amp;lt;/td&amp;gt;&lt;br /&gt;
      &amp;lt;td valign=&amp;quot;top&amp;quot;&amp;gt;This option tells Geeklog which type of database it's&lt;br /&gt;
        running on. Can be either &amp;lt;code&amp;gt;'mysql'&amp;lt;/code&amp;gt; (for MySQL) or &amp;lt;code&amp;gt;'mssql'&amp;lt;/code&amp;gt;&lt;br /&gt;
        (for Microsoft SQL Server).&amp;lt;/td&amp;gt;&lt;br /&gt;
    &amp;lt;/tr&amp;gt;&lt;br /&gt;
    &amp;lt;tr&amp;gt;&lt;br /&gt;
      &amp;lt;td valign=&amp;quot;top&amp;quot;&amp;gt;_DB_host&amp;lt;/td&amp;gt;&lt;br /&gt;
      &amp;lt;td valign=&amp;quot;top&amp;quot;&amp;gt;localhost&amp;lt;/td&amp;gt;&lt;br /&gt;
      &amp;lt;td valign=&amp;quot;top&amp;quot;&amp;gt;Database Server (to be entered in the form: &amp;lt;i&amp;gt;hostname:port:unixsocket&amp;lt;/i&amp;gt;).&lt;br /&gt;
        In most cases you won't need to change the default value.&amp;lt;/td&amp;gt;&lt;br /&gt;
    &amp;lt;/tr&amp;gt;&lt;br /&gt;
    &amp;lt;tr&amp;gt;&lt;br /&gt;
      &amp;lt;td valign=&amp;quot;top&amp;quot;&amp;gt;_DB_name&amp;lt;/td&amp;gt;&lt;br /&gt;
      &amp;lt;td valign=&amp;quot;top&amp;quot;&amp;gt;geeklog&amp;lt;/td&amp;gt;&lt;br /&gt;
      &amp;lt;td valign=&amp;quot;top&amp;quot;&amp;gt;Database Name&amp;lt;/td&amp;gt;&lt;br /&gt;
    &amp;lt;/tr&amp;gt;&lt;br /&gt;
    &amp;lt;tr&amp;gt;&lt;br /&gt;
      &amp;lt;td valign=&amp;quot;top&amp;quot;&amp;gt;_DB_user&amp;lt;/td&amp;gt;&lt;br /&gt;
      &amp;lt;td valign=&amp;quot;top&amp;quot;&amp;gt;root&amp;lt;/td&amp;gt;&lt;br /&gt;
      &amp;lt;td valign=&amp;quot;top&amp;quot;&amp;gt;Database User Account&amp;lt;/td&amp;gt;&lt;br /&gt;
    &amp;lt;/tr&amp;gt;&lt;br /&gt;
    &amp;lt;tr&amp;gt;&lt;br /&gt;
      &amp;lt;td valign=&amp;quot;top&amp;quot;&amp;gt;_DB_pass&amp;lt;/td&amp;gt;&lt;br /&gt;
      &amp;lt;td valign=&amp;quot;top&amp;quot;&amp;gt;null&amp;lt;/td&amp;gt;&lt;br /&gt;
      &amp;lt;td valign=&amp;quot;top&amp;quot;&amp;gt;Database User Password&amp;lt;/td&amp;gt;&lt;br /&gt;
    &amp;lt;/tr&amp;gt;&lt;br /&gt;
    &amp;lt;tr&amp;gt;&lt;br /&gt;
      &amp;lt;td valign=&amp;quot;top&amp;quot;&amp;gt;_DB_table_prefix&amp;lt;/td&amp;gt;&lt;br /&gt;
      &amp;lt;td valign=&amp;quot;top&amp;quot;&amp;gt;gl_&amp;lt;/td&amp;gt;&lt;br /&gt;
      &amp;lt;td valign=&amp;quot;top&amp;quot;&amp;gt;Prefix to put in front of all of Geeklog's table names&lt;br /&gt;
        (to avoid name collisions with tables used by other applications)&amp;lt;/td&amp;gt;&lt;br /&gt;
    &amp;lt;/tr&amp;gt;&lt;br /&gt;
    &amp;lt;tr&amp;gt;&lt;br /&gt;
      &amp;lt;td valign=&amp;quot;top&amp;quot;&amp;gt;_DB_mysqldump_path&amp;lt;/td&amp;gt;&lt;br /&gt;
      &amp;lt;td valign=&amp;quot;top&amp;quot;&amp;gt;/usr/bin/mysqldump&amp;lt;/td&amp;gt;&lt;br /&gt;
      &amp;lt;td valign=&amp;quot;top&amp;quot;&amp;gt;Complete path to the &amp;lt;a href=&amp;quot;http://www.mysql.com/doc/en/mysqldump.html&amp;quot;&amp;gt;mysqldump&amp;lt;/a&amp;gt;&lt;br /&gt;
        utility (part of MySQL) for making backups of your Geeklog database.&amp;lt;br&amp;gt;&lt;br /&gt;
        &amp;lt;i&amp;gt;(only used when running on a MySQL database)&amp;lt;/i&amp;gt;&amp;lt;/td&amp;gt;&lt;br /&gt;
    &amp;lt;/tr&amp;gt;&lt;br /&gt;
    &amp;lt;tr&amp;gt;&lt;br /&gt;
      &amp;lt;td valign=&amp;quot;top&amp;quot;&amp;gt;&amp;lt;a name=&amp;quot;desc_allow_mysqldump&amp;quot;&amp;gt;allow_mysqldump&amp;lt;/a&amp;gt;&amp;lt;/td&amp;gt;&lt;br /&gt;
      &amp;lt;td valign=&amp;quot;top&amp;quot;&amp;gt;1&amp;lt;/td&amp;gt;&lt;br /&gt;
      &amp;lt;td valign=&amp;quot;top&amp;quot;&amp;gt;Enable or disable the backup functionality (1 = on, 0 =&lt;br /&gt;
        off).&amp;lt;br&amp;gt;&lt;br /&gt;
        &amp;lt;i&amp;gt;(only used when running on a MySQL database)&amp;lt;/i&amp;gt;&amp;lt;/td&amp;gt;&lt;br /&gt;
    &amp;lt;/tr&amp;gt;&lt;br /&gt;
    &amp;lt;tr&amp;gt;&lt;br /&gt;
      &amp;lt;td valign=&amp;quot;top&amp;quot;&amp;gt;&amp;lt;a name=&amp;quot;desc_mysqldump_options&amp;quot;&amp;gt;mysqldump_options&amp;lt;/a&amp;gt;&amp;lt;/td&amp;gt;&lt;br /&gt;
      &amp;lt;td valign=&amp;quot;top&amp;quot;&amp;gt;-Q&amp;lt;/td&amp;gt;&lt;br /&gt;
      &amp;lt;td valign=&amp;quot;top&amp;quot;&amp;gt;Here you can include additional options for the &amp;lt;a href=&amp;quot;http://www.mysql.com/doc/en/mysqldump.html&amp;quot;&amp;gt;mysqldump&amp;lt;/a&amp;gt;&lt;br /&gt;
        call that Geeklog uses to create a backup from your database.&amp;lt;br&amp;gt;&lt;br /&gt;
        &amp;lt;i&amp;gt;(only used when running on a MySQL database)&amp;lt;/i&amp;gt;&amp;lt;/td&amp;gt;&lt;br /&gt;
    &amp;lt;/tr&amp;gt;&lt;br /&gt;
  &amp;lt;/tbody&amp;gt;&lt;br /&gt;
&amp;lt;/table&amp;gt;&lt;br /&gt;
&amp;lt;h3&amp;gt;&amp;lt;a name=&amp;quot;server&amp;quot;&amp;gt;Server Settings&amp;lt;/a&amp;gt;&amp;lt;/h3&amp;gt;&lt;br /&gt;
&amp;lt;table border=&amp;quot;1&amp;quot; width=&amp;quot;100%&amp;quot;&amp;gt;&lt;br /&gt;
  &amp;lt;tbody&amp;gt;&lt;br /&gt;
    &amp;lt;tr&amp;gt;&lt;br /&gt;
      &amp;lt;th width=&amp;quot;8%&amp;quot;&amp;gt;Variable&amp;lt;/th&amp;gt;&lt;br /&gt;
      &amp;lt;th width=&amp;quot;29%&amp;quot;&amp;gt;Default Value&amp;lt;/th&amp;gt;&lt;br /&gt;
      &amp;lt;th width=&amp;quot;63%&amp;quot;&amp;gt;Description&amp;lt;/th&amp;gt;&lt;br /&gt;
    &amp;lt;/tr&amp;gt;&lt;br /&gt;
    &amp;lt;tr&amp;gt;&lt;br /&gt;
      &amp;lt;td valign=&amp;quot;top&amp;quot;&amp;gt;&amp;lt;a name=&amp;quot;desc_path&amp;quot;&amp;gt;path&amp;lt;/a&amp;gt;&amp;lt;/td&amp;gt;&lt;br /&gt;
      &amp;lt;td valign=&amp;quot;top&amp;quot;&amp;gt;/path/to/geeklog/&amp;lt;/td&amp;gt;&lt;br /&gt;
      &amp;lt;td valign=&amp;quot;top&amp;quot;&amp;gt;Base file system path for your site (trailing slash&lt;br /&gt;
        necessary)&amp;lt;/td&amp;gt;&lt;br /&gt;
    &amp;lt;/tr&amp;gt;&lt;br /&gt;
    &amp;lt;tr&amp;gt;&lt;br /&gt;
      &amp;lt;td valign=&amp;quot;top&amp;quot;&amp;gt;&amp;lt;a name=&amp;quot;desc_path_system&amp;quot;&amp;gt;path_system&amp;lt;/a&amp;gt;&amp;lt;/td&amp;gt;&lt;br /&gt;
      &amp;lt;td valign=&amp;quot;top&amp;quot;&amp;gt;/path/to/geeklog/system/&amp;lt;/td&amp;gt;&lt;br /&gt;
      &amp;lt;td valign=&amp;quot;top&amp;quot;&amp;gt;Path to your system directory for your site (trailing&lt;br /&gt;
        slash necessary). This directory holds the code libraries used&lt;br /&gt;
        throughout Geeklog&amp;lt;/td&amp;gt;&lt;br /&gt;
    &amp;lt;/tr&amp;gt;&lt;br /&gt;
    &amp;lt;tr&amp;gt;&lt;br /&gt;
      &amp;lt;td valign=&amp;quot;top&amp;quot;&amp;gt;&amp;lt;a name=&amp;quot;desc_path_html&amp;quot;&amp;gt;path_html&amp;lt;/a&amp;gt;&amp;lt;/td&amp;gt;&lt;br /&gt;
      &amp;lt;td valign=&amp;quot;top&amp;quot;&amp;gt;/path/to/geeklog/public_html/&amp;lt;/td&amp;gt;&lt;br /&gt;
      &amp;lt;td valign=&amp;quot;top&amp;quot;&amp;gt;Path to your web tree directory for your site (trailing&lt;br /&gt;
        slash necessary). This directory holds all the web pages used by&lt;br /&gt;
        Geeklog.&amp;lt;/td&amp;gt;&lt;br /&gt;
    &amp;lt;/tr&amp;gt;&lt;br /&gt;
    &amp;lt;tr&amp;gt;&lt;br /&gt;
      &amp;lt;td valign=&amp;quot;top&amp;quot;&amp;gt;&amp;lt;a name=&amp;quot;desc_path_images&amp;quot;&amp;gt;path_images&amp;lt;/a&amp;gt;&amp;lt;/td&amp;gt;&lt;br /&gt;
      &amp;lt;td valign=&amp;quot;top&amp;quot;&amp;gt;/path/to/geeklog/public_html/images/&amp;lt;/td&amp;gt;&lt;br /&gt;
      &amp;lt;td valign=&amp;quot;top&amp;quot;&amp;gt;Path where Geeklog expects to find its images, including&lt;br /&gt;
        user photos and images for stories.&amp;lt;/td&amp;gt;&lt;br /&gt;
    &amp;lt;/tr&amp;gt;&lt;br /&gt;
    &amp;lt;tr&amp;gt;&lt;br /&gt;
      &amp;lt;td valign=&amp;quot;top&amp;quot;&amp;gt;&amp;lt;a name=&amp;quot;desc_path_log&amp;quot;&amp;gt;path_log&amp;lt;/a&amp;gt;&amp;lt;/td&amp;gt;&lt;br /&gt;
      &amp;lt;td valign=&amp;quot;top&amp;quot;&amp;gt;/path/to/geeklog/logs/&amp;lt;/td&amp;gt;&lt;br /&gt;
      &amp;lt;td valign=&amp;quot;top&amp;quot;&amp;gt;File system path for the log files&amp;lt;/td&amp;gt;&lt;br /&gt;
    &amp;lt;/tr&amp;gt;&lt;br /&gt;
    &amp;lt;tr&amp;gt;&lt;br /&gt;
      &amp;lt;td valign=&amp;quot;top&amp;quot;&amp;gt;&amp;lt;a name=&amp;quot;desc_path_language&amp;quot;&amp;gt;path_language&amp;lt;/a&amp;gt;&amp;lt;/td&amp;gt;&lt;br /&gt;
      &amp;lt;td valign=&amp;quot;top&amp;quot;&amp;gt;/path/to/geeklog/language/&amp;lt;/td&amp;gt;&lt;br /&gt;
      &amp;lt;td valign=&amp;quot;top&amp;quot;&amp;gt;location of the Geeklog language files&amp;lt;/td&amp;gt;&lt;br /&gt;
    &amp;lt;/tr&amp;gt;&lt;br /&gt;
    &amp;lt;tr&amp;gt;&lt;br /&gt;
      &amp;lt;td valign=&amp;quot;top&amp;quot;&amp;gt;&amp;lt;a name=&amp;quot;desc_backup_path&amp;quot;&amp;gt;backup_path&amp;lt;/a&amp;gt;&amp;lt;/td&amp;gt;&lt;br /&gt;
      &amp;lt;td valign=&amp;quot;top&amp;quot;&amp;gt;/path/to/geeklog/backups/&amp;lt;/td&amp;gt;&lt;br /&gt;
      &amp;lt;td valign=&amp;quot;top&amp;quot;&amp;gt;location where mysqldump (see above) will store database&lt;br /&gt;
        backups&amp;lt;/td&amp;gt;&lt;br /&gt;
    &amp;lt;/tr&amp;gt;&lt;br /&gt;
    &amp;lt;tr&amp;gt;&lt;br /&gt;
      &amp;lt;td valign=&amp;quot;top&amp;quot;&amp;gt;&amp;lt;a name=&amp;quot;desc_path_data&amp;quot;&amp;gt;path_data&amp;lt;/a&amp;gt;&amp;lt;/td&amp;gt;&lt;br /&gt;
      &amp;lt;td valign=&amp;quot;top&amp;quot;&amp;gt;/path/to/geeklog/data/&amp;lt;/td&amp;gt;&lt;br /&gt;
      &amp;lt;td valign=&amp;quot;top&amp;quot;&amp;gt;File system path for the data directory, used e.g. for&lt;br /&gt;
        the user batch add feature&amp;lt;/td&amp;gt;&lt;br /&gt;
    &amp;lt;/tr&amp;gt;&lt;br /&gt;
    &amp;lt;tr&amp;gt;&lt;br /&gt;
      &amp;lt;td valign=&amp;quot;top&amp;quot;&amp;gt;&amp;lt;a name=&amp;quot;desc_have_pear&amp;quot;&amp;gt;have_pear&amp;lt;/a&amp;gt;&amp;lt;/td&amp;gt;&lt;br /&gt;
      &amp;lt;td valign=&amp;quot;top&amp;quot;&amp;gt;&amp;lt;code&amp;gt;false&amp;lt;/code&amp;gt;&amp;lt;/td&amp;gt;&lt;br /&gt;
      &amp;lt;td valign=&amp;quot;top&amp;quot;&amp;gt;Whether you have &amp;lt;a href=&amp;quot;http://pear.php.net/&amp;quot;&amp;gt;PEAR&amp;lt;/a&amp;gt;&lt;br /&gt;
        installed on your server (&amp;lt;code&amp;gt;= true&amp;lt;/code&amp;gt;) or not (&amp;lt;code&amp;gt;= false&amp;lt;/code&amp;gt;).&lt;br /&gt;
        When set to &amp;lt;code&amp;gt;false&amp;lt;/code&amp;gt;, Geeklog will use the PEAR packages&lt;br /&gt;
        installed in &amp;lt;code&amp;gt;$_CONF['path_pear']&amp;lt;/code&amp;gt; (see below)&amp;lt;/td&amp;gt;&lt;br /&gt;
    &amp;lt;/tr&amp;gt;&lt;br /&gt;
    &amp;lt;tr&amp;gt;&lt;br /&gt;
      &amp;lt;td valign=&amp;quot;top&amp;quot;&amp;gt;&amp;lt;a name=&amp;quot;desc_path_pear&amp;quot;&amp;gt;path_pear&amp;lt;/a&amp;gt;&amp;lt;/td&amp;gt;&lt;br /&gt;
      &amp;lt;td valign=&amp;quot;top&amp;quot;&amp;gt;&amp;lt;tt&amp;gt;/path/to/geeklog/system/pear/&amp;lt;/tt&amp;gt;&amp;lt;/td&amp;gt;&lt;br /&gt;
      &amp;lt;td valign=&amp;quot;top&amp;quot;&amp;gt;When &amp;lt;code&amp;gt;$_CONF['have_pear']&amp;lt;/code&amp;gt; (see above) is set&lt;br /&gt;
        to &amp;lt;code&amp;gt;false&amp;lt;/code&amp;gt;, this is the path where Geeklog expects to find&lt;br /&gt;
        the &amp;lt;a href=&amp;quot;http://pear.php.net/&amp;quot;&amp;gt;PEAR&amp;lt;/a&amp;gt; packages it requires (e.g.&lt;br /&gt;
        PEAR::Mail for sending emails).&amp;lt;/td&amp;gt;&lt;br /&gt;
    &amp;lt;/tr&amp;gt;&lt;br /&gt;
  &amp;lt;/tbody&amp;gt;&lt;br /&gt;
&amp;lt;/table&amp;gt;&lt;br /&gt;
&amp;lt;h3&amp;gt;&amp;lt;a name=&amp;quot;site&amp;quot;&amp;gt;Site Settings&amp;lt;/a&amp;gt;&amp;lt;/h3&amp;gt;&lt;br /&gt;
&amp;lt;table border=&amp;quot;1&amp;quot; width=&amp;quot;100%&amp;quot;&amp;gt;&lt;br /&gt;
  &amp;lt;tbody&amp;gt;&lt;br /&gt;
    &amp;lt;tr&amp;gt;&lt;br /&gt;
      &amp;lt;th width=&amp;quot;8%&amp;quot;&amp;gt;Variable&amp;lt;/th&amp;gt;&lt;br /&gt;
      &amp;lt;th width=&amp;quot;29%&amp;quot;&amp;gt;Default Value&amp;lt;/th&amp;gt;&lt;br /&gt;
      &amp;lt;th width=&amp;quot;63%&amp;quot;&amp;gt;Description&amp;lt;/th&amp;gt;&lt;br /&gt;
    &amp;lt;/tr&amp;gt;&lt;br /&gt;
    &amp;lt;tr&amp;gt;&lt;br /&gt;
      &amp;lt;td valign=&amp;quot;top&amp;quot;&amp;gt;&amp;lt;a name=&amp;quot;desc_site_name&amp;quot;&amp;gt;site_name&amp;lt;/a&amp;gt;&amp;lt;/td&amp;gt;&lt;br /&gt;
      &amp;lt;td valign=&amp;quot;top&amp;quot;&amp;gt;GeekLog Site&amp;lt;/td&amp;gt;&lt;br /&gt;
      &amp;lt;td valign=&amp;quot;top&amp;quot;&amp;gt;Name of your site&amp;lt;/td&amp;gt;&lt;br /&gt;
    &amp;lt;/tr&amp;gt;&lt;br /&gt;
    &amp;lt;tr&amp;gt;&lt;br /&gt;
      &amp;lt;td valign=&amp;quot;top&amp;quot;&amp;gt;&amp;lt;a name=&amp;quot;desc_site_slogan&amp;quot;&amp;gt;site_slogan&amp;lt;/a&amp;gt;&amp;lt;/td&amp;gt;&lt;br /&gt;
      &amp;lt;td valign=&amp;quot;top&amp;quot;&amp;gt;Another Nifty GeekLog Site&amp;lt;/td&amp;gt;&lt;br /&gt;
      &amp;lt;td valign=&amp;quot;top&amp;quot;&amp;gt;Slogan for your site. This is added to the HTML title&lt;br /&gt;
        field.&amp;lt;/td&amp;gt;&lt;br /&gt;
    &amp;lt;/tr&amp;gt;&lt;br /&gt;
    &amp;lt;tr&amp;gt;&lt;br /&gt;
      &amp;lt;td valign=&amp;quot;top&amp;quot;&amp;gt;&amp;lt;a name=&amp;quot;desc_site_mail&amp;quot;&amp;gt;site_mail&amp;lt;/a&amp;gt;&amp;lt;/td&amp;gt;&lt;br /&gt;
      &amp;lt;td valign=&amp;quot;top&amp;quot;&amp;gt;admin@example.com&amp;lt;/td&amp;gt;&lt;br /&gt;
      &amp;lt;td valign=&amp;quot;top&amp;quot;&amp;gt;E-mail address for all admin mail&amp;lt;/td&amp;gt;&lt;br /&gt;
    &amp;lt;/tr&amp;gt;&lt;br /&gt;
    &amp;lt;tr&amp;gt;&lt;br /&gt;
      &amp;lt;td valign=&amp;quot;top&amp;quot;&amp;gt;&amp;lt;a name=&amp;quot;desc_site_url&amp;quot;&amp;gt;site_url&amp;lt;/a&amp;gt;&amp;lt;/td&amp;gt;&lt;br /&gt;
      &amp;lt;td valign=&amp;quot;top&amp;quot;&amp;gt;http://www.example.com&amp;lt;/td&amp;gt;&lt;br /&gt;
      &amp;lt;td valign=&amp;quot;top&amp;quot;&amp;gt;Base URL for your site (no trailing slash)&amp;lt;/td&amp;gt;&lt;br /&gt;
    &amp;lt;/tr&amp;gt;&lt;br /&gt;
    &amp;lt;tr&amp;gt;&lt;br /&gt;
      &amp;lt;td valign=&amp;quot;top&amp;quot;&amp;gt;&amp;lt;a name=&amp;quot;desc_site_admin_url&amp;quot;&amp;gt;site_admin_url&amp;lt;/a&amp;gt;&amp;lt;/td&amp;gt;&lt;br /&gt;
      &amp;lt;td valign=&amp;quot;top&amp;quot;&amp;gt;http://www.example.com/admin&amp;lt;/td&amp;gt;&lt;br /&gt;
      &amp;lt;td valign=&amp;quot;top&amp;quot;&amp;gt;Base URL of the admin area of your site (no trailing&lt;br /&gt;
        slash). You won't have to change this normally, but some hosting&lt;br /&gt;
        services use a predefined &amp;amp;quot;admin&amp;amp;quot; directory for other&lt;br /&gt;
        purposes. In this case, you can rename Geeklog's &amp;lt;tt&amp;gt;admin&amp;lt;/tt&amp;gt;&lt;br /&gt;
        directory and adjust the URL accordingly to avoid conflicts.&amp;lt;/td&amp;gt;&lt;br /&gt;
    &amp;lt;/tr&amp;gt;&lt;br /&gt;
    &amp;lt;tr&amp;gt;&lt;br /&gt;
      &amp;lt;td valign=&amp;quot;top&amp;quot;&amp;gt;&amp;lt;a name=&amp;quot;desc_theme&amp;quot;&amp;gt;theme&amp;lt;/a&amp;gt;&amp;lt;/td&amp;gt;&lt;br /&gt;
      &amp;lt;td valign=&amp;quot;top&amp;quot;&amp;gt;professional&amp;lt;/td&amp;gt;&lt;br /&gt;
      &amp;lt;td valign=&amp;quot;top&amp;quot;&amp;gt;Default theme to use on the site&amp;lt;/td&amp;gt;&lt;br /&gt;
    &amp;lt;/tr&amp;gt;&lt;br /&gt;
    &amp;lt;tr&amp;gt;&lt;br /&gt;
      &amp;lt;td valign=&amp;quot;top&amp;quot;&amp;gt;&amp;lt;a name=&amp;quot;desc_layout_url&amp;quot;&amp;gt;layout_url&amp;lt;/a&amp;gt;&amp;lt;/td&amp;gt;&lt;br /&gt;
      &amp;lt;td valign=&amp;quot;top&amp;quot;&amp;gt;Site URL path, with layout dir and default layout&amp;lt;/td&amp;gt;&lt;br /&gt;
      &amp;lt;td valign=&amp;quot;top&amp;quot;&amp;gt;Location of the default layout&amp;lt;/td&amp;gt;&lt;br /&gt;
    &amp;lt;/tr&amp;gt;&lt;br /&gt;
    &amp;lt;tr&amp;gt;&lt;br /&gt;
      &amp;lt;td valign=&amp;quot;top&amp;quot;&amp;gt;&amp;lt;a name=&amp;quot;desc_path_themes&amp;quot;&amp;gt;path_themes&amp;lt;/a&amp;gt;&amp;lt;/td&amp;gt;&lt;br /&gt;
      &amp;lt;td valign=&amp;quot;top&amp;quot;&amp;gt;/path/to/geeklog/public_html/layout/&amp;lt;/td&amp;gt;&lt;br /&gt;
      &amp;lt;td valign=&amp;quot;top&amp;quot;&amp;gt;Directory where all themes reside&amp;lt;/td&amp;gt;&lt;br /&gt;
    &amp;lt;/tr&amp;gt;&lt;br /&gt;
    &amp;lt;tr&amp;gt;&lt;br /&gt;
      &amp;lt;td valign=&amp;quot;top&amp;quot;&amp;gt;&amp;lt;a name=&amp;quot;desc_path_layout&amp;quot;&amp;gt;path_layout&amp;lt;/a&amp;gt;&amp;lt;/td&amp;gt;&lt;br /&gt;
      &amp;lt;td valign=&amp;quot;top&amp;quot;&amp;gt;/path/to/geeklog/public_html/layout/professional/&amp;lt;/td&amp;gt;&lt;br /&gt;
      &amp;lt;td valign=&amp;quot;top&amp;quot;&amp;gt;Path to current theme directory&amp;lt;/td&amp;gt;&lt;br /&gt;
    &amp;lt;/tr&amp;gt;&lt;br /&gt;
    &amp;lt;tr&amp;gt;&lt;br /&gt;
      &amp;lt;td valign=&amp;quot;top&amp;quot;&amp;gt;&amp;lt;a name=&amp;quot;desc_allow_user_themes&amp;quot;&amp;gt;allow_user_themes&amp;lt;/a&amp;gt;&amp;lt;/td&amp;gt;&lt;br /&gt;
      &amp;lt;td valign=&amp;quot;top&amp;quot;&amp;gt;Can be 1 or 0&amp;lt;/td&amp;gt;&lt;br /&gt;
      &amp;lt;td valign=&amp;quot;top&amp;quot;&amp;gt;If set to 1, users can set their own theme that the site&lt;br /&gt;
        uses&amp;lt;/td&amp;gt;&lt;br /&gt;
    &amp;lt;/tr&amp;gt;&lt;br /&gt;
    &amp;lt;tr&amp;gt;&lt;br /&gt;
      &amp;lt;td valign=&amp;quot;top&amp;quot;&amp;gt;&amp;lt;a name=&amp;quot;desc_allow_user_language&amp;quot;&amp;gt;allow_user_language&amp;lt;/a&amp;gt;&amp;lt;/td&amp;gt;&lt;br /&gt;
      &amp;lt;td valign=&amp;quot;top&amp;quot;&amp;gt;Can be 1 or 0&amp;lt;/td&amp;gt;&lt;br /&gt;
      &amp;lt;td valign=&amp;quot;top&amp;quot;&amp;gt;If set to 1, users can select the language for the site&lt;br /&gt;
        navigation&amp;lt;/td&amp;gt;&lt;br /&gt;
    &amp;lt;/tr&amp;gt;&lt;br /&gt;
    &amp;lt;tr&amp;gt;&lt;br /&gt;
      &amp;lt;td valign=&amp;quot;top&amp;quot;&amp;gt;&amp;lt;a name=&amp;quot;desc_allow_user_photo&amp;quot;&amp;gt;allow_user_photo&amp;lt;/a&amp;gt;&amp;lt;/td&amp;gt;&lt;br /&gt;
      &amp;lt;td valign=&amp;quot;top&amp;quot;&amp;gt;Can be 1 or 0&amp;lt;/td&amp;gt;&lt;br /&gt;
      &amp;lt;td valign=&amp;quot;top&amp;quot;&amp;gt;If set to 1, users can upload a photo to their profile&amp;lt;/td&amp;gt;&lt;br /&gt;
    &amp;lt;/tr&amp;gt;&lt;br /&gt;
    &amp;lt;tr&amp;gt;&lt;br /&gt;
      &amp;lt;td valign=&amp;quot;top&amp;quot;&amp;gt;&amp;lt;a name=&amp;quot;desc_hide_author_exclusion&amp;quot;&amp;gt;hide_author_exclusion&amp;lt;/a&amp;gt;&amp;lt;/td&amp;gt;&lt;br /&gt;
      &amp;lt;td valign=&amp;quot;top&amp;quot;&amp;gt;Can be 1 or 0&amp;lt;/td&amp;gt;&lt;br /&gt;
      &amp;lt;td valign=&amp;quot;top&amp;quot;&amp;gt;If set to 1, the option to to exclude certain authors&lt;br /&gt;
        from being seen is hidden from the user's preferences.&amp;lt;/td&amp;gt;&lt;br /&gt;
    &amp;lt;/tr&amp;gt;&lt;br /&gt;
    &amp;lt;tr&amp;gt;&lt;br /&gt;
      &amp;lt;td valign=&amp;quot;top&amp;quot;&amp;gt;&amp;lt;a name=&amp;quot;desc_show_fullname&amp;quot;&amp;gt;show_fullname&amp;lt;/a&amp;gt;&amp;lt;/td&amp;gt;&lt;br /&gt;
      &amp;lt;td valign=&amp;quot;top&amp;quot;&amp;gt;0&amp;lt;/td&amp;gt;&lt;br /&gt;
      &amp;lt;td valign=&amp;quot;top&amp;quot;&amp;gt;Whether to display a user's full name (= 1) or only their&lt;br /&gt;
        username (= 0). For users that haven't entered their full name, Geeklog&lt;br /&gt;
        will always display the username.&amp;lt;/td&amp;gt;&lt;br /&gt;
    &amp;lt;/tr&amp;gt;&lt;br /&gt;
    &amp;lt;tr&amp;gt;&lt;br /&gt;
      &amp;lt;td valign=&amp;quot;top&amp;quot;&amp;gt;&amp;lt;a name=&amp;quot;desc_remoteauthentication&amp;quot;&amp;gt;remoteauthentication&amp;lt;/a&amp;gt;&amp;lt;/td&amp;gt;&lt;br /&gt;
      &amp;lt;td valign=&amp;quot;top&amp;quot;&amp;gt;false&amp;lt;/td&amp;gt;&lt;br /&gt;
      &amp;lt;td valign=&amp;quot;top&amp;quot;&amp;gt;Allow (when set to &amp;lt;tt&amp;gt;true&amp;lt;/tt&amp;gt;) users who already have&lt;br /&gt;
        an account with some other service to log into your Geeklog site with&lt;br /&gt;
        the login for that service. Currently supported: Blogger and LiveJournal.&amp;lt;br&amp;gt;&lt;br /&gt;
        Please note that to enable login for a specific service, you need an&lt;br /&gt;
        authorization class in &amp;lt;tt&amp;gt;system/classes/authentication&amp;lt;/tt&amp;gt;. If you&lt;br /&gt;
        only want to allow Blogger but not LiveJournal users (or vice versa),&lt;br /&gt;
        simply remove the class file for the unwanted service(s).&amp;lt;/td&amp;gt;&lt;br /&gt;
    &amp;lt;/tr&amp;gt;&lt;br /&gt;
    &amp;lt;tr&amp;gt;&lt;br /&gt;
      &amp;lt;td valign=&amp;quot;top&amp;quot;&amp;gt;&amp;lt;a name=&amp;quot;desc_show_servicename&amp;quot;&amp;gt;show_servicename&amp;lt;/a&amp;gt;&amp;lt;/td&amp;gt;&lt;br /&gt;
      &amp;lt;td valign=&amp;quot;top&amp;quot;&amp;gt;true&amp;lt;/td&amp;gt;&lt;br /&gt;
      &amp;lt;td valign=&amp;quot;top&amp;quot;&amp;gt;If you allow users to log in with accounts on remote&lt;br /&gt;
        services (like Blogger or LiveJournal), this option will at the&lt;br /&gt;
        service's name to the username to avoid confusion with local users of&lt;br /&gt;
        the same name. Set to &amp;lt;tt&amp;gt;false&amp;lt;/tt&amp;gt; to disable.&amp;lt;/td&amp;gt;&lt;br /&gt;
    &amp;lt;/tr&amp;gt;&lt;br /&gt;
    &amp;lt;tr&amp;gt;&lt;br /&gt;
      &amp;lt;td valign=&amp;quot;top&amp;quot;&amp;gt;&amp;lt;a name=&amp;quot;desc_site_enabled&amp;quot;&amp;gt;site_enabled&amp;lt;/a&amp;gt;&amp;lt;/td&amp;gt;&lt;br /&gt;
      &amp;lt;td valign=&amp;quot;top&amp;quot;&amp;gt;true&amp;lt;/td&amp;gt;&lt;br /&gt;
      &amp;lt;td valign=&amp;quot;top&amp;quot;&amp;gt;A Geeklog site can be disabled quickly (e.g. for&lt;br /&gt;
        maintenance) by setting this to 'false'.&amp;lt;/td&amp;gt;&lt;br /&gt;
    &amp;lt;/tr&amp;gt;&lt;br /&gt;
    &amp;lt;tr&amp;gt;&lt;br /&gt;
      &amp;lt;td valign=&amp;quot;top&amp;quot;&amp;gt;&amp;lt;a name=&amp;quot;desc_site_disabled_msg&amp;quot;&amp;gt;site_disabled_msg&amp;lt;/a&amp;gt;&amp;lt;/td&amp;gt;&lt;br /&gt;
      &amp;lt;td valign=&amp;quot;top&amp;quot;&amp;gt;'Geeklog Site is down. Please come back soon.'&amp;lt;/td&amp;gt;&lt;br /&gt;
      &amp;lt;td valign=&amp;quot;top&amp;quot;&amp;gt;This contains the message to display when a Geeklog site&lt;br /&gt;
        is disabled. If the text begins with &amp;amp;quot;http:&amp;amp;quot; then visitors are&lt;br /&gt;
        redirected to that URL.&amp;lt;/td&amp;gt;&lt;br /&gt;
    &amp;lt;/tr&amp;gt;&lt;br /&gt;
    &amp;lt;tr&amp;gt;&lt;br /&gt;
      &amp;lt;td valign=&amp;quot;top&amp;quot;&amp;gt;&amp;lt;a name=&amp;quot;desc_sort_admin&amp;quot;&amp;gt;sort_admin&amp;lt;/a&amp;gt;&amp;lt;/td&amp;gt;&lt;br /&gt;
      &amp;lt;td valign=&amp;quot;top&amp;quot;&amp;gt;false&amp;lt;/td&amp;gt;&lt;br /&gt;
      &amp;lt;td valign=&amp;quot;top&amp;quot;&amp;gt;If set to &amp;lt;tt&amp;gt;true&amp;lt;/tt&amp;gt; will sort the entries in the&lt;br /&gt;
        Admin's block and the icons on the Submissions page (&amp;lt;tt&amp;gt;moderation.php&amp;lt;/tt&amp;gt;)&lt;br /&gt;
        alphabetically.&amp;lt;/td&amp;gt;&lt;br /&gt;
    &amp;lt;/tr&amp;gt;&lt;br /&gt;
    &amp;lt;tr&amp;gt;&lt;br /&gt;
      &amp;lt;td valign=&amp;quot;top&amp;quot;&amp;gt;&amp;lt;a name=&amp;quot;desc_link_documentation&amp;quot;&amp;gt;link_documentation&amp;lt;/a&amp;gt;&amp;lt;/td&amp;gt;&lt;br /&gt;
      &amp;lt;td valign=&amp;quot;top&amp;quot;&amp;gt;1&amp;lt;/td&amp;gt;&lt;br /&gt;
      &amp;lt;td valign=&amp;quot;top&amp;quot;&amp;gt;Add a link to Geeklog's documentation to the Admin block.&lt;br /&gt;
        Set this to 0 if you don't want that link to show up.&amp;lt;/td&amp;gt;&lt;br /&gt;
    &amp;lt;/tr&amp;gt;&lt;br /&gt;
    &amp;lt;tr&amp;gt;&lt;br /&gt;
      &amp;lt;td valign=&amp;quot;top&amp;quot;&amp;gt;&amp;lt;a name=&amp;quot;desc_menu_elements&amp;quot;&amp;gt;menu_elements&amp;lt;/a&amp;gt;&amp;lt;/td&amp;gt;&lt;br /&gt;
      &amp;lt;td valign=&amp;quot;top&amp;quot;&amp;gt;&amp;lt;code&amp;gt;array('contribute', 'calendar', 'search', 'stats',&lt;br /&gt;
        'directory', 'plugins')&amp;lt;/code&amp;gt;&amp;lt;/td&amp;gt;&lt;br /&gt;
      &amp;lt;td valign=&amp;quot;top&amp;quot;&amp;gt;Specifies which entries are displayed in the site's menu&lt;br /&gt;
        bar (if your theme uses the &amp;lt;code&amp;gt;{menu_elements}&amp;lt;/code&amp;gt; variable to&lt;br /&gt;
        display the menu bar). Can be any combination of &amp;lt;tt&amp;gt;'home'&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;'contribute'&amp;lt;/tt&amp;gt;,&lt;br /&gt;
        &amp;lt;tt&amp;gt;'calendar'&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;'search'&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;'directory'&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;'prefs'&amp;lt;/tt&amp;gt;,&lt;br /&gt;
        &amp;lt;tt&amp;gt;'plugins'&amp;lt;/tt&amp;gt;, and &amp;lt;tt&amp;gt;'custom'&amp;lt;/tt&amp;gt; where &amp;lt;tt&amp;gt;'plugins'&amp;lt;/tt&amp;gt; is&lt;br /&gt;
        the same as the &amp;lt;code&amp;gt;{plg_menu_elements}&amp;lt;/code&amp;gt; variable, i.e. a list&lt;br /&gt;
        of the menu entries provided by plugins, and &amp;lt;tt&amp;gt;'custom'&amp;lt;/tt&amp;gt; displays&lt;br /&gt;
        the entries returned by a custom function &amp;lt;code&amp;gt;CUSTOM_menuEntries&amp;lt;/code&amp;gt;&lt;br /&gt;
        (see &amp;lt;tt&amp;gt;lib-custom.php&amp;lt;/tt&amp;gt; for details).&amp;lt;/td&amp;gt;&lt;br /&gt;
    &amp;lt;/tr&amp;gt;&lt;br /&gt;
    &amp;lt;tr&amp;gt;&lt;br /&gt;
      &amp;lt;td valign=&amp;quot;top&amp;quot;&amp;gt;&amp;lt;a name=&amp;quot;desc_custom_registration&amp;quot;&amp;gt;custom_registration&amp;lt;/a&amp;gt;&amp;lt;/td&amp;gt;&lt;br /&gt;
      &amp;lt;td valign=&amp;quot;top&amp;quot;&amp;gt;&amp;lt;code&amp;gt;false&amp;lt;/code&amp;gt;&amp;lt;/td&amp;gt;&lt;br /&gt;
      &amp;lt;td valign=&amp;quot;top&amp;quot;&amp;gt;When set to &amp;lt;code&amp;gt;true&amp;lt;/code&amp;gt;, Geeklog will let you use&lt;br /&gt;
        your own signup form for new user registrations. Please see the file &amp;lt;tt&amp;gt;lib-custom.php&amp;lt;/tt&amp;gt;&lt;br /&gt;
        that ships with Geeklog for an example.&amp;lt;/td&amp;gt;&lt;br /&gt;
    &amp;lt;/tr&amp;gt;&lt;br /&gt;
    &amp;lt;tr&amp;gt;&lt;br /&gt;
      &amp;lt;td valign=&amp;quot;top&amp;quot;&amp;gt;&amp;lt;a name=&amp;quot;desc_spamx&amp;quot;&amp;gt;spamx&amp;lt;/a&amp;gt;&amp;lt;/td&amp;gt;&lt;br /&gt;
      &amp;lt;td valign=&amp;quot;top&amp;quot;&amp;gt;128&amp;lt;/td&amp;gt;&lt;br /&gt;
      &amp;lt;td valign=&amp;quot;top&amp;quot;&amp;gt;Tells Geeklog's &amp;lt;a href=&amp;quot;http://www.geeklog.net/docs/spamx.html&amp;quot; rel=&amp;quot;nofollow&amp;quot;&amp;gt;Spam-X&amp;lt;/a&amp;gt;&lt;br /&gt;
        plugin what to do when a spam post has been detected. The value is the&lt;br /&gt;
        sum of all values that uniquely identify the Spam-X modules that should&lt;br /&gt;
        be executed. E.g. the &amp;amp;quot;delete&amp;amp;quot; action module uses 128, the&lt;br /&gt;
        &amp;amp;quot;email admin&amp;amp;quot; module uses 8, so if both modules should be&lt;br /&gt;
        executed, this option should be set to 128 + 8 = 136.&amp;lt;/td&amp;gt;&lt;br /&gt;
    &amp;lt;/tr&amp;gt;&lt;br /&gt;
    &amp;lt;tr&amp;gt;&lt;br /&gt;
      &amp;lt;td valign=&amp;quot;top&amp;quot;&amp;gt;&amp;lt;a name=&amp;quot;desc_rootdebug&amp;quot;&amp;gt;rootdebug&amp;lt;/a&amp;gt;&amp;lt;/td&amp;gt;&lt;br /&gt;
      &amp;lt;td valign=&amp;quot;top&amp;quot;&amp;gt;&amp;lt;code&amp;gt;false&amp;lt;/code&amp;gt;&amp;lt;/td&amp;gt;&lt;br /&gt;
      &amp;lt;td valign=&amp;quot;top&amp;quot;&amp;gt;When a PHP error occurs, Geeklog's error handler will&lt;br /&gt;
        only display the actual error message to members of the Root group (to&lt;br /&gt;
        prevent leakage of possibly sensitive information). When set to &amp;lt;code&amp;gt;true&amp;lt;/code&amp;gt;,&lt;br /&gt;
        this information will be displayed to &amp;lt;em&amp;gt;all&amp;lt;/em&amp;gt; users. &amp;lt;strong&amp;gt;Use&lt;br /&gt;
        only for debugging purposes!&amp;lt;/strong&amp;gt;&amp;lt;/td&amp;gt;&lt;br /&gt;
    &amp;lt;/tr&amp;gt;&lt;br /&gt;
    &amp;lt;tr&amp;gt;&lt;br /&gt;
      &amp;lt;td valign=&amp;quot;top&amp;quot;&amp;gt;&amp;lt;a name=&amp;quot;desc_lastlogin&amp;quot;&amp;gt;lastlogin&amp;lt;/a&amp;gt;&amp;lt;/td&amp;gt;&lt;br /&gt;
      &amp;lt;td valign=&amp;quot;top&amp;quot;&amp;gt;&amp;lt;code&amp;gt;true&amp;lt;/code&amp;gt;&amp;lt;/td&amp;gt;&lt;br /&gt;
      &amp;lt;td valign=&amp;quot;top&amp;quot;&amp;gt;Whether to keep track of when a user last logged in (&amp;lt;code&amp;gt;=&lt;br /&gt;
        true&amp;lt;/code&amp;gt;) or not (&amp;lt;code&amp;gt;= false&amp;lt;/code&amp;gt;).&amp;lt;/td&amp;gt;&lt;br /&gt;
    &amp;lt;/tr&amp;gt;&lt;br /&gt;
    &amp;lt;tr&amp;gt;&lt;br /&gt;
      &amp;lt;td valign=&amp;quot;top&amp;quot;&amp;gt;&amp;lt;a name=&amp;quot;desc_cron_schedule_interval&amp;quot;&amp;gt;cron_schedule_interval&amp;lt;/a&amp;gt;&amp;lt;/td&amp;gt;&lt;br /&gt;
      &amp;lt;td valign=&amp;quot;top&amp;quot;&amp;gt;86400&amp;lt;/td&amp;gt;&lt;br /&gt;
      &amp;lt;td valign=&amp;quot;top&amp;quot;&amp;gt;Geeklog can emulate a &amp;lt;a href=&amp;quot;http://en.wikipedia.org/wiki/Cronjob&amp;quot;&amp;gt;cronjob&amp;lt;/a&amp;gt;,&lt;br /&gt;
        i.e. trigger a certain action at a given time. The code to be executed&lt;br /&gt;
        can be provided by a plugin or through the &amp;lt;code&amp;gt;CUSTOM_runScheduledTask&amp;lt;/code&amp;gt;&lt;br /&gt;
        function in your &amp;lt;tt&amp;gt;lib-custom.php&amp;lt;/tt&amp;gt;. The value given is in seconds&lt;br /&gt;
        and specifies the interval in which the code should be executed.&amp;lt;br&amp;gt;&lt;br /&gt;
        Please note that to trigger this action, you will need to have someone&lt;br /&gt;
        visit your site at around the specified time. On a site with few&lt;br /&gt;
        visitors, the code may only be executed with considerable delay.&amp;lt;br&amp;gt;&lt;br /&gt;
        Set to 0 to disable.&amp;lt;/td&amp;gt;&lt;br /&gt;
    &amp;lt;/tr&amp;gt;&lt;br /&gt;
  &amp;lt;/tbody&amp;gt;&lt;br /&gt;
&amp;lt;/table&amp;gt;&lt;br /&gt;
&amp;lt;h3&amp;gt;&amp;lt;a name=&amp;quot;locale&amp;quot;&amp;gt;Locale Settings&amp;lt;/a&amp;gt;&amp;lt;/h3&amp;gt;&lt;br /&gt;
&amp;lt;table border=&amp;quot;1&amp;quot; width=&amp;quot;100%&amp;quot;&amp;gt;&lt;br /&gt;
  &amp;lt;tbody&amp;gt;&lt;br /&gt;
    &amp;lt;tr&amp;gt;&lt;br /&gt;
      &amp;lt;th width=&amp;quot;8%&amp;quot;&amp;gt;Variable&amp;lt;/th&amp;gt;&lt;br /&gt;
      &amp;lt;th width=&amp;quot;29%&amp;quot;&amp;gt;Default Value&amp;lt;/th&amp;gt;&lt;br /&gt;
      &amp;lt;th width=&amp;quot;63%&amp;quot;&amp;gt;Description&amp;lt;/th&amp;gt;&lt;br /&gt;
    &amp;lt;/tr&amp;gt;&lt;br /&gt;
    &amp;lt;tr&amp;gt;&lt;br /&gt;
      &amp;lt;td valign=&amp;quot;top&amp;quot;&amp;gt;&amp;lt;a name=&amp;quot;desc_language&amp;quot;&amp;gt;language&amp;lt;/a&amp;gt;&amp;lt;/td&amp;gt;&lt;br /&gt;
      &amp;lt;td valign=&amp;quot;top&amp;quot;&amp;gt;english&amp;lt;/td&amp;gt;&lt;br /&gt;
      &amp;lt;td valign=&amp;quot;top&amp;quot;&amp;gt;Name of your language file. Additional language files may&lt;br /&gt;
        be available for download at &amp;lt;a href=&amp;quot;http://www.geeklog.net/&amp;quot;&amp;gt;http://www.geeklog.net&amp;lt;/a&amp;gt;.&lt;br /&gt;
        If you translate a language file, please send it to us. Also see &amp;lt;a href=&amp;quot;http://www.geeklog.net/docs/config.html#Localization&amp;quot;&amp;gt;Localization&amp;lt;/a&amp;gt;&lt;br /&gt;
        below.&amp;lt;/td&amp;gt;&lt;br /&gt;
    &amp;lt;/tr&amp;gt;&lt;br /&gt;
    &amp;lt;tr&amp;gt;&lt;br /&gt;
      &amp;lt;td valign=&amp;quot;top&amp;quot;&amp;gt;&amp;lt;a name=&amp;quot;desc_locale&amp;quot;&amp;gt;locale&amp;lt;/a&amp;gt;&amp;lt;/td&amp;gt;&lt;br /&gt;
      &amp;lt;td valign=&amp;quot;top&amp;quot;&amp;gt;en_GB&amp;lt;/td&amp;gt;&lt;br /&gt;
      &amp;lt;td valign=&amp;quot;top&amp;quot;&amp;gt;&amp;lt;a href=&amp;quot;http://en.wikipedia.org/wiki/Locale&amp;quot;&amp;gt;Locale&amp;lt;/a&amp;gt;&lt;br /&gt;
        for the system. This defines both the language and the country that PHP&lt;br /&gt;
        will use when deciding how to display localized information such as&lt;br /&gt;
        dates (e.g. for the names of months).&amp;lt;/td&amp;gt;&lt;br /&gt;
    &amp;lt;/tr&amp;gt;&lt;br /&gt;
    &amp;lt;tr&amp;gt;&lt;br /&gt;
      &amp;lt;td valign=&amp;quot;top&amp;quot;&amp;gt;&amp;lt;a name=&amp;quot;desc_date&amp;quot;&amp;gt;date&amp;lt;/a&amp;gt;&amp;lt;/td&amp;gt;&lt;br /&gt;
      &amp;lt;td valign=&amp;quot;top&amp;quot;&amp;gt;%A, %B %d %Y @ %I:%M %p %Z&amp;lt;/td&amp;gt;&lt;br /&gt;
      &amp;lt;td valign=&amp;quot;top&amp;quot;&amp;gt;Date format used for most of the site, including story&lt;br /&gt;
        displays. See &amp;lt;a href=&amp;quot;http://www.geeklog.net/docs/config.html#date_formats&amp;quot;&amp;gt;date&lt;br /&gt;
        formats&amp;lt;/a&amp;gt; below.&amp;lt;/td&amp;gt;&lt;br /&gt;
    &amp;lt;/tr&amp;gt;&lt;br /&gt;
    &amp;lt;tr&amp;gt;&lt;br /&gt;
      &amp;lt;td valign=&amp;quot;top&amp;quot;&amp;gt;&amp;lt;a name=&amp;quot;desc_daytime&amp;quot;&amp;gt;daytime&amp;lt;/a&amp;gt;&amp;lt;/td&amp;gt;&lt;br /&gt;
      &amp;lt;td valign=&amp;quot;top&amp;quot;&amp;gt;%m/%d %I:%M%p&amp;lt;/td&amp;gt;&lt;br /&gt;
      &amp;lt;td valign=&amp;quot;top&amp;quot;&amp;gt;Date format used when a shorter date is needed. See &amp;lt;a href=&amp;quot;http://www.geeklog.net/docs/config.html#date_formats&amp;quot;&amp;gt;date&lt;br /&gt;
        formats&amp;lt;/a&amp;gt; below.&amp;lt;/td&amp;gt;&lt;br /&gt;
    &amp;lt;/tr&amp;gt;&lt;br /&gt;
    &amp;lt;tr&amp;gt;&lt;br /&gt;
      &amp;lt;td valign=&amp;quot;top&amp;quot;&amp;gt;&amp;lt;a name=&amp;quot;desc_shortdate&amp;quot;&amp;gt;shortdate&amp;lt;/a&amp;gt;&amp;lt;/td&amp;gt;&lt;br /&gt;
      &amp;lt;td valign=&amp;quot;top&amp;quot;&amp;gt;%x&amp;lt;/td&amp;gt;&lt;br /&gt;
      &amp;lt;td valign=&amp;quot;top&amp;quot;&amp;gt;Date format this is the shortest date. See &amp;lt;a href=&amp;quot;http://www.geeklog.net/docs/config.html#date_formats&amp;quot;&amp;gt;date&lt;br /&gt;
        formats&amp;lt;/a&amp;gt; below.&amp;lt;/td&amp;gt;&lt;br /&gt;
    &amp;lt;/tr&amp;gt;&lt;br /&gt;
    &amp;lt;tr&amp;gt;&lt;br /&gt;
      &amp;lt;td valign=&amp;quot;top&amp;quot;&amp;gt;&amp;lt;a name=&amp;quot;desc_dateonly&amp;quot;&amp;gt;dateonly&amp;lt;/a&amp;gt;&amp;lt;/td&amp;gt;&lt;br /&gt;
      &amp;lt;td valign=&amp;quot;top&amp;quot;&amp;gt;%d-%b&amp;lt;/td&amp;gt;&lt;br /&gt;
      &amp;lt;td valign=&amp;quot;top&amp;quot;&amp;gt;Short date format (day and month only), to be used e.g.&lt;br /&gt;
        in the Upcoming Events and Older Stories blocks. See &amp;lt;a href=&amp;quot;http://www.geeklog.net/docs/config.html#date_formats&amp;quot;&amp;gt;date&lt;br /&gt;
        formats&amp;lt;/a&amp;gt; below.&amp;lt;/td&amp;gt;&lt;br /&gt;
    &amp;lt;/tr&amp;gt;&lt;br /&gt;
    &amp;lt;tr&amp;gt;&lt;br /&gt;
      &amp;lt;td valign=&amp;quot;top&amp;quot;&amp;gt;&amp;lt;a name=&amp;quot;desc_timeonly&amp;quot;&amp;gt;timeonly&amp;lt;/a&amp;gt;&amp;lt;/td&amp;gt;&lt;br /&gt;
      &amp;lt;td valign=&amp;quot;top&amp;quot;&amp;gt;%I:%M %p %Z&amp;lt;/td&amp;gt;&lt;br /&gt;
      &amp;lt;td valign=&amp;quot;top&amp;quot;&amp;gt;Format string for the time only, to be used e.g. on the&lt;br /&gt;
        Event Details page. See &amp;lt;a href=&amp;quot;http://www.geeklog.net/docs/config.html#date_formats&amp;quot;&amp;gt;date&lt;br /&gt;
        formats&amp;lt;/a&amp;gt; below.&amp;lt;/td&amp;gt;&lt;br /&gt;
    &amp;lt;/tr&amp;gt;&lt;br /&gt;
    &amp;lt;tr&amp;gt;&lt;br /&gt;
      &amp;lt;td valign=&amp;quot;top&amp;quot;&amp;gt;&amp;lt;a name=&amp;quot;desc_week_start&amp;quot;&amp;gt;week_start&amp;lt;/a&amp;gt;&amp;lt;/td&amp;gt;&lt;br /&gt;
      &amp;lt;td valign=&amp;quot;top&amp;quot;&amp;gt;Sun&amp;lt;/td&amp;gt;&lt;br /&gt;
      &amp;lt;td valign=&amp;quot;top&amp;quot;&amp;gt;First day of the week in the calendar. Can be either &amp;lt;tt&amp;gt;'Sun'&amp;lt;/tt&amp;gt;&lt;br /&gt;
        (Sunday) or &amp;lt;tt&amp;gt;'Mon'&amp;lt;/tt&amp;gt; (Monday).&amp;lt;/td&amp;gt;&lt;br /&gt;
    &amp;lt;/tr&amp;gt;&lt;br /&gt;
    &amp;lt;tr&amp;gt;&lt;br /&gt;
      &amp;lt;td valign=&amp;quot;top&amp;quot;&amp;gt;&amp;lt;a name=&amp;quot;desc_hour_mode&amp;quot;&amp;gt;hour_mode&amp;lt;/a&amp;gt;&amp;lt;/td&amp;gt;&lt;br /&gt;
      &amp;lt;td valign=&amp;quot;top&amp;quot;&amp;gt;12&amp;lt;/td&amp;gt;&lt;br /&gt;
      &amp;lt;td valign=&amp;quot;top&amp;quot;&amp;gt;Which format to use when submitting or editing an object&lt;br /&gt;
        with a time setting (e.g. the publish time of a story). Can be 12 (for&lt;br /&gt;
        the 12 hour am/pm format) or 24 (for the 24 hour format).&amp;lt;/td&amp;gt;&lt;br /&gt;
    &amp;lt;/tr&amp;gt;&lt;br /&gt;
    &amp;lt;tr&amp;gt;&lt;br /&gt;
      &amp;lt;td valign=&amp;quot;top&amp;quot;&amp;gt;&amp;lt;a name=&amp;quot;desc_default_charset&amp;quot;&amp;gt;default_charset&amp;lt;/a&amp;gt;&amp;lt;/td&amp;gt;&lt;br /&gt;
      &amp;lt;td valign=&amp;quot;top&amp;quot;&amp;gt;iso-8859-1&amp;lt;/td&amp;gt;&lt;br /&gt;
      &amp;lt;td valign=&amp;quot;top&amp;quot;&amp;gt;Character encoding used by Geeklog when serving HTML&lt;br /&gt;
        pages or sending email. Only used if the language file did not already&lt;br /&gt;
        set another character encoding.&amp;lt;br&amp;gt;&lt;br /&gt;
        For &amp;lt;a href=&amp;quot;http://wiki.geeklog.net/wiki/index.php/Multilingual_Support&amp;quot;&amp;gt;multilingualism&amp;lt;/a&amp;gt;&lt;br /&gt;
        setups, using &amp;lt;code&amp;gt;'utf-8'&amp;lt;/code&amp;gt; as the default character set is&lt;br /&gt;
        recommended.&amp;lt;/td&amp;gt;&lt;br /&gt;
    &amp;lt;/tr&amp;gt;&lt;br /&gt;
    &amp;lt;tr&amp;gt;&lt;br /&gt;
      &amp;lt;td valign=&amp;quot;top&amp;quot;&amp;gt;&amp;lt;a name=&amp;quot;desc_thousand_separator&amp;quot;&amp;gt;thousand_separator&amp;lt;/a&amp;gt;&amp;lt;/td&amp;gt;&lt;br /&gt;
      &amp;lt;td valign=&amp;quot;top&amp;quot;&amp;gt;&amp;lt;code&amp;gt;,&amp;lt;/code&amp;gt;&amp;lt;/td&amp;gt;&lt;br /&gt;
      &amp;lt;td valign=&amp;quot;top&amp;quot;&amp;gt;Character to use between every group of thousands.&amp;lt;/td&amp;gt;&lt;br /&gt;
    &amp;lt;/tr&amp;gt;&lt;br /&gt;
    &amp;lt;tr&amp;gt;&lt;br /&gt;
      &amp;lt;td valign=&amp;quot;top&amp;quot;&amp;gt;&amp;lt;a name=&amp;quot;desc_decimal_separator&amp;quot;&amp;gt;decimal_separator&amp;lt;/a&amp;gt;&amp;lt;/td&amp;gt;&lt;br /&gt;
      &amp;lt;td valign=&amp;quot;top&amp;quot;&amp;gt;&amp;lt;code&amp;gt;.&amp;lt;/code&amp;gt;&amp;lt;/td&amp;gt;&lt;br /&gt;
      &amp;lt;td valign=&amp;quot;top&amp;quot;&amp;gt;Character to use before decimals.&amp;lt;/td&amp;gt;&lt;br /&gt;
    &amp;lt;/tr&amp;gt;&lt;br /&gt;
    &amp;lt;tr&amp;gt;&lt;br /&gt;
      &amp;lt;td valign=&amp;quot;top&amp;quot;&amp;gt;&amp;lt;a name=&amp;quot;desc_decimal_count&amp;quot;&amp;gt;decimal_count&amp;lt;/a&amp;gt;&amp;lt;/td&amp;gt;&lt;br /&gt;
      &amp;lt;td valign=&amp;quot;top&amp;quot;&amp;gt;2&amp;lt;/td&amp;gt;&lt;br /&gt;
      &amp;lt;td valign=&amp;quot;top&amp;quot;&amp;gt;How many decimal places to display.&amp;lt;/td&amp;gt;&lt;br /&gt;
    &amp;lt;/tr&amp;gt;&lt;br /&gt;
    &amp;lt;tr&amp;gt;&lt;br /&gt;
      &amp;lt;td valign=&amp;quot;top&amp;quot;&amp;gt;&amp;lt;a name=&amp;quot;desc_timezone&amp;quot;&amp;gt;timezone&amp;lt;/a&amp;gt;&amp;lt;/td&amp;gt;&lt;br /&gt;
      &amp;lt;td valign=&amp;quot;top&amp;quot;&amp;gt;&amp;lt;i&amp;gt;(commented out)&amp;lt;/i&amp;gt;&amp;lt;/td&amp;gt;&lt;br /&gt;
      &amp;lt;td valign=&amp;quot;top&amp;quot;&amp;gt;If your server is located in a different timezone, use&lt;br /&gt;
        this option to set your local (i.e. your own) timezone, so that the time&lt;br /&gt;
        and date on the site match your own.&amp;lt;br&amp;gt;&lt;br /&gt;
        This option is known as the &amp;amp;quot;&amp;lt;a href=&amp;quot;http://www.geeklog.net/forum/viewtopic.php?showtopic=21232&amp;quot;&amp;gt;timezone&lt;br /&gt;
        hack&amp;lt;/a&amp;gt;&amp;amp;quot; and may not work on some servers.&amp;lt;/td&amp;gt;&lt;br /&gt;
    &amp;lt;/tr&amp;gt;&lt;br /&gt;
  &amp;lt;/tbody&amp;gt;&lt;br /&gt;
&amp;lt;/table&amp;gt;&lt;br /&gt;
&amp;lt;h3&amp;gt;&amp;lt;a name=&amp;quot;session&amp;quot;&amp;gt;Session Settings&amp;lt;/a&amp;gt;&amp;lt;/h3&amp;gt;&lt;br /&gt;
&amp;lt;table border=&amp;quot;1&amp;quot; width=&amp;quot;100%&amp;quot;&amp;gt;&lt;br /&gt;
  &amp;lt;tbody&amp;gt;&lt;br /&gt;
    &amp;lt;tr&amp;gt;&lt;br /&gt;
      &amp;lt;th width=&amp;quot;8%&amp;quot;&amp;gt;Variable&amp;lt;/th&amp;gt;&lt;br /&gt;
      &amp;lt;th width=&amp;quot;29%&amp;quot;&amp;gt;Default Value&amp;lt;/th&amp;gt;&lt;br /&gt;
      &amp;lt;th width=&amp;quot;63%&amp;quot;&amp;gt;Description&amp;lt;/th&amp;gt;&lt;br /&gt;
    &amp;lt;/tr&amp;gt;&lt;br /&gt;
    &amp;lt;tr&amp;gt;&lt;br /&gt;
      &amp;lt;td valign=&amp;quot;top&amp;quot;&amp;gt;&amp;lt;a name=&amp;quot;desc_cookie_ip&amp;quot;&amp;gt;cookie_ip&amp;lt;/a&amp;gt;&amp;lt;/td&amp;gt;&lt;br /&gt;
      &amp;lt;td valign=&amp;quot;top&amp;quot;&amp;gt;0&amp;lt;/td&amp;gt;&lt;br /&gt;
      &amp;lt;td valign=&amp;quot;top&amp;quot;&amp;gt;Session ID to contain IP address of user as well as&lt;br /&gt;
        random number. This is more secure but will more than likely require&lt;br /&gt;
        dialed up users to login each and every time. (0=no, 1=yes)&amp;lt;/td&amp;gt;&lt;br /&gt;
    &amp;lt;/tr&amp;gt;&lt;br /&gt;
    &amp;lt;tr&amp;gt;&lt;br /&gt;
      &amp;lt;td valign=&amp;quot;top&amp;quot;&amp;gt;&amp;lt;a name=&amp;quot;desc_default_perm_cookie_timeout&amp;quot;&amp;gt;default_perm_cookie_timeout&amp;lt;/a&amp;gt;&amp;lt;/td&amp;gt;&lt;br /&gt;
      &amp;lt;td valign=&amp;quot;top&amp;quot;&amp;gt;28800&amp;lt;/td&amp;gt;&lt;br /&gt;
      &amp;lt;td valign=&amp;quot;top&amp;quot;&amp;gt;Permanent cookie timeout in seconds (28800 = 8 hours).&amp;lt;/td&amp;gt;&lt;br /&gt;
    &amp;lt;/tr&amp;gt;&lt;br /&gt;
    &amp;lt;tr&amp;gt;&lt;br /&gt;
      &amp;lt;td valign=&amp;quot;top&amp;quot;&amp;gt;&amp;lt;a name=&amp;quot;desc_session_cookie_timeout&amp;quot;&amp;gt;session_cookie_timeout&amp;lt;/a&amp;gt;&amp;lt;/td&amp;gt;&lt;br /&gt;
      &amp;lt;td valign=&amp;quot;top&amp;quot;&amp;gt;7200&amp;lt;/td&amp;gt;&lt;br /&gt;
      &amp;lt;td valign=&amp;quot;top&amp;quot;&amp;gt;Session cookie timeout (in seconds).&amp;lt;/td&amp;gt;&lt;br /&gt;
    &amp;lt;/tr&amp;gt;&lt;br /&gt;
    &amp;lt;tr&amp;gt;&lt;br /&gt;
      &amp;lt;td valign=&amp;quot;top&amp;quot;&amp;gt;&amp;lt;a name=&amp;quot;desc_cookie_path&amp;quot;&amp;gt;cookie_path&amp;lt;/a&amp;gt;&amp;lt;/td&amp;gt;&lt;br /&gt;
      &amp;lt;td valign=&amp;quot;top&amp;quot;&amp;gt;/&amp;lt;/td&amp;gt;&lt;br /&gt;
      &amp;lt;td valign=&amp;quot;top&amp;quot;&amp;gt;Cookie path (see the &amp;lt;a href=&amp;quot;http://www.php.net/manual/en/function.setcookie.php&amp;quot;&amp;gt;PHP&lt;br /&gt;
        manual&amp;lt;/a&amp;gt; for details).&amp;lt;/td&amp;gt;&lt;br /&gt;
    &amp;lt;/tr&amp;gt;&lt;br /&gt;
    &amp;lt;tr&amp;gt;&lt;br /&gt;
      &amp;lt;td valign=&amp;quot;top&amp;quot;&amp;gt;&amp;lt;a name=&amp;quot;desc_cookiedomain&amp;quot;&amp;gt;cookiedomain&amp;lt;/a&amp;gt;&amp;lt;/td&amp;gt;&lt;br /&gt;
      &amp;lt;td valign=&amp;quot;top&amp;quot;&amp;gt;&amp;lt;i&amp;gt;(empty)&amp;lt;/i&amp;gt;&amp;lt;/td&amp;gt;&lt;br /&gt;
      &amp;lt;td valign=&amp;quot;top&amp;quot;&amp;gt;The domain that the cookie is available. Geeklog will&lt;br /&gt;
        attempt to guess the correct value for this setting (based on the 'site_url'&lt;br /&gt;
        variable). See the &amp;lt;a href=&amp;quot;http://www.php.net/manual/en/function.setcookie.php&amp;quot;&amp;gt;PHP&lt;br /&gt;
        manual&amp;lt;/a&amp;gt; for details.&amp;lt;/td&amp;gt;&lt;br /&gt;
    &amp;lt;/tr&amp;gt;&lt;br /&gt;
    &amp;lt;tr&amp;gt;&lt;br /&gt;
      &amp;lt;td valign=&amp;quot;top&amp;quot;&amp;gt;&amp;lt;a name=&amp;quot;desc_cookiesecure&amp;quot;&amp;gt;cookiesecure&amp;lt;/a&amp;gt;&amp;lt;/td&amp;gt;&lt;br /&gt;
      &amp;lt;td valign=&amp;quot;top&amp;quot;&amp;gt;0&amp;lt;/td&amp;gt;&lt;br /&gt;
      &amp;lt;td valign=&amp;quot;top&amp;quot;&amp;gt;Only set to 1 if your site uses HTTPS (see the &amp;lt;a href=&amp;quot;http://www.php.net/manual/en/function.setcookie.php&amp;quot;&amp;gt;PHP&lt;br /&gt;
        manual&amp;lt;/a&amp;gt; for details).&amp;lt;/td&amp;gt;&lt;br /&gt;
    &amp;lt;/tr&amp;gt;&lt;br /&gt;
  &amp;lt;/tbody&amp;gt;&lt;br /&gt;
&amp;lt;/table&amp;gt;&lt;br /&gt;
&amp;lt;h3&amp;gt;&amp;lt;a name=&amp;quot;cookie&amp;quot;&amp;gt;Cookie Names&amp;lt;/a&amp;gt;&amp;lt;/h3&amp;gt;&lt;br /&gt;
&amp;lt;p&amp;gt;These variables define the names of all of Geeklog's cookies. They can easily&lt;br /&gt;
be changed in case there's a name collision with the cookies used by some other&lt;br /&gt;
software package that you may use on your site.&amp;lt;/p&amp;gt;&lt;br /&gt;
&amp;lt;table border=&amp;quot;1&amp;quot; width=&amp;quot;100%&amp;quot;&amp;gt;&lt;br /&gt;
  &amp;lt;tbody&amp;gt;&lt;br /&gt;
    &amp;lt;tr&amp;gt;&lt;br /&gt;
      &amp;lt;th width=&amp;quot;8%&amp;quot;&amp;gt;Variable&amp;lt;/th&amp;gt;&lt;br /&gt;
      &amp;lt;th width=&amp;quot;29%&amp;quot;&amp;gt;Default Value&amp;lt;/th&amp;gt;&lt;br /&gt;
      &amp;lt;th width=&amp;quot;63%&amp;quot;&amp;gt;Description&amp;lt;/th&amp;gt;&lt;br /&gt;
    &amp;lt;/tr&amp;gt;&lt;br /&gt;
    &amp;lt;tr&amp;gt;&lt;br /&gt;
      &amp;lt;td valign=&amp;quot;top&amp;quot;&amp;gt;&amp;lt;a name=&amp;quot;desc_cookie_session&amp;quot;&amp;gt;cookie_session&amp;lt;/a&amp;gt;&amp;lt;/td&amp;gt;&lt;br /&gt;
      &amp;lt;td valign=&amp;quot;top&amp;quot;&amp;gt;gl_session&amp;lt;/td&amp;gt;&lt;br /&gt;
      &amp;lt;td valign=&amp;quot;top&amp;quot;&amp;gt;Name of the cookie that stores the session ID.&amp;lt;/td&amp;gt;&lt;br /&gt;
    &amp;lt;/tr&amp;gt;&lt;br /&gt;
    &amp;lt;tr&amp;gt;&lt;br /&gt;
      &amp;lt;td valign=&amp;quot;top&amp;quot;&amp;gt;&amp;lt;a name=&amp;quot;desc_cookie_name&amp;quot;&amp;gt;cookie_name&amp;lt;/a&amp;gt;&amp;lt;/td&amp;gt;&lt;br /&gt;
      &amp;lt;td valign=&amp;quot;top&amp;quot;&amp;gt;geeklog&amp;lt;/td&amp;gt;&lt;br /&gt;
      &amp;lt;td valign=&amp;quot;top&amp;quot;&amp;gt;Name of the permanent cookie.&amp;lt;/td&amp;gt;&lt;br /&gt;
    &amp;lt;/tr&amp;gt;&lt;br /&gt;
    &amp;lt;tr&amp;gt;&lt;br /&gt;
      &amp;lt;td valign=&amp;quot;top&amp;quot;&amp;gt;&amp;lt;a name=&amp;quot;desc_cookie_password&amp;quot;&amp;gt;cookie_password&amp;lt;/a&amp;gt;&amp;lt;/td&amp;gt;&lt;br /&gt;
      &amp;lt;td valign=&amp;quot;top&amp;quot;&amp;gt;password&amp;lt;/td&amp;gt;&lt;br /&gt;
      &amp;lt;td valign=&amp;quot;top&amp;quot;&amp;gt;Name of the password cookie.&amp;lt;/td&amp;gt;&lt;br /&gt;
    &amp;lt;/tr&amp;gt;&lt;br /&gt;
    &amp;lt;tr&amp;gt;&lt;br /&gt;
      &amp;lt;td valign=&amp;quot;top&amp;quot;&amp;gt;&amp;lt;a name=&amp;quot;desc_cookie_theme&amp;quot;&amp;gt;cookie_theme&amp;lt;/a&amp;gt;&amp;lt;/td&amp;gt;&lt;br /&gt;
      &amp;lt;td valign=&amp;quot;top&amp;quot;&amp;gt;theme&amp;lt;/td&amp;gt;&lt;br /&gt;
      &amp;lt;td valign=&amp;quot;top&amp;quot;&amp;gt;Name of the theme cookie.&amp;lt;/td&amp;gt;&lt;br /&gt;
    &amp;lt;/tr&amp;gt;&lt;br /&gt;
    &amp;lt;tr&amp;gt;&lt;br /&gt;
      &amp;lt;td valign=&amp;quot;top&amp;quot;&amp;gt;&amp;lt;a name=&amp;quot;desc_cookie_language&amp;quot;&amp;gt;cookie_language&amp;lt;/a&amp;gt;&amp;lt;/td&amp;gt;&lt;br /&gt;
      &amp;lt;td valign=&amp;quot;top&amp;quot;&amp;gt;language&amp;lt;/td&amp;gt;&lt;br /&gt;
      &amp;lt;td valign=&amp;quot;top&amp;quot;&amp;gt;Name of the language cookie.&amp;lt;/td&amp;gt;&lt;br /&gt;
    &amp;lt;/tr&amp;gt;&lt;br /&gt;
  &amp;lt;/tbody&amp;gt;&lt;br /&gt;
&amp;lt;/table&amp;gt;&lt;br /&gt;
&amp;lt;h3&amp;gt;&amp;lt;a name=&amp;quot;desc_mail_settings&amp;quot;&amp;gt;E-Mail Settings&amp;lt;/a&amp;gt;&amp;lt;a name=&amp;quot;email&amp;quot;&amp;gt;&amp;lt;/a&amp;gt;&amp;lt;/h3&amp;gt;&lt;br /&gt;
&amp;lt;p&amp;gt;Starting with Geeklog 1.3.9, Geeklog uses the PEAR::Mail class to send all&lt;br /&gt;
emails. You can then select whether emails should be sent through SMTP, sendmail,&lt;br /&gt;
or PHP's &amp;lt;code&amp;gt;mail()&amp;lt;/code&amp;gt; function.&amp;lt;/p&amp;gt;&lt;br /&gt;
&amp;lt;p&amp;gt;Within &amp;lt;code&amp;gt;$_CONF['mail_settings']&amp;lt;/code&amp;gt; you have the following options:&amp;lt;/p&amp;gt;&lt;br /&gt;
&amp;lt;table border=&amp;quot;1&amp;quot; width=&amp;quot;100%&amp;quot;&amp;gt;&lt;br /&gt;
  &amp;lt;tbody&amp;gt;&lt;br /&gt;
    &amp;lt;tr&amp;gt;&lt;br /&gt;
      &amp;lt;th width=&amp;quot;8%&amp;quot;&amp;gt;Variable&amp;lt;/th&amp;gt;&lt;br /&gt;
      &amp;lt;th width=&amp;quot;29%&amp;quot;&amp;gt;Default Value&amp;lt;/th&amp;gt;&lt;br /&gt;
      &amp;lt;th width=&amp;quot;63%&amp;quot;&amp;gt;Description&amp;lt;/th&amp;gt;&lt;br /&gt;
    &amp;lt;/tr&amp;gt;&lt;br /&gt;
    &amp;lt;tr&amp;gt;&lt;br /&gt;
      &amp;lt;td valign=&amp;quot;top&amp;quot;&amp;gt;&amp;lt;a name=&amp;quot;desc_backend&amp;quot;&amp;gt;backend&amp;lt;/a&amp;gt;&amp;lt;/td&amp;gt;&lt;br /&gt;
      &amp;lt;td valign=&amp;quot;top&amp;quot;&amp;gt;mail&amp;lt;/td&amp;gt;&lt;br /&gt;
      &amp;lt;td valign=&amp;quot;top&amp;quot;&amp;gt;Used to select how to send email. Can be one of 'smtp', 'sendmail',&lt;br /&gt;
        or 'mail'.&amp;lt;/td&amp;gt;&lt;br /&gt;
    &amp;lt;/tr&amp;gt;&lt;br /&gt;
    &amp;lt;tr&amp;gt;&lt;br /&gt;
      &amp;lt;td valign=&amp;quot;top&amp;quot;&amp;gt;&amp;lt;a name=&amp;quot;desc_sendmail_path&amp;quot;&amp;gt;sendmail_path&amp;lt;/a&amp;gt;&amp;lt;/td&amp;gt;&lt;br /&gt;
      &amp;lt;td valign=&amp;quot;top&amp;quot;&amp;gt;&amp;lt;tt&amp;gt;/usr/bin/sendmail&amp;lt;/tt&amp;gt;&amp;lt;/td&amp;gt;&lt;br /&gt;
      &amp;lt;td valign=&amp;quot;top&amp;quot;&amp;gt;If you chose 'sendmail' for the backend setting, this&lt;br /&gt;
        specifies the complete path to the sendmail binary.&amp;lt;/td&amp;gt;&lt;br /&gt;
    &amp;lt;/tr&amp;gt;&lt;br /&gt;
    &amp;lt;tr&amp;gt;&lt;br /&gt;
      &amp;lt;td valign=&amp;quot;top&amp;quot;&amp;gt;&amp;lt;a name=&amp;quot;desc_sendmail_args&amp;quot;&amp;gt;sendmail_args&amp;lt;/a&amp;gt;&amp;lt;/td&amp;gt;&lt;br /&gt;
      &amp;lt;td valign=&amp;quot;top&amp;quot;&amp;gt;&amp;lt;tt&amp;gt;''&amp;lt;/tt&amp;gt; &amp;lt;i&amp;gt;(empty)&amp;lt;/i&amp;gt;&amp;lt;/td&amp;gt;&lt;br /&gt;
      &amp;lt;td valign=&amp;quot;top&amp;quot;&amp;gt;If you chose 'sendmail' for the backend setting, this&lt;br /&gt;
        variable can be used to pass additional parameters to the sendmail&lt;br /&gt;
        binary.&amp;lt;/td&amp;gt;&lt;br /&gt;
    &amp;lt;/tr&amp;gt;&lt;br /&gt;
    &amp;lt;tr&amp;gt;&lt;br /&gt;
      &amp;lt;td valign=&amp;quot;top&amp;quot;&amp;gt;&amp;lt;a name=&amp;quot;desc_host&amp;quot;&amp;gt;host&amp;lt;/a&amp;gt;&amp;lt;/td&amp;gt;&lt;br /&gt;
      &amp;lt;td valign=&amp;quot;top&amp;quot;&amp;gt;smtp.example.com&amp;lt;/td&amp;gt;&lt;br /&gt;
      &amp;lt;td valign=&amp;quot;top&amp;quot;&amp;gt;If you chose 'smtp' for the backend setting, this is the&lt;br /&gt;
        SMTP server to use.&amp;lt;/td&amp;gt;&lt;br /&gt;
    &amp;lt;/tr&amp;gt;&lt;br /&gt;
    &amp;lt;tr&amp;gt;&lt;br /&gt;
      &amp;lt;td valign=&amp;quot;top&amp;quot;&amp;gt;&amp;lt;a name=&amp;quot;desc_port&amp;quot;&amp;gt;port&amp;lt;/a&amp;gt;&amp;lt;/td&amp;gt;&lt;br /&gt;
      &amp;lt;td valign=&amp;quot;top&amp;quot;&amp;gt;25&amp;lt;/td&amp;gt;&lt;br /&gt;
      &amp;lt;td valign=&amp;quot;top&amp;quot;&amp;gt;If you chose 'smtp' for the backend setting, this is the&lt;br /&gt;
        port number to talk to on the SMTP server.&amp;lt;/td&amp;gt;&lt;br /&gt;
    &amp;lt;/tr&amp;gt;&lt;br /&gt;
    &amp;lt;tr&amp;gt;&lt;br /&gt;
      &amp;lt;td valign=&amp;quot;top&amp;quot;&amp;gt;&amp;lt;a name=&amp;quot;desc_auth&amp;quot;&amp;gt;auth&amp;lt;/a&amp;gt;&amp;lt;/td&amp;gt;&lt;br /&gt;
      &amp;lt;td valign=&amp;quot;top&amp;quot;&amp;gt;false&amp;lt;/td&amp;gt;&lt;br /&gt;
      &amp;lt;td valign=&amp;quot;top&amp;quot;&amp;gt;If you chose 'smtp' for the backend setting, set this to &amp;lt;code&amp;gt;true&amp;lt;/code&amp;gt;&lt;br /&gt;
        if your SMTP server requires authorization, and &amp;lt;code&amp;gt;false&amp;lt;/code&amp;gt; if it&lt;br /&gt;
        doesn't.&amp;lt;/td&amp;gt;&lt;br /&gt;
    &amp;lt;/tr&amp;gt;&lt;br /&gt;
    &amp;lt;tr&amp;gt;&lt;br /&gt;
      &amp;lt;td valign=&amp;quot;top&amp;quot;&amp;gt;&amp;lt;a name=&amp;quot;desc_username&amp;quot;&amp;gt;username&amp;lt;/a&amp;gt;&amp;lt;/td&amp;gt;&lt;br /&gt;
      &amp;lt;td valign=&amp;quot;top&amp;quot;&amp;gt;smtp-username&amp;lt;/td&amp;gt;&lt;br /&gt;
      &amp;lt;td valign=&amp;quot;top&amp;quot;&amp;gt;If you chose 'smtp' for the backend setting, this is the&lt;br /&gt;
        name of your SMTP account.&amp;lt;/td&amp;gt;&lt;br /&gt;
    &amp;lt;/tr&amp;gt;&lt;br /&gt;
    &amp;lt;tr&amp;gt;&lt;br /&gt;
      &amp;lt;td valign=&amp;quot;top&amp;quot;&amp;gt;&amp;lt;a name=&amp;quot;desc_password&amp;quot;&amp;gt;password&amp;lt;/a&amp;gt;&amp;lt;/td&amp;gt;&lt;br /&gt;
      &amp;lt;td valign=&amp;quot;top&amp;quot;&amp;gt;smtp-password&amp;lt;/td&amp;gt;&lt;br /&gt;
      &amp;lt;td valign=&amp;quot;top&amp;quot;&amp;gt;If you chose 'smtp' for the backend setting, this is the&lt;br /&gt;
        password for your SMTP account.&amp;lt;/td&amp;gt;&lt;br /&gt;
    &amp;lt;/tr&amp;gt;&lt;br /&gt;
  &amp;lt;/tbody&amp;gt;&lt;br /&gt;
&amp;lt;/table&amp;gt;&lt;br /&gt;
&amp;lt;h3&amp;gt;&amp;lt;a name=&amp;quot;login&amp;quot;&amp;gt;Login Settings&amp;lt;/a&amp;gt;&amp;lt;/h3&amp;gt;&lt;br /&gt;
&amp;lt;table border=&amp;quot;1&amp;quot; width=&amp;quot;100%&amp;quot;&amp;gt;&lt;br /&gt;
  &amp;lt;tbody&amp;gt;&lt;br /&gt;
    &amp;lt;tr&amp;gt;&lt;br /&gt;
      &amp;lt;th width=&amp;quot;8%&amp;quot;&amp;gt;Variable&amp;lt;/th&amp;gt;&lt;br /&gt;
      &amp;lt;th width=&amp;quot;29%&amp;quot;&amp;gt;Default Value&amp;lt;/th&amp;gt;&lt;br /&gt;
      &amp;lt;th width=&amp;quot;63%&amp;quot;&amp;gt;Description&amp;lt;/th&amp;gt;&lt;br /&gt;
    &amp;lt;/tr&amp;gt;&lt;br /&gt;
    &amp;lt;tr&amp;gt;&lt;br /&gt;
      &amp;lt;td valign=&amp;quot;top&amp;quot;&amp;gt;&amp;lt;a name=&amp;quot;desc_loginrequired&amp;quot;&amp;gt;loginrequired&amp;lt;/a&amp;gt;&amp;lt;/td&amp;gt;&lt;br /&gt;
      &amp;lt;td valign=&amp;quot;top&amp;quot;&amp;gt;0&amp;lt;/td&amp;gt;&lt;br /&gt;
      &amp;lt;td valign=&amp;quot;top&amp;quot;&amp;gt;Login is required to access &amp;lt;em&amp;gt;any&amp;lt;/em&amp;gt; part of the&lt;br /&gt;
        site. When set to 1, this overrides the following settings. When you&lt;br /&gt;
        only want to block access to certain parts of the site, set this to 0&lt;br /&gt;
        and select from the following settings.&amp;lt;/td&amp;gt;&lt;br /&gt;
    &amp;lt;/tr&amp;gt;&lt;br /&gt;
    &amp;lt;tr&amp;gt;&lt;br /&gt;
      &amp;lt;td valign=&amp;quot;top&amp;quot;&amp;gt;&amp;lt;a name=&amp;quot;desc_submitloginrequired&amp;quot;&amp;gt;submitloginrequired&amp;lt;/a&amp;gt;&amp;lt;/td&amp;gt;&lt;br /&gt;
      &amp;lt;td valign=&amp;quot;top&amp;quot;&amp;gt;0&amp;lt;/td&amp;gt;&lt;br /&gt;
      &amp;lt;td valign=&amp;quot;top&amp;quot;&amp;gt;When set to 1, only registered users can submit stories&lt;br /&gt;
        and items handled by plugins, e.g. links and events&amp;lt;/td&amp;gt;&lt;br /&gt;
    &amp;lt;/tr&amp;gt;&lt;br /&gt;
    &amp;lt;tr&amp;gt;&lt;br /&gt;
      &amp;lt;td valign=&amp;quot;top&amp;quot;&amp;gt;&amp;lt;a name=&amp;quot;desc_commentsloginrequired&amp;quot;&amp;gt;commentsloginrequired&amp;lt;/a&amp;gt;&amp;lt;/td&amp;gt;&lt;br /&gt;
      &amp;lt;td valign=&amp;quot;top&amp;quot;&amp;gt;0&amp;lt;/td&amp;gt;&lt;br /&gt;
      &amp;lt;td valign=&amp;quot;top&amp;quot;&amp;gt;When set to 1, only registered users can submit comments&amp;lt;/td&amp;gt;&lt;br /&gt;
    &amp;lt;/tr&amp;gt;&lt;br /&gt;
    &amp;lt;tr&amp;gt;&lt;br /&gt;
      &amp;lt;td valign=&amp;quot;top&amp;quot;&amp;gt;&amp;lt;a name=&amp;quot;desc_calendarloginrequired&amp;quot;&amp;gt;calendarloginrequired&amp;lt;/a&amp;gt;&amp;lt;/td&amp;gt;&lt;br /&gt;
      &amp;lt;td valign=&amp;quot;top&amp;quot;&amp;gt;0&amp;lt;/td&amp;gt;&lt;br /&gt;
      &amp;lt;td valign=&amp;quot;top&amp;quot;&amp;gt;When set to 1, only registered users can access the&lt;br /&gt;
        calendar&amp;lt;/td&amp;gt;&lt;br /&gt;
    &amp;lt;/tr&amp;gt;&lt;br /&gt;
    &amp;lt;tr&amp;gt;&lt;br /&gt;
      &amp;lt;td valign=&amp;quot;top&amp;quot;&amp;gt;&amp;lt;a name=&amp;quot;desc_statsloginrequired&amp;quot;&amp;gt;statsloginrequired&amp;lt;/a&amp;gt;&amp;lt;/td&amp;gt;&lt;br /&gt;
      &amp;lt;td valign=&amp;quot;top&amp;quot;&amp;gt;0&amp;lt;/td&amp;gt;&lt;br /&gt;
      &amp;lt;td valign=&amp;quot;top&amp;quot;&amp;gt;When set to 1, only registered users can access the site&lt;br /&gt;
        stats&amp;lt;/td&amp;gt;&lt;br /&gt;
    &amp;lt;/tr&amp;gt;&lt;br /&gt;
    &amp;lt;tr&amp;gt;&lt;br /&gt;
      &amp;lt;td valign=&amp;quot;top&amp;quot;&amp;gt;&amp;lt;a name=&amp;quot;desc_searchloginrequired&amp;quot;&amp;gt;searchloginrequired&amp;lt;/a&amp;gt;&amp;lt;/td&amp;gt;&lt;br /&gt;
      &amp;lt;td valign=&amp;quot;top&amp;quot;&amp;gt;0&amp;lt;/td&amp;gt;&lt;br /&gt;
      &amp;lt;td valign=&amp;quot;top&amp;quot;&amp;gt;When set to 1, only registered users can use the advanced&lt;br /&gt;
        search. When set to 2, the simple search is blocked for anonymous users,&lt;br /&gt;
        too.&amp;lt;/td&amp;gt;&lt;br /&gt;
    &amp;lt;/tr&amp;gt;&lt;br /&gt;
    &amp;lt;tr&amp;gt;&lt;br /&gt;
      &amp;lt;td valign=&amp;quot;top&amp;quot;&amp;gt;&amp;lt;a name=&amp;quot;desc_profileloginrequired&amp;quot;&amp;gt;profileloginrequired&amp;lt;/a&amp;gt;&amp;lt;/td&amp;gt;&lt;br /&gt;
      &amp;lt;td valign=&amp;quot;top&amp;quot;&amp;gt;0&amp;lt;/td&amp;gt;&lt;br /&gt;
      &amp;lt;td valign=&amp;quot;top&amp;quot;&amp;gt;When set to 1, only registered users can view another&lt;br /&gt;
        user's profile&amp;lt;/td&amp;gt;&lt;br /&gt;
    &amp;lt;/tr&amp;gt;&lt;br /&gt;
    &amp;lt;tr&amp;gt;&lt;br /&gt;
      &amp;lt;td valign=&amp;quot;top&amp;quot;&amp;gt;&amp;lt;a name=&amp;quot;desc_emailuserloginrequired&amp;quot;&amp;gt;emailuserloginrequired&amp;lt;/a&amp;gt;&amp;lt;/td&amp;gt;&lt;br /&gt;
      &amp;lt;td valign=&amp;quot;top&amp;quot;&amp;gt;0&amp;lt;/td&amp;gt;&lt;br /&gt;
      &amp;lt;td valign=&amp;quot;top&amp;quot;&amp;gt;When set to 1, only registered users can use the email&lt;br /&gt;
        submission form to send an email to another user&amp;lt;/td&amp;gt;&lt;br /&gt;
    &amp;lt;/tr&amp;gt;&lt;br /&gt;
    &amp;lt;tr&amp;gt;&lt;br /&gt;
      &amp;lt;td valign=&amp;quot;top&amp;quot;&amp;gt;&amp;lt;a name=&amp;quot;desc_emailstoryloginrequired&amp;quot;&amp;gt;emailstoryloginrequired&amp;lt;/a&amp;gt;&amp;lt;/td&amp;gt;&lt;br /&gt;
      &amp;lt;td valign=&amp;quot;top&amp;quot;&amp;gt;0&amp;lt;/td&amp;gt;&lt;br /&gt;
      &amp;lt;td valign=&amp;quot;top&amp;quot;&amp;gt;When set to 1, only registered users can email stories&amp;lt;/td&amp;gt;&lt;br /&gt;
    &amp;lt;/tr&amp;gt;&lt;br /&gt;
    &amp;lt;tr&amp;gt;&lt;br /&gt;
      &amp;lt;td valign=&amp;quot;top&amp;quot;&amp;gt;&amp;lt;a name=&amp;quot;desc_directoryloginrequired&amp;quot;&amp;gt;directoryloginrequired&amp;lt;/a&amp;gt;&amp;lt;/td&amp;gt;&lt;br /&gt;
      &amp;lt;td valign=&amp;quot;top&amp;quot;&amp;gt;0&amp;lt;/td&amp;gt;&lt;br /&gt;
      &amp;lt;td valign=&amp;quot;top&amp;quot;&amp;gt;When set to 1, only registered users can access the list&lt;br /&gt;
        of past articles&amp;lt;/td&amp;gt;&lt;br /&gt;
    &amp;lt;/tr&amp;gt;&lt;br /&gt;
  &amp;lt;/tbody&amp;gt;&lt;br /&gt;
&amp;lt;/table&amp;gt;&lt;br /&gt;
&amp;lt;h3&amp;gt;&amp;lt;a name=&amp;quot;submission&amp;quot;&amp;gt;Submission Settings&amp;lt;/a&amp;gt;&amp;lt;/h3&amp;gt;&lt;br /&gt;
&amp;lt;table border=&amp;quot;1&amp;quot; width=&amp;quot;100%&amp;quot;&amp;gt;&lt;br /&gt;
  &amp;lt;tbody&amp;gt;&lt;br /&gt;
    &amp;lt;tr&amp;gt;&lt;br /&gt;
      &amp;lt;th width=&amp;quot;8%&amp;quot;&amp;gt;Variable&amp;lt;/th&amp;gt;&lt;br /&gt;
      &amp;lt;th width=&amp;quot;29%&amp;quot;&amp;gt;Default Value&amp;lt;/th&amp;gt;&lt;br /&gt;
      &amp;lt;th width=&amp;quot;63%&amp;quot;&amp;gt;Description&amp;lt;/th&amp;gt;&lt;br /&gt;
    &amp;lt;/tr&amp;gt;&lt;br /&gt;
    &amp;lt;tr&amp;gt;&lt;br /&gt;
      &amp;lt;td valign=&amp;quot;top&amp;quot;&amp;gt;&amp;lt;a name=&amp;quot;desc_storysubmission&amp;quot;&amp;gt;storysubmission&amp;lt;/a&amp;gt;&amp;lt;/td&amp;gt;&lt;br /&gt;
      &amp;lt;td valign=&amp;quot;top&amp;quot;&amp;gt;1&amp;lt;/td&amp;gt;&lt;br /&gt;
      &amp;lt;td valign=&amp;quot;top&amp;quot;&amp;gt;Enable (1) or disable (0) the story submission queue&amp;lt;/td&amp;gt;&lt;br /&gt;
    &amp;lt;/tr&amp;gt;&lt;br /&gt;
    &amp;lt;tr&amp;gt;&lt;br /&gt;
      &amp;lt;td valign=&amp;quot;top&amp;quot;&amp;gt;&amp;lt;a name=&amp;quot;desc_usersubmission&amp;quot;&amp;gt;usersubmission&amp;lt;/a&amp;gt;&amp;lt;/td&amp;gt;&lt;br /&gt;
      &amp;lt;td valign=&amp;quot;top&amp;quot;&amp;gt;0&amp;lt;/td&amp;gt;&lt;br /&gt;
      &amp;lt;td valign=&amp;quot;top&amp;quot;&amp;gt;Enable (1) or disable (0) the user submission queue (i.e.&lt;br /&gt;
        new users must be approved before they receive their password)&amp;lt;/td&amp;gt;&lt;br /&gt;
    &amp;lt;/tr&amp;gt;&lt;br /&gt;
    &amp;lt;tr&amp;gt;&lt;br /&gt;
      &amp;lt;td valign=&amp;quot;top&amp;quot;&amp;gt;&amp;lt;a name=&amp;quot;desc_disable_new_user_registration&amp;quot;&amp;gt;disable_new_user_registration&amp;lt;/a&amp;gt;&amp;lt;/td&amp;gt;&lt;br /&gt;
      &amp;lt;td valign=&amp;quot;top&amp;quot;&amp;gt;false&amp;lt;/td&amp;gt;&lt;br /&gt;
      &amp;lt;td valign=&amp;quot;top&amp;quot;&amp;gt;When set to &amp;lt;tt&amp;gt;true&amp;lt;/tt&amp;gt; completely disables all options&lt;br /&gt;
        to sign up as a new user.&amp;lt;/td&amp;gt;&lt;br /&gt;
    &amp;lt;/tr&amp;gt;&lt;br /&gt;
    &amp;lt;tr&amp;gt;&lt;br /&gt;
      &amp;lt;td valign=&amp;quot;top&amp;quot;&amp;gt;&amp;lt;a name=&amp;quot;desc_allow_domains&amp;quot;&amp;gt;allow_domains&amp;lt;/a&amp;gt;&amp;lt;/td&amp;gt;&lt;br /&gt;
      &amp;lt;td valign=&amp;quot;top&amp;quot;&amp;gt;''&amp;lt;/td&amp;gt;&lt;br /&gt;
      &amp;lt;td valign=&amp;quot;top&amp;quot;&amp;gt;When the user submission queue is enabled this can&lt;br /&gt;
        contain a comma-separated list of domain names from which user&lt;br /&gt;
        submissions will not be queued (but approved automatically). Regular&lt;br /&gt;
        expressions are also allowed and interpreted.&amp;lt;br&amp;gt;&lt;br /&gt;
        &amp;lt;strong&amp;gt;Example:&amp;lt;/strong&amp;gt; &amp;lt;tt&amp;gt;'mycompany.com,myothercompany.com'&amp;lt;/tt&amp;gt;&amp;lt;/td&amp;gt;&lt;br /&gt;
    &amp;lt;/tr&amp;gt;&lt;br /&gt;
    &amp;lt;tr&amp;gt;&lt;br /&gt;
      &amp;lt;td valign=&amp;quot;top&amp;quot;&amp;gt;&amp;lt;a name=&amp;quot;desc_disallow_domains&amp;quot;&amp;gt;disallow_domains&amp;lt;/a&amp;gt;&amp;lt;/td&amp;gt;&lt;br /&gt;
      &amp;lt;td valign=&amp;quot;top&amp;quot;&amp;gt;''&amp;lt;/td&amp;gt;&lt;br /&gt;
      &amp;lt;td valign=&amp;quot;top&amp;quot;&amp;gt;This is the opposite of &amp;lt;code&amp;gt;$_CONF['allow_domains']&amp;lt;/code&amp;gt;&lt;br /&gt;
        (see above): A list of domain names that are &amp;lt;em&amp;gt;not&amp;lt;/em&amp;gt; allowed in&lt;br /&gt;
        email addresses of new users. Note that this list is &amp;lt;em&amp;gt;always&amp;lt;/em&amp;gt;&lt;br /&gt;
        used, even when the user submission queue has been switched off. Again,&lt;br /&gt;
        regular expression can be used.&amp;lt;br&amp;gt;&lt;br /&gt;
        &amp;lt;strong&amp;gt;Example&amp;lt;/strong&amp;gt; disallow email addresses with a certain domain&lt;br /&gt;
        name and from any &amp;amp;quot;.edu&amp;amp;quot; domain: &amp;lt;tt&amp;gt;'somebaddomain.com,\.edu$'&amp;lt;/tt&amp;gt;&amp;lt;/td&amp;gt;&lt;br /&gt;
    &amp;lt;/tr&amp;gt;&lt;br /&gt;
    &amp;lt;tr&amp;gt;&lt;br /&gt;
      &amp;lt;td valign=&amp;quot;top&amp;quot;&amp;gt;&amp;lt;a name=&amp;quot;desc_notification&amp;quot;&amp;gt;notification&amp;lt;/a&amp;gt;&amp;lt;/td&amp;gt;&lt;br /&gt;
      &amp;lt;td valign=&amp;quot;top&amp;quot;&amp;gt;array()&amp;lt;/td&amp;gt;&lt;br /&gt;
      &amp;lt;td valign=&amp;quot;top&amp;quot;&amp;gt;Send an email notification to &amp;lt;tt&amp;gt;$_CONF['site_email']&amp;lt;/tt&amp;gt;&lt;br /&gt;
        when a new story, comment, trackback or pingback has been submitted or a&lt;br /&gt;
        new user has registered with the site. The &amp;lt;tt&amp;gt;array()&amp;lt;/tt&amp;gt; can hold any&lt;br /&gt;
        combination of the strings &amp;lt;tt&amp;gt;'story'&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;'comment'&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;'trackback'&amp;lt;/tt&amp;gt;,&lt;br /&gt;
        &amp;lt;tt&amp;gt;'pingback'&amp;lt;/tt&amp;gt;, and &amp;lt;tt&amp;gt;'user'&amp;lt;/tt&amp;gt; (separated by commas),&lt;br /&gt;
        depending on which notification(s) you want.&amp;lt;br&amp;gt;&lt;br /&gt;
        &amp;lt;strong&amp;gt;Example:&amp;lt;/strong&amp;gt; &amp;lt;code&amp;gt;array('story','user');&amp;lt;/code&amp;gt; would send&lt;br /&gt;
        notifications when a new story has been submitted or a new user has&lt;br /&gt;
        registered. No notifications would be sent, for example, for new&lt;br /&gt;
        comments.&amp;lt;/td&amp;gt;&lt;br /&gt;
    &amp;lt;/tr&amp;gt;&lt;br /&gt;
    &amp;lt;tr&amp;gt;&lt;br /&gt;
      &amp;lt;td valign=&amp;quot;top&amp;quot;&amp;gt;&amp;lt;a name=&amp;quot;desc_listdraftstories&amp;quot;&amp;gt;listdraftstories&amp;lt;/a&amp;gt;&amp;lt;/td&amp;gt;&lt;br /&gt;
      &amp;lt;td valign=&amp;quot;top&amp;quot;&amp;gt;0&amp;lt;/td&amp;gt;&lt;br /&gt;
      &amp;lt;td valign=&amp;quot;top&amp;quot;&amp;gt;When set to 1, this will display an additional block on&lt;br /&gt;
        the submissions page (&amp;lt;tt&amp;gt;moderation.php&amp;lt;/tt&amp;gt;) that lists all the&lt;br /&gt;
        stories that have the 'draft' flag set.&amp;lt;/td&amp;gt;&lt;br /&gt;
    &amp;lt;/tr&amp;gt;&lt;br /&gt;
    &amp;lt;tr&amp;gt;&lt;br /&gt;
      &amp;lt;td valign=&amp;quot;top&amp;quot;&amp;gt;&amp;lt;a name=&amp;quot;desc_postmode&amp;quot;&amp;gt;postmode&amp;lt;/a&amp;gt;&amp;lt;/td&amp;gt;&lt;br /&gt;
      &amp;lt;td valign=&amp;quot;top&amp;quot;&amp;gt;plaintext&amp;lt;/td&amp;gt;&lt;br /&gt;
      &amp;lt;td valign=&amp;quot;top&amp;quot;&amp;gt;Sets the default submission mode to 'html' or 'plaintext'&amp;lt;/td&amp;gt;&lt;br /&gt;
    &amp;lt;/tr&amp;gt;&lt;br /&gt;
    &amp;lt;tr&amp;gt;&lt;br /&gt;
      &amp;lt;td valign=&amp;quot;top&amp;quot;&amp;gt;&amp;lt;a name=&amp;quot;desc_speedlimit&amp;quot;&amp;gt;speedlimit&amp;lt;/a&amp;gt;&amp;lt;/td&amp;gt;&lt;br /&gt;
      &amp;lt;td valign=&amp;quot;top&amp;quot;&amp;gt;45&amp;lt;/td&amp;gt;&lt;br /&gt;
      &amp;lt;td valign=&amp;quot;top&amp;quot;&amp;gt;Minimum delay between submissions in seconds. This helps&lt;br /&gt;
        prevent Denial of Service (DOS) attacks&amp;lt;/td&amp;gt;&lt;br /&gt;
    &amp;lt;/tr&amp;gt;&lt;br /&gt;
    &amp;lt;tr&amp;gt;&lt;br /&gt;
      &amp;lt;td valign=&amp;quot;top&amp;quot;&amp;gt;&amp;lt;a name=&amp;quot;desc_skip_preview&amp;quot;&amp;gt;skip_preview&amp;lt;/a&amp;gt;&amp;lt;/td&amp;gt;&lt;br /&gt;
      &amp;lt;td valign=&amp;quot;top&amp;quot;&amp;gt;0&amp;lt;/td&amp;gt;&lt;br /&gt;
      &amp;lt;td valign=&amp;quot;top&amp;quot;&amp;gt;If 1, allows submission of stories and comments without&lt;br /&gt;
        previewing (i.e. the submission form will always have a Preview &amp;lt;em&amp;gt;and&amp;lt;/em&amp;gt;&lt;br /&gt;
        a Submit button).&amp;lt;/td&amp;gt;&lt;br /&gt;
    &amp;lt;/tr&amp;gt;&lt;br /&gt;
    &amp;lt;tr&amp;gt;&lt;br /&gt;
      &amp;lt;td valign=&amp;quot;top&amp;quot;&amp;gt;&amp;lt;a name=&amp;quot;desc_advanced_editor&amp;quot;&amp;gt;advanced_editor&amp;lt;/a&amp;gt;&amp;lt;/td&amp;gt;&lt;br /&gt;
      &amp;lt;td valign=&amp;quot;top&amp;quot;&amp;gt;false&amp;lt;/td&amp;gt;&lt;br /&gt;
      &amp;lt;td valign=&amp;quot;top&amp;quot;&amp;gt;Enable (if set to &amp;lt;code&amp;gt;true&amp;lt;/code&amp;gt;) a WYSIWYG editor for&lt;br /&gt;
        story and comment submissions and static pages. Geeklog ships with &amp;lt;a href=&amp;quot;http://www.fckeditor.net/&amp;quot;&amp;gt;FCKeditor&amp;lt;/a&amp;gt;.&amp;lt;/td&amp;gt;&lt;br /&gt;
    &amp;lt;/tr&amp;gt;&lt;br /&gt;
  &amp;lt;/tbody&amp;gt;&lt;br /&gt;
&amp;lt;/table&amp;gt;&lt;br /&gt;
&amp;lt;h3&amp;gt;&amp;lt;a name=&amp;quot;trackback&amp;quot;&amp;gt;Trackback, Pingback, and Ping Settings&amp;lt;/a&amp;gt;&amp;lt;/h3&amp;gt;&lt;br /&gt;
&amp;lt;table border=&amp;quot;1&amp;quot; width=&amp;quot;100%&amp;quot;&amp;gt;&lt;br /&gt;
  &amp;lt;tbody&amp;gt;&lt;br /&gt;
    &amp;lt;tr&amp;gt;&lt;br /&gt;
      &amp;lt;th width=&amp;quot;8%&amp;quot;&amp;gt;Variable&amp;lt;/th&amp;gt;&lt;br /&gt;
      &amp;lt;th width=&amp;quot;29%&amp;quot;&amp;gt;Default Value&amp;lt;/th&amp;gt;&lt;br /&gt;
      &amp;lt;th width=&amp;quot;63%&amp;quot;&amp;gt;Description&amp;lt;/th&amp;gt;&lt;br /&gt;
    &amp;lt;/tr&amp;gt;&lt;br /&gt;
    &amp;lt;tr&amp;gt;&lt;br /&gt;
      &amp;lt;td valign=&amp;quot;top&amp;quot;&amp;gt;&amp;lt;a name=&amp;quot;desc_trackback_enabled&amp;quot;&amp;gt;trackback_enabled&amp;lt;/a&amp;gt;&amp;lt;/td&amp;gt;&lt;br /&gt;
      &amp;lt;td valign=&amp;quot;top&amp;quot;&amp;gt;true&amp;lt;/td&amp;gt;&lt;br /&gt;
      &amp;lt;td valign=&amp;quot;top&amp;quot;&amp;gt;Enable (true) or disable (true) &amp;lt;a href=&amp;quot;http://en.wikipedia.org/wiki/Trackback&amp;quot;&amp;gt;trackback&amp;lt;/a&amp;gt;&lt;br /&gt;
        comments. This applies to both sending and receiving trackback comments.&amp;lt;/td&amp;gt;&lt;br /&gt;
    &amp;lt;/tr&amp;gt;&lt;br /&gt;
    &amp;lt;tr&amp;gt;&lt;br /&gt;
      &amp;lt;td valign=&amp;quot;top&amp;quot;&amp;gt;&amp;lt;a name=&amp;quot;desc_pingback_enabled&amp;quot;&amp;gt;pingback_enabled&amp;lt;/a&amp;gt;&amp;lt;/td&amp;gt;&lt;br /&gt;
      &amp;lt;td valign=&amp;quot;top&amp;quot;&amp;gt;true&amp;lt;/td&amp;gt;&lt;br /&gt;
      &amp;lt;td valign=&amp;quot;top&amp;quot;&amp;gt;Enable (true) or disable (true) &amp;lt;a href=&amp;quot;http://en.wikipedia.org/wiki/Pingback&amp;quot;&amp;gt;pingback&amp;lt;/a&amp;gt;&lt;br /&gt;
        support. This applies to both sending and receiving pingbacks.&amp;lt;/td&amp;gt;&lt;br /&gt;
    &amp;lt;/tr&amp;gt;&lt;br /&gt;
    &amp;lt;tr&amp;gt;&lt;br /&gt;
      &amp;lt;td valign=&amp;quot;top&amp;quot;&amp;gt;&amp;lt;a name=&amp;quot;desc_ping_enabled&amp;quot;&amp;gt;ping_enabled&amp;lt;/a&amp;gt;&amp;lt;/td&amp;gt;&lt;br /&gt;
      &amp;lt;td valign=&amp;quot;top&amp;quot;&amp;gt;true&amp;lt;/td&amp;gt;&lt;br /&gt;
      &amp;lt;td valign=&amp;quot;top&amp;quot;&amp;gt;Enable (true) or disable (true) the ability to ping&lt;br /&gt;
        weblog directory services like &amp;lt;a href=&amp;quot;http://technorati.com/&amp;quot;&amp;gt;Technorati&amp;lt;/a&amp;gt;.&amp;lt;/td&amp;gt;&lt;br /&gt;
    &amp;lt;/tr&amp;gt;&lt;br /&gt;
    &amp;lt;tr&amp;gt;&lt;br /&gt;
      &amp;lt;td valign=&amp;quot;top&amp;quot;&amp;gt;&amp;lt;a name=&amp;quot;desc_trackback_code&amp;quot;&amp;gt;trackback_code&amp;lt;/a&amp;gt;&amp;lt;/td&amp;gt;&lt;br /&gt;
      &amp;lt;td valign=&amp;quot;top&amp;quot;&amp;gt;0&amp;lt;/td&amp;gt;&lt;br /&gt;
      &amp;lt;td valign=&amp;quot;top&amp;quot;&amp;gt;Default value for new stories: Trackback enabled (0) or&lt;br /&gt;
        disabled (-1)&amp;lt;/td&amp;gt;&lt;br /&gt;
    &amp;lt;/tr&amp;gt;&lt;br /&gt;
    &amp;lt;tr&amp;gt;&lt;br /&gt;
      &amp;lt;td valign=&amp;quot;top&amp;quot;&amp;gt;&amp;lt;a name=&amp;quot;desc_multiple_trackbacks&amp;quot;&amp;gt;multiple_trackbacks&amp;lt;/a&amp;gt;&amp;lt;/td&amp;gt;&lt;br /&gt;
      &amp;lt;td valign=&amp;quot;top&amp;quot;&amp;gt;0&amp;lt;/td&amp;gt;&lt;br /&gt;
      &amp;lt;td valign=&amp;quot;top&amp;quot;&amp;gt;How to handle multiple trackbacks and pingbacks from the&lt;br /&gt;
        same source: 0 = keep only the first, reject any further trackbacks /&lt;br /&gt;
        pingbacks; 1 = overwrite, i.e. only keep the latest trackback / pingback;&lt;br /&gt;
        2 = allow multiple trackbacks / pingbacks, i.e. list them all&amp;lt;/td&amp;gt;&lt;br /&gt;
    &amp;lt;/tr&amp;gt;&lt;br /&gt;
    &amp;lt;tr&amp;gt;&lt;br /&gt;
      &amp;lt;td valign=&amp;quot;top&amp;quot;&amp;gt;&amp;lt;a name=&amp;quot;desc_trackbackspeedlimit&amp;quot;&amp;gt;trackbackspeedlimit&amp;lt;/a&amp;gt;&amp;lt;/td&amp;gt;&lt;br /&gt;
      &amp;lt;td valign=&amp;quot;top&amp;quot;&amp;gt;300&amp;lt;/td&amp;gt;&lt;br /&gt;
      &amp;lt;td valign=&amp;quot;top&amp;quot;&amp;gt;Number of seconds between two trackbacks / pingbacks from&lt;br /&gt;
        the same IP address.&amp;lt;/td&amp;gt;&lt;br /&gt;
    &amp;lt;/tr&amp;gt;&lt;br /&gt;
    &amp;lt;tr&amp;gt;&lt;br /&gt;
      &amp;lt;td valign=&amp;quot;top&amp;quot;&amp;gt;&amp;lt;a name=&amp;quot;desc_check_trackback_link&amp;quot;&amp;gt;check_trackback_link&amp;lt;/a&amp;gt;&amp;lt;/td&amp;gt;&lt;br /&gt;
      &amp;lt;td valign=&amp;quot;top&amp;quot;&amp;gt;2&amp;lt;/td&amp;gt;&lt;br /&gt;
      &amp;lt;td valign=&amp;quot;top&amp;quot;&amp;gt;This option can be used to check the validity of a&lt;br /&gt;
        trackback. You can check if the URL in the trackback actually contains a&lt;br /&gt;
        link back to your site (otherwise, it's probably spam). You can also&lt;br /&gt;
        check if the trackback was sent from the proper IP address, i.e. the IP&lt;br /&gt;
        of the site in the trackback URL (again, if they don't match, it's&lt;br /&gt;
        probably spam). Note that you can &amp;lt;strong&amp;gt;add up the values&amp;lt;/strong&amp;gt;&lt;br /&gt;
        below to do more than one check (but using option 1 &amp;lt;em&amp;gt;and&amp;lt;/em&amp;gt; 2&lt;br /&gt;
        doesn't make sense and will be treated as if you requested option 2).&amp;lt;br&amp;gt;&lt;br /&gt;
        Options are: 0 = don't perform any checks, 1 = check only for your&lt;br /&gt;
        site's main URL (&amp;lt;code&amp;gt;$_CONF['site_url']&amp;lt;/code&amp;gt;), 2 = check for the&lt;br /&gt;
        exact URL of the entry (e.g. an article) on your site, 4 = check IP&lt;br /&gt;
        address of the sender of the trackback against the site referred to in&lt;br /&gt;
        the trackback URL.&amp;lt;br&amp;gt;&lt;br /&gt;
        &amp;lt;b&amp;gt;Example:&amp;lt;/b&amp;gt; &amp;lt;code&amp;gt;$_CONF['check_trackback_link'] = 6; // check for&lt;br /&gt;
        the exact URL (2) and proper IP address (4)&amp;lt;/code&amp;gt;&amp;lt;/td&amp;gt;&lt;br /&gt;
    &amp;lt;/tr&amp;gt;&lt;br /&gt;
    &amp;lt;tr&amp;gt;&lt;br /&gt;
      &amp;lt;td valign=&amp;quot;top&amp;quot;&amp;gt;&amp;lt;a name=&amp;quot;desc_pingback_self&amp;quot;&amp;gt;pingback_self&amp;lt;/a&amp;gt;&amp;lt;/td&amp;gt;&lt;br /&gt;
      &amp;lt;td valign=&amp;quot;top&amp;quot;&amp;gt;0&amp;lt;/td&amp;gt;&lt;br /&gt;
      &amp;lt;td valign=&amp;quot;top&amp;quot;&amp;gt;Pingbacks are sent out automatically to &amp;lt;em&amp;gt;all&amp;lt;/em&amp;gt; the&lt;br /&gt;
        URLs linked from a story - which includes stories on your own site that&lt;br /&gt;
        you may have linked in the article. This option lets you specify how&lt;br /&gt;
        these &amp;amp;quot;self pingbacks&amp;amp;quot; are to be handled: 0 = skip them, i.e.&lt;br /&gt;
        don't send pingbacks to stories on your own site; 1 = allow them, but&lt;br /&gt;
        obey the speed limit; 2 = allow them and ignore the speed limit.&amp;lt;br&amp;gt;&lt;br /&gt;
        If your article contains more than one link to other stories on your&lt;br /&gt;
        site, then option 1 is probably of limited use, as it would only&lt;br /&gt;
        pingback the first linked story and run into the speed limit for the&lt;br /&gt;
        others.&amp;lt;/td&amp;gt;&lt;br /&gt;
    &amp;lt;/tr&amp;gt;&lt;br /&gt;
  &amp;lt;/tbody&amp;gt;&lt;br /&gt;
&amp;lt;/table&amp;gt;&lt;br /&gt;
&amp;lt;h3&amp;gt;&amp;lt;a name=&amp;quot;misc&amp;quot;&amp;gt;Topic, What's New, and E-mail Settings&amp;lt;/a&amp;gt;&amp;lt;/h3&amp;gt;&lt;br /&gt;
&amp;lt;table border=&amp;quot;1&amp;quot; width=&amp;quot;100%&amp;quot;&amp;gt;&lt;br /&gt;
  &amp;lt;tbody&amp;gt;&lt;br /&gt;
    &amp;lt;tr&amp;gt;&lt;br /&gt;
      &amp;lt;th width=&amp;quot;8%&amp;quot;&amp;gt;Variable&amp;lt;/th&amp;gt;&lt;br /&gt;
      &amp;lt;th width=&amp;quot;29%&amp;quot;&amp;gt;Default Value&amp;lt;/th&amp;gt;&lt;br /&gt;
      &amp;lt;th width=&amp;quot;63%&amp;quot;&amp;gt;Description&amp;lt;/th&amp;gt;&lt;br /&gt;
    &amp;lt;/tr&amp;gt;&lt;br /&gt;
    &amp;lt;tr&amp;gt;&lt;br /&gt;
      &amp;lt;td valign=&amp;quot;top&amp;quot;&amp;gt;&amp;lt;a name=&amp;quot;desc_sortmethod&amp;quot;&amp;gt;sortmethod&amp;lt;/a&amp;gt;&amp;lt;/td&amp;gt;&lt;br /&gt;
      &amp;lt;td valign=&amp;quot;top&amp;quot;&amp;gt;sortnum&amp;lt;/td&amp;gt;&lt;br /&gt;
      &amp;lt;td valign=&amp;quot;top&amp;quot;&amp;gt;alpha = Sort topics in topic list alphabetically&amp;lt;br&amp;gt;&lt;br /&gt;
        sortnum = Sort topics in topic list by sort number&amp;lt;/td&amp;gt;&lt;br /&gt;
    &amp;lt;/tr&amp;gt;&lt;br /&gt;
    &amp;lt;tr&amp;gt;&lt;br /&gt;
      &amp;lt;td valign=&amp;quot;top&amp;quot;&amp;gt;&amp;lt;a name=&amp;quot;desc_showstorycount&amp;quot;&amp;gt;showstorycount&amp;lt;/a&amp;gt;&amp;lt;/td&amp;gt;&lt;br /&gt;
      &amp;lt;td valign=&amp;quot;top&amp;quot;&amp;gt;1&amp;lt;/td&amp;gt;&lt;br /&gt;
      &amp;lt;td valign=&amp;quot;top&amp;quot;&amp;gt;Show the number of stories in a topic in the Sections&lt;br /&gt;
        block (0=no, 1=yes)&amp;lt;/td&amp;gt;&lt;br /&gt;
    &amp;lt;/tr&amp;gt;&lt;br /&gt;
    &amp;lt;tr&amp;gt;&lt;br /&gt;
      &amp;lt;td valign=&amp;quot;top&amp;quot;&amp;gt;&amp;lt;a name=&amp;quot;desc_showsubmissioncount&amp;quot;&amp;gt;showsubmissioncount&amp;lt;/a&amp;gt;&amp;lt;/td&amp;gt;&lt;br /&gt;
      &amp;lt;td valign=&amp;quot;top&amp;quot;&amp;gt;1&amp;lt;/td&amp;gt;&lt;br /&gt;
      &amp;lt;td valign=&amp;quot;top&amp;quot;&amp;gt;Show the number of story submissions for a topic in the&lt;br /&gt;
        Sections block (0=no, 1=yes)&amp;lt;/td&amp;gt;&lt;br /&gt;
    &amp;lt;/tr&amp;gt;&lt;br /&gt;
    &amp;lt;tr&amp;gt;&lt;br /&gt;
      &amp;lt;td valign=&amp;quot;top&amp;quot;&amp;gt;&amp;lt;a name=&amp;quot;desc_hide_home_link&amp;quot;&amp;gt;hide_home_link&amp;lt;/a&amp;gt;&amp;lt;/td&amp;gt;&lt;br /&gt;
      &amp;lt;td valign=&amp;quot;top&amp;quot;&amp;gt;0&amp;lt;/td&amp;gt;&lt;br /&gt;
      &amp;lt;td valign=&amp;quot;top&amp;quot;&amp;gt;Hide the &amp;amp;quot;Home&amp;amp;quot; link from the Sections block&lt;br /&gt;
        (0=no, 1=yes)&amp;lt;/td&amp;gt;&lt;br /&gt;
    &amp;lt;/tr&amp;gt;&lt;br /&gt;
    &amp;lt;tr&amp;gt;&lt;br /&gt;
      &amp;lt;td valign=&amp;quot;top&amp;quot;&amp;gt;&amp;lt;a name=&amp;quot;desc_whosonline_threshold&amp;quot;&amp;gt;whosonline_threshold&amp;lt;/a&amp;gt;&amp;lt;/td&amp;gt;&lt;br /&gt;
      &amp;lt;td valign=&amp;quot;top&amp;quot;&amp;gt;300&amp;lt;/td&amp;gt;&lt;br /&gt;
      &amp;lt;td valign=&amp;quot;top&amp;quot;&amp;gt;How long, in seconds, users can be idle before removing&lt;br /&gt;
        them from the whosonline block&amp;lt;/td&amp;gt;&lt;br /&gt;
    &amp;lt;/tr&amp;gt;&lt;br /&gt;
    &amp;lt;tr&amp;gt;&lt;br /&gt;
      &amp;lt;td valign=&amp;quot;top&amp;quot;&amp;gt;&amp;lt;a name=&amp;quot;desc_whosonline_anonymous&amp;quot;&amp;gt;whosonline_anonymous&amp;lt;/a&amp;gt;&amp;lt;/td&amp;gt;&lt;br /&gt;
      &amp;lt;td valign=&amp;quot;top&amp;quot;&amp;gt;0&amp;lt;/td&amp;gt;&lt;br /&gt;
      &amp;lt;td valign=&amp;quot;top&amp;quot;&amp;gt;If enabled (i.e. set to 1), anonymous users will only see&lt;br /&gt;
        the number of registered users currently online in the Who's Online&lt;br /&gt;
        block but not their names. Only logged-in users will see the names of&lt;br /&gt;
        other users that are currently online.&amp;lt;/td&amp;gt;&lt;br /&gt;
    &amp;lt;/tr&amp;gt;&lt;br /&gt;
    &amp;lt;tr&amp;gt;&lt;br /&gt;
      &amp;lt;td valign=&amp;quot;top&amp;quot;&amp;gt;&amp;lt;a name=&amp;quot;desc_emailstories&amp;quot;&amp;gt;emailstories&amp;lt;/a&amp;gt;&amp;lt;/td&amp;gt;&lt;br /&gt;
      &amp;lt;td valign=&amp;quot;top&amp;quot;&amp;gt;0&amp;lt;/td&amp;gt;&lt;br /&gt;
      &amp;lt;td valign=&amp;quot;top&amp;quot;&amp;gt;Let users get stories e-mailed to them (0=no, 1=yes), aka&lt;br /&gt;
        Daily Digest. Please note that this requires cron and the use of PHP as&lt;br /&gt;
        a shell script.&amp;lt;/td&amp;gt;&lt;br /&gt;
    &amp;lt;/tr&amp;gt;&lt;br /&gt;
    &amp;lt;tr&amp;gt;&lt;br /&gt;
      &amp;lt;td valign=&amp;quot;top&amp;quot;&amp;gt;&amp;lt;a name=&amp;quot;desc_emailstorieslength&amp;quot;&amp;gt;emailstorieslength&amp;lt;/a&amp;gt;&amp;lt;/td&amp;gt;&lt;br /&gt;
      &amp;lt;td valign=&amp;quot;top&amp;quot;&amp;gt;1&amp;lt;/td&amp;gt;&lt;br /&gt;
      &amp;lt;td valign=&amp;quot;top&amp;quot;&amp;gt;When emailstories (above) is enabled, send only the title&lt;br /&gt;
        and the link to the new stories (0), or send the entire introtext (1) or&lt;br /&gt;
        send the first &amp;lt;i&amp;gt;n&amp;lt;/i&amp;gt; characters from the introtext (where &amp;lt;i&amp;gt;n&amp;lt;/i&amp;gt; =&lt;br /&gt;
        any other number)&amp;lt;/td&amp;gt;&lt;br /&gt;
    &amp;lt;/tr&amp;gt;&lt;br /&gt;
    &amp;lt;tr&amp;gt;&lt;br /&gt;
      &amp;lt;td valign=&amp;quot;top&amp;quot;&amp;gt;&amp;lt;a name=&amp;quot;desc_emailstoriesperdefault&amp;quot;&amp;gt;emailstoriesperdefault&amp;lt;/a&amp;gt;&amp;lt;/td&amp;gt;&lt;br /&gt;
      &amp;lt;td valign=&amp;quot;top&amp;quot;&amp;gt;0&amp;lt;/td&amp;gt;&lt;br /&gt;
      &amp;lt;td valign=&amp;quot;top&amp;quot;&amp;gt;When set to 1, new users will be subscribed to the daily&lt;br /&gt;
        digest automatically when they register with the site.&amp;lt;/td&amp;gt;&lt;br /&gt;
    &amp;lt;/tr&amp;gt;&lt;br /&gt;
    &amp;lt;tr&amp;gt;&lt;br /&gt;
      &amp;lt;td valign=&amp;quot;top&amp;quot;&amp;gt;&amp;lt;a name=&amp;quot;desc_newstoriesinterval&amp;quot;&amp;gt;newstoriesinterval&amp;lt;/a&amp;gt;&amp;lt;/td&amp;gt;&lt;br /&gt;
      &amp;lt;td valign=&amp;quot;top&amp;quot;&amp;gt;86400&amp;lt;/td&amp;gt;&lt;br /&gt;
      &amp;lt;td valign=&amp;quot;top&amp;quot;&amp;gt;Stories are &amp;amp;quot;new&amp;amp;quot; if they are this many seconds&lt;br /&gt;
        old.&amp;lt;/td&amp;gt;&lt;br /&gt;
    &amp;lt;/tr&amp;gt;&lt;br /&gt;
    &amp;lt;tr&amp;gt;&lt;br /&gt;
      &amp;lt;td valign=&amp;quot;top&amp;quot;&amp;gt;&amp;lt;a name=&amp;quot;desc_newcommentsinterval&amp;quot;&amp;gt;newcommentsinterval&amp;lt;/a&amp;gt;&amp;lt;/td&amp;gt;&lt;br /&gt;
      &amp;lt;td valign=&amp;quot;top&amp;quot;&amp;gt;172800&amp;lt;/td&amp;gt;&lt;br /&gt;
      &amp;lt;td valign=&amp;quot;top&amp;quot;&amp;gt;Comments are &amp;amp;quot;new&amp;amp;quot; if they are this many&lt;br /&gt;
        seconds old.&amp;lt;/td&amp;gt;&lt;br /&gt;
    &amp;lt;/tr&amp;gt;&lt;br /&gt;
    &amp;lt;tr&amp;gt;&lt;br /&gt;
      &amp;lt;td valign=&amp;quot;top&amp;quot;&amp;gt;&amp;lt;a name=&amp;quot;desc_newtrackbackinterval&amp;quot;&amp;gt;newtrackbackinterval&amp;lt;/a&amp;gt;&amp;lt;/td&amp;gt;&lt;br /&gt;
      &amp;lt;td valign=&amp;quot;top&amp;quot;&amp;gt;172800&amp;lt;/td&amp;gt;&lt;br /&gt;
      &amp;lt;td valign=&amp;quot;top&amp;quot;&amp;gt;Trackback comments are &amp;amp;quot;new&amp;amp;quot; if they are this&lt;br /&gt;
        many seconds old.&amp;lt;/td&amp;gt;&lt;br /&gt;
    &amp;lt;/tr&amp;gt;&lt;br /&gt;
    &amp;lt;tr&amp;gt;&lt;br /&gt;
      &amp;lt;td valign=&amp;quot;top&amp;quot;&amp;gt;&amp;lt;a name=&amp;quot;desc_hidenewstories&amp;quot;&amp;gt;hidenewstories&amp;lt;/a&amp;gt;&amp;lt;/td&amp;gt;&lt;br /&gt;
      &amp;lt;td valign=&amp;quot;top&amp;quot;&amp;gt;0&amp;lt;/td&amp;gt;&lt;br /&gt;
      &amp;lt;td valign=&amp;quot;top&amp;quot;&amp;gt;Set to 1 to hide new stories from the What's New block.&amp;lt;/td&amp;gt;&lt;br /&gt;
    &amp;lt;/tr&amp;gt;&lt;br /&gt;
    &amp;lt;tr&amp;gt;&lt;br /&gt;
      &amp;lt;td valign=&amp;quot;top&amp;quot;&amp;gt;&amp;lt;a name=&amp;quot;desc_hidenewcomments&amp;quot;&amp;gt;hidenewcomments&amp;lt;/a&amp;gt;&amp;lt;/td&amp;gt;&lt;br /&gt;
      &amp;lt;td valign=&amp;quot;top&amp;quot;&amp;gt;0&amp;lt;/td&amp;gt;&lt;br /&gt;
      &amp;lt;td valign=&amp;quot;top&amp;quot;&amp;gt;Set to 1 to hide new comments from the What's New block.&amp;lt;/td&amp;gt;&lt;br /&gt;
    &amp;lt;/tr&amp;gt;&lt;br /&gt;
    &amp;lt;tr&amp;gt;&lt;br /&gt;
      &amp;lt;td valign=&amp;quot;top&amp;quot;&amp;gt;&amp;lt;a name=&amp;quot;desc_hidenewtrackbacks&amp;quot;&amp;gt;hidenewtrackbacks&amp;lt;/a&amp;gt;&amp;lt;/td&amp;gt;&lt;br /&gt;
      &amp;lt;td valign=&amp;quot;top&amp;quot;&amp;gt;0&amp;lt;/td&amp;gt;&lt;br /&gt;
      &amp;lt;td valign=&amp;quot;top&amp;quot;&amp;gt;Set to 1 to hide new trackback comments from the What's&lt;br /&gt;
        New block.&amp;lt;/td&amp;gt;&lt;br /&gt;
    &amp;lt;/tr&amp;gt;&lt;br /&gt;
    &amp;lt;tr&amp;gt;&lt;br /&gt;
      &amp;lt;td valign=&amp;quot;top&amp;quot;&amp;gt;&amp;lt;a name=&amp;quot;desc_hidenewplugins&amp;quot;&amp;gt;hidenewplugins&amp;lt;/a&amp;gt;&amp;lt;/td&amp;gt;&lt;br /&gt;
      &amp;lt;td valign=&amp;quot;top&amp;quot;&amp;gt;0&amp;lt;/td&amp;gt;&lt;br /&gt;
      &amp;lt;td valign=&amp;quot;top&amp;quot;&amp;gt;Set to 1 to hide new entries by plugins from the What's&lt;br /&gt;
        New block.&amp;lt;/td&amp;gt;&lt;br /&gt;
    &amp;lt;/tr&amp;gt;&lt;br /&gt;
    &amp;lt;tr&amp;gt;&lt;br /&gt;
      &amp;lt;td valign=&amp;quot;top&amp;quot;&amp;gt;&amp;lt;a name=&amp;quot;desc_title_trim_length&amp;quot;&amp;gt;title_trim_length&amp;lt;/a&amp;gt;&amp;lt;/td&amp;gt;&lt;br /&gt;
      &amp;lt;td valign=&amp;quot;top&amp;quot;&amp;gt;20&amp;lt;/td&amp;gt;&lt;br /&gt;
      &amp;lt;td valign=&amp;quot;top&amp;quot;&amp;gt;Max. length of the title of items listed in the What's&lt;br /&gt;
        New block.&amp;lt;/td&amp;gt;&lt;br /&gt;
    &amp;lt;/tr&amp;gt;&lt;br /&gt;
    &amp;lt;tr&amp;gt;&lt;br /&gt;
      &amp;lt;td valign=&amp;quot;top&amp;quot;&amp;gt;&amp;lt;a name=&amp;quot;desc_copyrightyear&amp;quot;&amp;gt;copyrightyear&amp;lt;/a&amp;gt;&amp;lt;/td&amp;gt;&lt;br /&gt;
      &amp;lt;td valign=&amp;quot;top&amp;quot;&amp;gt;&amp;lt;i&amp;gt;(commented out)&amp;lt;/i&amp;gt;&amp;lt;/td&amp;gt;&lt;br /&gt;
      &amp;lt;td valign=&amp;quot;top&amp;quot;&amp;gt;Set this to the year you want to appear in the copyright&lt;br /&gt;
        notice of your site's footer. If not set, Geeklog will use the current&lt;br /&gt;
        year.&amp;lt;/td&amp;gt;&lt;br /&gt;
    &amp;lt;/tr&amp;gt;&lt;br /&gt;
    &amp;lt;tr&amp;gt;&lt;br /&gt;
      &amp;lt;td valign=&amp;quot;top&amp;quot;&amp;gt;&amp;lt;a name=&amp;quot;desc_allow_username_change&amp;quot;&amp;gt;allow_username_change&amp;lt;/a&amp;gt;&amp;lt;/td&amp;gt;&lt;br /&gt;
      &amp;lt;td valign=&amp;quot;top&amp;quot;&amp;gt;0&amp;lt;/td&amp;gt;&lt;br /&gt;
      &amp;lt;td valign=&amp;quot;top&amp;quot;&amp;gt;If set to 1, users will be allowed to change their&lt;br /&gt;
        username (login name). Stories and comments posted under the old&lt;br /&gt;
        username will automatically show the new username.&amp;lt;/td&amp;gt;&lt;br /&gt;
    &amp;lt;/tr&amp;gt;&lt;br /&gt;
    &amp;lt;tr&amp;gt;&lt;br /&gt;
      &amp;lt;td valign=&amp;quot;top&amp;quot;&amp;gt;&amp;lt;a name=&amp;quot;desc_allow_account_delete&amp;quot;&amp;gt;allow_account_delete&amp;lt;/a&amp;gt;&amp;lt;/td&amp;gt;&lt;br /&gt;
      &amp;lt;td valign=&amp;quot;top&amp;quot;&amp;gt;0&amp;lt;/td&amp;gt;&lt;br /&gt;
      &amp;lt;td valign=&amp;quot;top&amp;quot;&amp;gt;If set to 1, users will be allowed to delete their&lt;br /&gt;
        accounts. Stories and comments posted under that account will be kept&lt;br /&gt;
        and show up as being posted by &amp;amp;quot;Anonymous&amp;amp;quot;.&amp;lt;/td&amp;gt;&lt;br /&gt;
    &amp;lt;/tr&amp;gt;&lt;br /&gt;
    &amp;lt;tr&amp;gt;&lt;br /&gt;
      &amp;lt;td valign=&amp;quot;top&amp;quot;&amp;gt;&amp;lt;a name=&amp;quot;desc_passwordspeedlimit&amp;quot;&amp;gt;passwordspeedlimit&amp;lt;/a&amp;gt;&amp;lt;/td&amp;gt;&lt;br /&gt;
      &amp;lt;td valign=&amp;quot;top&amp;quot;&amp;gt;300&amp;lt;/td&amp;gt;&lt;br /&gt;
      &amp;lt;td valign=&amp;quot;top&amp;quot;&amp;gt;Minimum delay between two requests for a new password, in&lt;br /&gt;
        seconds.&amp;lt;/td&amp;gt;&lt;br /&gt;
    &amp;lt;/tr&amp;gt;&lt;br /&gt;
    &amp;lt;tr&amp;gt;&lt;br /&gt;
      &amp;lt;td valign=&amp;quot;top&amp;quot;&amp;gt;&amp;lt;a name=&amp;quot;desc_login_attempts&amp;quot;&amp;gt;login_attempts&amp;lt;/a&amp;gt;&amp;lt;/td&amp;gt;&lt;br /&gt;
      &amp;lt;td valign=&amp;quot;top&amp;quot;&amp;gt;3&amp;lt;/td&amp;gt;&lt;br /&gt;
      &amp;lt;td valign=&amp;quot;top&amp;quot;&amp;gt;Max. number of login attempts before the speedlimit (see&lt;br /&gt;
        below) kicks in and further logins are blocked for the given amount of&lt;br /&gt;
        time.&amp;lt;/td&amp;gt;&lt;br /&gt;
    &amp;lt;/tr&amp;gt;&lt;br /&gt;
    &amp;lt;tr&amp;gt;&lt;br /&gt;
      &amp;lt;td valign=&amp;quot;top&amp;quot;&amp;gt;&amp;lt;a name=&amp;quot;desc_login_speedlimit&amp;quot;&amp;gt;login_speedlimit&amp;lt;/a&amp;gt;&amp;lt;/td&amp;gt;&lt;br /&gt;
      &amp;lt;td valign=&amp;quot;top&amp;quot;&amp;gt;300&amp;lt;/td&amp;gt;&lt;br /&gt;
      &amp;lt;td valign=&amp;quot;top&amp;quot;&amp;gt;How many seconds have to pass before another login&lt;br /&gt;
        attempt can be made after &amp;lt;code&amp;gt;$_CONF['login_attempts']&amp;lt;/code&amp;gt; (see&lt;br /&gt;
        above) login attempts have failed.&amp;lt;/td&amp;gt;&lt;br /&gt;
    &amp;lt;/tr&amp;gt;&lt;br /&gt;
    &amp;lt;tr&amp;gt;&lt;br /&gt;
      &amp;lt;td valign=&amp;quot;top&amp;quot;&amp;gt;&amp;lt;a name=&amp;quot;desc_ip_lookup&amp;quot;&amp;gt;ip_lookup&amp;lt;/a&amp;gt;&amp;lt;/td&amp;gt;&lt;br /&gt;
      &amp;lt;td valign=&amp;quot;top&amp;quot;&amp;gt;&amp;lt;i&amp;gt;not set&amp;lt;/i&amp;gt;&amp;lt;/td&amp;gt;&lt;br /&gt;
      &amp;lt;td valign=&amp;quot;top&amp;quot;&amp;gt;The IP addresses of comment posters are logged and&lt;br /&gt;
        displayed for admin users. When this variable is set to point to a&lt;br /&gt;
        service that can do IP address lookups, it's possible to lookup the&lt;br /&gt;
        owner of an IP address by clicking on it, making it easier to report&lt;br /&gt;
        abuse to ISPs, etc.&amp;lt;br&amp;gt;&lt;br /&gt;
        &amp;lt;code&amp;gt;$_CONF['ip_lookup']&amp;lt;/code&amp;gt; should hold the complete URL to the&lt;br /&gt;
        lookup service, with a '&amp;lt;code&amp;gt;*&amp;lt;/code&amp;gt;' marking the place where the IP&lt;br /&gt;
        address should go. It's also possible to use Tom Willet's &amp;lt;a href=&amp;quot;http://sourceforge.net/project/showfiles.php?group_id=68255&amp;amp;amp;package_id=95743&amp;quot;&amp;gt;NetTools&amp;lt;/a&amp;gt;&lt;br /&gt;
        package, in which case the correct setting would be &amp;lt;code&amp;gt;$_CONF['ip_lookup']&lt;br /&gt;
        = $_CONF['site_url'] . '/nettools/whois.php?domain=*';&amp;lt;/code&amp;gt;&amp;lt;/td&amp;gt;&lt;br /&gt;
    &amp;lt;/tr&amp;gt;&lt;br /&gt;
    &amp;lt;tr&amp;gt;&lt;br /&gt;
      &amp;lt;td valign=&amp;quot;top&amp;quot;&amp;gt;&amp;lt;a name=&amp;quot;desc_num_search_results&amp;quot;&amp;gt;num_search_results&amp;lt;/a&amp;gt;&amp;lt;/td&amp;gt;&lt;br /&gt;
      &amp;lt;td valign=&amp;quot;top&amp;quot;&amp;gt;10&amp;lt;/td&amp;gt;&lt;br /&gt;
      &amp;lt;td valign=&amp;quot;top&amp;quot;&amp;gt;Number of search results per page (and per type).&amp;lt;/td&amp;gt;&lt;br /&gt;
    &amp;lt;/tr&amp;gt;&lt;br /&gt;
  &amp;lt;/tbody&amp;gt;&lt;br /&gt;
&amp;lt;/table&amp;gt;&lt;br /&gt;
&amp;lt;h3&amp;gt;&amp;lt;a name=&amp;quot;story&amp;quot;&amp;gt;Story Settings&amp;lt;/a&amp;gt;&amp;lt;/h3&amp;gt;&lt;br /&gt;
&amp;lt;table border=&amp;quot;1&amp;quot; width=&amp;quot;100%&amp;quot;&amp;gt;&lt;br /&gt;
  &amp;lt;tbody&amp;gt;&lt;br /&gt;
    &amp;lt;tr&amp;gt;&lt;br /&gt;
      &amp;lt;th width=&amp;quot;8%&amp;quot;&amp;gt;Variable&amp;lt;/th&amp;gt;&lt;br /&gt;
      &amp;lt;th width=&amp;quot;29%&amp;quot;&amp;gt;Default Value&amp;lt;/th&amp;gt;&lt;br /&gt;
      &amp;lt;th width=&amp;quot;63%&amp;quot;&amp;gt;Description&amp;lt;/th&amp;gt;&lt;br /&gt;
    &amp;lt;/tr&amp;gt;&lt;br /&gt;
    &amp;lt;tr&amp;gt;&lt;br /&gt;
      &amp;lt;td valign=&amp;quot;top&amp;quot;&amp;gt;&amp;lt;a name=&amp;quot;desc_maximagesperarticle&amp;quot;&amp;gt;maximagesperarticle&amp;lt;/a&amp;gt;&amp;lt;/td&amp;gt;&lt;br /&gt;
      &amp;lt;td valign=&amp;quot;top&amp;quot;&amp;gt;5&amp;lt;/td&amp;gt;&lt;br /&gt;
      &amp;lt;td valign=&amp;quot;top&amp;quot;&amp;gt;max. number of images you can have in a story&amp;lt;/td&amp;gt;&lt;br /&gt;
    &amp;lt;/tr&amp;gt;&lt;br /&gt;
    &amp;lt;tr&amp;gt;&lt;br /&gt;
      &amp;lt;td valign=&amp;quot;top&amp;quot;&amp;gt;&amp;lt;a name=&amp;quot;desc_limitnews&amp;quot;&amp;gt;limitnews&amp;lt;/a&amp;gt;&amp;lt;/td&amp;gt;&lt;br /&gt;
      &amp;lt;td valign=&amp;quot;top&amp;quot;&amp;gt;10&amp;lt;/td&amp;gt;&lt;br /&gt;
      &amp;lt;td valign=&amp;quot;top&amp;quot;&amp;gt;Number of stories to limit the index page to, this same&lt;br /&gt;
        number will appear in the older stuff block&amp;lt;/td&amp;gt;&lt;br /&gt;
    &amp;lt;/tr&amp;gt;&lt;br /&gt;
    &amp;lt;tr&amp;gt;&lt;br /&gt;
      &amp;lt;td valign=&amp;quot;top&amp;quot;&amp;gt;&amp;lt;a name=&amp;quot;desc_minnews&amp;quot;&amp;gt;minnews&amp;lt;/a&amp;gt;&amp;lt;/td&amp;gt;&lt;br /&gt;
      &amp;lt;td valign=&amp;quot;top&amp;quot;&amp;gt;1&amp;lt;/td&amp;gt;&lt;br /&gt;
      &amp;lt;td valign=&amp;quot;top&amp;quot;&amp;gt;Minimum numbers of stories than can appear on a topic&lt;br /&gt;
        page&amp;lt;/td&amp;gt;&lt;br /&gt;
    &amp;lt;/tr&amp;gt;&lt;br /&gt;
    &amp;lt;tr&amp;gt;&lt;br /&gt;
      &amp;lt;td valign=&amp;quot;top&amp;quot;&amp;gt;&amp;lt;a name=&amp;quot;desc_contributedbyline&amp;quot;&amp;gt;contributedbyline&amp;lt;/a&amp;gt;&amp;lt;/td&amp;gt;&lt;br /&gt;
      &amp;lt;td valign=&amp;quot;top&amp;quot;&amp;gt;1&amp;lt;/td&amp;gt;&lt;br /&gt;
      &amp;lt;td valign=&amp;quot;top&amp;quot;&amp;gt;Show author username to public, and enable search by&lt;br /&gt;
        username (0=no, 1=yes)&amp;lt;/td&amp;gt;&lt;br /&gt;
    &amp;lt;/tr&amp;gt;&lt;br /&gt;
    &amp;lt;tr&amp;gt;&lt;br /&gt;
      &amp;lt;td valign=&amp;quot;top&amp;quot;&amp;gt;&amp;lt;a name=&amp;quot;desc_hideviewscount&amp;quot;&amp;gt;hideviewscount&amp;lt;/a&amp;gt;&amp;lt;/td&amp;gt;&lt;br /&gt;
      &amp;lt;td valign=&amp;quot;top&amp;quot;&amp;gt;0&amp;lt;/td&amp;gt;&lt;br /&gt;
      &amp;lt;td valign=&amp;quot;top&amp;quot;&amp;gt;Whether to show (= 0) or to hide (= 1) the number of&lt;br /&gt;
        views a story has had.&amp;lt;/td&amp;gt;&lt;br /&gt;
    &amp;lt;/tr&amp;gt;&lt;br /&gt;
    &amp;lt;tr&amp;gt;&lt;br /&gt;
      &amp;lt;td valign=&amp;quot;top&amp;quot;&amp;gt;&amp;lt;a name=&amp;quot;desc_article_image_align&amp;quot;&amp;gt;article_image_align&amp;lt;/a&amp;gt;&amp;lt;/td&amp;gt;&lt;br /&gt;
      &amp;lt;td valign=&amp;quot;top&amp;quot;&amp;gt;right&amp;lt;/td&amp;gt;&lt;br /&gt;
      &amp;lt;td valign=&amp;quot;top&amp;quot;&amp;gt;Which side of article the topic image should be shown&lt;br /&gt;
        (right or left)&amp;lt;/td&amp;gt;&lt;br /&gt;
    &amp;lt;/tr&amp;gt;&lt;br /&gt;
    &amp;lt;tr&amp;gt;&lt;br /&gt;
      &amp;lt;td valign=&amp;quot;top&amp;quot;&amp;gt;&amp;lt;a name=&amp;quot;desc_show_topic_icon&amp;quot;&amp;gt;show_topic_icon&amp;lt;/a&amp;gt;&amp;lt;/td&amp;gt;&lt;br /&gt;
      &amp;lt;td valign=&amp;quot;top&amp;quot;&amp;gt;1&amp;lt;/td&amp;gt;&lt;br /&gt;
      &amp;lt;td valign=&amp;quot;top&amp;quot;&amp;gt;Default setting for new stories and story submissions:&lt;br /&gt;
        Whether to show the topic icon (1) or not (0).&amp;lt;/td&amp;gt;&lt;br /&gt;
    &amp;lt;/tr&amp;gt;&lt;br /&gt;
    &amp;lt;tr&amp;gt;&lt;br /&gt;
      &amp;lt;td valign=&amp;quot;top&amp;quot;&amp;gt;&amp;lt;a name=&amp;quot;desc_draft_flag&amp;quot;&amp;gt;draft_flag&amp;lt;/a&amp;gt;&amp;lt;/td&amp;gt;&lt;br /&gt;
      &amp;lt;td valign=&amp;quot;top&amp;quot;&amp;gt;0&amp;lt;/td&amp;gt;&lt;br /&gt;
      &amp;lt;td valign=&amp;quot;top&amp;quot;&amp;gt;Default setting for new stories created by Story Admins:&lt;br /&gt;
        Whether the story's draft flag should be set (1) or not (0).&amp;lt;/td&amp;gt;&lt;br /&gt;
    &amp;lt;/tr&amp;gt;&lt;br /&gt;
    &amp;lt;tr&amp;gt;&lt;br /&gt;
      &amp;lt;td valign=&amp;quot;top&amp;quot;&amp;gt;&amp;lt;a name=&amp;quot;desc_frontpage&amp;quot;&amp;gt;frontpage&amp;lt;/a&amp;gt;&amp;lt;/td&amp;gt;&lt;br /&gt;
      &amp;lt;td valign=&amp;quot;top&amp;quot;&amp;gt;0&amp;lt;/td&amp;gt;&lt;br /&gt;
      &amp;lt;td valign=&amp;quot;top&amp;quot;&amp;gt;Default setting for new stories and story submissions:&lt;br /&gt;
        Whether the story should appear on the site's frontpage (1) or only in&lt;br /&gt;
        its topic's page (0). Please note that for stories submitted to the&lt;br /&gt;
        archive topic, this setting will be ignored and the story will &amp;lt;em&amp;gt;not&amp;lt;/em&amp;gt;&lt;br /&gt;
        appear on the frontpage.&amp;lt;/td&amp;gt;&lt;br /&gt;
    &amp;lt;/tr&amp;gt;&lt;br /&gt;
    &amp;lt;tr&amp;gt;&lt;br /&gt;
      &amp;lt;td valign=&amp;quot;top&amp;quot;&amp;gt;&amp;lt;a name=&amp;quot;desc_onlyrootfeatures&amp;quot;&amp;gt;onlyrootfeatures&amp;lt;/a&amp;gt;&amp;lt;/td&amp;gt;&lt;br /&gt;
      &amp;lt;td valign=&amp;quot;top&amp;quot;&amp;gt;0&amp;lt;/td&amp;gt;&lt;br /&gt;
      &amp;lt;td valign=&amp;quot;top&amp;quot;&amp;gt;When set to 1, this will only allow members of the Root&lt;br /&gt;
        group to make a story &amp;amp;quot;featured&amp;amp;quot;, i.e. the sticky top story on&lt;br /&gt;
        the site.&amp;lt;/td&amp;gt;&lt;br /&gt;
    &amp;lt;/tr&amp;gt;&lt;br /&gt;
    &amp;lt;tr&amp;gt;&lt;br /&gt;
      &amp;lt;td valign=&amp;quot;top&amp;quot;&amp;gt;&amp;lt;a name=&amp;quot;desc_hideemailicon&amp;quot;&amp;gt;hideemailicon&amp;lt;/a&amp;gt;&amp;lt;/td&amp;gt;&lt;br /&gt;
      &amp;lt;td valign=&amp;quot;top&amp;quot;&amp;gt;0&amp;lt;/td&amp;gt;&lt;br /&gt;
      &amp;lt;td valign=&amp;quot;top&amp;quot;&amp;gt;When set to 1, this will disable the ability to send a&lt;br /&gt;
        story by email. It will also hide the email icon from stories and the&lt;br /&gt;
        &amp;amp;quot;Email Article To a Friend&amp;amp;quot; from the Story Options block.&amp;lt;/td&amp;gt;&lt;br /&gt;
    &amp;lt;/tr&amp;gt;&lt;br /&gt;
    &amp;lt;tr&amp;gt;&lt;br /&gt;
      &amp;lt;td valign=&amp;quot;top&amp;quot;&amp;gt;&amp;lt;a name=&amp;quot;desc_hideprintericon&amp;quot;&amp;gt;hideprintericon&amp;lt;/a&amp;gt;&amp;lt;/td&amp;gt;&lt;br /&gt;
      &amp;lt;td valign=&amp;quot;top&amp;quot;&amp;gt;0&amp;lt;/td&amp;gt;&lt;br /&gt;
      &amp;lt;td valign=&amp;quot;top&amp;quot;&amp;gt;When set to 1, this will disable display of a story in a&lt;br /&gt;
        &amp;amp;quot;printer friendly&amp;amp;quot; format. It will also hide the printer icon&lt;br /&gt;
        from stories and the &amp;amp;quot;View Printable Version&amp;amp;quot; from the Story&lt;br /&gt;
        Options block.&amp;lt;/td&amp;gt;&lt;br /&gt;
    &amp;lt;/tr&amp;gt;&lt;br /&gt;
    &amp;lt;tr&amp;gt;&lt;br /&gt;
      &amp;lt;td valign=&amp;quot;top&amp;quot;&amp;gt;&amp;lt;a name=&amp;quot;desc_hide_no_news_msg&amp;quot;&amp;gt;hide_no_news_msg&amp;lt;/a&amp;gt;&amp;lt;/td&amp;gt;&lt;br /&gt;
      &amp;lt;td valign=&amp;quot;top&amp;quot;&amp;gt;0&amp;lt;/td&amp;gt;&lt;br /&gt;
      &amp;lt;td valign=&amp;quot;top&amp;quot;&amp;gt;When set to 1, hide the &amp;amp;quot;No News To Display&amp;amp;quot;&lt;br /&gt;
        message on the index page (e.g. when viewing a topic without any stories&lt;br /&gt;
        in it)&amp;lt;/td&amp;gt;&lt;br /&gt;
    &amp;lt;/tr&amp;gt;&lt;br /&gt;
    &amp;lt;tr&amp;gt;&lt;br /&gt;
      &amp;lt;td valign=&amp;quot;top&amp;quot;&amp;gt;&amp;lt;a name=&amp;quot;desc_hide_main_page_navigation&amp;quot;&amp;gt;hide_main_page_navigation&amp;lt;/a&amp;gt;&amp;lt;/td&amp;gt;&lt;br /&gt;
      &amp;lt;td valign=&amp;quot;top&amp;quot;&amp;gt;0&amp;lt;/td&amp;gt;&lt;br /&gt;
      &amp;lt;td valign=&amp;quot;top&amp;quot;&amp;gt;When set to 1, this option will hide the &amp;amp;quot;Google&lt;br /&gt;
        paging&amp;amp;quot; navigation from index.php, i.e. from the site's frontpage&lt;br /&gt;
        and all topic pages. This may come in handy for more advanced layouts&lt;br /&gt;
        but will of course prevent people from easily reaching older articles.&amp;lt;/td&amp;gt;&lt;br /&gt;
    &amp;lt;/tr&amp;gt;&lt;br /&gt;
    &amp;lt;tr&amp;gt;&lt;br /&gt;
      &amp;lt;td valign=&amp;quot;top&amp;quot;&amp;gt;&amp;lt;a name=&amp;quot;desc_allow_page_breaks&amp;quot;&amp;gt;allow_page_breaks&amp;lt;/a&amp;gt;&amp;lt;/td&amp;gt;&lt;br /&gt;
      &amp;lt;td valign=&amp;quot;top&amp;quot;&amp;gt;1&amp;lt;/td&amp;gt;&lt;br /&gt;
      &amp;lt;td valign=&amp;quot;top&amp;quot;&amp;gt;Allow usage of the &amp;lt;code&amp;gt;[page_break]&amp;lt;/code&amp;gt; tag in&lt;br /&gt;
        stories (when set to 1), so that stories can spread over multiple pages.&amp;lt;/td&amp;gt;&lt;br /&gt;
    &amp;lt;/tr&amp;gt;&lt;br /&gt;
    &amp;lt;tr&amp;gt;&lt;br /&gt;
      &amp;lt;td valign=&amp;quot;top&amp;quot;&amp;gt;&amp;lt;a name=&amp;quot;desc_page_break_comments&amp;quot;&amp;gt;page_break_comments&amp;lt;/a&amp;gt;&amp;lt;/td&amp;gt;&lt;br /&gt;
      &amp;lt;td valign=&amp;quot;top&amp;quot;&amp;gt;last&amp;lt;/td&amp;gt;&lt;br /&gt;
      &amp;lt;td valign=&amp;quot;top&amp;quot;&amp;gt;When the &amp;lt;code&amp;gt;[page_break]&amp;lt;/code&amp;gt; tag is allowed in&lt;br /&gt;
        stories (see above), where should the story's comments be displayed: &amp;lt;code&amp;gt;'last'&amp;lt;/code&amp;gt;&lt;br /&gt;
        = on the story's last page only, &amp;lt;code&amp;gt;'first'&amp;lt;/code&amp;gt; = on the first&lt;br /&gt;
        page only, &amp;lt;code&amp;gt;'all'&amp;lt;/code&amp;gt; = on every page.&amp;lt;/td&amp;gt;&lt;br /&gt;
    &amp;lt;/tr&amp;gt;&lt;br /&gt;
    &amp;lt;tr&amp;gt;&lt;br /&gt;
      &amp;lt;td valign=&amp;quot;top&amp;quot;&amp;gt;&amp;lt;a name=&amp;quot;desc_show_right_blocks&amp;quot;&amp;gt;show_right_blocks&amp;lt;/a&amp;gt;&amp;lt;/td&amp;gt;&lt;br /&gt;
      &amp;lt;td valign=&amp;quot;top&amp;quot;&amp;gt;false&amp;lt;/td&amp;gt;&lt;br /&gt;
      &amp;lt;td valign=&amp;quot;top&amp;quot;&amp;gt;If set to &amp;lt;tt&amp;gt;true&amp;lt;/tt&amp;gt;, the right-side column of blocks&lt;br /&gt;
        will be displayed on &amp;lt;em&amp;gt;all&amp;lt;/em&amp;gt; pages (instead of only on the index&lt;br /&gt;
        page).&amp;lt;/td&amp;gt;&lt;br /&gt;
    &amp;lt;/tr&amp;gt;&lt;br /&gt;
    &amp;lt;tr&amp;gt;&lt;br /&gt;
      &amp;lt;td valign=&amp;quot;top&amp;quot;&amp;gt;&amp;lt;a name=&amp;quot;desc_showfirstasfeatured&amp;quot;&amp;gt;showfirstasfeatured&amp;lt;/a&amp;gt;&amp;lt;/td&amp;gt;&lt;br /&gt;
      &amp;lt;td valign=&amp;quot;top&amp;quot;&amp;gt;0&amp;lt;/td&amp;gt;&lt;br /&gt;
      &amp;lt;td valign=&amp;quot;top&amp;quot;&amp;gt;When set to 1, this will render the first story on &amp;lt;em&amp;gt;any&amp;lt;/em&amp;gt;&lt;br /&gt;
        page using the templates for a featured story, even if that story is not&lt;br /&gt;
        featured. This will even be applied to the first story on page 2 of a&lt;br /&gt;
        topic page, for example.&amp;lt;/td&amp;gt;&lt;br /&gt;
    &amp;lt;/tr&amp;gt;&lt;br /&gt;
    &amp;lt;tr&amp;gt;&lt;br /&gt;
      &amp;lt;td valign=&amp;quot;top&amp;quot;&amp;gt;&amp;lt;a name=&amp;quot;desc_showfirstasfeatured&amp;quot;&amp;gt;onlyrootfeatures&amp;lt;/a&amp;gt;&amp;lt;/td&amp;gt;&lt;br /&gt;
      &amp;lt;td valign=&amp;quot;top&amp;quot;&amp;gt;0&amp;lt;/td&amp;gt;&lt;br /&gt;
      &amp;lt;td valign=&amp;quot;top&amp;quot;&amp;gt;This restricts the featuring of stories to root user(s).&lt;br /&gt;
        If you have several story admins that can create content that is not&lt;br /&gt;
        visible to other story admins, and such a content is featured, another&lt;br /&gt;
        admin might think its ok to feature his own content. To prevent that two&lt;br /&gt;
        admins unknowingly take features from each other away, only a user who&lt;br /&gt;
        can see all content (= root) should be able to feature a story.&amp;lt;/td&amp;gt;&lt;br /&gt;
    &amp;lt;/tr&amp;gt;&lt;br /&gt;
    &amp;lt;tr&amp;gt;&lt;br /&gt;
      &amp;lt;td valign=&amp;quot;top&amp;quot;&amp;gt;&amp;lt;a name=&amp;quot;desc_left_blocks_in_footer&amp;quot;&amp;gt;left_blocks_in_footer&amp;lt;/a&amp;gt;&amp;lt;/td&amp;gt;&lt;br /&gt;
      &amp;lt;td valign=&amp;quot;top&amp;quot;&amp;gt;0&amp;lt;/td&amp;gt;&lt;br /&gt;
      &amp;lt;td valign=&amp;quot;top&amp;quot;&amp;gt;When set to 1, this will make the &amp;lt;code&amp;gt;{left_blocks}&amp;lt;/code&amp;gt;&lt;br /&gt;
        variable available in &amp;lt;tt&amp;gt;footer.thtml&amp;lt;/tt&amp;gt; (and disable it in &amp;lt;tt&amp;gt;header.thtml&amp;lt;/tt&amp;gt;).&lt;br /&gt;
        This is really only useful for two-column layouts where you want the&lt;br /&gt;
        left column contain the stories and the right columni contain the&lt;br /&gt;
        standard blocks.&amp;lt;/td&amp;gt;&lt;br /&gt;
    &amp;lt;/tr&amp;gt;&lt;br /&gt;
  &amp;lt;/tbody&amp;gt;&lt;br /&gt;
&amp;lt;/table&amp;gt;&lt;br /&gt;
&amp;lt;h3&amp;gt;&amp;lt;a name=&amp;quot;comment&amp;quot;&amp;gt;Comment Settings&amp;lt;/a&amp;gt;&amp;lt;/h3&amp;gt;&lt;br /&gt;
&amp;lt;table border=&amp;quot;1&amp;quot; width=&amp;quot;100%&amp;quot;&amp;gt;&lt;br /&gt;
  &amp;lt;tbody&amp;gt;&lt;br /&gt;
    &amp;lt;tr&amp;gt;&lt;br /&gt;
      &amp;lt;th width=&amp;quot;8%&amp;quot;&amp;gt;Variable&amp;lt;/th&amp;gt;&lt;br /&gt;
      &amp;lt;th width=&amp;quot;29%&amp;quot;&amp;gt;Default Value&amp;lt;/th&amp;gt;&lt;br /&gt;
      &amp;lt;th width=&amp;quot;63%&amp;quot;&amp;gt;Description&amp;lt;/th&amp;gt;&lt;br /&gt;
    &amp;lt;/tr&amp;gt;&lt;br /&gt;
    &amp;lt;tr&amp;gt;&lt;br /&gt;
      &amp;lt;td valign=&amp;quot;top&amp;quot;&amp;gt;&amp;lt;a name=&amp;quot;desc_commentspeedlimit&amp;quot;&amp;gt;commentspeedlimit&amp;lt;/a&amp;gt;&amp;lt;/td&amp;gt;&lt;br /&gt;
      &amp;lt;td valign=&amp;quot;top&amp;quot;&amp;gt;45&amp;lt;/td&amp;gt;&lt;br /&gt;
      &amp;lt;td valign=&amp;quot;top&amp;quot;&amp;gt;Number of seconds between posting a comment for the user&amp;lt;/td&amp;gt;&lt;br /&gt;
    &amp;lt;/tr&amp;gt;&lt;br /&gt;
    &amp;lt;tr&amp;gt;&lt;br /&gt;
      &amp;lt;td valign=&amp;quot;top&amp;quot;&amp;gt;&amp;lt;a name=&amp;quot;desc_comment_limit&amp;quot;&amp;gt;comment_limit&amp;lt;/a&amp;gt;&amp;lt;/td&amp;gt;&lt;br /&gt;
      &amp;lt;td valign=&amp;quot;top&amp;quot;&amp;gt;100&amp;lt;/td&amp;gt;&lt;br /&gt;
      &amp;lt;td valign=&amp;quot;top&amp;quot;&amp;gt;Most number of comments to show at any one time&amp;lt;/td&amp;gt;&lt;br /&gt;
    &amp;lt;/tr&amp;gt;&lt;br /&gt;
    &amp;lt;tr&amp;gt;&lt;br /&gt;
      &amp;lt;td valign=&amp;quot;top&amp;quot;&amp;gt;&amp;lt;a name=&amp;quot;desc_comment_mode&amp;quot;&amp;gt;comment_mode&amp;lt;/a&amp;gt;&amp;lt;/td&amp;gt;&lt;br /&gt;
      &amp;lt;td valign=&amp;quot;top&amp;quot;&amp;gt;threaded&amp;lt;/td&amp;gt;&lt;br /&gt;
      &amp;lt;td valign=&amp;quot;top&amp;quot;&amp;gt;How to display comments (threaded, nested, flat or&lt;br /&gt;
        nocomments)&amp;lt;/td&amp;gt;&lt;br /&gt;
    &amp;lt;/tr&amp;gt;&lt;br /&gt;
    &amp;lt;tr&amp;gt;&lt;br /&gt;
      &amp;lt;td valign=&amp;quot;top&amp;quot;&amp;gt;&amp;lt;a name=&amp;quot;desc_comment_code&amp;quot;&amp;gt;comment_code&amp;lt;/a&amp;gt;&amp;lt;/td&amp;gt;&lt;br /&gt;
      &amp;lt;td valign=&amp;quot;top&amp;quot;&amp;gt;0&amp;lt;/td&amp;gt;&lt;br /&gt;
      &amp;lt;td valign=&amp;quot;top&amp;quot;&amp;gt;Default value for new stories: Comments enabled (0) or&lt;br /&gt;
        disabled (-1)&amp;lt;/td&amp;gt;&lt;br /&gt;
    &amp;lt;/tr&amp;gt;&lt;br /&gt;
  &amp;lt;/tbody&amp;gt;&lt;br /&gt;
&amp;lt;/table&amp;gt;&lt;br /&gt;
&amp;lt;h3&amp;gt;&amp;lt;a name=&amp;quot;image&amp;quot;&amp;gt;Image Settings&amp;lt;/a&amp;gt;&amp;lt;/h3&amp;gt;&lt;br /&gt;
&amp;lt;table border=&amp;quot;1&amp;quot; width=&amp;quot;100%&amp;quot;&amp;gt;&lt;br /&gt;
  &amp;lt;tbody&amp;gt;&lt;br /&gt;
    &amp;lt;tr&amp;gt;&lt;br /&gt;
      &amp;lt;th width=&amp;quot;8%&amp;quot;&amp;gt;Variable&amp;lt;/th&amp;gt;&lt;br /&gt;
      &amp;lt;th width=&amp;quot;29%&amp;quot;&amp;gt;Default Value&amp;lt;/th&amp;gt;&lt;br /&gt;
      &amp;lt;th width=&amp;quot;63%&amp;quot;&amp;gt;Description&amp;lt;/th&amp;gt;&lt;br /&gt;
    &amp;lt;/tr&amp;gt;&lt;br /&gt;
    &amp;lt;tr&amp;gt;&lt;br /&gt;
      &amp;lt;td valign=&amp;quot;top&amp;quot;&amp;gt;&amp;lt;a name=&amp;quot;desc_image_lib&amp;quot;&amp;gt;image_lib&amp;lt;/a&amp;gt;&amp;lt;/td&amp;gt;&lt;br /&gt;
      &amp;lt;td valign=&amp;quot;top&amp;quot;&amp;gt;'' &amp;lt;i&amp;gt;(empty string)&amp;lt;/i&amp;gt;&amp;lt;/td&amp;gt;&lt;br /&gt;
      &amp;lt;td valign=&amp;quot;top&amp;quot;&amp;gt;Set this to either 'imagemagick', 'netpbm', or 'gdlib' if&lt;br /&gt;
        images should be resized during upload. Leave as '' if you don't want&lt;br /&gt;
        images to be resized or if you don't have those packages available.&amp;lt;/td&amp;gt;&lt;br /&gt;
    &amp;lt;/tr&amp;gt;&lt;br /&gt;
    &amp;lt;tr&amp;gt;&lt;br /&gt;
      &amp;lt;td valign=&amp;quot;top&amp;quot;&amp;gt;&amp;lt;a name=&amp;quot;desc_path_to_mogrify&amp;quot;&amp;gt;path_to_mogrify&amp;lt;/a&amp;gt;&amp;lt;/td&amp;gt;&lt;br /&gt;
      &amp;lt;td valign=&amp;quot;top&amp;quot;&amp;gt;&amp;lt;i&amp;gt;(commented out)&amp;lt;/i&amp;gt;&amp;lt;/td&amp;gt;&lt;br /&gt;
      &amp;lt;td valign=&amp;quot;top&amp;quot;&amp;gt;If you chose 'imagemagick' for &amp;lt;code&amp;gt;$_CONF['image_lib']&amp;lt;/code&amp;gt;&lt;br /&gt;
        above, then this should hold the &amp;lt;strong&amp;gt;complete path&amp;lt;/strong&amp;gt; to the&lt;br /&gt;
        mogrify executable (from the ImageMagick package), e.g. '/usr/bin/mogrify'.&amp;lt;br&amp;gt;&lt;br /&gt;
        You will need a fairly recent version of &amp;lt;a href=&amp;quot;http://www.imagemagick.org/&amp;quot;&amp;gt;ImageMagick&amp;lt;/a&amp;gt;&lt;br /&gt;
        for this to work (version 5.4.9 or newer is recommended).&amp;lt;/td&amp;gt;&lt;br /&gt;
    &amp;lt;/tr&amp;gt;&lt;br /&gt;
    &amp;lt;tr&amp;gt;&lt;br /&gt;
      &amp;lt;td valign=&amp;quot;top&amp;quot;&amp;gt;&amp;lt;a name=&amp;quot;desc_path_to_netpbm&amp;quot;&amp;gt;path_to_netpbm&amp;lt;/a&amp;gt;&amp;lt;/td&amp;gt;&lt;br /&gt;
      &amp;lt;td valign=&amp;quot;top&amp;quot;&amp;gt;&amp;lt;i&amp;gt;(commented out)&amp;lt;/i&amp;gt;&amp;lt;/td&amp;gt;&lt;br /&gt;
      &amp;lt;td valign=&amp;quot;top&amp;quot;&amp;gt;If you chose 'netpbm' for &amp;lt;code&amp;gt;$_CONF['image_lib']&amp;lt;/code&amp;gt;&lt;br /&gt;
        above, then this should hold the complete path to the &amp;lt;em&amp;gt;directory&amp;lt;/em&amp;gt;&lt;br /&gt;
        where the binaries from the netpbm package are kept, e.g. &amp;lt;code&amp;gt;'/usr/bin/netpbm/'&amp;lt;/code&amp;gt;.&lt;br /&gt;
        Note that the path must end in a slash.&amp;lt;br&amp;gt;&lt;br /&gt;
        Precompiled binaries of the netpbm package for various platforms can be&lt;br /&gt;
        downloaded from the &amp;lt;a href=&amp;quot;http://sourceforge.net/projects/gallery/&amp;quot;&amp;gt;Homepage&lt;br /&gt;
        of the Gallery project&amp;lt;/a&amp;gt;.&amp;lt;/td&amp;gt;&lt;br /&gt;
    &amp;lt;/tr&amp;gt;&lt;br /&gt;
    &amp;lt;tr&amp;gt;&lt;br /&gt;
      &amp;lt;td valign=&amp;quot;top&amp;quot;&amp;gt;&amp;lt;a name=&amp;quot;desc_keep_unscaled_image&amp;quot;&amp;gt;keep_unscaled_image&amp;lt;/a&amp;gt;&amp;lt;/td&amp;gt;&lt;br /&gt;
      &amp;lt;td valign=&amp;quot;top&amp;quot;&amp;gt;0&amp;lt;/td&amp;gt;&lt;br /&gt;
      &amp;lt;td valign=&amp;quot;top&amp;quot;&amp;gt;Set this to 1 if you want Geeklog to keep the original,&lt;br /&gt;
        unscaled images after upload. The smaller image will then be used as a&lt;br /&gt;
        thumbnail and will link to the original image. Note that this may use a&lt;br /&gt;
        lot of disk space (depending on the size of your images).&amp;lt;/td&amp;gt;&lt;br /&gt;
    &amp;lt;/tr&amp;gt;&lt;br /&gt;
    &amp;lt;tr&amp;gt;&lt;br /&gt;
      &amp;lt;td valign=&amp;quot;top&amp;quot;&amp;gt;&amp;lt;a name=&amp;quot;desc_allow_user_scaling&amp;quot;&amp;gt;allow_user_scaling&amp;lt;/a&amp;gt;&amp;lt;/td&amp;gt;&lt;br /&gt;
      &amp;lt;td valign=&amp;quot;top&amp;quot;&amp;gt;1&amp;lt;/td&amp;gt;&lt;br /&gt;
      &amp;lt;td valign=&amp;quot;top&amp;quot;&amp;gt;When unscaled images are kept (see above), this option&lt;br /&gt;
        lets the user chose between using the scaled or unscaled image in the&lt;br /&gt;
        story, i.e. enables the &amp;lt;code&amp;gt;[unscaled&amp;lt;i&amp;gt;X&amp;lt;/i&amp;gt;]&amp;lt;/code&amp;gt; image tag (in&lt;br /&gt;
        addition to the &amp;lt;code&amp;gt;[image&amp;lt;i&amp;gt;X&amp;lt;/i&amp;gt;]&amp;lt;/code&amp;gt; tag).&amp;lt;/td&amp;gt;&lt;br /&gt;
    &amp;lt;/tr&amp;gt;&lt;br /&gt;
    &amp;lt;tr&amp;gt;&lt;br /&gt;
      &amp;lt;td valign=&amp;quot;top&amp;quot;&amp;gt;&amp;lt;a name=&amp;quot;desc_max_image_width&amp;quot;&amp;gt;max_image_width&amp;lt;/a&amp;gt;&amp;lt;/td&amp;gt;&lt;br /&gt;
      &amp;lt;td valign=&amp;quot;top&amp;quot;&amp;gt;160&amp;lt;/td&amp;gt;&lt;br /&gt;
      &amp;lt;td valign=&amp;quot;top&amp;quot;&amp;gt;Max. width of an image in pixels. If it exceeds this, it&lt;br /&gt;
        is either rejected or resized (depending on the setting of &amp;lt;code&amp;gt;$_CONF['image_lib']&amp;lt;/code&amp;gt;&lt;br /&gt;
        above).&amp;lt;/td&amp;gt;&lt;br /&gt;
    &amp;lt;/tr&amp;gt;&lt;br /&gt;
    &amp;lt;tr&amp;gt;&lt;br /&gt;
      &amp;lt;td valign=&amp;quot;top&amp;quot;&amp;gt;&amp;lt;a name=&amp;quot;desc_max_image_height&amp;quot;&amp;gt;max_image_height&amp;lt;/a&amp;gt;&amp;lt;/td&amp;gt;&lt;br /&gt;
      &amp;lt;td valign=&amp;quot;top&amp;quot;&amp;gt;120&amp;lt;/td&amp;gt;&lt;br /&gt;
      &amp;lt;td valign=&amp;quot;top&amp;quot;&amp;gt;Max. height of an image in pixels. If it exceeds this, it&lt;br /&gt;
        is either rejected or resized (depending on the setting of &amp;lt;code&amp;gt;$_CONF['image_lib']&amp;lt;/code&amp;gt;&lt;br /&gt;
        above).&amp;lt;/td&amp;gt;&lt;br /&gt;
    &amp;lt;/tr&amp;gt;&lt;br /&gt;
    &amp;lt;tr&amp;gt;&lt;br /&gt;
      &amp;lt;td valign=&amp;quot;top&amp;quot;&amp;gt;&amp;lt;a name=&amp;quot;desc_max_image_size&amp;quot;&amp;gt;max_image_size&amp;lt;/a&amp;gt;&amp;lt;/td&amp;gt;&lt;br /&gt;
      &amp;lt;td valign=&amp;quot;top&amp;quot;&amp;gt;1048576 &amp;lt;i&amp;gt;(equals 1 MB)&amp;lt;/i&amp;gt;&amp;lt;/td&amp;gt;&lt;br /&gt;
      &amp;lt;td valign=&amp;quot;top&amp;quot;&amp;gt;Max. size of an image in bytes. If it exceeds this, it is&lt;br /&gt;
        is rejected (even if you're using a graphics package to resize images).&amp;lt;/td&amp;gt;&lt;br /&gt;
    &amp;lt;/tr&amp;gt;&lt;br /&gt;
    &amp;lt;tr&amp;gt;&lt;br /&gt;
      &amp;lt;td valign=&amp;quot;top&amp;quot;&amp;gt;&amp;lt;a name=&amp;quot;desc_max_topicicon_width&amp;quot;&amp;gt;max_topicicon_width&amp;lt;/a&amp;gt;&amp;lt;/td&amp;gt;&lt;br /&gt;
      &amp;lt;td valign=&amp;quot;top&amp;quot;&amp;gt;48&amp;lt;/td&amp;gt;&lt;br /&gt;
      &amp;lt;td valign=&amp;quot;top&amp;quot;&amp;gt;Max. width of a topic icon in pixels. If it exceeds this,&lt;br /&gt;
        it is either rejected or resized (depending on the setting of &amp;lt;code&amp;gt;$_CONF['image_lib']&amp;lt;/code&amp;gt;&lt;br /&gt;
        above).&amp;lt;/td&amp;gt;&lt;br /&gt;
    &amp;lt;/tr&amp;gt;&lt;br /&gt;
    &amp;lt;tr&amp;gt;&lt;br /&gt;
      &amp;lt;td valign=&amp;quot;top&amp;quot;&amp;gt;&amp;lt;a name=&amp;quot;desc_max_topicicon_height&amp;quot;&amp;gt;max_topicicon_height&amp;lt;/a&amp;gt;&amp;lt;/td&amp;gt;&lt;br /&gt;
      &amp;lt;td valign=&amp;quot;top&amp;quot;&amp;gt;48&amp;lt;/td&amp;gt;&lt;br /&gt;
      &amp;lt;td valign=&amp;quot;top&amp;quot;&amp;gt;Max. height of a topic icon in pixels. If it exceeds&lt;br /&gt;
        this, it is either rejected or resized (depending on the setting of &amp;lt;code&amp;gt;$_CONF['image_lib']&amp;lt;/code&amp;gt;&lt;br /&gt;
        above).&amp;lt;/td&amp;gt;&lt;br /&gt;
    &amp;lt;/tr&amp;gt;&lt;br /&gt;
    &amp;lt;tr&amp;gt;&lt;br /&gt;
      &amp;lt;td valign=&amp;quot;top&amp;quot;&amp;gt;&amp;lt;a name=&amp;quot;desc_max_topicicon_size&amp;quot;&amp;gt;max_topicicon_size&amp;lt;/a&amp;gt;&amp;lt;/td&amp;gt;&lt;br /&gt;
      &amp;lt;td valign=&amp;quot;top&amp;quot;&amp;gt;65536 &amp;lt;i&amp;gt;(equals 64 KB)&amp;lt;/i&amp;gt;&amp;lt;/td&amp;gt;&lt;br /&gt;
      &amp;lt;td valign=&amp;quot;top&amp;quot;&amp;gt;Max. size of a user photo in bytes. If it exceeds this,&lt;br /&gt;
        it is rejected (even if you're using a graphics package to resize&lt;br /&gt;
        images).&amp;lt;/td&amp;gt;&lt;br /&gt;
    &amp;lt;/tr&amp;gt;&lt;br /&gt;
    &amp;lt;tr&amp;gt;&lt;br /&gt;
      &amp;lt;td valign=&amp;quot;top&amp;quot;&amp;gt;&amp;lt;a name=&amp;quot;desc_debug_image_upload&amp;quot;&amp;gt;debug_image_upload&amp;lt;/a&amp;gt;&amp;lt;/td&amp;gt;&lt;br /&gt;
      &amp;lt;td valign=&amp;quot;top&amp;quot;&amp;gt;&amp;lt;i&amp;gt;(commented out)&amp;lt;/i&amp;gt;&amp;lt;/td&amp;gt;&lt;br /&gt;
      &amp;lt;td valign=&amp;quot;top&amp;quot;&amp;gt;When not commented out(!) and set to &amp;lt;code&amp;gt;true&amp;lt;/code&amp;gt;,&lt;br /&gt;
        this option enables debugging output to be written into Geeklog's &amp;lt;tt&amp;gt;error.log&amp;lt;/tt&amp;gt;&lt;br /&gt;
        file during the upload of an image. This is useful to track down&lt;br /&gt;
        problems with the image upload.&amp;lt;/td&amp;gt;&lt;br /&gt;
    &amp;lt;/tr&amp;gt;&lt;br /&gt;
  &amp;lt;/tbody&amp;gt;&lt;br /&gt;
&amp;lt;/table&amp;gt;&lt;br /&gt;
&amp;lt;h4&amp;gt;&amp;lt;a name=&amp;quot;userphoto&amp;quot;&amp;gt;User photo&amp;lt;/a&amp;gt;&amp;lt;/h4&amp;gt;&lt;br /&gt;
&amp;lt;p&amp;gt;Additional options for the user photo.&amp;lt;/p&amp;gt;&lt;br /&gt;
&amp;lt;table border=&amp;quot;1&amp;quot; width=&amp;quot;100%&amp;quot;&amp;gt;&lt;br /&gt;
  &amp;lt;tbody&amp;gt;&lt;br /&gt;
    &amp;lt;tr&amp;gt;&lt;br /&gt;
      &amp;lt;th width=&amp;quot;8%&amp;quot;&amp;gt;Variable&amp;lt;/th&amp;gt;&lt;br /&gt;
      &amp;lt;th width=&amp;quot;29%&amp;quot;&amp;gt;Default Value&amp;lt;/th&amp;gt;&lt;br /&gt;
      &amp;lt;th width=&amp;quot;63%&amp;quot;&amp;gt;Description&amp;lt;/th&amp;gt;&lt;br /&gt;
    &amp;lt;/tr&amp;gt;&lt;br /&gt;
    &amp;lt;tr&amp;gt;&lt;br /&gt;
      &amp;lt;td valign=&amp;quot;top&amp;quot;&amp;gt;&amp;lt;a name=&amp;quot;desc_max_photo_width&amp;quot;&amp;gt;max_photo_width&amp;lt;/a&amp;gt;&amp;lt;/td&amp;gt;&lt;br /&gt;
      &amp;lt;td valign=&amp;quot;top&amp;quot;&amp;gt;128&amp;lt;/td&amp;gt;&lt;br /&gt;
      &amp;lt;td valign=&amp;quot;top&amp;quot;&amp;gt;Max. width of a user photo in pixels. If it exceeds this,&lt;br /&gt;
        it is either rejected or resized (depending on the setting of &amp;lt;code&amp;gt;$_CONF['image_lib']&amp;lt;/code&amp;gt;&lt;br /&gt;
        above).&amp;lt;/td&amp;gt;&lt;br /&gt;
    &amp;lt;/tr&amp;gt;&lt;br /&gt;
    &amp;lt;tr&amp;gt;&lt;br /&gt;
      &amp;lt;td valign=&amp;quot;top&amp;quot;&amp;gt;&amp;lt;a name=&amp;quot;desc_max_photo_height&amp;quot;&amp;gt;max_photo_height&amp;lt;/a&amp;gt;&amp;lt;/td&amp;gt;&lt;br /&gt;
      &amp;lt;td valign=&amp;quot;top&amp;quot;&amp;gt;128&amp;lt;/td&amp;gt;&lt;br /&gt;
      &amp;lt;td valign=&amp;quot;top&amp;quot;&amp;gt;Max. height of a user photo in pixels. If it exceeds&lt;br /&gt;
        this, it is either rejected or resized (depending on the setting of &amp;lt;code&amp;gt;$_CONF['image_lib']&amp;lt;/code&amp;gt;&lt;br /&gt;
        above).&amp;lt;/td&amp;gt;&lt;br /&gt;
    &amp;lt;/tr&amp;gt;&lt;br /&gt;
    &amp;lt;tr&amp;gt;&lt;br /&gt;
      &amp;lt;td valign=&amp;quot;top&amp;quot;&amp;gt;&amp;lt;a name=&amp;quot;desc_max_photo_size&amp;quot;&amp;gt;max_photo_size&amp;lt;/a&amp;gt;&amp;lt;/td&amp;gt;&lt;br /&gt;
      &amp;lt;td valign=&amp;quot;top&amp;quot;&amp;gt;65536 &amp;lt;i&amp;gt;(equals 64 KB)&amp;lt;/i&amp;gt;&amp;lt;/td&amp;gt;&lt;br /&gt;
      &amp;lt;td valign=&amp;quot;top&amp;quot;&amp;gt;Max. size of a user photo in bytes. If it exceeds this,&lt;br /&gt;
        it is rejected (even if you're using a graphics package to resize&lt;br /&gt;
        images).&amp;lt;/td&amp;gt;&lt;br /&gt;
    &amp;lt;/tr&amp;gt;&lt;br /&gt;
    &amp;lt;tr&amp;gt;&lt;br /&gt;
      &amp;lt;td valign=&amp;quot;top&amp;quot;&amp;gt;&amp;lt;a name=&amp;quot;desc_use_gravatar&amp;quot;&amp;gt;use_gravatar&amp;lt;/a&amp;gt;&amp;lt;/td&amp;gt;&lt;br /&gt;
      &amp;lt;td valign=&amp;quot;top&amp;quot;&amp;gt;false&amp;lt;/td&amp;gt;&lt;br /&gt;
      &amp;lt;td valign=&amp;quot;top&amp;quot;&amp;gt;If enabled (set to &amp;lt;tt&amp;gt;true&amp;lt;/tt&amp;gt;), a user's avatar image&lt;br /&gt;
        will be requested from &amp;lt;a href=&amp;quot;http://gravatar.com/&amp;quot;&amp;gt;gravatar.com&amp;lt;/a&amp;gt;&lt;br /&gt;
        if the user didn't upload a user photo (i.e. an uploaded photo always&lt;br /&gt;
        takes priority).&amp;lt;br&amp;gt;&lt;br /&gt;
        Please note that this option may slow down your site on pages that&lt;br /&gt;
        display a lot of userphotos for different users (e.g. forum threads).&amp;lt;/td&amp;gt;&lt;br /&gt;
    &amp;lt;/tr&amp;gt;&lt;br /&gt;
    &amp;lt;tr&amp;gt;&lt;br /&gt;
      &amp;lt;td valign=&amp;quot;top&amp;quot;&amp;gt;&amp;lt;a name=&amp;quot;desc_gravatar_rating&amp;quot;&amp;gt;gravatar_rating&amp;lt;/a&amp;gt;&amp;lt;/td&amp;gt;&lt;br /&gt;
      &amp;lt;td valign=&amp;quot;top&amp;quot;&amp;gt;&amp;lt;i&amp;gt;(commented out)&amp;lt;/i&amp;gt;&amp;lt;/td&amp;gt;&lt;br /&gt;
      &amp;lt;td valign=&amp;quot;top&amp;quot;&amp;gt;Avatars submitted to gravatar.com are &amp;lt;a href=&amp;quot;http://gravatar.com/rating.php&amp;quot;&amp;gt;rated&amp;lt;/a&amp;gt;&lt;br /&gt;
        with the rating system used for movies (in the U.S.), i.e. the letters&lt;br /&gt;
        G, PG, R, or X. This option will let you chose the &amp;lt;em&amp;gt;maximum&amp;lt;/em&amp;gt;&lt;br /&gt;
        allowed rating for an avatar. For example, a max. rating of R will make&lt;br /&gt;
        sure that no X-rated avatars will be displayed on your site (only G, PG,&lt;br /&gt;
        and R).&amp;lt;/td&amp;gt;&lt;br /&gt;
    &amp;lt;/tr&amp;gt;&lt;br /&gt;
    &amp;lt;tr&amp;gt;&lt;br /&gt;
      &amp;lt;td valign=&amp;quot;top&amp;quot;&amp;gt;&amp;lt;a name=&amp;quot;desc_force_photo_width&amp;quot;&amp;gt;force_photo_width&amp;lt;/a&amp;gt;&amp;lt;/td&amp;gt;&lt;br /&gt;
      &amp;lt;td valign=&amp;quot;top&amp;quot;&amp;gt;&amp;lt;i&amp;gt;(commented out)&amp;lt;/i&amp;gt;&amp;lt;/td&amp;gt;&lt;br /&gt;
      &amp;lt;td valign=&amp;quot;top&amp;quot;&amp;gt;This option, when enabled, will only apply when &amp;lt;em&amp;gt;displaying&amp;lt;/em&amp;gt;&lt;br /&gt;
        a user photo. The &amp;lt;code&amp;gt;&amp;amp;lt;img&amp;amp;gt;&amp;lt;/code&amp;gt; tag for the user photo will&lt;br /&gt;
        be emitted with a max. width, as specified by this option. This means&lt;br /&gt;
        that the actual photo can still be larger, but will only be displayed&lt;br /&gt;
        smaller. This is useful for cases where you don't want oddly shaped user&lt;br /&gt;
        photos to break your page's layout (e.g. in a forum).&amp;lt;/td&amp;gt;&lt;br /&gt;
    &amp;lt;/tr&amp;gt;&lt;br /&gt;
    &amp;lt;tr&amp;gt;&lt;br /&gt;
      &amp;lt;td valign=&amp;quot;top&amp;quot;&amp;gt;&amp;lt;a name=&amp;quot;desc_default_photo&amp;quot;&amp;gt;default_photo&amp;lt;/a&amp;gt;&amp;lt;/td&amp;gt;&lt;br /&gt;
      &amp;lt;td valign=&amp;quot;top&amp;quot;&amp;gt;&amp;lt;i&amp;gt;(commented out)&amp;lt;/i&amp;gt;&amp;lt;/td&amp;gt;&lt;br /&gt;
      &amp;lt;td valign=&amp;quot;top&amp;quot;&amp;gt;When enabled, this option should point to an image (full&lt;br /&gt;
        URL required!) that should be displayed for users without a user photo.&lt;br /&gt;
        When this option is not set and a user does not have a user photo (or an&lt;br /&gt;
        avatar) then Geeklog will simply not display anything.&amp;lt;/td&amp;gt;&lt;br /&gt;
    &amp;lt;/tr&amp;gt;&lt;br /&gt;
  &amp;lt;/tbody&amp;gt;&lt;br /&gt;
&amp;lt;/table&amp;gt;&lt;br /&gt;
&amp;lt;h3&amp;gt;&amp;lt;a name=&amp;quot;rdf&amp;quot;&amp;gt;Syndication Settings&amp;lt;/a&amp;gt;&amp;lt;/h3&amp;gt;&lt;br /&gt;
&amp;lt;p&amp;gt;Geeklog can export its headlines to a news feed in various formats (RSS, RDF,&lt;br /&gt;
and Atom). This will let you share your news with other sites (Hint: Create a&lt;br /&gt;
Portal block from Geeklog's Block menu to import news feeds from other sites).&amp;lt;/p&amp;gt;&lt;br /&gt;
&amp;lt;p&amp;gt;Starting with Geeklog 1.3.9, feeds can be created and configured from&lt;br /&gt;
Geeklog's Admin menu (&amp;amp;quot;Content Syndication&amp;amp;quot;). The following settings&lt;br /&gt;
will only be used as the &amp;lt;em&amp;gt;default settings&amp;lt;/em&amp;gt; for any new feeds that you&lt;br /&gt;
create from the admin panel.&amp;lt;/p&amp;gt;&lt;br /&gt;
&amp;lt;table border=&amp;quot;1&amp;quot; width=&amp;quot;100%&amp;quot;&amp;gt;&lt;br /&gt;
  &amp;lt;tbody&amp;gt;&lt;br /&gt;
    &amp;lt;tr&amp;gt;&lt;br /&gt;
      &amp;lt;th width=&amp;quot;8%&amp;quot;&amp;gt;Variable&amp;lt;/th&amp;gt;&lt;br /&gt;
      &amp;lt;th width=&amp;quot;29%&amp;quot;&amp;gt;Default Value&amp;lt;/th&amp;gt;&lt;br /&gt;
      &amp;lt;th width=&amp;quot;63%&amp;quot;&amp;gt;Description&amp;lt;/th&amp;gt;&lt;br /&gt;
    &amp;lt;/tr&amp;gt;&lt;br /&gt;
    &amp;lt;tr&amp;gt;&lt;br /&gt;
      &amp;lt;td valign=&amp;quot;top&amp;quot;&amp;gt;&amp;lt;a name=&amp;quot;desc_backend&amp;quot;&amp;gt;backend&amp;lt;/a&amp;gt;&amp;lt;/td&amp;gt;&lt;br /&gt;
      &amp;lt;td valign=&amp;quot;top&amp;quot;&amp;gt;1&amp;lt;/td&amp;gt;&lt;br /&gt;
      &amp;lt;td valign=&amp;quot;top&amp;quot;&amp;gt;Create a feed file for the stories in rdf_file (0=no,&lt;br /&gt;
        1=yes)&amp;lt;/td&amp;gt;&lt;br /&gt;
    &amp;lt;/tr&amp;gt;&lt;br /&gt;
    &amp;lt;tr&amp;gt;&lt;br /&gt;
      &amp;lt;td valign=&amp;quot;top&amp;quot;&amp;gt;&amp;lt;a name=&amp;quot;desc_rdf_file&amp;quot;&amp;gt;rdf_file&amp;lt;/a&amp;gt;&amp;lt;/td&amp;gt;&lt;br /&gt;
      &amp;lt;td valign=&amp;quot;top&amp;quot;&amp;gt;HTML path with &amp;amp;quot;/backend/geeklog.rss&amp;amp;quot; suffix&amp;lt;/td&amp;gt;&lt;br /&gt;
      &amp;lt;td valign=&amp;quot;top&amp;quot;&amp;gt;File system path for the feed file. This file allows you&lt;br /&gt;
        to share your site's headlines with others&amp;lt;/td&amp;gt;&lt;br /&gt;
    &amp;lt;/tr&amp;gt;&lt;br /&gt;
    &amp;lt;tr&amp;gt;&lt;br /&gt;
      &amp;lt;td valign=&amp;quot;top&amp;quot;&amp;gt;&amp;lt;a name=&amp;quot;desc_rdf_language&amp;quot;&amp;gt;rdf_language&amp;lt;/a&amp;gt;&amp;lt;/td&amp;gt;&lt;br /&gt;
      &amp;lt;td valign=&amp;quot;top&amp;quot;&amp;gt;en-gb&amp;lt;/td&amp;gt;&lt;br /&gt;
      &amp;lt;td valign=&amp;quot;top&amp;quot;&amp;gt;Value for the feed's language tag. Depending on your&lt;br /&gt;
        site's language and operating system, this may differ from the language&lt;br /&gt;
        setting in the locale (see above).&amp;lt;br&amp;gt;&lt;br /&gt;
        &amp;lt;strong&amp;gt;Example:&amp;lt;/strong&amp;gt; The PHP locale setting for German is 'de_DE'&lt;br /&gt;
        while the correct language setting for a German RSS feed would be&lt;br /&gt;
        'de-DE' (note the dash instead of the underscore).&amp;lt;/td&amp;gt;&lt;br /&gt;
    &amp;lt;/tr&amp;gt;&lt;br /&gt;
    &amp;lt;tr&amp;gt;&lt;br /&gt;
      &amp;lt;td valign=&amp;quot;top&amp;quot;&amp;gt;&amp;lt;a name=&amp;quot;desc_rdf_limit&amp;quot;&amp;gt;rdf_limit&amp;lt;/a&amp;gt;&amp;lt;/td&amp;gt;&lt;br /&gt;
      &amp;lt;td valign=&amp;quot;top&amp;quot;&amp;gt;10&amp;lt;/td&amp;gt;&lt;br /&gt;
      &amp;lt;td valign=&amp;quot;top&amp;quot;&amp;gt;Limit the number of stories to export to the news feed.&lt;br /&gt;
        If the value for this setting is a number, the feed will hold this many&lt;br /&gt;
        stories. If the number is followed by a lower-case 'h' (e.g. 24h) it&lt;br /&gt;
        denotes the number of hours from which to chose the stories.&amp;lt;/td&amp;gt;&lt;br /&gt;
    &amp;lt;/tr&amp;gt;&lt;br /&gt;
    &amp;lt;tr&amp;gt;&lt;br /&gt;
      &amp;lt;td valign=&amp;quot;top&amp;quot;&amp;gt;&amp;lt;a name=&amp;quot;desc_rdf_storytext&amp;quot;&amp;gt;rdf_storytext&amp;lt;/a&amp;gt;&amp;lt;/td&amp;gt;&lt;br /&gt;
      &amp;lt;td valign=&amp;quot;top&amp;quot;&amp;gt;0&amp;lt;/td&amp;gt;&lt;br /&gt;
      &amp;lt;td valign=&amp;quot;top&amp;quot;&amp;gt;If this value is 1, then the entire introtext of the&lt;br /&gt;
        stories will be included in the news feed. Any number greater than 1&lt;br /&gt;
        limits the introtext to that many characters (e.g. a value of 80 would&lt;br /&gt;
        only include the first 80 characters from the introtext in the feed). If&lt;br /&gt;
        set to 0, the introtext is not included in the feed.&amp;lt;/td&amp;gt;&lt;br /&gt;
    &amp;lt;/tr&amp;gt;&lt;br /&gt;
    &amp;lt;tr&amp;gt;&lt;br /&gt;
      &amp;lt;td valign=&amp;quot;top&amp;quot;&amp;gt;&amp;lt;a name=&amp;quot;desc_syndication_max_headlines&amp;quot;&amp;gt;syndication_max_headlines&amp;lt;/a&amp;gt;&amp;lt;/td&amp;gt;&lt;br /&gt;
      &amp;lt;td valign=&amp;quot;top&amp;quot;&amp;gt;0&amp;lt;/td&amp;gt;&lt;br /&gt;
      &amp;lt;td valign=&amp;quot;top&amp;quot;&amp;gt;Upper limit for the max. number of headlines when &amp;lt;em&amp;gt;importing&amp;lt;/em&amp;gt;&lt;br /&gt;
        a feed (into a portal block). The limit can also be set for each&lt;br /&gt;
        individual portal block in the block menu.&amp;lt;br&amp;gt;&lt;br /&gt;
        When set to 0, all headlines are imported.&amp;lt;/td&amp;gt;&lt;br /&gt;
    &amp;lt;/tr&amp;gt;&lt;br /&gt;
  &amp;lt;/tbody&amp;gt;&lt;br /&gt;
&amp;lt;/table&amp;gt;&lt;br /&gt;
&amp;lt;h3&amp;gt;&amp;lt;a name=&amp;quot;content&amp;quot;&amp;gt;Content Control Settings&amp;lt;/a&amp;gt;&amp;lt;/h3&amp;gt;&lt;br /&gt;
&amp;lt;table border=&amp;quot;1&amp;quot; width=&amp;quot;100%&amp;quot;&amp;gt;&lt;br /&gt;
  &amp;lt;tbody&amp;gt;&lt;br /&gt;
    &amp;lt;tr&amp;gt;&lt;br /&gt;
      &amp;lt;th width=&amp;quot;8%&amp;quot;&amp;gt;Variable&amp;lt;/th&amp;gt;&lt;br /&gt;
      &amp;lt;th width=&amp;quot;29%&amp;quot;&amp;gt;Default Value&amp;lt;/th&amp;gt;&lt;br /&gt;
      &amp;lt;th width=&amp;quot;63%&amp;quot;&amp;gt;Description&amp;lt;/th&amp;gt;&lt;br /&gt;
    &amp;lt;/tr&amp;gt;&lt;br /&gt;
    &amp;lt;tr&amp;gt;&lt;br /&gt;
      &amp;lt;td valign=&amp;quot;top&amp;quot;&amp;gt;&amp;lt;a name=&amp;quot;desc_user_html&amp;quot;&amp;gt;user_html&amp;lt;/a&amp;gt;&amp;lt;/td&amp;gt;&lt;br /&gt;
      &amp;lt;td valign=&amp;quot;top&amp;quot;&amp;gt;&amp;amp;lt;p&amp;amp;gt;, &amp;amp;lt;b&amp;amp;gt;, &amp;amp;lt;i&amp;amp;gt;, &amp;amp;lt;a&amp;amp;gt;, &amp;amp;lt;em&amp;amp;gt;,&lt;br /&gt;
        &amp;amp;lt;br&amp;amp;gt;, &amp;amp;lt;tt&amp;amp;gt;, &amp;amp;lt;hr&amp;amp;gt;, &amp;amp;lt;ol&amp;amp;gt;, &amp;amp;lt;ul&amp;amp;gt;, &amp;amp;lt;li&amp;amp;gt;,&lt;br /&gt;
        &amp;amp;lt;code&amp;amp;gt;, &amp;amp;lt;pre&amp;amp;gt;&amp;lt;/td&amp;gt;&lt;br /&gt;
      &amp;lt;td valign=&amp;quot;top&amp;quot;&amp;gt;HTML tags and attributes that normal users are allowed to&lt;br /&gt;
        use in story submissions and comments.&amp;lt;/td&amp;gt;&lt;br /&gt;
    &amp;lt;/tr&amp;gt;&lt;br /&gt;
    &amp;lt;tr&amp;gt;&lt;br /&gt;
      &amp;lt;td valign=&amp;quot;top&amp;quot;&amp;gt;&amp;lt;a name=&amp;quot;desc_admin_html&amp;quot;&amp;gt;admin_html&amp;lt;/a&amp;gt;&amp;lt;/td&amp;gt;&lt;br /&gt;
      &amp;lt;td valign=&amp;quot;top&amp;quot;&amp;gt;additional HTML tags, e.g. for tables&amp;lt;/td&amp;gt;&lt;br /&gt;
      &amp;lt;td valign=&amp;quot;top&amp;quot;&amp;gt;HTML tags and attributes that admin users are allowed to&lt;br /&gt;
        use (in addition to those from user_html). Redefining a tag with&lt;br /&gt;
        additional attributes will overwrite the definition from user_html.&amp;lt;/td&amp;gt;&lt;br /&gt;
    &amp;lt;/tr&amp;gt;&lt;br /&gt;
    &amp;lt;tr&amp;gt;&lt;br /&gt;
      &amp;lt;td valign=&amp;quot;top&amp;quot;&amp;gt;&amp;lt;a name=&amp;quot;desc_allowed_protocols&amp;quot;&amp;gt;allowed_protocols&amp;lt;/a&amp;gt;&amp;lt;/td&amp;gt;&lt;br /&gt;
      &amp;lt;td valign=&amp;quot;top&amp;quot;&amp;gt;array ('http', 'https', 'ftp');&amp;lt;/td&amp;gt;&lt;br /&gt;
      &amp;lt;td valign=&amp;quot;top&amp;quot;&amp;gt;Defines which protocols are allowed in links (i.e. HTML &amp;lt;code&amp;gt;&amp;amp;lt;a&amp;amp;gt;&amp;lt;/code&amp;gt;&lt;br /&gt;
        tags).&amp;lt;/td&amp;gt;&lt;br /&gt;
    &amp;lt;/tr&amp;gt;&lt;br /&gt;
    &amp;lt;tr&amp;gt;&lt;br /&gt;
      &amp;lt;td valign=&amp;quot;top&amp;quot;&amp;gt;&amp;lt;a name=&amp;quot;desc_skip_html_filter_for_root&amp;quot;&amp;gt;skip_html_filter_for_root&amp;lt;/a&amp;gt;&amp;lt;/td&amp;gt;&lt;br /&gt;
      &amp;lt;td valign=&amp;quot;top&amp;quot;&amp;gt;0&amp;lt;/td&amp;gt;&lt;br /&gt;
      &amp;lt;td valign=&amp;quot;top&amp;quot;&amp;gt;When set to 1, this will allow members of the Root group&lt;br /&gt;
        to use &amp;lt;em&amp;gt;all&amp;lt;/em&amp;gt; HTML in their posts. &amp;lt;strong&amp;gt;Use at your own risk!&amp;lt;/strong&amp;gt;&amp;lt;/td&amp;gt;&lt;br /&gt;
    &amp;lt;/tr&amp;gt;&lt;br /&gt;
    &amp;lt;tr&amp;gt;&lt;br /&gt;
      &amp;lt;td valign=&amp;quot;top&amp;quot;&amp;gt;&amp;lt;a name=&amp;quot;desc_disable_autolinks&amp;quot;&amp;gt;disable_autolinks&amp;lt;/a&amp;gt;&amp;lt;/td&amp;gt;&lt;br /&gt;
      &amp;lt;td valign=&amp;quot;top&amp;quot;&amp;gt;0&amp;lt;/td&amp;gt;&lt;br /&gt;
      &amp;lt;td valign=&amp;quot;top&amp;quot;&amp;gt;If set to 1, disables the autolinks. I.e. links using the&lt;br /&gt;
        [story:] etc. syntax are not interpreted any more.&amp;lt;/td&amp;gt;&lt;br /&gt;
    &amp;lt;/tr&amp;gt;&lt;br /&gt;
    &amp;lt;tr&amp;gt;&lt;br /&gt;
      &amp;lt;td valign=&amp;quot;top&amp;quot;&amp;gt;&amp;lt;a name=&amp;quot;desc_censormode&amp;quot;&amp;gt;censormode&amp;lt;/a&amp;gt;&amp;lt;/td&amp;gt;&lt;br /&gt;
      &amp;lt;td valign=&amp;quot;top&amp;quot;&amp;gt;1&amp;lt;/td&amp;gt;&lt;br /&gt;
      &amp;lt;td valign=&amp;quot;top&amp;quot;&amp;gt;Censor submissions and comments (0=no, 1=yes)&amp;lt;/td&amp;gt;&lt;br /&gt;
    &amp;lt;/tr&amp;gt;&lt;br /&gt;
    &amp;lt;tr&amp;gt;&lt;br /&gt;
      &amp;lt;td valign=&amp;quot;top&amp;quot;&amp;gt;&amp;lt;a name=&amp;quot;desc_censorreplace&amp;quot;&amp;gt;censorreplace&amp;lt;/a&amp;gt;&amp;lt;/td&amp;gt;&lt;br /&gt;
      &amp;lt;td valign=&amp;quot;top&amp;quot;&amp;gt;*censored*&amp;lt;/td&amp;gt;&lt;br /&gt;
      &amp;lt;td valign=&amp;quot;top&amp;quot;&amp;gt;Text to replace a censored word with&amp;lt;/td&amp;gt;&lt;br /&gt;
    &amp;lt;/tr&amp;gt;&lt;br /&gt;
    &amp;lt;tr&amp;gt;&lt;br /&gt;
      &amp;lt;td valign=&amp;quot;top&amp;quot;&amp;gt;&amp;lt;a name=&amp;quot;desc_censorlist&amp;quot;&amp;gt;censorlist&amp;lt;/a&amp;gt;&amp;lt;/td&amp;gt;&lt;br /&gt;
      &amp;lt;td valign=&amp;quot;top&amp;quot;&amp;gt;array(&amp;lt;i&amp;gt;a list of &amp;amp;quot;bad&amp;amp;quot; words goes here ...&amp;lt;/i&amp;gt;)&amp;lt;/td&amp;gt;&lt;br /&gt;
      &amp;lt;td valign=&amp;quot;top&amp;quot;&amp;gt;An array of censored words&amp;lt;/td&amp;gt;&lt;br /&gt;
    &amp;lt;/tr&amp;gt;&lt;br /&gt;
  &amp;lt;/tbody&amp;gt;&lt;br /&gt;
&amp;lt;/table&amp;gt;&lt;br /&gt;
&amp;lt;h3&amp;gt;&amp;lt;a name=&amp;quot;url-rewrite&amp;quot;&amp;gt;URL Rewriting&amp;lt;/a&amp;gt;&amp;lt;/h3&amp;gt;&lt;br /&gt;
&amp;lt;p&amp;gt;Geeklog includes a simple but useful URL rewriting feature which can help&lt;br /&gt;
make your site more crawler friendly (i.e. the URLs of your site are more likely&lt;br /&gt;
to be picked up by the search engine's indexing bots). This feature is supported&lt;br /&gt;
for URLs to stories, static pages, the article directory, and links.&amp;lt;/p&amp;gt;&lt;br /&gt;
&amp;lt;p&amp;gt;URL rewriting means that your URLs will look like this&amp;lt;/p&amp;gt;&lt;br /&gt;
&amp;lt;p align=&amp;quot;center&amp;quot;&amp;gt;&amp;lt;tt&amp;gt;http://www.geeklog.net/article.php/20021022234959146&amp;lt;/tt&amp;gt;&amp;lt;/p&amp;gt;&lt;br /&gt;
&amp;lt;p&amp;gt;instead of like this&amp;lt;/p&amp;gt;&lt;br /&gt;
&amp;lt;p align=&amp;quot;center&amp;quot;&amp;gt;&amp;lt;tt&amp;gt;http://www.geeklog.net/article.php?story=20021022234959146&amp;lt;/tt&amp;gt;&amp;lt;/p&amp;gt;&lt;br /&gt;
&amp;lt;p&amp;gt;While some search engines will pick up the second form, Google seems to&lt;br /&gt;
prefer the first format and completely ignores the second format.&amp;lt;/p&amp;gt;&lt;br /&gt;
&amp;lt;p&amp;gt;&amp;lt;strong&amp;gt;Note:&amp;lt;/strong&amp;gt; This feature may not work with all web servers. It is&lt;br /&gt;
known to work with Apache (all versions) and known &amp;lt;em&amp;gt;not&amp;lt;/em&amp;gt; to work with IIS&lt;br /&gt;
(at least some versions). Please try it out before you go public with your site.&amp;lt;/p&amp;gt;&lt;br /&gt;
&amp;lt;table border=&amp;quot;1&amp;quot; width=&amp;quot;100%&amp;quot;&amp;gt;&lt;br /&gt;
  &amp;lt;tbody&amp;gt;&lt;br /&gt;
    &amp;lt;tr&amp;gt;&lt;br /&gt;
      &amp;lt;th width=&amp;quot;8%&amp;quot;&amp;gt;Variable&amp;lt;/th&amp;gt;&lt;br /&gt;
      &amp;lt;th width=&amp;quot;29%&amp;quot;&amp;gt;Default Value&amp;lt;/th&amp;gt;&lt;br /&gt;
      &amp;lt;th width=&amp;quot;63%&amp;quot;&amp;gt;Description&amp;lt;/th&amp;gt;&lt;br /&gt;
    &amp;lt;/tr&amp;gt;&lt;br /&gt;
    &amp;lt;tr&amp;gt;&lt;br /&gt;
      &amp;lt;td valign=&amp;quot;top&amp;quot;&amp;gt;&amp;lt;a name=&amp;quot;desc_url_rewrite&amp;quot;&amp;gt;url_rewrite&amp;lt;/a&amp;gt;&amp;lt;/td&amp;gt;&lt;br /&gt;
      &amp;lt;td valign=&amp;quot;top&amp;quot;&amp;gt;false&amp;lt;/td&amp;gt;&lt;br /&gt;
      &amp;lt;td valign=&amp;quot;top&amp;quot;&amp;gt;Enable (true) or disable (false) URL rewriting.&amp;lt;/td&amp;gt;&lt;br /&gt;
    &amp;lt;/tr&amp;gt;&lt;br /&gt;
  &amp;lt;/tbody&amp;gt;&lt;br /&gt;
&amp;lt;/table&amp;gt;&lt;br /&gt;
&amp;lt;h3&amp;gt;&amp;lt;a name=&amp;quot;unused&amp;quot;&amp;gt;Unused Settings&amp;lt;/a&amp;gt;&amp;lt;/h3&amp;gt;&lt;br /&gt;
&amp;lt;p&amp;gt;This is a list of &amp;lt;tt&amp;gt;config.php&amp;lt;/tt&amp;gt; options that are currently unused, e.g.&lt;br /&gt;
because the feature they were intended for has not been implemented yet.&amp;lt;/p&amp;gt;&lt;br /&gt;
&amp;lt;table border=&amp;quot;1&amp;quot; width=&amp;quot;100%&amp;quot;&amp;gt;&lt;br /&gt;
  &amp;lt;tbody&amp;gt;&lt;br /&gt;
    &amp;lt;tr&amp;gt;&lt;br /&gt;
      &amp;lt;th width=&amp;quot;8%&amp;quot;&amp;gt;Variable&amp;lt;/th&amp;gt;&lt;br /&gt;
      &amp;lt;th width=&amp;quot;29%&amp;quot;&amp;gt;Default Value&amp;lt;/th&amp;gt;&lt;br /&gt;
      &amp;lt;th width=&amp;quot;63%&amp;quot;&amp;gt;Description&amp;lt;/th&amp;gt;&lt;br /&gt;
    &amp;lt;/tr&amp;gt;&lt;br /&gt;
    &amp;lt;tr&amp;gt;&lt;br /&gt;
      &amp;lt;td valign=&amp;quot;top&amp;quot;&amp;gt;&amp;lt;a name=&amp;quot;desc_ostype&amp;quot;&amp;gt;ostype&amp;lt;/a&amp;gt;&amp;lt;/td&amp;gt;&lt;br /&gt;
      &amp;lt;td valign=&amp;quot;top&amp;quot;&amp;gt;&amp;lt;code&amp;gt;PHP_OS&amp;lt;/code&amp;gt;&amp;lt;/td&amp;gt;&lt;br /&gt;
      &amp;lt;td valign=&amp;quot;top&amp;quot;&amp;gt;Identifies the operating system running on your webserver.&amp;lt;/td&amp;gt;&lt;br /&gt;
    &amp;lt;/tr&amp;gt;&lt;br /&gt;
    &amp;lt;tr&amp;gt;&lt;br /&gt;
      &amp;lt;td valign=&amp;quot;top&amp;quot;&amp;gt;&amp;lt;a name=&amp;quot;desc_pdf_enabled&amp;quot;&amp;gt;pdf_enabled&amp;lt;/a&amp;gt;&amp;lt;/td&amp;gt;&lt;br /&gt;
      &amp;lt;td valign=&amp;quot;top&amp;quot;&amp;gt;0&amp;lt;/td&amp;gt;&lt;br /&gt;
      &amp;lt;td valign=&amp;quot;top&amp;quot;&amp;gt;PDF conversion of stories has not been fully implemented&lt;br /&gt;
        yet. Leave this option as is to prevent unfinished options from showing&lt;br /&gt;
        up on your site.&amp;lt;/td&amp;gt;&lt;br /&gt;
    &amp;lt;/tr&amp;gt;&lt;br /&gt;
  &amp;lt;/tbody&amp;gt;&lt;br /&gt;
&amp;lt;/table&amp;gt;&lt;br /&gt;
&amp;lt;h2&amp;gt;&amp;lt;a name=&amp;quot;Localization&amp;quot;&amp;gt;Localization&amp;lt;/a&amp;gt;&amp;lt;/h2&amp;gt;&lt;br /&gt;
&amp;lt;p&amp;gt;Localizing GeekLog is fairly easy. All strings are contained in a language&lt;br /&gt;
file. The default file that ships with the tarball is english.php. People&lt;br /&gt;
interested in translating Geeklog to other languages are encouraged to join the &amp;lt;a href=&amp;quot;http://lists.geeklog.net/listinfo/geeklog-translations&amp;quot;&amp;gt;geeklog-translations&amp;lt;/a&amp;gt;&lt;br /&gt;
mailing list. All important information concerning translating Geeklog will be&lt;br /&gt;
posted there.&amp;lt;/p&amp;gt;&lt;br /&gt;
&amp;lt;h3&amp;gt;&amp;lt;a name=&amp;quot;date_formats&amp;quot;&amp;gt;Locale and Date Formats&amp;lt;/a&amp;gt;&amp;lt;/h3&amp;gt;&lt;br /&gt;
&amp;lt;p&amp;gt;You can set the locale and date format in the config.php file. To set the&lt;br /&gt;
locale, set the variable to the proper string or if you leave it blank it will&lt;br /&gt;
pull the default locale from the operating system. The date formats are handled&lt;br /&gt;
by your locale. Isn't that smart? Locale names are OS dependent. On most UNIX&lt;br /&gt;
hosts, you can find locale codes in the &amp;lt;i&amp;gt;/usr/share/locale/locale.alias&amp;lt;/i&amp;gt;&lt;br /&gt;
file and on some systems the command &amp;lt;i&amp;gt;locale -a&amp;lt;/i&amp;gt; will display all available&lt;br /&gt;
locales on a system. If a locale doesn't exist you can create it using the &amp;lt;i&amp;gt;localedef&amp;lt;/i&amp;gt;&lt;br /&gt;
command.&amp;lt;/p&amp;gt;&lt;br /&gt;
&amp;lt;p&amp;gt;More info on locale: &amp;lt;a href=&amp;quot;http://www.opengroup.org/onlinepubs/7908799/xbd/locale.html&amp;quot;&amp;gt;http://www.opengroup.org/onlinepubs/7908799/xbd/locale.html&amp;lt;/a&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
More info on localdef: &amp;lt;a href=&amp;quot;http://www.opengroup.org/onlinepubs/7908799/xcu/localedef.html&amp;quot;&amp;gt;http://www.opengroup.org/onlinepubs/7908799/xcu/localedef.html&amp;lt;/a&amp;gt;&amp;lt;/p&amp;gt;&lt;br /&gt;
&amp;lt;h3&amp;gt;Date Format Syntax&amp;lt;/h3&amp;gt;&lt;br /&gt;
&amp;lt;ul&amp;gt;&lt;br /&gt;
  &amp;lt;li&amp;gt;&amp;lt;tt&amp;gt;%a - abbreviated weekday name according to the current locale&amp;lt;/tt&amp;gt;&amp;lt;/li&amp;gt;&lt;br /&gt;
  &amp;lt;li&amp;gt;&amp;lt;tt&amp;gt;%A - full weekday name according to the current locale&amp;lt;/tt&amp;gt;&amp;lt;/li&amp;gt;&lt;br /&gt;
  &amp;lt;li&amp;gt;&amp;lt;tt&amp;gt;%b - abbreviated month name according to the current locale&amp;lt;/tt&amp;gt;&amp;lt;/li&amp;gt;&lt;br /&gt;
  &amp;lt;li&amp;gt;&amp;lt;tt&amp;gt;%B - full month name according to the current locale&amp;lt;/tt&amp;gt;&amp;lt;/li&amp;gt;&lt;br /&gt;
  &amp;lt;li&amp;gt;&amp;lt;tt&amp;gt;%c - preferred date and time representation for the current locale&amp;lt;/tt&amp;gt;&amp;lt;/li&amp;gt;&lt;br /&gt;
  &amp;lt;li&amp;gt;&amp;lt;tt&amp;gt;%C - century number (the year divided by 100 and truncated to an&lt;br /&gt;
    integer, range 00 to 99)&amp;lt;/tt&amp;gt;&amp;lt;/li&amp;gt;&lt;br /&gt;
  &amp;lt;li&amp;gt;&amp;lt;tt&amp;gt;%d - day of the month as a decimal number (range 00 to 31)&amp;lt;/tt&amp;gt;&amp;lt;/li&amp;gt;&lt;br /&gt;
  &amp;lt;li&amp;gt;&amp;lt;tt&amp;gt;%D - same as %m/%d/%y&amp;lt;/tt&amp;gt;&amp;lt;/li&amp;gt;&lt;br /&gt;
  &amp;lt;li&amp;gt;&amp;lt;tt&amp;gt;%e - day of the month as a decimal number, a single digit is preceded&lt;br /&gt;
    by a space (range ' 1' to '31')&amp;lt;/tt&amp;gt;&amp;lt;/li&amp;gt;&lt;br /&gt;
  &amp;lt;li&amp;gt;&amp;lt;tt&amp;gt;%h - same as %b&amp;lt;/tt&amp;gt;&amp;lt;/li&amp;gt;&lt;br /&gt;
  &amp;lt;li&amp;gt;&amp;lt;tt&amp;gt;%H - hour as a decimal number using a 24-hour clock (range 00 to 23)&amp;lt;/tt&amp;gt;&amp;lt;/li&amp;gt;&lt;br /&gt;
  &amp;lt;li&amp;gt;&amp;lt;tt&amp;gt;%I - hour as a decimal number using a 12-hour clock (range 01 to 12)&amp;lt;/tt&amp;gt;&amp;lt;/li&amp;gt;&lt;br /&gt;
  &amp;lt;li&amp;gt;&amp;lt;tt&amp;gt;%j - day of the year as a decimal number (range 001 to 366)&amp;lt;/tt&amp;gt;&amp;lt;/li&amp;gt;&lt;br /&gt;
  &amp;lt;li&amp;gt;&amp;lt;tt&amp;gt;%m - month as a decimal number (range 1 to 12)&amp;lt;/tt&amp;gt;&amp;lt;/li&amp;gt;&lt;br /&gt;
  &amp;lt;li&amp;gt;&amp;lt;tt&amp;gt;%M - minute as a decimal number&amp;lt;/tt&amp;gt;&amp;lt;/li&amp;gt;&lt;br /&gt;
  &amp;lt;li&amp;gt;&amp;lt;tt&amp;gt;%n - newline character&amp;lt;/tt&amp;gt;&amp;lt;/li&amp;gt;&lt;br /&gt;
  &amp;lt;li&amp;gt;&amp;lt;tt&amp;gt;%p - either `am' or `pm' according to the given time value, or the&lt;br /&gt;
    corresponding strings for the current locale&amp;lt;/tt&amp;gt;&amp;lt;/li&amp;gt;&lt;br /&gt;
  &amp;lt;li&amp;gt;&amp;lt;tt&amp;gt;%r - time in a.m. and p.m. notation&amp;lt;/tt&amp;gt;&amp;lt;/li&amp;gt;&lt;br /&gt;
  &amp;lt;li&amp;gt;&amp;lt;tt&amp;gt;%R - time in 24 hour notation&amp;lt;/tt&amp;gt;&amp;lt;/li&amp;gt;&lt;br /&gt;
  &amp;lt;li&amp;gt;&amp;lt;tt&amp;gt;%S - second as a decimal number&amp;lt;/tt&amp;gt;&amp;lt;/li&amp;gt;&lt;br /&gt;
  &amp;lt;li&amp;gt;&amp;lt;tt&amp;gt;%t - tab character&amp;lt;/tt&amp;gt;&amp;lt;/li&amp;gt;&lt;br /&gt;
  &amp;lt;li&amp;gt;&amp;lt;tt&amp;gt;%T - current time, equal to %H:%M:%S&amp;lt;/tt&amp;gt;&amp;lt;/li&amp;gt;&lt;br /&gt;
  &amp;lt;li&amp;gt;&amp;lt;tt&amp;gt;%u - weekday as a decimal number [1,7], with 1 representing Monday&amp;lt;/tt&amp;gt;&amp;lt;/li&amp;gt;&lt;br /&gt;
  &amp;lt;li&amp;gt;&amp;lt;tt&amp;gt;%U - week number of the current year as a decimal number, starting&lt;br /&gt;
    with the first Sunday as the first day of the first week&amp;lt;/tt&amp;gt;&amp;lt;/li&amp;gt;&lt;br /&gt;
  &amp;lt;li&amp;gt;&amp;lt;tt&amp;gt;%V - The ISO 8601:1988 week number of the current year as a decimal&lt;br /&gt;
    number, range 01 to 53, where week 1 is the first week that has at least 4&lt;br /&gt;
    days in the current year, and with Monday as the first day of the week.&amp;lt;/tt&amp;gt;&amp;lt;/li&amp;gt;&lt;br /&gt;
  &amp;lt;li&amp;gt;&amp;lt;tt&amp;gt;%W - week number of the current year as a decimal number, starting&lt;br /&gt;
    with the first Monday as the first day of the first week&amp;lt;/tt&amp;gt;&amp;lt;/li&amp;gt;&lt;br /&gt;
  &amp;lt;li&amp;gt;&amp;lt;tt&amp;gt;%w - day of the week as a decimal, Sunday being 0&amp;lt;/tt&amp;gt;&amp;lt;/li&amp;gt;&lt;br /&gt;
  &amp;lt;li&amp;gt;&amp;lt;tt&amp;gt;%x - preferred date representation for the current locale without the&lt;br /&gt;
    time&amp;lt;/tt&amp;gt;&amp;lt;/li&amp;gt;&lt;br /&gt;
  &amp;lt;li&amp;gt;&amp;lt;tt&amp;gt;%X - preferred time representation for the current locale without the&lt;br /&gt;
    date&amp;lt;/tt&amp;gt;&amp;lt;/li&amp;gt;&lt;br /&gt;
  &amp;lt;li&amp;gt;&amp;lt;tt&amp;gt;%y - year as a decimal number without a century (range 00 to 99)&amp;lt;/tt&amp;gt;&amp;lt;/li&amp;gt;&lt;br /&gt;
  &amp;lt;li&amp;gt;&amp;lt;tt&amp;gt;%Y - year as a decimal number including the century&amp;lt;/tt&amp;gt;&amp;lt;/li&amp;gt;&lt;br /&gt;
  &amp;lt;li&amp;gt;&amp;lt;tt&amp;gt;%Z - time zone or name or abbreviation&amp;lt;/tt&amp;gt;&amp;lt;/li&amp;gt;&lt;br /&gt;
  &amp;lt;li&amp;gt;&amp;lt;tt&amp;gt;%% - a literal `%' character&amp;lt;/tt&amp;gt;&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;/ul&amp;gt;&lt;/div&gt;</summary>
		<author><name>LWC</name></author>	</entry>

	<entry>
		<id>http://gwiki3.thatlinuxbox.com/index.php?title=Multilingual_Support&amp;diff=5618</id>
		<title>Multilingual Support</title>
		<link rel="alternate" type="text/html" href="http://gwiki3.thatlinuxbox.com/index.php?title=Multilingual_Support&amp;diff=5618"/>
				<updated>2009-10-31T00:28:40Z</updated>
		
		<summary type="html">&lt;p&gt;LWC: Fixed English&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Background ==&lt;br /&gt;
&lt;br /&gt;
The Geeklog language files have been translated into more than 25 languages - but that only means that you can have the user interface in one of those languages. For the actual site content (articles, static pages, ...), there was no support for multiple languages, which means that you either had to have everything in one language only or you ended up with all the different language versions of, e.g. an article, being displayed to anyone.&lt;br /&gt;
&lt;br /&gt;
Euan McKay then came up with a [http://heatherengineering.com/staticpages/index.php/multilingual-en first multilingual hack], which was later [http://www.geeklog.net/forum/viewtopic.php?showtopic=61999 built upon and generalized] by LWC.&lt;br /&gt;
&lt;br /&gt;
The multilingual support in Geeklog (as of version 1.4.1) is based on this earlier work by Euan and LWC.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== How it works ==&lt;br /&gt;
&lt;br /&gt;
The basic idea behind the multilingual support is to encode the language of an object into its ID. For example, for a story to encode it into the story ID, like so:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;http://www.example.com/article.php/introduction_en -- English version&lt;br /&gt;
http://www.example.com/article.php/introduction_de -- German version&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Now there is a way to identify the language of an object (article, topic, static page, ...) and it can be displayed (or not), based on the user's language preferences. It's also possible then to switch between the various languages in which an object exists in the database.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Setting it up ==&lt;br /&gt;
&lt;br /&gt;
=== Geeklog 1.4.1 ===&lt;br /&gt;
&lt;br /&gt;
In config.php, there is a new section to enable multilingual support and to define the list of supported languages:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;// Multilingual support&lt;br /&gt;
// (note that this section is commented out - remove the '/*' and '*/' lines&lt;br /&gt;
//  below to activate it and make sure you understand what it does)&lt;br /&gt;
/*&lt;br /&gt;
&lt;br /&gt;
// IMPORTANT!&lt;br /&gt;
// 1) Both the $_CONF['language_files'] and the $_CONF['languages'] arrays&lt;br /&gt;
//    (see below) must have the same number of elements.&lt;br /&gt;
// 2) The shortcuts used must be the same in both arrays.&lt;br /&gt;
// 3) All shortcuts must have the same length, e.g. 2 characters.&lt;br /&gt;
&lt;br /&gt;
// The shortcuts are to be used in IDs of objects that are multilingual&lt;br /&gt;
// aware, e.g. /article.php/introduction_en and /article.php/introduction_de&lt;br /&gt;
// for the English and German version of an introductory article.&lt;br /&gt;
&lt;br /&gt;
// Supported languages&lt;br /&gt;
// Maps a shortcut to a Geeklog language file (without the '.php' extension)&lt;br /&gt;
$_CONF['language_files'] = array (&lt;br /&gt;
    'en' =&amp;gt; 'english',&lt;br /&gt;
    'de' =&amp;gt; 'german_formal'&lt;br /&gt;
);&lt;br /&gt;
&lt;br /&gt;
// Display names of supported languages&lt;br /&gt;
// Maps the same shortcuts as above to a language name. The language names&lt;br /&gt;
// are used to let users switch languages, e.g. in a drop-down menu.&lt;br /&gt;
$_CONF['languages'] = array (&lt;br /&gt;
    'en' =&amp;gt; 'English',&lt;br /&gt;
    'de' =&amp;gt; 'Deutsch'&lt;br /&gt;
);&lt;br /&gt;
&lt;br /&gt;
*/&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
To enable multilingual support, the two arrays $_CONF['language_files'] and $_CONF['languages'] have to be defined. In the default config.php, they are commented out and, therefore, not defined.&lt;br /&gt;
&lt;br /&gt;
=== Geeklog 1.5.0 and later ===&lt;br /&gt;
&lt;br /&gt;
As of Geeklog 1.5.0, the &amp;lt;tt&amp;gt;config.php&amp;lt;/tt&amp;gt; file has been replaced with a web-based configuration that can be found under &amp;quot;Configuration&amp;quot; in the Admin's block. Under the &amp;quot;Languages and Locale&amp;quot; heading, you'll find two options:&lt;br /&gt;
* Language Files&lt;br /&gt;
* Languages&lt;br /&gt;
These two options are the equivalents of the &amp;lt;code&amp;gt;$_CONF['language_files']&amp;lt;/code&amp;gt; and &amp;lt;code&amp;gt;$_CONF['languages']&amp;lt;/code&amp;gt; arrays, as explained above. To use the multilingual feature, '''both''' of these options have to be enabled. Other than that, the two options work as described above.&lt;br /&gt;
&lt;br /&gt;
Note that in Geeklog 1.5.0, you can not easily disable multilingual support again (for a workaround, see [http://www.geeklog.net/forum/viewtopic.php?showtopic=83327 here]). As of Geeklog 1.5.1, there is a litte &amp;lt;tt&amp;gt;(X)&amp;lt;/tt&amp;gt; next to the options (once they're enabled). Click on the &amp;lt;tt&amp;gt;(X)&amp;lt;/tt&amp;gt; to disable the options again (remember that you need to disable both of them).&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== The shortcuts ===&lt;br /&gt;
&lt;br /&gt;
For each of the languages you intend to support, you will have to define a shortcut that will then be used in the IDs of the multilingual objects, as explained above.&lt;br /&gt;
&lt;br /&gt;
You can freely define these shortcuts, but it would make sense to set them in some relation to the language which they represent. From Geeklog's point of view, though, it doesn't matter whether the English language is represented by a shortcut 'en' or by 'peter'.&lt;br /&gt;
&lt;br /&gt;
Please note:&lt;br /&gt;
* All the shortcuts in both of the arrays have to be of the same length.&lt;br /&gt;
* The shortcut must be appended to the ''end'' of an object's ID and it must be preceded by an underscore '_' character.&lt;br /&gt;
* It's recommended that you use a language's ISO abbreviation ('en' for English, 'de' for German, etc.), either with or without the country appendix ('en-US'), as Geeklog will also try to determine a user's preferred language from their browser setting.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== The language files ===&lt;br /&gt;
&lt;br /&gt;
The $_CONF['language_files'] array defines which language files should represent which language. Note that Geeklog also uses the language file name for a user's language setting (in their preferences).&lt;br /&gt;
&lt;br /&gt;
It's recommended that you remove all the other language files, i.e. those for which you do not intend to have content in that particular language on your site.&lt;br /&gt;
&lt;br /&gt;
'''Note:''' Be careful when mixing languages that use different character sets (e.g. Russian and Japanese). You may want to switch to the UTF-8 versions of ''all'' language files for such a setup.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== The language names ===&lt;br /&gt;
&lt;br /&gt;
The $_CONF['languages'] array defines a set of display names for the supported languages. These names are used to let the user switch between the supported languages, e.g. from a drop-down menu.&lt;br /&gt;
&lt;br /&gt;
Most of the time, you'll want to use the native names of the languages, e.g. &amp;quot;Deutsch&amp;quot; instead of &amp;quot;German&amp;quot;, but that's only a convention.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Blocks ==&lt;br /&gt;
&lt;br /&gt;
Multilingual blocks are only supported as of Geeklog 1.5.1. The setup differs slightly from the setup for stories, topics, etc.&lt;br /&gt;
&lt;br /&gt;
Let's assume you want to create a multilingual &amp;quot;about this site&amp;quot; block and that your site is configured for two languages (say, English and German). For this setup you would then need ''three''(!) blocks. The block name serves as the ID and you would create blocks with the following names:&lt;br /&gt;
* about_en&lt;br /&gt;
* about_de&lt;br /&gt;
* about&lt;br /&gt;
The first two blocks would simply contain your content in English and German, respectively. Both blocks should be ''disabled''. The third block then serves as a placeholder for the actual block for the current language. Therefore, only this block (&amp;quot;about&amp;quot;, in our example) should be enabled. When the multilingual support is enabled, you will never see the contents of that block, as it will be replaced with the proper block for the current language, e.g. &amp;quot;about_en&amp;quot; for English.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Switching languages ==&lt;br /&gt;
&lt;br /&gt;
Registered users can always switch their preferred language by selecting another language in their preferences.&lt;br /&gt;
&lt;br /&gt;
To make things more convenient (and also allow anonymous users to switch the language), you can put a PHP block on your site. Geeklog provides a function phpblock_switch_language that will display a drop-down menu of all available languages (if you only have two languages defined, it will display a simple link to the other language instead).&lt;br /&gt;
&lt;br /&gt;
This function can also be called from the header.thtml template file of your theme, so that you can put it into your site's menu:&lt;br /&gt;
&amp;lt;pre&amp;gt;&amp;lt;?php print phpblock_switch_language(); ?&amp;gt;&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Technically, switching the language will set a cookie (with the selected language) and also update a user's language preference, if they're registered with the site.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Detecting the language ==&lt;br /&gt;
&lt;br /&gt;
When a user comes to a multilingual enabled site, Geeklog will check for the user's preference setting first (if it's a registered user), then for the language cookie, and if that couldn't be found, it tries to get the language from the browser's 'Accept-Language' header (which only works if you chose to use the ISO shortcuts, as explained above). If all else fails, content will be presented in the site's default language, i.e. $_CONF['language'].&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Supporting multiple languages ==&lt;br /&gt;
&lt;br /&gt;
Developers of plugins and other add-ons don't have to do much to support multiple languages. Mainly, the objects under your plugin's control will have to have an editable, non-numerical ID (like Geeklog's stories have), so that the language shortcut can be appended to the ID.&lt;br /&gt;
&lt;br /&gt;
If you have a list of objects under your plugin's control and only want to show the objects in the current language, you can use the COM_getLangSQL() function when building your SQL request. It will provide the part of an SQL request to only return the objects in the current language (see the function's description in lib-common.php for details).&lt;br /&gt;
&lt;br /&gt;
COM_getLangSQL() will return an empty string when multilingual support is disabled, so you don't need to check for that yourself.&lt;br /&gt;
&lt;br /&gt;
Most of the time, that should be all that you need to know about supporting multiple languages in a plugin. In some scenarios, the following functions may also come in handy:&lt;br /&gt;
* COM_getLanguageId returns the shortcut of the current user's language&lt;br /&gt;
* COM_getLanguage returns the full name of the current user's language, i.e. the name of the Geeklog language file (without the .php extension)&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Switching locale settings ==&lt;br /&gt;
&lt;br /&gt;
Switching the language will often also require different formatting of the date, time, and other locale settings. For this, you can define alternative settings for each language in your site's config.php.&lt;br /&gt;
&lt;br /&gt;
For example, the default date formatting in Geeklog's config.php is&lt;br /&gt;
&amp;lt;pre&amp;gt;$_CONF['date'] = '%A, %B %d %Y @ %I:%M %p %Z';&amp;lt;/pre&amp;gt;&lt;br /&gt;
which, amongst other things, includes a time format using am/pm. If your site switches between, say, English and German, then your typical German visitor will expect the time to use a 24-hour format, e.g.&lt;br /&gt;
&amp;lt;pre&amp;gt;$_CONF['date'] = '%A, %d. %B %Y, %R Uhr';&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
If you're using the ISO abbreviation 'de' for German, then you could have the following in your site's config.php:&lt;br /&gt;
&amp;lt;pre&amp;gt;$_CONF['date'] = '%A, %B %d %Y @ %I:%M %p %Z';&lt;br /&gt;
$_CONF['date_de'] = '%A, %d. %B %Y, %R Uhr';&amp;lt;/pre&amp;gt;&lt;br /&gt;
With these two lines, Geeklog would use the 'date_de' formatting when displaying content in German, and the 'date' formatting for all the other languages.&lt;br /&gt;
&lt;br /&gt;
Actually, for this to work properly, you will also have to set &amp;lt;code&amp;gt;$_CONF['locale']&amp;lt;/code&amp;gt; and &amp;lt;code&amp;gt;$_CONF['locale_de']&amp;lt;/code&amp;gt; accordingly, since some of the date formatting (localized day and month names) requires the correct locale to be set:&lt;br /&gt;
&amp;lt;pre&amp;gt;$_CONF['locale'] = 'en_GB';&lt;br /&gt;
$_CONF['locale_de'] = 'de_DE';&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
You can switch all of the following [http://www.geeklog.net/docs/english/config.html#languages_locale locale settings] as described above:&lt;br /&gt;
* &amp;lt;code&amp;gt;$_CONF['locale']&amp;lt;/code&amp;gt;&lt;br /&gt;
* &amp;lt;code&amp;gt;$_CONF['date']&amp;lt;/code&amp;gt;&lt;br /&gt;
* &amp;lt;code&amp;gt;$_CONF['daytime']&amp;lt;/code&amp;gt;&lt;br /&gt;
* &amp;lt;code&amp;gt;$_CONF['shortdate']&amp;lt;/code&amp;gt;&lt;br /&gt;
* &amp;lt;code&amp;gt;$_CONF['dateonly']&amp;lt;/code&amp;gt;&lt;br /&gt;
* &amp;lt;code&amp;gt;$_CONF['timeonly']&amp;lt;/code&amp;gt;&lt;br /&gt;
* &amp;lt;code&amp;gt;$_CONF['week_start']&amp;lt;/code&amp;gt;&lt;br /&gt;
* &amp;lt;code&amp;gt;$_CONF['hour_mode']&amp;lt;/code&amp;gt;&lt;br /&gt;
* &amp;lt;code&amp;gt;$_CONF['thousand_separator']&amp;lt;/code&amp;gt;&lt;br /&gt;
* &amp;lt;code&amp;gt;$_CONF['decimal_separator']&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
'''Note:''' In Geeklog 1.5.0 and later, you will have to add the language-specific entries ($_CONF['date_de'], etc.) to the &amp;lt;tt&amp;gt;siteconfig.php&amp;lt;/tt&amp;gt; file. The settings for the default language can be found in the Configuration admin panel:&lt;br /&gt;
&lt;br /&gt;
: Configuration &amp;gt; Geeklog &amp;gt; Languages and Locale&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Notes and ideas ==&lt;br /&gt;
&lt;br /&gt;
* To make things nicer for the user, the language could be hidden from the ID when editing objects. Instead, the user could be presented with a drop-down menu of the available languages. The shortcut could then be silently added to the ID when the object is saved.&lt;br /&gt;
* [[SoC improve multilingual feature|More ideas]]&lt;/div&gt;</summary>
		<author><name>LWC</name></author>	</entry>

	<entry>
		<id>http://gwiki3.thatlinuxbox.com/index.php?title=Summer_of_Code_2008&amp;diff=5617</id>
		<title>Summer of Code 2008</title>
		<link rel="alternate" type="text/html" href="http://gwiki3.thatlinuxbox.com/index.php?title=Summer_of_Code_2008&amp;diff=5617"/>
				<updated>2009-10-31T00:27:31Z</updated>
		
		<summary type="html">&lt;p&gt;LWC: Fixed link&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&lt;/div&gt;</summary>
		<author><name>LWC</name></author>	</entry>

	<entry>
		<id>http://gwiki3.thatlinuxbox.com/index.php?title=SoC_improve_multilingual_feature&amp;diff=5615</id>
		<title>SoC improve multilingual feature</title>
		<link rel="alternate" type="text/html" href="http://gwiki3.thatlinuxbox.com/index.php?title=SoC_improve_multilingual_feature&amp;diff=5615"/>
				<updated>2009-10-31T00:26:26Z</updated>
		
		<summary type="html">&lt;p&gt;LWC: SoC improve multi-language feature moved to SoC improve multilingual feature: Fixed English&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&amp;lt;center&amp;gt;(Return to the main idea page for the [[Google Summer of Code]])&amp;lt;/center&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Incentive ==&lt;br /&gt;
&lt;br /&gt;
While Geeklog's interface has been translated into more than 25 languages by now, actually having the site's content available in several languages was only added as an afterthought. So while multilingual support is there now and works most of the time, it is somewhat awkward to use in places.&lt;br /&gt;
&lt;br /&gt;
In this project, we would like someone to look at all the problems with the current solution and see what can be done about them so that multilingual sites are easier to maintain.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Details ==&lt;br /&gt;
&lt;br /&gt;
These are the known issues with the multilingual support that we would like the student to look into:&lt;br /&gt;
&lt;br /&gt;
=== Setting a Fallback Language ===&lt;br /&gt;
&lt;br /&gt;
There is no concept of a &amp;quot;fallback language&amp;quot;, i.e. for every piece of content there has to be a separate object in each of the supported languages. So if your site was set up to use English, German, and Spanish, you would need 3 copies of every story (one per language). You can not, say, publish a story in English only and have the English version show up automatically for the other languages.&lt;br /&gt;
&lt;br /&gt;
A related problem is adding another language to the site later. For example, starting a site in English and German and only adding Spanish later. In that case, you currently have to copy all the existing content over to a Spanish version (otherwise, Spanish visitors may see a note about the article not being available to them instead of at least falling back to, say, the English version).&lt;br /&gt;
&lt;br /&gt;
=== User Interface ===&lt;br /&gt;
&lt;br /&gt;
Missing support in the user interface: Users have to make sure to add the proper suffix ('_en', '_de') to objects (story, topic, ...). There's no protection against typos, for example.&lt;br /&gt;
&lt;br /&gt;
Adding a dropdown to select the language for an object would be a simple solution. There may be better ways, though.&lt;br /&gt;
&lt;br /&gt;
=== Anonymous Visitors ===&lt;br /&gt;
&lt;br /&gt;
For anonymous visitors (guests) of the site, switching the language requires a cookie to be set. Users that do not accept the cookie will not be able to switch the language. This includes bots (e.g. search engines), which won't be able to index the content in languages other than the default language. This can also lead to a mix of languages, e.g. when following a link to an article in English while the site's default language is German.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Level of Difficulty ==&lt;br /&gt;
&lt;br /&gt;
''medium to high''&lt;br /&gt;
&lt;br /&gt;
We don't actually expect a lot of new code to be written for this project. This is more of a research project aimed at people who love tinkering with existing code. For compatibility reasons, there is only limited room for radical changes. The project will require a lot of testing and attention to details.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Further reading ==&lt;br /&gt;
&lt;br /&gt;
* [[Multilingual_Support]] in Geeklog&lt;br /&gt;
* Bug: [http://project.geeklog.net/tracking/view.php?id=712 Using the browser's back button can cause confusion in multilingual setups]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Category:Summer of Code]] [[Category:Development]]&lt;/div&gt;</summary>
		<author><name>LWC</name></author>	</entry>

	<entry>
		<id>http://gwiki3.thatlinuxbox.com/index.php?title=SoC_improve_multi-language_feature&amp;diff=5616</id>
		<title>SoC improve multi-language feature</title>
		<link rel="alternate" type="text/html" href="http://gwiki3.thatlinuxbox.com/index.php?title=SoC_improve_multi-language_feature&amp;diff=5616"/>
				<updated>2009-10-31T00:26:26Z</updated>
		
		<summary type="html">&lt;p&gt;LWC: SoC improve multi-language feature moved to SoC improve multilingual feature: Fixed English&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;#REDIRECT [[SoC improve multilingual feature]]&lt;/div&gt;</summary>
		<author><name>LWC</name></author>	</entry>

	<entry>
		<id>http://gwiki3.thatlinuxbox.com/index.php?title=SoC_improve_multilingual_feature&amp;diff=5614</id>
		<title>SoC improve multilingual feature</title>
		<link rel="alternate" type="text/html" href="http://gwiki3.thatlinuxbox.com/index.php?title=SoC_improve_multilingual_feature&amp;diff=5614"/>
				<updated>2009-10-31T00:25:41Z</updated>
		
		<summary type="html">&lt;p&gt;LWC: Fixed English&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&amp;lt;center&amp;gt;(Return to the main idea page for the [[Google Summer of Code]])&amp;lt;/center&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Incentive ==&lt;br /&gt;
&lt;br /&gt;
While Geeklog's interface has been translated into more than 25 languages by now, actually having the site's content available in several languages was only added as an afterthought. So while multilingual support is there now and works most of the time, it is somewhat awkward to use in places.&lt;br /&gt;
&lt;br /&gt;
In this project, we would like someone to look at all the problems with the current solution and see what can be done about them so that multilingual sites are easier to maintain.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Details ==&lt;br /&gt;
&lt;br /&gt;
These are the known issues with the multilingual support that we would like the student to look into:&lt;br /&gt;
&lt;br /&gt;
=== Setting a Fallback Language ===&lt;br /&gt;
&lt;br /&gt;
There is no concept of a &amp;quot;fallback language&amp;quot;, i.e. for every piece of content there has to be a separate object in each of the supported languages. So if your site was set up to use English, German, and Spanish, you would need 3 copies of every story (one per language). You can not, say, publish a story in English only and have the English version show up automatically for the other languages.&lt;br /&gt;
&lt;br /&gt;
A related problem is adding another language to the site later. For example, starting a site in English and German and only adding Spanish later. In that case, you currently have to copy all the existing content over to a Spanish version (otherwise, Spanish visitors may see a note about the article not being available to them instead of at least falling back to, say, the English version).&lt;br /&gt;
&lt;br /&gt;
=== User Interface ===&lt;br /&gt;
&lt;br /&gt;
Missing support in the user interface: Users have to make sure to add the proper suffix ('_en', '_de') to objects (story, topic, ...). There's no protection against typos, for example.&lt;br /&gt;
&lt;br /&gt;
Adding a dropdown to select the language for an object would be a simple solution. There may be better ways, though.&lt;br /&gt;
&lt;br /&gt;
=== Anonymous Visitors ===&lt;br /&gt;
&lt;br /&gt;
For anonymous visitors (guests) of the site, switching the language requires a cookie to be set. Users that do not accept the cookie will not be able to switch the language. This includes bots (e.g. search engines), which won't be able to index the content in languages other than the default language. This can also lead to a mix of languages, e.g. when following a link to an article in English while the site's default language is German.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Level of Difficulty ==&lt;br /&gt;
&lt;br /&gt;
''medium to high''&lt;br /&gt;
&lt;br /&gt;
We don't actually expect a lot of new code to be written for this project. This is more of a research project aimed at people who love tinkering with existing code. For compatibility reasons, there is only limited room for radical changes. The project will require a lot of testing and attention to details.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Further reading ==&lt;br /&gt;
&lt;br /&gt;
* [[Multilingual_Support]] in Geeklog&lt;br /&gt;
* Bug: [http://project.geeklog.net/tracking/view.php?id=712 Using the browser's back button can cause confusion in multilingual setups]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Category:Summer of Code]] [[Category:Development]]&lt;/div&gt;</summary>
		<author><name>LWC</name></author>	</entry>

	<entry>
		<id>http://gwiki3.thatlinuxbox.com/index.php?title=Language_Tips_And_Tricks&amp;diff=5613</id>
		<title>Language Tips And Tricks</title>
		<link rel="alternate" type="text/html" href="http://gwiki3.thatlinuxbox.com/index.php?title=Language_Tips_And_Tricks&amp;diff=5613"/>
				<updated>2009-10-31T00:24:19Z</updated>
		
		<summary type="html">&lt;p&gt;LWC: Fixed links&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== General Things ==&lt;br /&gt;
&lt;br /&gt;
When you switch to another language in Geeklog, not only the menu text changes, but also the character set might change. This means that certain international characters might not be readable anymore. So if your site has German, Japanese or eastern European content, switching the language might turn your complete content unreadable.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Multilingual Sites ==&lt;br /&gt;
&lt;br /&gt;
If you plan to run a site where the content will be [[Multilingual Support|in several languages]], it is better to stick to languages that support UTF-8. Since they all use the same code, you will be able to display German Umlaut next to Japanese Characters for example. Otherwise, readers will always see unreadable characters next to readables, and will have to switch languages in order to read everything. Read below how to convert your favorite language to UTF-8.&lt;br /&gt;
&lt;br /&gt;
Further, to support proper search and other functions, you should enable --with-mb_string functions in your PHP. In Linux, this might mean that you have to recompile linux! If you do this remember also to set your php.ini to have &amp;quot;mbstring.func_overload = 7&amp;quot;. This makes php use multibyte-functions by default whenever a single-byte function is called.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Unwanted Languages ==&lt;br /&gt;
&lt;br /&gt;
You can remove unwanted languages by simply deleting the unwanted files from the &amp;lt;tt&amp;gt;/language/&amp;lt;/tt&amp;gt; directory. Or you might want to create a subfolder there and move the unwanted files into it. Like this you can avoid that users choose Languages with character sets that will turn content unreadable.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== How to convert Language file Character Sets ==&lt;br /&gt;
&lt;br /&gt;
First check in the download section of geeklog.net if nobody already converted the language file after the last release of Geeklog!&lt;br /&gt;
&lt;br /&gt;
If you have Windows &amp;amp; MS Word, there is a very easy way to convert your language files to UTF-8 or other formats: Simply open the language-file with Word (rename it .doc and double-click for example). Then you will be asked what Character set the Source has. Choose the one that allows you to read the characters properly in the preview. Then save the file again as &amp;quot;Text Only&amp;quot;-Format. You will be asked again what Character Set you want to use. Choose your preferred (&amp;quot;Unicode UTF-8&amp;quot; for example). Make sure you also correct the line 32 of the file so that it represents the format you want:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;$LANG_CHARSET = &amp;quot;utf-8&amp;quot;;&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Then, rename the file to &amp;quot;language_utf-8.php&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
If you have done so, you might want to publish the file also on the geeklog.net website.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== How to convert your complete Geeklog to Unicode/UTF-8 in 11 steps. ==&lt;br /&gt;
&lt;br /&gt;
If you started your server with one language, and want to move to a multi-language system later on, it can be quite difficult if you need different character sets for the different languages. With UTF-8 you can display all languages and letters at the same time in the same page without any problems. The best solution therefore would be to convert your ''complete'' data into Unicode in one go. You don't want to go through each story and comment and edit letters by hand after you switched the encoding of the page.&lt;br /&gt;
&lt;br /&gt;
For this procedure to work you need (1) a text editor like notepad that can save raw text data while choosing the encoding (Notepad unter windows for example), (2) direct access to you MySQL executable (Windows cmd or Linux Shell) and (3) a NON-Unicode-Capable Editor (!) such as PHPEdit (or linux shell editors AFAIK). You can find out which editor cannot handle Unicode by saving a small text containing a &amp;quot;xxöxx&amp;quot; or similar with notepad as UTF-8 (See step 3) and opening it with the other editor. If you the letter &amp;quot;ö&amp;quot; appears now as &amp;quot;Ã¶&amp;quot; you have the right one.&lt;br /&gt;
&lt;br /&gt;
Now let's start.&lt;br /&gt;
&lt;br /&gt;
# Make a Backup of your database using the Geeklog Backup function.&lt;br /&gt;
# Download the created file from your server, zip it, burn it on a CD and send it to your lawyer. He should keep it as a backup in case you need it later to go back to step one.&lt;br /&gt;
# Open the file in Notepad/unicode-able editor (Notepad.exe). If your database is large, this will take some time, but its worth waiting for. Save the file again under a different (!) filename. Before you press the save-button, you have a field called &amp;quot;Encoding&amp;quot; below the field where you entered the filename. Choose &amp;quot;UTF-8&amp;quot;.&lt;br /&gt;
# Now open the file in the non-Unicode-capable editor. You will see three strange letters &amp;quot;ï»¿&amp;quot; in the beginning of the file. Remove them. They cause error messages in the SQL later. Save the file again.&lt;br /&gt;
# Upload the file to your server. You might want to zip it first (also before downloading) to reduce transfer time.&lt;br /&gt;
# Create a new database if you can. If not delete all tables from your old one (call your lawyer to have your backup ready in an envelope).&lt;br /&gt;
# Write the data back into the database. Do this by typing &amp;lt;pre&amp;gt;mysql --user=root --password databasename file.txt&amp;lt;/pre&amp;gt; replace &amp;quot;databasename&amp;quot; with the name of the newly created or empty database, and file.txt with the name of the file that you saved with notepad. The file has to be in the same directory as you are, if not move the file there. In Windows, it has to be in the /Mysql/bin-directory, where your MySQL.exe resides. If you do not want to move the files, prepend the path to the mysql.exe and/or the filename path.&amp;lt;br&amp;gt;If you do not have root access to the database, exchange &amp;quot;root&amp;quot; with the username that you use to access your MySQL server.&lt;br /&gt;
# Hit enter. You will be prompted for the user's password. Enter it, and press return again. Now the database will be parsed back into the server.&lt;br /&gt;
# If you created a second database, edit your Geeklog's config.php so that it accesses the new one.&lt;br /&gt;
# Switch your Geeklog language to one of the _UTF-8 sets. If you want to reduce hassle with your users that have been using non-UTF-8 languages, convert all the language-files you have to UTF-8 with notepad (You don't need to remove the first three letter there) and change the encoding string in each file (Line 30) to &amp;lt;pre&amp;gt;$LANG_CHARSET = &amp;quot;utf-8&amp;quot;;&amp;lt;/pre&amp;gt;&lt;br /&gt;
# Change config.php so that the standard language file will be one of the UTF-8 sets also (somehwere line 239), &amp;lt;pre&amp;gt;$_CONF['language'] = &amp;quot;english_utf-8&amp;quot;;&amp;lt;/pre&amp;gt;&lt;br /&gt;
# You might want to delete all non-UTF-8 languages from your language folders.&lt;br /&gt;
&lt;br /&gt;
That's all. Good luck &amp;lt;tt&amp;gt;:-)&amp;lt;/tt&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Switching back to one language (1.3.9sr1 and before) ==&lt;br /&gt;
&lt;br /&gt;
If you set your config.php so that you use only one language, you might run into trouble if you have users that already registered and selected another language. These users will continue to use their pre-set language. Even if you set their language manually to the standard or NULL (with a tool such as [http://www.phpmyadmin.net/ phpMyAdmin]), the cookies on the user's computers will still call up the old one.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Links and Further Reading ==&lt;br /&gt;
&lt;br /&gt;
* [http://lists.geeklog.net/mailman/listinfo/geeklog-translations geeklog-translations mailing list]&lt;br /&gt;
* [[Multilingual Support]] (as of Geeklog 1.4.1)&lt;/div&gt;</summary>
		<author><name>LWC</name></author>	</entry>

	<entry>
		<id>http://gwiki3.thatlinuxbox.com/index.php?title=Multi-Language_Support&amp;diff=5612</id>
		<title>Multi-Language Support</title>
		<link rel="alternate" type="text/html" href="http://gwiki3.thatlinuxbox.com/index.php?title=Multi-Language_Support&amp;diff=5612"/>
				<updated>2009-10-31T00:23:17Z</updated>
		
		<summary type="html">&lt;p&gt;LWC: Multi-Language Support moved to Multilingual Support: Fixed English&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;#REDIRECT [[Multilingual Support]]&lt;/div&gt;</summary>
		<author><name>LWC</name></author>	</entry>

	<entry>
		<id>http://gwiki3.thatlinuxbox.com/index.php?title=Multilingual_Support&amp;diff=5611</id>
		<title>Multilingual Support</title>
		<link rel="alternate" type="text/html" href="http://gwiki3.thatlinuxbox.com/index.php?title=Multilingual_Support&amp;diff=5611"/>
				<updated>2009-10-31T00:23:17Z</updated>
		
		<summary type="html">&lt;p&gt;LWC: Multi-Language Support moved to Multilingual Support: Fixed English&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Background ==&lt;br /&gt;
&lt;br /&gt;
The Geeklog language files have been translated into more than 25 languages - but that only means that you can have the user interface in one of those languages. For the actual site content (articles, static pages, ...), there was no support for multiple languages, which means that you either had to have everything in one language only or you ended up with all the different language versions of, e.g. an article, being displayed to anyone.&lt;br /&gt;
&lt;br /&gt;
Euan McKay then came up with a [http://heatherengineering.com/staticpages/index.php/multilingual-en first multi-language hack], which was later [http://www.geeklog.net/forum/viewtopic.php?showtopic=61999 built upon and generalized] by LWC.&lt;br /&gt;
&lt;br /&gt;
The multi-language support in Geeklog (as of version 1.4.1) is based on this earlier work by Euan and LWC.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== How it works ==&lt;br /&gt;
&lt;br /&gt;
The basic idea behind the multi-language support is to encode the language of an object into its ID. For example, for a story to encode it into the story ID, like so:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;http://www.example.com/article.php/introduction_en -- English version&lt;br /&gt;
http://www.example.com/article.php/introduction_de -- German version&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Now there is a way to identify the language of an object (article, topic, static page, ...) and it can be displayed (or not), based on the user's language preferences. It's also possible then to switch between the various languages in which an object exists in the database.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Setting it up ==&lt;br /&gt;
&lt;br /&gt;
=== Geeklog 1.4.1 ===&lt;br /&gt;
&lt;br /&gt;
In config.php, there is a new section to enable multi-language support and to define the list of supported languages:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;// Multi-language support&lt;br /&gt;
// (note that this section is commented out - remove the '/*' and '*/' lines&lt;br /&gt;
//  below to activate it and make sure you understand what it does)&lt;br /&gt;
/*&lt;br /&gt;
&lt;br /&gt;
// IMPORTANT!&lt;br /&gt;
// 1) Both the $_CONF['language_files'] and the $_CONF['languages'] arrays&lt;br /&gt;
//    (see below) must have the same number of elements.&lt;br /&gt;
// 2) The shortcuts used must be the same in both arrays.&lt;br /&gt;
// 3) All shortcuts must have the same length, e.g. 2 characters.&lt;br /&gt;
&lt;br /&gt;
// The shortcuts are to be used in IDs of objects that are multi-language&lt;br /&gt;
// aware, e.g. /article.php/introduction_en and /article.php/introduction_de&lt;br /&gt;
// for the English and German version of an introductory article.&lt;br /&gt;
&lt;br /&gt;
// Supported languages&lt;br /&gt;
// Maps a shortcut to a Geeklog language file (without the '.php' extension)&lt;br /&gt;
$_CONF['language_files'] = array (&lt;br /&gt;
    'en' =&amp;gt; 'english',&lt;br /&gt;
    'de' =&amp;gt; 'german_formal'&lt;br /&gt;
);&lt;br /&gt;
&lt;br /&gt;
// Display names of supported languages&lt;br /&gt;
// Maps the same shortcuts as above to a language name. The language names&lt;br /&gt;
// are used to let users switch languages, e.g. in a drop-down menu.&lt;br /&gt;
$_CONF['languages'] = array (&lt;br /&gt;
    'en' =&amp;gt; 'English',&lt;br /&gt;
    'de' =&amp;gt; 'Deutsch'&lt;br /&gt;
);&lt;br /&gt;
&lt;br /&gt;
*/&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
To enable multi-language support, the two arrays $_CONF['language_files'] and $_CONF['languages'] have to be defined. In the default config.php, they are commented out and, therefore, not defined.&lt;br /&gt;
&lt;br /&gt;
=== Geeklog 1.5.0 and later ===&lt;br /&gt;
&lt;br /&gt;
As of Geeklog 1.5.0, the &amp;lt;tt&amp;gt;config.php&amp;lt;/tt&amp;gt; file has been replaced with a web-based configuration that can be found under &amp;quot;Configuration&amp;quot; in the Admin's block. Under the &amp;quot;Languages and Locale&amp;quot; heading, you'll find two options:&lt;br /&gt;
* Language Files&lt;br /&gt;
* Languages&lt;br /&gt;
These two options are the equivalents of the &amp;lt;code&amp;gt;$_CONF['language_files']&amp;lt;/code&amp;gt; and &amp;lt;code&amp;gt;$_CONF['languages']&amp;lt;/code&amp;gt; arrays, as explained above. To use the multi-language feature, '''both''' of these options have to be enabled. Other than that, the two options work as described above.&lt;br /&gt;
&lt;br /&gt;
Note that in Geeklog 1.5.0, you can not easily disable multi-language support again (for a workaround, see [http://www.geeklog.net/forum/viewtopic.php?showtopic=83327 here]). As of Geeklog 1.5.1, there is a litte &amp;lt;tt&amp;gt;(X)&amp;lt;/tt&amp;gt; next to the options (once they're enabled). Click on the &amp;lt;tt&amp;gt;(X)&amp;lt;/tt&amp;gt; to disable the options again (remember that you need to disable both of them).&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== The shortcuts ===&lt;br /&gt;
&lt;br /&gt;
For each of the languages you intend to support, you will have to define a shortcut that will then be used in the IDs of the multi-language objects, as explained above.&lt;br /&gt;
&lt;br /&gt;
You can freely define these shortcuts, but it would make sense to set them in some relation to the language which they represent. From Geeklog's point of view, though, it doesn't matter whether the English language is represented by a shortcut 'en' or by 'peter'.&lt;br /&gt;
&lt;br /&gt;
Please note:&lt;br /&gt;
* All the shortcuts in both of the arrays have to be of the same length.&lt;br /&gt;
* The shortcut must be appended to the ''end'' of an object's ID and it must be preceded by an underscore '_' character.&lt;br /&gt;
* It's recommended that you use a language's ISO abbreviation ('en' for English, 'de' for German, etc.), either with or without the country appendix ('en-US'), as Geeklog will also try to determine a user's preferred language from their browser setting.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== The language files ===&lt;br /&gt;
&lt;br /&gt;
The $_CONF['language_files'] array defines which language files should represent which language. Note that Geeklog also uses the language file name for a user's language setting (in their preferences).&lt;br /&gt;
&lt;br /&gt;
It's recommended that you remove all the other language files, i.e. those for which you do not intend to have content in that particular language on your site.&lt;br /&gt;
&lt;br /&gt;
'''Note:''' Be careful when mixing languages that use different character sets (e.g. Russian and Japanese). You may want to switch to the UTF-8 versions of ''all'' language files for such a setup.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== The language names ===&lt;br /&gt;
&lt;br /&gt;
The $_CONF['languages'] array defines a set of display names for the supported languages. These names are used to let the user switch between the supported languages, e.g. from a drop-down menu.&lt;br /&gt;
&lt;br /&gt;
Most of the time, you'll want to use the native names of the languages, e.g. &amp;quot;Deutsch&amp;quot; instead of &amp;quot;German&amp;quot;, but that's only a convention.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Blocks ==&lt;br /&gt;
&lt;br /&gt;
Multi-lingual blocks are only supported as of Geeklog 1.5.1. The setup differs slightly from the setup for stories, topics, etc.&lt;br /&gt;
&lt;br /&gt;
Let's assume you want to create a multi-lingual &amp;quot;about this site&amp;quot; block and that your site is configured for two languages (say, English and German). For this setup you would then need ''three''(!) blocks. The block name serves as the ID and you would create blocks with the following names:&lt;br /&gt;
* about_en&lt;br /&gt;
* about_de&lt;br /&gt;
* about&lt;br /&gt;
The first two blocks would simply contain your content in English and German, respectively. Both blocks should be ''disabled''. The third block then serves as a placeholder for the actual block for the current language. Therefore, only this block (&amp;quot;about&amp;quot;, in our example) should be enabled. When the multi-language support is enabled, you will never see the contents of that block, as it will be replaced with the proper block for the current language, e.g. &amp;quot;about_en&amp;quot; for English.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Switching languages ==&lt;br /&gt;
&lt;br /&gt;
Registered users can always switch their preferred language by selecting another language in their preferences.&lt;br /&gt;
&lt;br /&gt;
To make things more convenient (and also allow anonymous users to switch the language), you can put a PHP block on your site. Geeklog provides a function phpblock_switch_language that will display a drop-down menu of all available languages (if you only have two languages defined, it will display a simple link to the other language instead).&lt;br /&gt;
&lt;br /&gt;
This function can also be called from the header.thtml template file of your theme, so that you can put it into your site's menu:&lt;br /&gt;
&amp;lt;pre&amp;gt;&amp;lt;?php print phpblock_switch_language(); ?&amp;gt;&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Technically, switching the language will set a cookie (with the selected language) and also update a user's language preference, if they're registered with the site.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Detecting the language ==&lt;br /&gt;
&lt;br /&gt;
When a user comes to a multi-language enabled site, Geeklog will check for the user's preference setting first (if it's a registered user), then for the language cookie, and if that couldn't be found, it tries to get the language from the browser's 'Accept-Language' header (which only works if you chose to use the ISO shortcuts, as explained above). If all else fails, content will be presented in the site's default language, i.e. $_CONF['language'].&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Supporting multiple languages ==&lt;br /&gt;
&lt;br /&gt;
Developers of plugins and other add-ons don't have to do much to support multiple languages. Mainly, the objects under your plugin's control will have to have an editable, non-numerical ID (like Geeklog's stories have), so that the language shortcut can be appended to the ID.&lt;br /&gt;
&lt;br /&gt;
If you have a list of objects under your plugin's control and only want to show the objects in the current language, you can use the COM_getLangSQL() function when building your SQL request. It will provide the part of an SQL request to only return the objects in the current language (see the function's description in lib-common.php for details).&lt;br /&gt;
&lt;br /&gt;
COM_getLangSQL() will return an empty string when multi-language support is disabled, so you don't need to check for that yourself.&lt;br /&gt;
&lt;br /&gt;
Most of the time, that should be all that you need to know about supporting multiple languages in a plugin. In some scenarios, the following functions may also come in handy:&lt;br /&gt;
* COM_getLanguageId returns the shortcut of the current user's language&lt;br /&gt;
* COM_getLanguage returns the full name of the current user's language, i.e. the name of the Geeklog language file (without the .php extension)&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Switching locale settings ==&lt;br /&gt;
&lt;br /&gt;
Switching the language will often also require different formatting of the date, time, and other locale settings. For this, you can define alternative settings for each language in your site's config.php.&lt;br /&gt;
&lt;br /&gt;
For example, the default date formatting in Geeklog's config.php is&lt;br /&gt;
&amp;lt;pre&amp;gt;$_CONF['date'] = '%A, %B %d %Y @ %I:%M %p %Z';&amp;lt;/pre&amp;gt;&lt;br /&gt;
which, amongst other things, includes a time format using am/pm. If your site switches between, say, English and German, then your typical German visitor will expect the time to use a 24-hour format, e.g.&lt;br /&gt;
&amp;lt;pre&amp;gt;$_CONF['date'] = '%A, %d. %B %Y, %R Uhr';&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
If you're using the ISO abbreviation 'de' for German, then you could have the following in your site's config.php:&lt;br /&gt;
&amp;lt;pre&amp;gt;$_CONF['date'] = '%A, %B %d %Y @ %I:%M %p %Z';&lt;br /&gt;
$_CONF['date_de'] = '%A, %d. %B %Y, %R Uhr';&amp;lt;/pre&amp;gt;&lt;br /&gt;
With these two lines, Geeklog would use the 'date_de' formatting when displaying content in German, and the 'date' formatting for all the other languages.&lt;br /&gt;
&lt;br /&gt;
Actually, for this to work properly, you will also have to set &amp;lt;code&amp;gt;$_CONF['locale']&amp;lt;/code&amp;gt; and &amp;lt;code&amp;gt;$_CONF['locale_de']&amp;lt;/code&amp;gt; accordingly, since some of the date formatting (localized day and month names) requires the correct locale to be set:&lt;br /&gt;
&amp;lt;pre&amp;gt;$_CONF['locale'] = 'en_GB';&lt;br /&gt;
$_CONF['locale_de'] = 'de_DE';&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
You can switch all of the following [http://www.geeklog.net/docs/english/config.html#languages_locale locale settings] as described above:&lt;br /&gt;
* &amp;lt;code&amp;gt;$_CONF['locale']&amp;lt;/code&amp;gt;&lt;br /&gt;
* &amp;lt;code&amp;gt;$_CONF['date']&amp;lt;/code&amp;gt;&lt;br /&gt;
* &amp;lt;code&amp;gt;$_CONF['daytime']&amp;lt;/code&amp;gt;&lt;br /&gt;
* &amp;lt;code&amp;gt;$_CONF['shortdate']&amp;lt;/code&amp;gt;&lt;br /&gt;
* &amp;lt;code&amp;gt;$_CONF['dateonly']&amp;lt;/code&amp;gt;&lt;br /&gt;
* &amp;lt;code&amp;gt;$_CONF['timeonly']&amp;lt;/code&amp;gt;&lt;br /&gt;
* &amp;lt;code&amp;gt;$_CONF['week_start']&amp;lt;/code&amp;gt;&lt;br /&gt;
* &amp;lt;code&amp;gt;$_CONF['hour_mode']&amp;lt;/code&amp;gt;&lt;br /&gt;
* &amp;lt;code&amp;gt;$_CONF['thousand_separator']&amp;lt;/code&amp;gt;&lt;br /&gt;
* &amp;lt;code&amp;gt;$_CONF['decimal_separator']&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
'''Note:''' In Geeklog 1.5.0 and later, you will have to add the language-specific entries ($_CONF['date_de'], etc.) to the &amp;lt;tt&amp;gt;siteconfig.php&amp;lt;/tt&amp;gt; file. The settings for the default language can be found in the Configuration admin panel:&lt;br /&gt;
&lt;br /&gt;
: Configuration &amp;gt; Geeklog &amp;gt; Languages and Locale&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Notes and ideas ==&lt;br /&gt;
&lt;br /&gt;
* To make things nicer for the user, the language could be hidden from the ID when editing objects. Instead, the user could be presented with a drop-down menu of the available languages. The shortcut could then be silently added to the ID when the object is saved.&lt;br /&gt;
* [[SoC improve multi-language feature|More ideas]]&lt;/div&gt;</summary>
		<author><name>LWC</name></author>	</entry>

	<entry>
		<id>http://gwiki3.thatlinuxbox.com/index.php?title=Limit_Portal_Block_Entry&amp;diff=5604</id>
		<title>Limit Portal Block Entry</title>
		<link rel="alternate" type="text/html" href="http://gwiki3.thatlinuxbox.com/index.php?title=Limit_Portal_Block_Entry&amp;diff=5604"/>
				<updated>2009-10-28T23:21:26Z</updated>
		
		<summary type="html">&lt;p&gt;LWC: Fixed description&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Limiting Portal Block Entry ==&lt;br /&gt;
&lt;br /&gt;
You can limit the number of entries in a [[Block_Types#Portal_Block|Portal Block]] for each individual portal block in the block menu. The default is specified in the value of &amp;lt;code&amp;gt;$_CONF['syndication_max_headlines']&amp;lt;/code&amp;gt; (in &amp;lt;tt&amp;gt;Site: Syndication&amp;lt;/tt&amp;gt; in the Configuration admin panel or in &amp;lt;tt&amp;gt;config.php&amp;lt;/tt&amp;gt;, depending on the Geeklog version you're using).&lt;br /&gt;
&lt;br /&gt;
In really old Geeklog versions, you can limit the number of entries by changing the value of &amp;lt;code&amp;gt;$maxheadlines&amp;lt;/code&amp;gt; in &amp;lt;code&amp;gt;function COM_rdfImport($bid, $rdfurl)&amp;lt;/code&amp;gt; to any number that you want.&lt;br /&gt;
&lt;br /&gt;
== Reloading Portal Block ==&lt;br /&gt;
&lt;br /&gt;
After changing the limit, the portal block will not be updated until the next RSS update which by default is set to 3600 seconds/1 hour (specified in lib-common.php's function COM_rdfCheck). If you want to see the portal block updated immediately, you can go back to Blocks under the Admins function, select the portal block that you want to reload and save the portal block again.&lt;br /&gt;
&lt;br /&gt;
[[Category:Blocks]]&lt;/div&gt;</summary>
		<author><name>LWC</name></author>	</entry>

	<entry>
		<id>http://gwiki3.thatlinuxbox.com/index.php?title=SoC_improving_comments_2008&amp;diff=5602</id>
		<title>SoC improving comments 2008</title>
		<link rel="alternate" type="text/html" href="http://gwiki3.thatlinuxbox.com/index.php?title=SoC_improving_comments_2008&amp;diff=5602"/>
				<updated>2009-10-23T08:41:57Z</updated>
		
		<summary type="html">&lt;p&gt;LWC: Fixed grammar&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;This project was implemented in [[Summer of Code 2008]]. The comment improvements are available as of Geeklog 1.6.0. This project outline is therefore only of historical interest and you can not apply for this project in future instances of the Google Summer of Code. Please see our [[Google Summer of Code|ideas page]] for a current list of GSoC project ideas.&lt;br /&gt;
&lt;br /&gt;
== Incentive ==&lt;br /&gt;
&lt;br /&gt;
Comments are a simple and natural way to ask your readers for feedback to a particular article. Geeklog's comment system was originally written at a time when spam and heated discussions on websites were rare. Even though some improvements have since been made (e.g. integration of spam protection, reporting of abusive comments, etc.), the comment system is showing its age and is in desperate need of some changes and additions, as outlined in this project proposal.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Goals ==&lt;br /&gt;
&lt;br /&gt;
The goal of this project is to make comments more useful and attractive again for both visitors (so they are motivated to leave comments) and site administrators (so they are motivated to allow comments, despite the fear of spam). We believe this could be accomplished by implementing the following features:&lt;br /&gt;
&lt;br /&gt;
* a comment moderation queue&lt;br /&gt;
* &amp;quot;aging&amp;quot; of stories, i.e. automatically close a story for comments after a while&lt;br /&gt;
* make comments editable for users&lt;br /&gt;
* being able to actually see the comment or article you're replying to while writing a comment&lt;br /&gt;
* allow users to receive notifications about follow-up comments&lt;br /&gt;
* allow non-registered users to identify themselves&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Details ==&lt;br /&gt;
&lt;br /&gt;
Note: Geeklog has hierarchical comments, i.e. you can reply to a specific comment and your comment will be displayed below the comment you replied to (indented, instead of at the end of the list of comments).&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Moderation ===&lt;br /&gt;
&lt;br /&gt;
Just like story submissions, comments should - optionally - be held back until approved by a moderator.&lt;br /&gt;
&lt;br /&gt;
* Option to only hold back comments by anonymous users.&lt;br /&gt;
* Option to put already published comments back into the moderation queue for review (including comments that are replies to these comments).&lt;br /&gt;
* Option to auto-approve comments by certain users or user groups. &lt;br /&gt;
&lt;br /&gt;
The auto-approve should be implemented as a Geeklog right (permission), e.g. &amp;quot;comment.submit&amp;quot;, so that this right can be assigned to groups of users (consistent with the &amp;quot;story.submit&amp;quot; right for stories).&lt;br /&gt;
&lt;br /&gt;
For auto-approving comments by individual users, it may be worth looking at other systems for inspiration. Wordpress, for example, auto-approves comments by users once their first comment has been approved by a moderator. This works by setting a cookie and therefore doesn't require registration of an account.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== &amp;quot;Aging&amp;quot; ===&lt;br /&gt;
&lt;br /&gt;
Once a story has been up on a site for a while, it is less likely that someone wants to comment on it. At the same time, spammers are known to prefer spamming older posts in the hope that it will go unnoticed. Consequentially, it would make sense to have an option to automatically close a story for commenting after a while.&lt;br /&gt;
&lt;br /&gt;
* Option to automatically close the story for comments after a certain amount of time.&lt;br /&gt;
* Option to only keep the last &amp;lt;var&amp;gt;x&amp;lt;/var&amp;gt; stories open for comments (e.g. set to the number of stories on the homepage so that stories dropping off the homepage are closed automatically).&lt;br /&gt;
&lt;br /&gt;
The option to close a story for comments after some time should be on a per-story basis (with a global default). The option to only keep the latest stories open for comment should override (and disable) the time-based option.&lt;br /&gt;
&lt;br /&gt;
Note: Manual closing of comments is not available in Geeklog 1.4.1 but has been implemented in CVS for the upcoming version 1.5.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Editable comments ===&lt;br /&gt;
&lt;br /&gt;
Making comments editable isn't going to help prevent spam but is aimed at making the comment system more attractive so that posters can correct typos or rephrase their comment.&lt;br /&gt;
&lt;br /&gt;
Things to consider:&lt;br /&gt;
&lt;br /&gt;
* A comment should only be editable as long as there hasn't been a follow-up comment.&lt;br /&gt;
* There should be a time limit for how long the comment should be editable.&lt;br /&gt;
* Comments should always be editable for Admins.&lt;br /&gt;
* The user has to be identified somehow. So either this feature has to be restricted to registered users or a cookie has to be set to identify the original poster (also see [[SoC_improving_comments_2008#Moderation|auto-approve]] above).&lt;br /&gt;
&lt;br /&gt;
In order to indicate that a comment has been edited, it may be advisable to automatically add a ''(last edited by ... at ...)'' note to the comment. However, this should be made an option and it could also be left to the discretion of the user whether they want to leave that note in.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Seeing what you're commenting on ===&lt;br /&gt;
&lt;br /&gt;
This should be a pretty straightforward change in the user interface: Currently, the comment submission form takes over the entire page so that you can't see the comment or article you are replying to (unless you open a separate window or tab).&lt;br /&gt;
&lt;br /&gt;
This will also have to work with plugins that support comments, though, which may make things slightly more complicated than it seems at first.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Notifications ===&lt;br /&gt;
&lt;br /&gt;
Users who left a comment will usually be interested in any follow-up comment that is being made. Users should therefore have an option to receive an email when such a comment is posted.&lt;br /&gt;
&lt;br /&gt;
Things to consider:&lt;br /&gt;
&lt;br /&gt;
* This could lead to a lot of emails being sent and should therefore be a global option.&lt;br /&gt;
* Possible email options:&lt;br /&gt;
** immediate notification&lt;br /&gt;
** no further notification until the next visit&lt;br /&gt;
** inclusion of comment that was posted&lt;br /&gt;
** digest(?)&lt;br /&gt;
* Ability to unsubscribe needed (preferrably with a link in the email).&lt;br /&gt;
* Overview of a user's subscriptions (e.g. under &amp;quot;My Account&amp;quot;).&lt;br /&gt;
&lt;br /&gt;
'''Note:''' There is some overlap here with the proposal for a [[SoC_core_notification_support|Notification Service]]. Implementing the comment notifications using that service should make things much easier.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Less anonymous comments ===&lt;br /&gt;
&lt;br /&gt;
Geeklog currently lumps all comments made by users who are not logged in together under a guest user account called ''Anonymous''. If anonymous comments are enabled, there should  be an optional text entry field where the commenter can leave a name.&lt;br /&gt;
&lt;br /&gt;
Internally, these comments would still end up in the &amp;quot;Anonymous&amp;quot; account, but the display of a name should at least let them appear less anonymous.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Level of Difficulty ==&lt;br /&gt;
&lt;br /&gt;
''medium''&lt;br /&gt;
&lt;br /&gt;
This project will require some wrestling with legacy code when implementing the [[SoC_improving_comments_2008#Editable_comments|editable comments]], so that formatting and special characters will not get lost. [[SoC_improving_comments_2008#Moderation|Moderation]] will have to use Geeklog's plugin API for moderation and will depend on being able to edit the comments (due to the requirements of the API). These two tasks will probably require most of the time and work.&lt;br /&gt;
&lt;br /&gt;
The amount of work required for the [[SoC_improving_comments_2008#Notifications|notifications]] will depend on whether or not the project for a [[SoC_core_notification_support|Notification Service]] will be picked up and implemented. This task should probably be implemented last so that it can be cut down or dropped entirely, if necessary.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Further Reading ==&lt;br /&gt;
&lt;br /&gt;
* [http://vinny.furiafamily.com/article.php?story=20041129154258296 Representing Hierarchical Data in a Database] - How the comments are stored&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Category:Summer of Code]] [[Category:Development]]&lt;/div&gt;</summary>
		<author><name>LWC</name></author>	</entry>

	<entry>
		<id>http://gwiki3.thatlinuxbox.com/index.php?title=SoC_improving_comments&amp;diff=5601</id>
		<title>SoC improving comments</title>
		<link rel="alternate" type="text/html" href="http://gwiki3.thatlinuxbox.com/index.php?title=SoC_improving_comments&amp;diff=5601"/>
				<updated>2009-10-23T08:41:37Z</updated>
		
		<summary type="html">&lt;p&gt;LWC: Fixed grammar&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;This project was eventually implemented as [[SoC improving comments 2008]]. The comment improvements are available as of Geeklog 1.6.0. This project outline is therefore only of historical interest and you can not apply for this project in future instances of the Google Summer of Code. Please see our [[Google Summer of Code|ideas page]] for a current list of GSoC project ideas.&lt;br /&gt;
&lt;br /&gt;
== Incentive ==&lt;br /&gt;
&lt;br /&gt;
Comments are important for blogs and community-driven sites to get feedback from visitors. However, due to the rise of comment spam, it's becoming increasingly hard to keep comments open for everyone.&lt;br /&gt;
&lt;br /&gt;
In Geeklog, you can currently only open comments for everyone (including anonymous users) or for registered users only. While the latter reduces the number of spam comments, it also reduces the number of overall comments, as visitors are less likely to leave a comment if they have to register first.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Goals ==&lt;br /&gt;
&lt;br /&gt;
The goal of this project is to make comments more useful and attractive again by implementing:&lt;br /&gt;
&lt;br /&gt;
* a comment moderation queue&lt;br /&gt;
* &amp;quot;aging&amp;quot; of stories, i.e. automatically close a story for comments after a while&lt;br /&gt;
* make comments editable for users &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Details ==&lt;br /&gt;
&lt;br /&gt;
Note: Geeklog supports hierarchical comments, i.e. you can reply to a specific comment and your comment will be displayed below the comment you replied to (indented, instead of at the end of the list of comments).&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Moderation ===&lt;br /&gt;
&lt;br /&gt;
Just like story submissions, comments should - optionally - be held back until approved by a moderator.&lt;br /&gt;
&lt;br /&gt;
* Option to only hold back comments by anonymous users.&lt;br /&gt;
* Option to put already posted comments back into the moderation queue (including comments that are replies to these comments).&lt;br /&gt;
* Option to auto-approve comments by certain users or user groups. &lt;br /&gt;
* Possibly: Option to report moderated comments as spam (via the Spam-X plugin). This may be unnecessary, though, since the comments already went through the spam filter when they were posted initially.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== &amp;quot;Aging&amp;quot; ===&lt;br /&gt;
&lt;br /&gt;
Once a story has been up on a site for a while, it is less likely that someone wants to comment on it. At the same time, spammers are known to prefer spamming older posts in the hope that it will go unnoticed. Consequentially, it would make sense to have an option to automatically close a story for commenting after a while.&lt;br /&gt;
&lt;br /&gt;
* Option to close the story for comments after a certain amount of time,&lt;br /&gt;
* Option to close the story for comments once it drops off the homepage (i.e. after a certain amount of new stories have been posted).&lt;br /&gt;
&lt;br /&gt;
Note: Manual closing of comments is not available in Geeklog 1.4.1 but has been implemented in CVS (i.e. the current development version).&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Editable comments ===&lt;br /&gt;
&lt;br /&gt;
Making comments editable isn't going to help prevent spam, of course, but is aimed at making the comment system more attractive so that posters can correct typos or rephrase their comment.&lt;br /&gt;
&lt;br /&gt;
Things to consider:&lt;br /&gt;
&lt;br /&gt;
* A comment should only be editable as long as there hasn't been a follow-up comment.&lt;br /&gt;
* There should probably be a time-limit for how long the comment should be editable.&lt;br /&gt;
* Comments should always be editable for Admins, though.&lt;br /&gt;
* The user has to be identified somehow. So either this feature has to be restricted to registered users or a cookie has to be set to identify the original poster.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== More ideas ===&lt;br /&gt;
&lt;br /&gt;
There are more ideas and feature requests that would also help to make comments more attractive and motivate visitors to leave a comment:&lt;br /&gt;
&lt;br /&gt;
* Let anonymous users at least enter a name.&lt;br /&gt;
* Optionally send a notification email when a reply has been made to a user's comment (for registered users only).&lt;br /&gt;
* Being able to see the comment or original post while commenting on it.&lt;br /&gt;
&lt;br /&gt;
These ideas are not strictly part of the SoC task, but may be easy enough to implement or at least have to be considered in the design.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Category:Summer of Code]] [[Category:Development]]&lt;/div&gt;</summary>
		<author><name>LWC</name></author>	</entry>

	<entry>
		<id>http://gwiki3.thatlinuxbox.com/index.php?title=SoC_improving_comments_2008&amp;diff=5600</id>
		<title>SoC improving comments 2008</title>
		<link rel="alternate" type="text/html" href="http://gwiki3.thatlinuxbox.com/index.php?title=SoC_improving_comments_2008&amp;diff=5600"/>
				<updated>2009-10-23T08:40:37Z</updated>
		
		<summary type="html">&lt;p&gt;LWC: No longer future tense and added link&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;This project was implemented in [[Summer of Code 2008]]. The comment improvements is available as of Geeklog 1.6.0. This project outline is therefore only of historical interest and you can not apply for this project in future instances of the Google Summer of Code. Please see our [[Google Summer of Code|ideas page]] for a current list of GSoC project ideas.&lt;br /&gt;
&lt;br /&gt;
== Incentive ==&lt;br /&gt;
&lt;br /&gt;
Comments are a simple and natural way to ask your readers for feedback to a particular article. Geeklog's comment system was originally written at a time when spam and heated discussions on websites were rare. Even though some improvements have since been made (e.g. integration of spam protection, reporting of abusive comments, etc.), the comment system is showing its age and is in desperate need of some changes and additions, as outlined in this project proposal.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Goals ==&lt;br /&gt;
&lt;br /&gt;
The goal of this project is to make comments more useful and attractive again for both visitors (so they are motivated to leave comments) and site administrators (so they are motivated to allow comments, despite the fear of spam). We believe this could be accomplished by implementing the following features:&lt;br /&gt;
&lt;br /&gt;
* a comment moderation queue&lt;br /&gt;
* &amp;quot;aging&amp;quot; of stories, i.e. automatically close a story for comments after a while&lt;br /&gt;
* make comments editable for users&lt;br /&gt;
* being able to actually see the comment or article you're replying to while writing a comment&lt;br /&gt;
* allow users to receive notifications about follow-up comments&lt;br /&gt;
* allow non-registered users to identify themselves&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Details ==&lt;br /&gt;
&lt;br /&gt;
Note: Geeklog has hierarchical comments, i.e. you can reply to a specific comment and your comment will be displayed below the comment you replied to (indented, instead of at the end of the list of comments).&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Moderation ===&lt;br /&gt;
&lt;br /&gt;
Just like story submissions, comments should - optionally - be held back until approved by a moderator.&lt;br /&gt;
&lt;br /&gt;
* Option to only hold back comments by anonymous users.&lt;br /&gt;
* Option to put already published comments back into the moderation queue for review (including comments that are replies to these comments).&lt;br /&gt;
* Option to auto-approve comments by certain users or user groups. &lt;br /&gt;
&lt;br /&gt;
The auto-approve should be implemented as a Geeklog right (permission), e.g. &amp;quot;comment.submit&amp;quot;, so that this right can be assigned to groups of users (consistent with the &amp;quot;story.submit&amp;quot; right for stories).&lt;br /&gt;
&lt;br /&gt;
For auto-approving comments by individual users, it may be worth looking at other systems for inspiration. Wordpress, for example, auto-approves comments by users once their first comment has been approved by a moderator. This works by setting a cookie and therefore doesn't require registration of an account.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== &amp;quot;Aging&amp;quot; ===&lt;br /&gt;
&lt;br /&gt;
Once a story has been up on a site for a while, it is less likely that someone wants to comment on it. At the same time, spammers are known to prefer spamming older posts in the hope that it will go unnoticed. Consequentially, it would make sense to have an option to automatically close a story for commenting after a while.&lt;br /&gt;
&lt;br /&gt;
* Option to automatically close the story for comments after a certain amount of time.&lt;br /&gt;
* Option to only keep the last &amp;lt;var&amp;gt;x&amp;lt;/var&amp;gt; stories open for comments (e.g. set to the number of stories on the homepage so that stories dropping off the homepage are closed automatically).&lt;br /&gt;
&lt;br /&gt;
The option to close a story for comments after some time should be on a per-story basis (with a global default). The option to only keep the latest stories open for comment should override (and disable) the time-based option.&lt;br /&gt;
&lt;br /&gt;
Note: Manual closing of comments is not available in Geeklog 1.4.1 but has been implemented in CVS for the upcoming version 1.5.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Editable comments ===&lt;br /&gt;
&lt;br /&gt;
Making comments editable isn't going to help prevent spam but is aimed at making the comment system more attractive so that posters can correct typos or rephrase their comment.&lt;br /&gt;
&lt;br /&gt;
Things to consider:&lt;br /&gt;
&lt;br /&gt;
* A comment should only be editable as long as there hasn't been a follow-up comment.&lt;br /&gt;
* There should be a time limit for how long the comment should be editable.&lt;br /&gt;
* Comments should always be editable for Admins.&lt;br /&gt;
* The user has to be identified somehow. So either this feature has to be restricted to registered users or a cookie has to be set to identify the original poster (also see [[SoC_improving_comments_2008#Moderation|auto-approve]] above).&lt;br /&gt;
&lt;br /&gt;
In order to indicate that a comment has been edited, it may be advisable to automatically add a ''(last edited by ... at ...)'' note to the comment. However, this should be made an option and it could also be left to the discretion of the user whether they want to leave that note in.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Seeing what you're commenting on ===&lt;br /&gt;
&lt;br /&gt;
This should be a pretty straightforward change in the user interface: Currently, the comment submission form takes over the entire page so that you can't see the comment or article you are replying to (unless you open a separate window or tab).&lt;br /&gt;
&lt;br /&gt;
This will also have to work with plugins that support comments, though, which may make things slightly more complicated than it seems at first.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Notifications ===&lt;br /&gt;
&lt;br /&gt;
Users who left a comment will usually be interested in any follow-up comment that is being made. Users should therefore have an option to receive an email when such a comment is posted.&lt;br /&gt;
&lt;br /&gt;
Things to consider:&lt;br /&gt;
&lt;br /&gt;
* This could lead to a lot of emails being sent and should therefore be a global option.&lt;br /&gt;
* Possible email options:&lt;br /&gt;
** immediate notification&lt;br /&gt;
** no further notification until the next visit&lt;br /&gt;
** inclusion of comment that was posted&lt;br /&gt;
** digest(?)&lt;br /&gt;
* Ability to unsubscribe needed (preferrably with a link in the email).&lt;br /&gt;
* Overview of a user's subscriptions (e.g. under &amp;quot;My Account&amp;quot;).&lt;br /&gt;
&lt;br /&gt;
'''Note:''' There is some overlap here with the proposal for a [[SoC_core_notification_support|Notification Service]]. Implementing the comment notifications using that service should make things much easier.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Less anonymous comments ===&lt;br /&gt;
&lt;br /&gt;
Geeklog currently lumps all comments made by users who are not logged in together under a guest user account called ''Anonymous''. If anonymous comments are enabled, there should  be an optional text entry field where the commenter can leave a name.&lt;br /&gt;
&lt;br /&gt;
Internally, these comments would still end up in the &amp;quot;Anonymous&amp;quot; account, but the display of a name should at least let them appear less anonymous.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Level of Difficulty ==&lt;br /&gt;
&lt;br /&gt;
''medium''&lt;br /&gt;
&lt;br /&gt;
This project will require some wrestling with legacy code when implementing the [[SoC_improving_comments_2008#Editable_comments|editable comments]], so that formatting and special characters will not get lost. [[SoC_improving_comments_2008#Moderation|Moderation]] will have to use Geeklog's plugin API for moderation and will depend on being able to edit the comments (due to the requirements of the API). These two tasks will probably require most of the time and work.&lt;br /&gt;
&lt;br /&gt;
The amount of work required for the [[SoC_improving_comments_2008#Notifications|notifications]] will depend on whether or not the project for a [[SoC_core_notification_support|Notification Service]] will be picked up and implemented. This task should probably be implemented last so that it can be cut down or dropped entirely, if necessary.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Further Reading ==&lt;br /&gt;
&lt;br /&gt;
* [http://vinny.furiafamily.com/article.php?story=20041129154258296 Representing Hierarchical Data in a Database] - How the comments are stored&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Category:Summer of Code]] [[Category:Development]]&lt;/div&gt;</summary>
		<author><name>LWC</name></author>	</entry>

	<entry>
		<id>http://gwiki3.thatlinuxbox.com/index.php?title=SoC_improving_comments&amp;diff=5599</id>
		<title>SoC improving comments</title>
		<link rel="alternate" type="text/html" href="http://gwiki3.thatlinuxbox.com/index.php?title=SoC_improving_comments&amp;diff=5599"/>
				<updated>2009-10-23T08:40:00Z</updated>
		
		<summary type="html">&lt;p&gt;LWC: No longer future tense&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;This project was eventually implemented [[SoC improving comments 2008|in the 2008 Google Summer of Code]]. The comment improvements is available as of Geeklog 1.6.0. This project outline is therefore only of historical interest and you can not apply for this project in future instances of the Google Summer of Code. Please see our [[Google Summer of Code|ideas page]] for a current list of GSoC project ideas.&lt;br /&gt;
&lt;br /&gt;
== Incentive ==&lt;br /&gt;
&lt;br /&gt;
Comments are important for blogs and community-driven sites to get feedback from visitors. However, due to the rise of comment spam, it's becoming increasingly hard to keep comments open for everyone.&lt;br /&gt;
&lt;br /&gt;
In Geeklog, you can currently only open comments for everyone (including anonymous users) or for registered users only. While the latter reduces the number of spam comments, it also reduces the number of overall comments, as visitors are less likely to leave a comment if they have to register first.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Goals ==&lt;br /&gt;
&lt;br /&gt;
The goal of this project is to make comments more useful and attractive again by implementing:&lt;br /&gt;
&lt;br /&gt;
* a comment moderation queue&lt;br /&gt;
* &amp;quot;aging&amp;quot; of stories, i.e. automatically close a story for comments after a while&lt;br /&gt;
* make comments editable for users &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Details ==&lt;br /&gt;
&lt;br /&gt;
Note: Geeklog supports hierarchical comments, i.e. you can reply to a specific comment and your comment will be displayed below the comment you replied to (indented, instead of at the end of the list of comments).&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Moderation ===&lt;br /&gt;
&lt;br /&gt;
Just like story submissions, comments should - optionally - be held back until approved by a moderator.&lt;br /&gt;
&lt;br /&gt;
* Option to only hold back comments by anonymous users.&lt;br /&gt;
* Option to put already posted comments back into the moderation queue (including comments that are replies to these comments).&lt;br /&gt;
* Option to auto-approve comments by certain users or user groups. &lt;br /&gt;
* Possibly: Option to report moderated comments as spam (via the Spam-X plugin). This may be unnecessary, though, since the comments already went through the spam filter when they were posted initially.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== &amp;quot;Aging&amp;quot; ===&lt;br /&gt;
&lt;br /&gt;
Once a story has been up on a site for a while, it is less likely that someone wants to comment on it. At the same time, spammers are known to prefer spamming older posts in the hope that it will go unnoticed. Consequentially, it would make sense to have an option to automatically close a story for commenting after a while.&lt;br /&gt;
&lt;br /&gt;
* Option to close the story for comments after a certain amount of time,&lt;br /&gt;
* Option to close the story for comments once it drops off the homepage (i.e. after a certain amount of new stories have been posted).&lt;br /&gt;
&lt;br /&gt;
Note: Manual closing of comments is not available in Geeklog 1.4.1 but has been implemented in CVS (i.e. the current development version).&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Editable comments ===&lt;br /&gt;
&lt;br /&gt;
Making comments editable isn't going to help prevent spam, of course, but is aimed at making the comment system more attractive so that posters can correct typos or rephrase their comment.&lt;br /&gt;
&lt;br /&gt;
Things to consider:&lt;br /&gt;
&lt;br /&gt;
* A comment should only be editable as long as there hasn't been a follow-up comment.&lt;br /&gt;
* There should probably be a time-limit for how long the comment should be editable.&lt;br /&gt;
* Comments should always be editable for Admins, though.&lt;br /&gt;
* The user has to be identified somehow. So either this feature has to be restricted to registered users or a cookie has to be set to identify the original poster.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== More ideas ===&lt;br /&gt;
&lt;br /&gt;
There are more ideas and feature requests that would also help to make comments more attractive and motivate visitors to leave a comment:&lt;br /&gt;
&lt;br /&gt;
* Let anonymous users at least enter a name.&lt;br /&gt;
* Optionally send a notification email when a reply has been made to a user's comment (for registered users only).&lt;br /&gt;
* Being able to see the comment or original post while commenting on it.&lt;br /&gt;
&lt;br /&gt;
These ideas are not strictly part of the SoC task, but may be easy enough to implement or at least have to be considered in the design.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Category:Summer of Code]] [[Category:Development]]&lt;/div&gt;</summary>
		<author><name>LWC</name></author>	</entry>

	<entry>
		<id>http://gwiki3.thatlinuxbox.com/index.php?title=CommentAlgorithm&amp;diff=5598</id>
		<title>CommentAlgorithm</title>
		<link rel="alternate" type="text/html" href="http://gwiki3.thatlinuxbox.com/index.php?title=CommentAlgorithm&amp;diff=5598"/>
				<updated>2009-10-23T08:28:23Z</updated>
		
		<summary type="html">&lt;p&gt;LWC: /* Representing Geeklog's Comments in the Database */ Added titles&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;=Representing Geeklog's Comments in the Database=&lt;br /&gt;
&lt;br /&gt;
Since Geeklog 1.3.10, Geeklog's comments have been stored in the database with columns (''lft'', ''rht'') representing a (modified) pre-order traversal ordering. This method of storage was chosen to improve comment retrieval performance, especially when viewing a subset of the comments for a given story.&lt;br /&gt;
&lt;br /&gt;
==Details==&lt;br /&gt;
The idea behind pre-order traversal ordering, is that each node is ordered (or visited) before any of its children. In the modified preorder traversal algorithm implemented by Geeklog, the ''lft'' value of a comment is always less than the ''lft'' and ''rht'' values of all of the children of that node. Likewise the ''rht'' value of a node is always greater that the ''lft'' and ''rht'' values of all of the children of that node. (And trivially for any node, ''lft'' is always less than ''rht''.) A node without any children has the property ''rht'' is exactly one more than ''lft''. &lt;br /&gt;
&lt;br /&gt;
Example: Comment A is a top level comment to a story. Comments A-A and A-B are children of A and comments A-A-A, A-A-B, and A-A-C are children of A-A. The table below shows the values for each comment:&lt;br /&gt;
&lt;br /&gt;
{| cellpadding=&amp;quot;2&amp;quot; cellspacing=&amp;quot;0&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
! style=&amp;quot;width:25%&amp;quot; |comment&lt;br /&gt;
! style=&amp;quot;width:25%&amp;quot; |parent&lt;br /&gt;
! style=&amp;quot;width:25%&amp;quot; |lft&lt;br /&gt;
! style=&amp;quot;width:25%&amp;quot; |rht&lt;br /&gt;
|-&lt;br /&gt;
|A&lt;br /&gt;
|N/A&lt;br /&gt;
|1&lt;br /&gt;
|12&lt;br /&gt;
|-&lt;br /&gt;
|A-A&lt;br /&gt;
|A&lt;br /&gt;
|2&lt;br /&gt;
|9&lt;br /&gt;
|-&lt;br /&gt;
|A-B&lt;br /&gt;
|A&lt;br /&gt;
|10&lt;br /&gt;
|11&lt;br /&gt;
|-&lt;br /&gt;
|A-A-A&lt;br /&gt;
|A-A&lt;br /&gt;
|3&lt;br /&gt;
|4&lt;br /&gt;
|-&lt;br /&gt;
|A-A-B&lt;br /&gt;
|A-A&lt;br /&gt;
|5&lt;br /&gt;
|6&lt;br /&gt;
|-&lt;br /&gt;
|A-A-C&lt;br /&gt;
|A-A&lt;br /&gt;
|7&lt;br /&gt;
|8&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
The resulting database structure has many advantages. Selecting a subtree from the database is as easy as specifying the ''lft'' and ''rht'' numbers of the root node of the subtree. For instance, to get the subtree with root comment &amp;quot;A-A&amp;quot;:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;SELECT * FROM comments WHERE lft &amp;gt;= 2 AND rht &amp;lt;= 9&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Or selecting all the children of a give node:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;SELECT * FROM comments WHERE lft &amp;gt; 2 AND rht &amp;lt; 9&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
To select comments ordered for display in a &amp;quot;nested&amp;quot; format:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;SELECT * FROM comments ORDER BY lft&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Storing the preorder traversal information also allows us to easily find the path to a node (i.e. a nodes parents, grandparents, etc).&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;SELECT * FROM comments WHERE lft &amp;lt; 7 AND rht &amp;gt; 8&amp;lt;/tt&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Counting the number of children of a comment is equally easy: &amp;lt;code&amp;gt;('rht' - 'lft' - 1)/2&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Previously these operations required a (very slow) recursive algorithm. The way Geeklog had implemented this algorithm required one database query for every comment in the result set. Another way would have been to do one query to fetch all comments, and then use a recursive function to choose the desired comments. Both methods were extremely inefficient and caused load problems on frequently viewed Geeklog sites.&lt;br /&gt;
&lt;br /&gt;
The downside to this method is that inserting and deleting comments takes more work (three queries instead of one) and must be done in a single transaction (or a write lock on the table). Inserts:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;START TRANSACTION&amp;lt;br&amp;gt;&lt;br /&gt;
UPDATE comments SET rht = rht + 2 WHERE rht &amp;gt;= comment.rht&amp;lt;br&amp;gt;&lt;br /&gt;
UPDATE comments SET lft = lft + 2 WHERE lft &amp;gt;= comment.rht&amp;lt;br&amp;gt;&lt;br /&gt;
INSERT INTO comments SET lft = comment.rht, rht = comment.rht + 1&amp;lt;br&amp;gt;&lt;br /&gt;
COMMIT&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Deletions:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;START TRANSACTION&amp;lt;br&amp;gt;&lt;br /&gt;
UPDATE comments SET rht = rht - 2 WHERE rht &amp;gt; comment.rht&amp;lt;br&amp;gt;&lt;br /&gt;
UPDATE comments SET lft = lft - 2 WHERE lft &amp;gt; comment.rht&amp;lt;br&amp;gt;&lt;br /&gt;
DELETE FROM comments WHERE id = comment.id&amp;lt;br&amp;gt;&lt;br /&gt;
COMMIT&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
However, since fetching (reading) comments is a much more frequent action then adding or deleting comments and the increase in efficiency for fetching comments is much greater than the loss of efficiency for adding and deleting comments, the trade off is worth while.&lt;br /&gt;
&lt;br /&gt;
Please note that in the SQL examples above, parts of the query were left out to make the algorithm more clear. For more detail, see the Geeklog source code (specifically lib-comment.php).&lt;br /&gt;
&lt;br /&gt;
==External related articles==&lt;br /&gt;
* [http://www.sitepoint.com/article/hierarchical-data-database/2/ Storing Hierarchical Data in a Database]&lt;br /&gt;
* [http://www.ibase.ru/devinfo/DBMSTrees/sqltrees.html Trees in SQL]&lt;br /&gt;
* [http://en.wikipedia.org/wiki/Tree_traversal Tree Traversal]&lt;br /&gt;
* [http://dev.mysql.com/tech-resources/articles/hierarchical-data.html Managing Hierarchical Data in MySQL]&lt;/div&gt;</summary>
		<author><name>LWC</name></author>	</entry>

	<entry>
		<id>http://gwiki3.thatlinuxbox.com/index.php?title=PLG_getItemInfo&amp;diff=5503</id>
		<title>PLG getItemInfo</title>
		<link rel="alternate" type="text/html" href="http://gwiki3.thatlinuxbox.com/index.php?title=PLG_getItemInfo&amp;diff=5503"/>
				<updated>2009-06-01T15:28:41Z</updated>
		
		<summary type="html">&lt;p&gt;LWC: /* Additional properties */ =&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;= Introduction =&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;PLG_getItemInfo&amp;lt;/code&amp;gt; was introduced in Geeklog 1.4.0 and used internally as part of the implementation of Trackbacks and Pingbacks. The API was [[#Extended_API|extended]] in Geeklog 1.6.0 for use by the [[XMLSitemap Plugin]].&lt;br /&gt;
&lt;br /&gt;
The basic idea for this function is to request information for an item that is under a plugin's control (where, in this case, the list of &amp;quot;plugins&amp;quot; also includes Geeklog's built-in articles).&lt;br /&gt;
&lt;br /&gt;
= Original API =&lt;br /&gt;
&lt;br /&gt;
The API, as implemented in Geeklog versions 1.4.0 - 1.5.2:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;function PLG_getItemInfo($type, $id, $what)&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* &amp;lt;code&amp;gt;$type&amp;lt;/code&amp;gt; is the type of plugin we want to request information from. This is the internal name of the plugin, e.g. 'links' for the Links plugin. Additionally, 'article' can be used to request information for stories.&lt;br /&gt;
* &amp;lt;code&amp;gt;$id&amp;lt;/code&amp;gt; is the ID of the item we are requesting information about, e.g. the story ID (sid), link ID (lid), etc.&lt;br /&gt;
* &amp;lt;code&amp;gt;$what&amp;lt;/code&amp;gt; is a comma-separated list of keywords indicating the information we are requesting for the specified item. We will call these key/value pairs ''properties'' from now on.&amp;lt;br&amp;gt;Currently, the following properties are defined:&lt;br /&gt;
** 'url' - the complete URL of the item&lt;br /&gt;
** 'title' - the item's title or subject&lt;br /&gt;
** 'excerpt' - a short description of the item&lt;br /&gt;
** 'description' - the full description of the item, e.g. the article text&lt;br /&gt;
&lt;br /&gt;
The function returns an array of strings of the requested information, in the order defined by the &amp;lt;code&amp;gt;$what&amp;lt;/code&amp;gt; parameter, e.g. for&lt;br /&gt;
&amp;lt;pre&amp;gt;PLG_getItemInfo('article', 'welcome', 'url,title');&amp;lt;/pre&amp;gt;&lt;br /&gt;
it would return information about the default story on a fresh install of Geeklog:&lt;br /&gt;
&amp;lt;pre&amp;gt;array('http://www.example.com/article.php/welcome', 'Welcome to Geeklog!');&amp;lt;/pre&amp;gt;&lt;br /&gt;
For properties not supported by the plugin, an empty string will be returned.&lt;br /&gt;
&lt;br /&gt;
= Extended API =&lt;br /&gt;
&lt;br /&gt;
The idea behind this extended API (as of Geeklog 1.6.0) is to allow Geeklog and other plugins to request a list of items and information about those items at the same time. The extensions are designed to be backward-compatible, as outlined below.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;function PLG_getItemInfo($type, $id, $what, $uid = 0, $options = array())&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Plugin type ($type) ==&lt;br /&gt;
This includes 'article' for stories.&lt;br /&gt;
&lt;br /&gt;
== Item ID ($id) ==&lt;br /&gt;
&lt;br /&gt;
When requesting information for more than one item, the &amp;lt;code&amp;gt;$id&amp;lt;/code&amp;gt; parameter is not needed. In this case, it should be set to &amp;lt;tt&amp;gt;'*'&amp;lt;/tt&amp;gt; (a single asterisk character). This indicates to the plugin, that information for more than one item is requested.&lt;br /&gt;
&lt;br /&gt;
==Which properties ($what)==&lt;br /&gt;
A comma-separated list of item properties.&lt;br /&gt;
&lt;br /&gt;
== User ID ($uid) ==&lt;br /&gt;
&lt;br /&gt;
The original API did not allow for access control. All operations were performed with the access control of the current user. With the $uid parameter, it is now possible to request items that are only visible to a specific user.&lt;br /&gt;
&lt;br /&gt;
* Default: &amp;lt;code&amp;gt;$uid == 0&amp;lt;/code&amp;gt; - use the permissions of the current user. This is for backward-compatibility with the original API.&lt;br /&gt;
* For a &amp;lt;code&amp;gt;$uid &amp;gt; 0&amp;lt;/code&amp;gt;, only items that are accessible to that user should be returned.&lt;br /&gt;
&lt;br /&gt;
== Options ($options) ==&lt;br /&gt;
&lt;br /&gt;
''reserved for future extensions''&lt;br /&gt;
&lt;br /&gt;
== Return values ==&lt;br /&gt;
&lt;br /&gt;
When returning more than one entry, the return value is supposed to be an array of arrays (even if it only contains one entry). The properties should be returned using PHP's associative arrays using key/value pairs instead of relying on the order of properties. Properties that are not supported or available will not be set in the returned arrays, e.g. for &amp;lt;code&amp;gt;$what = 'url,something-unknown,title'&amp;lt;/code&amp;gt;:&lt;br /&gt;
&amp;lt;pre&amp;gt;array(&lt;br /&gt;
    array(&lt;br /&gt;
        'url' =&amp;gt; 'http://www.example.com/article.php/welcome',&lt;br /&gt;
        'title' =&amp;gt; 'Welcome to Geeklog!'&lt;br /&gt;
    ),&lt;br /&gt;
    array(&lt;br /&gt;
        'url' =&amp;gt; 'http://www.example.com/article.php/about',&lt;br /&gt;
        'title' =&amp;gt; 'About this site'&lt;br /&gt;
    )&lt;br /&gt;
)&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Additional properties ===&lt;br /&gt;
&lt;br /&gt;
* 'id' - an item's ID. Obviously, when requesting information about more than one item, we also need the IDs of those items to tell them apart.&lt;br /&gt;
* 'date-created' - date when the item was created, as a Unix timestamp.&lt;br /&gt;
* 'date-modified' - date when the item was last modified, as a Unix timestamp.&lt;br /&gt;
&lt;br /&gt;
'''Note:''' Plugins that only have one of either 'date-created' or 'date-modified' should only return that information (i.e. do not return a modified date when it's really the item's creation date). Plugins that do not keep any date information should, obviously, not return any either.&lt;br /&gt;
&lt;br /&gt;
Unknown properties should be silently ignored. This will allow for future extensions as well as for using properties that are only supported by some plugins.&lt;br /&gt;
&lt;br /&gt;
[[Category:Plugin Development]]&lt;/div&gt;</summary>
		<author><name>LWC</name></author>	</entry>

	<entry>
		<id>http://gwiki3.thatlinuxbox.com/index.php?title=PLG_getItemInfo&amp;diff=5502</id>
		<title>PLG getItemInfo</title>
		<link rel="alternate" type="text/html" href="http://gwiki3.thatlinuxbox.com/index.php?title=PLG_getItemInfo&amp;diff=5502"/>
				<updated>2009-06-01T15:28:07Z</updated>
		
		<summary type="html">&lt;p&gt;LWC: Deleted linebreaks and fixed order and added others&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;= Introduction =&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;PLG_getItemInfo&amp;lt;/code&amp;gt; was introduced in Geeklog 1.4.0 and used internally as part of the implementation of Trackbacks and Pingbacks. The API was [[#Extended_API|extended]] in Geeklog 1.6.0 for use by the [[XMLSitemap Plugin]].&lt;br /&gt;
&lt;br /&gt;
The basic idea for this function is to request information for an item that is under a plugin's control (where, in this case, the list of &amp;quot;plugins&amp;quot; also includes Geeklog's built-in articles).&lt;br /&gt;
&lt;br /&gt;
= Original API =&lt;br /&gt;
&lt;br /&gt;
The API, as implemented in Geeklog versions 1.4.0 - 1.5.2:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;function PLG_getItemInfo($type, $id, $what)&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* &amp;lt;code&amp;gt;$type&amp;lt;/code&amp;gt; is the type of plugin we want to request information from. This is the internal name of the plugin, e.g. 'links' for the Links plugin. Additionally, 'article' can be used to request information for stories.&lt;br /&gt;
* &amp;lt;code&amp;gt;$id&amp;lt;/code&amp;gt; is the ID of the item we are requesting information about, e.g. the story ID (sid), link ID (lid), etc.&lt;br /&gt;
* &amp;lt;code&amp;gt;$what&amp;lt;/code&amp;gt; is a comma-separated list of keywords indicating the information we are requesting for the specified item. We will call these key/value pairs ''properties'' from now on.&amp;lt;br&amp;gt;Currently, the following properties are defined:&lt;br /&gt;
** 'url' - the complete URL of the item&lt;br /&gt;
** 'title' - the item's title or subject&lt;br /&gt;
** 'excerpt' - a short description of the item&lt;br /&gt;
** 'description' - the full description of the item, e.g. the article text&lt;br /&gt;
&lt;br /&gt;
The function returns an array of strings of the requested information, in the order defined by the &amp;lt;code&amp;gt;$what&amp;lt;/code&amp;gt; parameter, e.g. for&lt;br /&gt;
&amp;lt;pre&amp;gt;PLG_getItemInfo('article', 'welcome', 'url,title');&amp;lt;/pre&amp;gt;&lt;br /&gt;
it would return information about the default story on a fresh install of Geeklog:&lt;br /&gt;
&amp;lt;pre&amp;gt;array('http://www.example.com/article.php/welcome', 'Welcome to Geeklog!');&amp;lt;/pre&amp;gt;&lt;br /&gt;
For properties not supported by the plugin, an empty string will be returned.&lt;br /&gt;
&lt;br /&gt;
= Extended API =&lt;br /&gt;
&lt;br /&gt;
The idea behind this extended API (as of Geeklog 1.6.0) is to allow Geeklog and other plugins to request a list of items and information about those items at the same time. The extensions are designed to be backward-compatible, as outlined below.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;function PLG_getItemInfo($type, $id, $what, $uid = 0, $options = array())&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Plugin type ($type) ==&lt;br /&gt;
This includes 'article' for stories.&lt;br /&gt;
&lt;br /&gt;
== Item ID ($id) ==&lt;br /&gt;
&lt;br /&gt;
When requesting information for more than one item, the &amp;lt;code&amp;gt;$id&amp;lt;/code&amp;gt; parameter is not needed. In this case, it should be set to &amp;lt;tt&amp;gt;'*'&amp;lt;/tt&amp;gt; (a single asterisk character). This indicates to the plugin, that information for more than one item is requested.&lt;br /&gt;
&lt;br /&gt;
==Which properties ($what)==&lt;br /&gt;
A comma-separated list of item properties.&lt;br /&gt;
&lt;br /&gt;
== User ID ($uid) ==&lt;br /&gt;
&lt;br /&gt;
The original API did not allow for access control. All operations were performed with the access control of the current user. With the $uid parameter, it is now possible to request items that are only visible to a specific user.&lt;br /&gt;
&lt;br /&gt;
* Default: &amp;lt;code&amp;gt;$uid == 0&amp;lt;/code&amp;gt; - use the permissions of the current user. This is for backward-compatibility with the original API.&lt;br /&gt;
* For a &amp;lt;code&amp;gt;$uid &amp;gt; 0&amp;lt;/code&amp;gt;, only items that are accessible to that user should be returned.&lt;br /&gt;
&lt;br /&gt;
== Options ($options) ==&lt;br /&gt;
&lt;br /&gt;
''reserved for future extensions''&lt;br /&gt;
&lt;br /&gt;
== Return values ==&lt;br /&gt;
&lt;br /&gt;
When returning more than one entry, the return value is supposed to be an array of arrays (even if it only contains one entry). The properties should be returned using PHP's associative arrays using key/value pairs instead of relying on the order of properties. Properties that are not supported or available will not be set in the returned arrays, e.g. for &amp;lt;code&amp;gt;$what = 'url,something-unknown,title'&amp;lt;/code&amp;gt;:&lt;br /&gt;
&amp;lt;pre&amp;gt;array(&lt;br /&gt;
    array(&lt;br /&gt;
        'url' =&amp;gt; 'http://www.example.com/article.php/welcome',&lt;br /&gt;
        'title' =&amp;gt; 'Welcome to Geeklog!'&lt;br /&gt;
    ),&lt;br /&gt;
    array(&lt;br /&gt;
        'url' =&amp;gt; 'http://www.example.com/article.php/about',&lt;br /&gt;
        'title' =&amp;gt; 'About this site'&lt;br /&gt;
    )&lt;br /&gt;
)&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Additional properties ==&lt;br /&gt;
&lt;br /&gt;
* 'id' - an item's ID. Obviously, when requesting information about more than one item, we also need the IDs of those items to tell them apart.&lt;br /&gt;
* 'date-created' - date when the item was created, as a Unix timestamp.&lt;br /&gt;
* 'date-modified' - date when the item was last modified, as a Unix timestamp.&lt;br /&gt;
&lt;br /&gt;
'''Note:''' Plugins that only have one of either 'date-created' or 'date-modified' should only return that information (i.e. do not return a modified date when it's really the item's creation date). Plugins that do not keep any date information should, obviously, not return any either.&lt;br /&gt;
&lt;br /&gt;
Unknown properties should be silently ignored. This will allow for future extensions as well as for using properties that are only supported by some plugins.&lt;br /&gt;
&lt;br /&gt;
[[Category:Plugin Development]]&lt;/div&gt;</summary>
		<author><name>LWC</name></author>	</entry>

	<entry>
		<id>http://gwiki3.thatlinuxbox.com/index.php?title=Adding_Moderation_Capability&amp;diff=5490</id>
		<title>Adding Moderation Capability</title>
		<link rel="alternate" type="text/html" href="http://gwiki3.thatlinuxbox.com/index.php?title=Adding_Moderation_Capability&amp;diff=5490"/>
				<updated>2009-05-30T09:42:19Z</updated>
		
		<summary type="html">&lt;p&gt;LWC: /* The functions */ Spaces&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;This section will describe and document how to enable your plugin to use the Geeklog moderation engine.&lt;br /&gt;
&lt;br /&gt;
==Note==&lt;br /&gt;
This set of functions is optional when creating your plugin, but should be used when your plugin has functionality that includes submitting of an item that needs to be reviewed by a site admin or plugin admin before posting to the site.  The Geeklog (GL) developers have made the implementation of this API very straight forward and enabled the API calls into the moderation related &lt;br /&gt;
core programs.&lt;br /&gt;
&lt;br /&gt;
===Version note===&lt;br /&gt;
You will need to be using Geeklog version 1.3.7 or apply the &lt;br /&gt;
changes noted in the appendix to successfully use the Moderation API's, though some functionality may work with previous versions of Geeklog.  The changes with 1.3.7 release include the following programs:  moderation.php, submit.php, plugin.class.php and lib-plugins.php.&lt;br /&gt;
Refer to the appendix if you have a previous release and want to review the needed changes.&lt;br /&gt;
&lt;br /&gt;
==The functions==&lt;br /&gt;
There are six (6) plugin functions that are required for the moderation plugin and two (2) optional functions.  The example functions that are provided can be used as guide, but they will required some changes to make them work for your plugin.  &lt;br /&gt;
&lt;br /&gt;
The following table summarizes the functions:&lt;br /&gt;
&lt;br /&gt;
{|cellPadding=&amp;quot;2&amp;quot; width=&amp;quot;100%&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
!width=4%|&lt;br /&gt;
!Function&lt;br /&gt;
!Description of Function&lt;br /&gt;
|-&lt;br /&gt;
|1&lt;br /&gt;
|[[#plugin_ismoderator_&amp;lt;plugin name&amp;gt;|plugin_ismoderator_&amp;lt;plugin name&amp;gt;]]&lt;br /&gt;
|Checks if the current user has rights to moderate for the plugin and returns true if this is the case, false otherwise.&lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
|2&lt;br /&gt;
|[[#plugin_submissioncount_&amp;lt;plugin name&amp;gt;|plugin_submissioncount_&amp;lt;plugin name&amp;gt;]]&lt;br /&gt;
|Calculates the current number of submissions awaiting moderation and returns that number.&lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
|3&lt;br /&gt;
|[[#plugin_savesubmission_&amp;lt;plugin name&amp;gt;|plugin_savesubmission_&amp;lt;plugin name&amp;gt;]]&lt;br /&gt;
|Takes the data input by the plugin submission form and populates the &amp;lt;plugin name&amp;gt; submission table with that data.&lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
|4&lt;br /&gt;
|[[#plugin_moderationvalues_&amp;lt;plugin name&amp;gt;|plugin_moderationvalues_&amp;lt;plugin name&amp;gt;]]&lt;br /&gt;
|Returns a list of important moderation values.  The list contains (in order): the row 'id' label, the main plugin table name, comma separated string of moderation fields, and the plugin submission table name.&lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
|5&lt;br /&gt;
|[[#plugin_itemlist_&amp;lt;plugin name&amp;gt;|plugin_itemlist_&amp;lt;plugin name&amp;gt;]]&lt;br /&gt;
|Uses the plugin class to return data required by moderation.php to list plugin objects that need to be moderated.&lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
|6&lt;br /&gt;
|[[#plugin_submit_&amp;lt;plugin name&amp;gt;|plugin_submit_&amp;lt;plugin name&amp;gt;]]&lt;br /&gt;
|Returns a string containing the HTML to display the plugin submission form.&lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
|7&lt;br /&gt;
|[[#plugin_moderationapprove_&amp;lt;plugin name&amp;gt;|plugin_moderationapprove_&amp;lt;plugin name&amp;gt;]]&lt;br /&gt;
|This optional function supplements moderation.php.  While moderation.php actually moves data from the &amp;lt;plugin name&amp;gt; submission table to the main &amp;lt;plugin name&amp;gt; table, this function executes all other submission approval tasks including any other database updates required by your plugin.&lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
|8&lt;br /&gt;
|[[#plugin_moderationdelete_&amp;lt;plugin name&amp;gt;|plugin_moderationdelete_&amp;lt;plugin name&amp;gt;]]&lt;br /&gt;
|This optional function supplements moderation.php.  While moderation.php actually removes data from the &amp;lt;plugin name&amp;gt; submission table, this function executes all other submission removal tasks including any other database updates required by your plugin.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== How to call the Moderation Engine ===&lt;br /&gt;
&lt;br /&gt;
After you implement the moderation functions in your plugin, you will need to call the Geeklog moderation engine or program to create or moderate the submission. This can be done by adding a link or button which redirects the user to submit.php or moderate.php with the necessary parameters from your plugin.&lt;br /&gt;
&lt;br /&gt;
The example below was used by the Mailing Lists plugin to link to the 'submit new mailing list' page.  The link to submit.php needs to be passed with the parameter '''type''' to indicate which plugin's submission form should be displayed.  The  variable $retval is assigned the formatted link which will be displayed as a link in the plugin display.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;$retval = &amp;quot;&amp;lt;a href='&amp;quot; . $_CONF['site_url'] . &amp;quot;/submit.php?type=lists'&amp;gt;&amp;quot; . $LANG_LISTS['SUBMITLIST'] . &amp;quot;&amp;lt;/a&amp;gt;&amp;quot;;&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
'''Admin interaction with the Moderation Engine:''' Once all the moderation&lt;br /&gt;
functions are implemented, the 'Submissions' link in the admin block will include a list of all submissions to be moderated (they can be approved, removed or edited).  You must write your own submission edit function located in $_CONF['site_admin_url'] . '/plugins/&amp;lt;plugin name&amp;gt;/&amp;lt;plugin name&amp;gt;.php. It will be passed the http variables id=&amp;lt;item id&amp;gt; and mode=editsubmission.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Plugin database changes ===&lt;br /&gt;
&lt;br /&gt;
The table &amp;lt;plugin name&amp;gt; submission must be the name of your submission &lt;br /&gt;
table.  This table can only contain a proper subset of the columns from the main &amp;lt;plugin name&amp;gt; table.  This allows the moderation.php script to &lt;br /&gt;
automatically copy those columns from the submission to the main table upon&lt;br /&gt;
approval.  All data in columns of the submission table that are not in the main table will be lost.&lt;br /&gt;
&lt;br /&gt;
=== Function details and examples ===&lt;br /&gt;
&lt;br /&gt;
This explanation of the plugin moderation API functions will use the Mailing Lists plugin for examples and give a detailed description of each function.&lt;br /&gt;
&lt;br /&gt;
====plugin_ismoderator_&amp;lt;plugin name&amp;gt;====&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
function plugin_ismoderator_lists()&lt;br /&gt;
{&lt;br /&gt;
    global $_USER, $_TABLES;&lt;br /&gt;
&lt;br /&gt;
    return SEC_hasRights('lists.admin');&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
====plugin_submissioncount_&amp;lt;plugin name&amp;gt;====&lt;br /&gt;
The '''''plugin_ismoderator'''''  function simply returns TRUE if &lt;br /&gt;
the current user has moderation privileges for the plugin.  In the example&lt;br /&gt;
to the right, The mailing lists plugin simply uses the security function &lt;br /&gt;
SEC_hasRights to determine if a user has the required rights.  The lists.admin permission was installed with the plugin.  You could use your own SQL query or some other criteria to determine access rights.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
function plugin_submissioncount_lists()&lt;br /&gt;
{&lt;br /&gt;
    global $_TABLES;&lt;br /&gt;
&lt;br /&gt;
    return DB_count($_TABLES['listssubmission']);&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
====plugin_savesubmission_&amp;lt;plugin name&amp;gt;====&lt;br /&gt;
The '''''plugin_submissioncount''''' function returns the number of &lt;br /&gt;
submissions for this plugin that are awaiting moderation.  This value is used to indicate the number of waiting submissions in the admin block.  A DB_count() on the plugin submission table is usually sufficient for this.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
function plugin_savesubmission_lists($A)&lt;br /&gt;
{&lt;br /&gt;
    global $_TABLES, $_USER, $_CONF;&lt;br /&gt;
&lt;br /&gt;
    // check for missing fields&lt;br /&gt;
    if (empty($A['ml_name']) || empty($A['ml_descr'])) {&lt;br /&gt;
        return false;&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    if (empty($_USER['uid'])) {&lt;br /&gt;
        $owner_id = 1;&lt;br /&gt;
    } else {&lt;br /&gt;
        $owner_id = $_USER['uid'];&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    if (SEC_hasRights('links.admin')) {&lt;br /&gt;
        $result = DB_getItem($_TABLES['groups'], '*', &amp;quot;grp_name = 'lists Admin'&amp;quot;);&lt;br /&gt;
        if ($_CONF['listsarchive'] == 'optional') {&lt;br /&gt;
            $archive = $_CONF['listsarchivedefault'];&lt;br /&gt;
        } elseif ($_CONF['listsarchive'] == 'no') {&lt;br /&gt;
            $archive = 0;&lt;br /&gt;
        } else {     // $_CONF['listsarchive'] == 'yes'&lt;br /&gt;
            $archive = 1;&lt;br /&gt;
        }&lt;br /&gt;
        DB_save($_TABLES['lists'], 'ml_id, ml_name, ml_descr, html, archive, owner_id, group_id',&lt;br /&gt;
                &amp;quot;'&amp;quot; . COM_makeSid() . &amp;quot;', '&amp;quot; . $A['ml_name'] . &amp;quot;', '&amp;quot; . $A['ml_descr'] &lt;br /&gt;
              . &amp;quot;', &amp;quot; . $_CONF['listshtml'] . &amp;quot;, $archive, $owner_id, &amp;quot; . $result['grp_id']);&lt;br /&gt;
    } elseif ($_CONF['listssubmission'] == 1) {&lt;br /&gt;
        DB_save($_TABLES['listssubmission'],&lt;br /&gt;
                'ml_id, ml_name, ml_descr',&lt;br /&gt;
                &amp;quot;'&amp;quot; . COM_makeSid() . &amp;quot;', '&amp;quot; . $A['ml_name'] . &amp;quot;', '&amp;quot; &lt;br /&gt;
              . $A['ml_descr'] . &amp;quot;'&amp;quot;);&lt;br /&gt;
    } else {&lt;br /&gt;
        return false;&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    if (DB_error()) {&lt;br /&gt;
        return false;&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    return true;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
====plugin_moderationvalues_&amp;lt;plugin name&amp;gt;====&lt;br /&gt;
The '''''plugin_savesubmission''''' function takes data entered into&lt;br /&gt;
the submission form and saves it to the submission table.  Optionally, this function can use different logic for an admin or power user as seen in the Mailing Lists Plugin.  &lt;br /&gt;
In addition to saving the information to the plugin's submission table, it must also check data entered for validity.   Upon failure the function should return false or redirect to the submission form.  If successful, the function should redirect to a relevant page, or return true.  In Geeklog 1.3.7 the plugin API expects the function to do a redirect (COM_refresh()).  If it does not, a successful return from the function &lt;br /&gt;
will redirect the user back to the Geeklog home page.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
function plugin_moderationvalues_lists()&lt;br /&gt;
{&lt;br /&gt;
    global $_TABLES;&lt;br /&gt;
&lt;br /&gt;
    return array('ml_id', $_TABLES['lists'], 'ml_id, ml_name, ml_descr', $_TABLES['listssubmission']);&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
====plugin_itemlist_&amp;lt;plugin name&amp;gt;====&lt;br /&gt;
The '''''plugin_moderationvalues''''' function returns important information used by the Plugin API to handle plugin submissions.  It must return an array consisting of the main column id (ml_id), the main table name ($_TABLES['lists']), a comma separated list of columns that will be copied from the plugin submission table to the main table (ml_id, ml_name, ml_descr), and the name of the submission table ($_TABLE['listssubmission']).  This information is used to automatically&lt;br /&gt;
copy information from the plugin submission table to the plugin main table when a submission is approved.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
function plugin_itemlist_lists()&lt;br /&gt;
{&lt;br /&gt;
    global $_TABLES;&lt;br /&gt;
&lt;br /&gt;
    if (plugin_ismoderator_lists()) {&lt;br /&gt;
        $plugin = new Plugin();&lt;br /&gt;
        $plugin-&amp;gt;submissionlabel = 'Mailing List Submissions';&lt;br /&gt;
        $plugin-&amp;gt;getsubmissionssql = SELECT ml_id as id, ml_name, ml_descr FROM  &lt;br /&gt;
                                   . $_TABLES['listssubmission'];&lt;br /&gt;
        $plugin-&amp;gt;addSubmissionHeading('List Name');&lt;br /&gt;
        $plugin-&amp;gt;addSubmissionHeading('List Description');&lt;br /&gt;
&lt;br /&gt;
        return $plugin;&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
====plugin_submit_&amp;lt;plugin name&amp;gt;====&lt;br /&gt;
The function '''''plugin_itemlist''''' returns a Plugin() class containing information that will displayed on the moderation.php page.  The following member variables of the Plugin class must be filled out:&lt;br /&gt;
&lt;br /&gt;
* '''submissionlabel:''' The title that indicate the plugin submission section.&lt;br /&gt;
* '''getsubmissionsql:''' An SQL query that will select all the data that will be displayed in the plugin submission section.  NOTE: one item (the unique id column) must be labeled id ('as id').&lt;br /&gt;
* '''addSubmissionHeading():'''  This function must be called once for every field besides the one labeled id.  The parameter passed should be the column name to be displayed.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
function plugin_submit_lists()&lt;br /&gt;
{&lt;br /&gt;
    global $_CONF, $LANG12;&lt;br /&gt;
&lt;br /&gt;
    if ($_CONF['listssubmission'] == 0 &amp;amp;amp;&amp;amp;amp; !SEC_hasRights('lists.admin')) {&lt;br /&gt;
        return &amp;quot;Submission queue disabled for mailing lists&amp;quot;;&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    if ($_POST['mode'] == $LANG12[32]) { // preview&lt;br /&gt;
        $A = $_POST;&lt;br /&gt;
        $ml_id = $A['ml_id'];&lt;br /&gt;
    } else {&lt;br /&gt;
        $ml_id = COM_makesid();&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    $template = new Template($_CONF['path'] . &amp;quot;plugins/lists/templates/public&amp;quot;);&lt;br /&gt;
    $template-&amp;gt;set_file(array('form' =&amp;gt; 'submit_form.thtml'));&lt;br /&gt;
    $template-&amp;gt;set_var('site_url', $_CONF['site_url']);&lt;br /&gt;
    $template-&amp;gt;set_var('lang_name', 'List Name');&lt;br /&gt;
    $template-&amp;gt;set_var('ml_name', $A['ml_name']);&lt;br /&gt;
    $template-&amp;gt;set_var('lang_descr', 'Description');&lt;br /&gt;
    $template-&amp;gt;set_var('ml_descr', $A['ml_descr']);&lt;br /&gt;
    $template-&amp;gt;set_var('ml_id', $ml_id);&lt;br /&gt;
    $template-&amp;gt;set_var('lang_preview', $LANG12[32]);&lt;br /&gt;
    $template-&amp;gt;set_var('lang_save', $LANG12[8]);&lt;br /&gt;
&lt;br /&gt;
    return $template-&amp;gt;parse('output', 'form');&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
====plugin_moderationapprove_&amp;lt;plugin name&amp;gt; ====&lt;br /&gt;
The function '''''plugin_submit''''' creates HTML that contains the submission form for the plugin.  It is recommended to use the Geeklog template functionality as shown here to create the form.  See the section of this manual [[Using Templates and Language Files|on templates]] for more information.  When creating the form, be sure to include fields for each variable you would like the user to fill along with preview and submit buttons.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
function plugin_moderationapprove_lists($id)&lt;br /&gt;
{&lt;br /&gt;
    global $_TABLES, $_USER, $_CONF;&lt;br /&gt;
&lt;br /&gt;
    $result = DB_query(&amp;quot;SELECT * FROM &amp;quot; . $_TABLES['groups'] &lt;br /&gt;
                     . &amp;quot; WHERE grp_name = 'lists Admin'&amp;quot;);&lt;br /&gt;
    $group  = DB_fetchArray($result);&lt;br /&gt;
    if ($_CONF['listsarchive'] == 'optional') {&lt;br /&gt;
        $archive = $_CONF['listsarchivedefault'];&lt;br /&gt;
    } elseif ($_CONF['listsarchive'] == 'no') {&lt;br /&gt;
        $archive = 0;&lt;br /&gt;
    } else {     // $_CONF['listsarchive'] == 'yes'&lt;br /&gt;
        $archive = 1;&lt;br /&gt;
    }&lt;br /&gt;
    $sql = &amp;quot;UPDATE &amp;quot; . $_TABLES['lists'] . &amp;quot; SET owner_id = &amp;quot; . $_USER['uid'] &lt;br /&gt;
         . &amp;quot;, group_id = &amp;quot; . $group['grp_id'] . &amp;quot;, html = &amp;quot; . $_CONF['listshtml']&lt;br /&gt;
         . &amp;quot;, archive = $archive WHERE ml_id = '$id'&amp;quot;;&lt;br /&gt;
    $result = DB_query($sql);&lt;br /&gt;
&lt;br /&gt;
    if (DB_error()) {&lt;br /&gt;
       return 'Error';&lt;br /&gt;
    }&lt;br /&gt;
    return '';&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
====plugin_moderationdelete_&amp;lt;plugin name&amp;gt;====&lt;br /&gt;
Although the moderation.php script takes care of the work of actually moving data from the plugin submission table to the main plugin table, often times a plugin requires more to be done to the plugin tables or for other information to be updated.  Geeklog provides the function '''''plugin_moderationapprove''''' for these tasks.  In the case of the lists plugin, the main plugin table is updated with additional data that it is not desirable for a user to enter.  Instead this function takes care of placing that information into the table.  As of now the return value for this function is ignored.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
function plugin_moderationdelete_lists($id)&lt;br /&gt;
{&lt;br /&gt;
    global $_TABLES;&lt;br /&gt;
&lt;br /&gt;
    // these tables should not contain any rows with ml_id = $id&lt;br /&gt;
    // this is done 'just in case'&lt;br /&gt;
    DB_delete($_TABLES['listsubscriptions'], 'ml_id', $id);&lt;br /&gt;
    DB_delete($_TABLES['listarchive'], 'ml_id', $id);&lt;br /&gt;
    DB_delete($_TABLES['listpermissions'], 'ml_id', $id);&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Although the moderation.php script takes care of the work of actually removing data from the plugin submission table for a submission deletion, often times a plugin requires more to be done to the plugin tables or for other information to be updated.  Geeklog provides the function '''''plugin_moderationdelete''''' for these tasks.  In the case of the lists plugin, tables are checked for extraneous data (that should not exist in most cases) and that data is removed if found.  As of now the return value for this function is ignored.&lt;br /&gt;
&lt;br /&gt;
[[Category:Plugin Developers Handbook]] [[Category:Plugin Development]]&lt;/div&gt;</summary>
		<author><name>LWC</name></author>	</entry>

	<entry>
		<id>http://gwiki3.thatlinuxbox.com/index.php?title=Adding_Moderation_Capability&amp;diff=5489</id>
		<title>Adding Moderation Capability</title>
		<link rel="alternate" type="text/html" href="http://gwiki3.thatlinuxbox.com/index.php?title=Adding_Moderation_Capability&amp;diff=5489"/>
				<updated>2009-05-30T09:41:36Z</updated>
		
		<summary type="html">&lt;p&gt;LWC: /* The functions */ Space&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;This section will describe and document how to enable your plugin to use the Geeklog moderation engine.&lt;br /&gt;
&lt;br /&gt;
==Note==&lt;br /&gt;
This set of functions is optional when creating your plugin, but should be used when your plugin has functionality that includes submitting of an item that needs to be reviewed by a site admin or plugin admin before posting to the site.  The Geeklog (GL) developers have made the implementation of this API very straight forward and enabled the API calls into the moderation related &lt;br /&gt;
core programs.&lt;br /&gt;
&lt;br /&gt;
===Version note===&lt;br /&gt;
You will need to be using Geeklog version 1.3.7 or apply the &lt;br /&gt;
changes noted in the appendix to successfully use the Moderation API's, though some functionality may work with previous versions of Geeklog.  The changes with 1.3.7 release include the following programs:  moderation.php, submit.php, plugin.class.php and lib-plugins.php.&lt;br /&gt;
Refer to the appendix if you have a previous release and want to review the needed changes.&lt;br /&gt;
&lt;br /&gt;
==The functions==&lt;br /&gt;
There are six (6) plugin functions that are required for the moderation plugin and two (2) optional functions.  The example functions that are provided can be used as guide, but they will required some changes to make them work for your plugin.  &lt;br /&gt;
&lt;br /&gt;
The following table summarizes the functions:&lt;br /&gt;
&lt;br /&gt;
{|cellPadding=&amp;quot;2&amp;quot; width=&amp;quot;100%&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
!width=4%|&lt;br /&gt;
!Function&lt;br /&gt;
!Description of Function&lt;br /&gt;
|-&lt;br /&gt;
|1&lt;br /&gt;
|[[#plugin_ismoderator_&amp;lt;plugin name&amp;gt;|plugin_ismoderator_&amp;lt;plugin name&amp;gt;]]&lt;br /&gt;
|Checks if the current user has rights to moderate for the plugin and returns true if this is the case, false otherwise.&lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
|2&lt;br /&gt;
|[[#plugin_submissioncount_&amp;lt;plugin name&amp;gt;|plugin_submissioncount_&amp;lt;plugin name&amp;gt;]]&lt;br /&gt;
|Calculates the current number of submissions awaiting moderation and returns that number.&lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
|3&lt;br /&gt;
|[[#plugin_savesubmission_&amp;lt;plugin name&amp;gt;|plugin_savesubmission_&amp;lt;plugin name&amp;gt;]]&lt;br /&gt;
|Takes the data input by the plugin submission form and populates the &amp;lt;plugin name&amp;gt; submission table with that data.&lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
|4&lt;br /&gt;
|[[#plugin_moderationvalues_&amp;lt;plugin name&amp;gt;|plugin_moderationvalues_&amp;lt;plugin name&amp;gt;]]&lt;br /&gt;
|Returns a list of important moderation values.  The list contains (in order): the row 'id' label, the main plugin table name, comma separated string of moderation fields, and the plugin submission table name.&lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
|5&lt;br /&gt;
|[[#plugin_itemlist_&amp;lt;plugin name&amp;gt;|plugin_itemlist_&amp;lt;plugin name&amp;gt;]]&lt;br /&gt;
|Uses the plugin class to return data required by moderation.php to list plugin objects that need to be moderated.&lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
|6&lt;br /&gt;
|[[#plugin_submit_&amp;lt;plugin name&amp;gt;|plugin_submit_&amp;lt;plugin name&amp;gt;]]&lt;br /&gt;
|Returns a string containing the HTML to display the plugin submission form.&lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
|7&lt;br /&gt;
|[[#plugin_moderationapprove_&amp;lt;plugin name&amp;gt;|plugin_moderationapprove_&amp;lt;plugin name&amp;gt;]]&lt;br /&gt;
|This optional function supplements moderation.php.  While moderation.php actually moves data from the &amp;lt;plugin name&amp;gt;submission table to the main &amp;lt;plugin name&amp;gt; table, this function executes all other submission approval tasks including any other database updates required by your plugin.&lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
|8&lt;br /&gt;
|[[#plugin_moderationdelete_&amp;lt;plugin name&amp;gt;|plugin_moderationdelete_&amp;lt;plugin name&amp;gt;]]&lt;br /&gt;
|This optional function supplements moderation.php.  While moderation.php actually removes data from the &amp;lt;plugin name&amp;gt;submission table, this function executes all other submission removal tasks including any other database updates required by your plugin.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== How to call the Moderation Engine ===&lt;br /&gt;
&lt;br /&gt;
After you implement the moderation functions in your plugin, you will need to call the Geeklog moderation engine or program to create or moderate the submission. This can be done by adding a link or button which redirects the user to submit.php or moderate.php with the necessary parameters from your plugin.&lt;br /&gt;
&lt;br /&gt;
The example below was used by the Mailing Lists plugin to link to the 'submit new mailing list' page.  The link to submit.php needs to be passed with the parameter '''type''' to indicate which plugin's submission form should be displayed.  The  variable $retval is assigned the formatted link which will be displayed as a link in the plugin display.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;$retval = &amp;quot;&amp;lt;a href='&amp;quot; . $_CONF['site_url'] . &amp;quot;/submit.php?type=lists'&amp;gt;&amp;quot; . $LANG_LISTS['SUBMITLIST'] . &amp;quot;&amp;lt;/a&amp;gt;&amp;quot;;&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
'''Admin interaction with the Moderation Engine:''' Once all the moderation&lt;br /&gt;
functions are implemented, the 'Submissions' link in the admin block will include a list of all submissions to be moderated (they can be approved, removed or edited).  You must write your own submission edit function located in $_CONF['site_admin_url'] . '/plugins/&amp;lt;plugin name&amp;gt;/&amp;lt;plugin name&amp;gt;.php. It will be passed the http variables id=&amp;lt;item id&amp;gt; and mode=editsubmission.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Plugin database changes ===&lt;br /&gt;
&lt;br /&gt;
The table &amp;lt;plugin name&amp;gt;submission must be the name of your submission &lt;br /&gt;
table.  This table can only contain a proper subset of the columns from the main &amp;lt;plugin name&amp;gt; table.  This allows the moderation.php script to &lt;br /&gt;
automatically copy those columns from the submission to the main table upon&lt;br /&gt;
approval.  All data in columns of the submission table that are not in the main table will be lost.&lt;br /&gt;
&lt;br /&gt;
=== Function details and examples ===&lt;br /&gt;
&lt;br /&gt;
This explanation of the plugin moderation API functions will use the Mailing Lists plugin for examples and give a detailed description of each function.&lt;br /&gt;
&lt;br /&gt;
====plugin_ismoderator_&amp;lt;plugin name&amp;gt;====&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
function plugin_ismoderator_lists()&lt;br /&gt;
{&lt;br /&gt;
    global $_USER, $_TABLES;&lt;br /&gt;
&lt;br /&gt;
    return SEC_hasRights('lists.admin');&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
====plugin_submissioncount_&amp;lt;plugin name&amp;gt;====&lt;br /&gt;
The '''''plugin_ismoderator'''''  function simply returns TRUE if &lt;br /&gt;
the current user has moderation privileges for the plugin.  In the example&lt;br /&gt;
to the right, The mailing lists plugin simply uses the security function &lt;br /&gt;
SEC_hasRights to determine if a user has the required rights.  The lists.admin permission was installed with the plugin.  You could use your own SQL query or some other criteria to determine access rights.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
function plugin_submissioncount_lists()&lt;br /&gt;
{&lt;br /&gt;
    global $_TABLES;&lt;br /&gt;
&lt;br /&gt;
    return DB_count($_TABLES['listssubmission']);&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
====plugin_savesubmission_&amp;lt;plugin name&amp;gt;====&lt;br /&gt;
The '''''plugin_submissioncount''''' function returns the number of &lt;br /&gt;
submissions for this plugin that are awaiting moderation.  This value is used to indicate the number of waiting submissions in the admin block.  A DB_count() on the plugin submission table is usually sufficient for this.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
function plugin_savesubmission_lists($A)&lt;br /&gt;
{&lt;br /&gt;
    global $_TABLES, $_USER, $_CONF;&lt;br /&gt;
&lt;br /&gt;
    // check for missing fields&lt;br /&gt;
    if (empty($A['ml_name']) || empty($A['ml_descr'])) {&lt;br /&gt;
        return false;&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    if (empty($_USER['uid'])) {&lt;br /&gt;
        $owner_id = 1;&lt;br /&gt;
    } else {&lt;br /&gt;
        $owner_id = $_USER['uid'];&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    if (SEC_hasRights('links.admin')) {&lt;br /&gt;
        $result = DB_getItem($_TABLES['groups'], '*', &amp;quot;grp_name = 'lists Admin'&amp;quot;);&lt;br /&gt;
        if ($_CONF['listsarchive'] == 'optional') {&lt;br /&gt;
            $archive = $_CONF['listsarchivedefault'];&lt;br /&gt;
        } elseif ($_CONF['listsarchive'] == 'no') {&lt;br /&gt;
            $archive = 0;&lt;br /&gt;
        } else {     // $_CONF['listsarchive'] == 'yes'&lt;br /&gt;
            $archive = 1;&lt;br /&gt;
        }&lt;br /&gt;
        DB_save($_TABLES['lists'], 'ml_id, ml_name, ml_descr, html, archive, owner_id, group_id',&lt;br /&gt;
                &amp;quot;'&amp;quot; . COM_makeSid() . &amp;quot;', '&amp;quot; . $A['ml_name'] . &amp;quot;', '&amp;quot; . $A['ml_descr'] &lt;br /&gt;
              . &amp;quot;', &amp;quot; . $_CONF['listshtml'] . &amp;quot;, $archive, $owner_id, &amp;quot; . $result['grp_id']);&lt;br /&gt;
    } elseif ($_CONF['listssubmission'] == 1) {&lt;br /&gt;
        DB_save($_TABLES['listssubmission'],&lt;br /&gt;
                'ml_id, ml_name, ml_descr',&lt;br /&gt;
                &amp;quot;'&amp;quot; . COM_makeSid() . &amp;quot;', '&amp;quot; . $A['ml_name'] . &amp;quot;', '&amp;quot; &lt;br /&gt;
              . $A['ml_descr'] . &amp;quot;'&amp;quot;);&lt;br /&gt;
    } else {&lt;br /&gt;
        return false;&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    if (DB_error()) {&lt;br /&gt;
        return false;&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    return true;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
====plugin_moderationvalues_&amp;lt;plugin name&amp;gt;====&lt;br /&gt;
The '''''plugin_savesubmission''''' function takes data entered into&lt;br /&gt;
the submission form and saves it to the submission table.  Optionally, this function can use different logic for an admin or power user as seen in the Mailing Lists Plugin.  &lt;br /&gt;
In addition to saving the information to the plugin's submission table, it must also check data entered for validity.   Upon failure the function should return false or redirect to the submission form.  If successful, the function should redirect to a relevant page, or return true.  In Geeklog 1.3.7 the plugin API expects the function to do a redirect (COM_refresh()).  If it does not, a successful return from the function &lt;br /&gt;
will redirect the user back to the Geeklog home page.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
function plugin_moderationvalues_lists()&lt;br /&gt;
{&lt;br /&gt;
    global $_TABLES;&lt;br /&gt;
&lt;br /&gt;
    return array('ml_id', $_TABLES['lists'], 'ml_id, ml_name, ml_descr', $_TABLES['listssubmission']);&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
====plugin_itemlist_&amp;lt;plugin name&amp;gt;====&lt;br /&gt;
The '''''plugin_moderationvalues''''' function returns important information used by the Plugin API to handle plugin submissions.  It must return an array consisting of the main column id (ml_id), the main table name ($_TABLES['lists']), a comma separated list of columns that will be copied from the plugin submission table to the main table (ml_id, ml_name, ml_descr), and the name of the submission table ($_TABLE['listssubmission']).  This information is used to automatically&lt;br /&gt;
copy information from the plugin submission table to the plugin main table when a submission is approved.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
function plugin_itemlist_lists()&lt;br /&gt;
{&lt;br /&gt;
    global $_TABLES;&lt;br /&gt;
&lt;br /&gt;
    if (plugin_ismoderator_lists()) {&lt;br /&gt;
        $plugin = new Plugin();&lt;br /&gt;
        $plugin-&amp;gt;submissionlabel = 'Mailing List Submissions';&lt;br /&gt;
        $plugin-&amp;gt;getsubmissionssql = SELECT ml_id as id, ml_name, ml_descr FROM  &lt;br /&gt;
                                   . $_TABLES['listssubmission'];&lt;br /&gt;
        $plugin-&amp;gt;addSubmissionHeading('List Name');&lt;br /&gt;
        $plugin-&amp;gt;addSubmissionHeading('List Description');&lt;br /&gt;
&lt;br /&gt;
        return $plugin;&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
====plugin_submit_&amp;lt;plugin name&amp;gt;====&lt;br /&gt;
The function '''''plugin_itemlist''''' returns a Plugin() class containing information that will displayed on the moderation.php page.  The following member variables of the Plugin class must be filled out:&lt;br /&gt;
&lt;br /&gt;
* '''submissionlabel:''' The title that indicate the plugin submission section.&lt;br /&gt;
* '''getsubmissionsql:''' An SQL query that will select all the data that will be displayed in the plugin submission section.  NOTE: one item (the unique id column) must be labeled id ('as id').&lt;br /&gt;
* '''addSubmissionHeading():'''  This function must be called once for every field besides the one labeled id.  The parameter passed should be the column name to be displayed.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
function plugin_submit_lists()&lt;br /&gt;
{&lt;br /&gt;
    global $_CONF, $LANG12;&lt;br /&gt;
&lt;br /&gt;
    if ($_CONF['listssubmission'] == 0 &amp;amp;amp;&amp;amp;amp; !SEC_hasRights('lists.admin')) {&lt;br /&gt;
        return &amp;quot;Submission queue disabled for mailing lists&amp;quot;;&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    if ($_POST['mode'] == $LANG12[32]) { // preview&lt;br /&gt;
        $A = $_POST;&lt;br /&gt;
        $ml_id = $A['ml_id'];&lt;br /&gt;
    } else {&lt;br /&gt;
        $ml_id = COM_makesid();&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    $template = new Template($_CONF['path'] . &amp;quot;plugins/lists/templates/public&amp;quot;);&lt;br /&gt;
    $template-&amp;gt;set_file(array('form' =&amp;gt; 'submit_form.thtml'));&lt;br /&gt;
    $template-&amp;gt;set_var('site_url', $_CONF['site_url']);&lt;br /&gt;
    $template-&amp;gt;set_var('lang_name', 'List Name');&lt;br /&gt;
    $template-&amp;gt;set_var('ml_name', $A['ml_name']);&lt;br /&gt;
    $template-&amp;gt;set_var('lang_descr', 'Description');&lt;br /&gt;
    $template-&amp;gt;set_var('ml_descr', $A['ml_descr']);&lt;br /&gt;
    $template-&amp;gt;set_var('ml_id', $ml_id);&lt;br /&gt;
    $template-&amp;gt;set_var('lang_preview', $LANG12[32]);&lt;br /&gt;
    $template-&amp;gt;set_var('lang_save', $LANG12[8]);&lt;br /&gt;
&lt;br /&gt;
    return $template-&amp;gt;parse('output', 'form');&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
====plugin_moderationapprove_&amp;lt;plugin name&amp;gt; ====&lt;br /&gt;
The function '''''plugin_submit''''' creates HTML that contains the submission form for the plugin.  It is recommended to use the Geeklog template functionality as shown here to create the form.  See the section of this manual [[Using Templates and Language Files|on templates]] for more information.  When creating the form, be sure to include fields for each variable you would like the user to fill along with preview and submit buttons.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
function plugin_moderationapprove_lists($id)&lt;br /&gt;
{&lt;br /&gt;
    global $_TABLES, $_USER, $_CONF;&lt;br /&gt;
&lt;br /&gt;
    $result = DB_query(&amp;quot;SELECT * FROM &amp;quot; . $_TABLES['groups'] &lt;br /&gt;
                     . &amp;quot; WHERE grp_name = 'lists Admin'&amp;quot;);&lt;br /&gt;
    $group  = DB_fetchArray($result);&lt;br /&gt;
    if ($_CONF['listsarchive'] == 'optional') {&lt;br /&gt;
        $archive = $_CONF['listsarchivedefault'];&lt;br /&gt;
    } elseif ($_CONF['listsarchive'] == 'no') {&lt;br /&gt;
        $archive = 0;&lt;br /&gt;
    } else {     // $_CONF['listsarchive'] == 'yes'&lt;br /&gt;
        $archive = 1;&lt;br /&gt;
    }&lt;br /&gt;
    $sql = &amp;quot;UPDATE &amp;quot; . $_TABLES['lists'] . &amp;quot; SET owner_id = &amp;quot; . $_USER['uid'] &lt;br /&gt;
         . &amp;quot;, group_id = &amp;quot; . $group['grp_id'] . &amp;quot;, html = &amp;quot; . $_CONF['listshtml']&lt;br /&gt;
         . &amp;quot;, archive = $archive WHERE ml_id = '$id'&amp;quot;;&lt;br /&gt;
    $result = DB_query($sql);&lt;br /&gt;
&lt;br /&gt;
    if (DB_error()) {&lt;br /&gt;
       return 'Error';&lt;br /&gt;
    }&lt;br /&gt;
    return '';&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
====plugin_moderationdelete_&amp;lt;plugin name&amp;gt;====&lt;br /&gt;
Although the moderation.php script takes care of the work of actually moving data from the plugin submission table to the main plugin table, often times a plugin requires more to be done to the plugin tables or for other information to be updated.  Geeklog provides the function '''''plugin_moderationapprove''''' for these tasks.  In the case of the lists plugin, the main plugin table is updated with additional data that it is not desirable for a user to enter.  Instead this function takes care of placing that information into the table.  As of now the return value for this function is ignored.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
function plugin_moderationdelete_lists($id)&lt;br /&gt;
{&lt;br /&gt;
    global $_TABLES;&lt;br /&gt;
&lt;br /&gt;
    // these tables should not contain any rows with ml_id = $id&lt;br /&gt;
    // this is done 'just in case'&lt;br /&gt;
    DB_delete($_TABLES['listsubscriptions'], 'ml_id', $id);&lt;br /&gt;
    DB_delete($_TABLES['listarchive'], 'ml_id', $id);&lt;br /&gt;
    DB_delete($_TABLES['listpermissions'], 'ml_id', $id);&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Although the moderation.php script takes care of the work of actually removing data from the plugin submission table for a submission deletion, often times a plugin requires more to be done to the plugin tables or for other information to be updated.  Geeklog provides the function '''''plugin_moderationdelete''''' for these tasks.  In the case of the lists plugin, tables are checked for extraneous data (that should not exist in most cases) and that data is removed if found.  As of now the return value for this function is ignored.&lt;br /&gt;
&lt;br /&gt;
[[Category:Plugin Developers Handbook]] [[Category:Plugin Development]]&lt;/div&gt;</summary>
		<author><name>LWC</name></author>	</entry>

	<entry>
		<id>http://gwiki3.thatlinuxbox.com/index.php?title=Adding_Moderation_Capability&amp;diff=5488</id>
		<title>Adding Moderation Capability</title>
		<link rel="alternate" type="text/html" href="http://gwiki3.thatlinuxbox.com/index.php?title=Adding_Moderation_Capability&amp;diff=5488"/>
				<updated>2009-05-30T09:40:32Z</updated>
		
		<summary type="html">&lt;p&gt;LWC: Formatted and fixed&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;This section will describe and document how to enable your plugin to use the Geeklog moderation engine.&lt;br /&gt;
&lt;br /&gt;
==Note==&lt;br /&gt;
This set of functions is optional when creating your plugin, but should be used when your plugin has functionality that includes submitting of an item that needs to be reviewed by a site admin or plugin admin before posting to the site.  The Geeklog (GL) developers have made the implementation of this API very straight forward and enabled the API calls into the moderation related &lt;br /&gt;
core programs.&lt;br /&gt;
&lt;br /&gt;
===Version note===&lt;br /&gt;
You will need to be using Geeklog version 1.3.7 or apply the &lt;br /&gt;
changes noted in the appendix to successfully use the Moderation API's, though some functionality may work with previous versions of Geeklog.  The changes with 1.3.7 release include the following programs:  moderation.php, submit.php, plugin.class.php and lib-plugins.php.&lt;br /&gt;
Refer to the appendix if you have a previous release and want to review the needed changes.&lt;br /&gt;
&lt;br /&gt;
==The functions==&lt;br /&gt;
There are six (6) plugin functions that are required for the moderation plugin and two (2) optional functions.  The example functions that are provided can be used as guide, but they will required some changes to make them work for your plugin.  &lt;br /&gt;
&lt;br /&gt;
The following table summarizes the functions:&lt;br /&gt;
&lt;br /&gt;
{|cellPadding=&amp;quot;2&amp;quot; width=&amp;quot;100%&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
!width=4%|&lt;br /&gt;
!Function&lt;br /&gt;
!Description of Function&lt;br /&gt;
|-&lt;br /&gt;
|1&lt;br /&gt;
|[[#plugin_ismoderator_&amp;lt;plugin name&amp;gt;|plugin_ismoderator_&amp;lt;plugin name&amp;gt;]]&lt;br /&gt;
|Checks if the current user has rights to moderate for the plugin and returns true if this is the case, false otherwise.&lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
|2&lt;br /&gt;
|[[#plugin_submissioncount_&amp;lt;plugin name&amp;gt;|plugin_submissioncount_&amp;lt;plugin name&amp;gt;]]&lt;br /&gt;
|Calculates the current number of submissions awaiting moderation and returns that number.&lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
|3&lt;br /&gt;
|[[#plugin_savesubmission_&amp;lt;plugin name&amp;gt;|plugin_savesubmission_&amp;lt;plugin name&amp;gt;]]&lt;br /&gt;
|Takes the data input by the plugin submission form and populates the &amp;lt;plugin name&amp;gt;submission table with that data.&lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
|4&lt;br /&gt;
|[[#plugin_moderationvalues_&amp;lt;plugin name&amp;gt;|plugin_moderationvalues_&amp;lt;plugin name&amp;gt;]]&lt;br /&gt;
|Returns a list of important moderation values.  The list contains (in order): the row 'id' label, the main plugin table name, comma separated string of moderation fields, and the plugin submission table name.&lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
|5&lt;br /&gt;
|[[#plugin_itemlist_&amp;lt;plugin name&amp;gt;|plugin_itemlist_&amp;lt;plugin name&amp;gt;]]&lt;br /&gt;
|Uses the plugin class to return data required by moderation.php to list plugin objects that need to be moderated.&lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
|6&lt;br /&gt;
|[[#plugin_submit_&amp;lt;plugin name&amp;gt;|plugin_submit_&amp;lt;plugin name&amp;gt;]]&lt;br /&gt;
|Returns a string containing the HTML to display the plugin submission form.&lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
|7&lt;br /&gt;
|[[#plugin_moderationapprove_&amp;lt;plugin name&amp;gt;|plugin_moderationapprove_&amp;lt;plugin name&amp;gt;]]&lt;br /&gt;
|This optional function supplements moderation.php.  While moderation.php actually moves data from the &amp;lt;plugin name&amp;gt;submission table to the main &amp;lt;plugin name&amp;gt; table, this function executes all other submission approval tasks including any other database updates required by your plugin.&lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
|8&lt;br /&gt;
|[[#plugin_moderationdelete_&amp;lt;plugin name&amp;gt;|plugin_moderationdelete_&amp;lt;plugin name&amp;gt;]]&lt;br /&gt;
|This optional function supplements moderation.php.  While moderation.php actually removes data from the &amp;lt;plugin name&amp;gt;submission table, this function executes all other submission removal tasks including any other database updates required by your plugin.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== How to call the Moderation Engine ===&lt;br /&gt;
&lt;br /&gt;
After you implement the moderation functions in your plugin, you will need to call the Geeklog moderation engine or program to create or moderate the submission. This can be done by adding a link or button which redirects the user to submit.php or moderate.php with the necessary parameters from your plugin.&lt;br /&gt;
&lt;br /&gt;
The example below was used by the Mailing Lists plugin to link to the 'submit new mailing list' page.  The link to submit.php needs to be passed with the parameter '''type''' to indicate which plugin's submission form should be displayed.  The  variable $retval is assigned the formatted link which will be displayed as a link in the plugin display.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;$retval = &amp;quot;&amp;lt;a href='&amp;quot; . $_CONF['site_url'] . &amp;quot;/submit.php?type=lists'&amp;gt;&amp;quot; . $LANG_LISTS['SUBMITLIST'] . &amp;quot;&amp;lt;/a&amp;gt;&amp;quot;;&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
'''Admin interaction with the Moderation Engine:''' Once all the moderation&lt;br /&gt;
functions are implemented, the 'Submissions' link in the admin block will include a list of all submissions to be moderated (they can be approved, removed or edited).  You must write your own submission edit function located in $_CONF['site_admin_url'] . '/plugins/&amp;lt;plugin name&amp;gt;/&amp;lt;plugin name&amp;gt;.php. It will be passed the http variables id=&amp;lt;item id&amp;gt; and mode=editsubmission.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Plugin database changes ===&lt;br /&gt;
&lt;br /&gt;
The table &amp;lt;plugin name&amp;gt;submission must be the name of your submission &lt;br /&gt;
table.  This table can only contain a proper subset of the columns from the main &amp;lt;plugin name&amp;gt; table.  This allows the moderation.php script to &lt;br /&gt;
automatically copy those columns from the submission to the main table upon&lt;br /&gt;
approval.  All data in columns of the submission table that are not in the main table will be lost.&lt;br /&gt;
&lt;br /&gt;
=== Function details and examples ===&lt;br /&gt;
&lt;br /&gt;
This explanation of the plugin moderation API functions will use the Mailing Lists plugin for examples and give a detailed description of each function.&lt;br /&gt;
&lt;br /&gt;
====plugin_ismoderator_&amp;lt;plugin name&amp;gt;====&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
function plugin_ismoderator_lists()&lt;br /&gt;
{&lt;br /&gt;
    global $_USER, $_TABLES;&lt;br /&gt;
&lt;br /&gt;
    return SEC_hasRights('lists.admin');&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
====plugin_submissioncount_&amp;lt;plugin name&amp;gt;====&lt;br /&gt;
The '''''plugin_ismoderator'''''  function simply returns TRUE if &lt;br /&gt;
the current user has moderation privileges for the plugin.  In the example&lt;br /&gt;
to the right, The mailing lists plugin simply uses the security function &lt;br /&gt;
SEC_hasRights to determine if a user has the required rights.  The lists.admin permission was installed with the plugin.  You could use your own SQL query or some other criteria to determine access rights.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
function plugin_submissioncount_lists()&lt;br /&gt;
{&lt;br /&gt;
    global $_TABLES;&lt;br /&gt;
&lt;br /&gt;
    return DB_count($_TABLES['listssubmission']);&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
====plugin_savesubmission_&amp;lt;plugin name&amp;gt;====&lt;br /&gt;
The '''''plugin_submissioncount''''' function returns the number of &lt;br /&gt;
submissions for this plugin that are awaiting moderation.  This value is used to indicate the number of waiting submissions in the admin block.  A DB_count() on the plugin submission table is usually sufficient for this.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
function plugin_savesubmission_lists($A)&lt;br /&gt;
{&lt;br /&gt;
    global $_TABLES, $_USER, $_CONF;&lt;br /&gt;
&lt;br /&gt;
    // check for missing fields&lt;br /&gt;
    if (empty($A['ml_name']) || empty($A['ml_descr'])) {&lt;br /&gt;
        return false;&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    if (empty($_USER['uid'])) {&lt;br /&gt;
        $owner_id = 1;&lt;br /&gt;
    } else {&lt;br /&gt;
        $owner_id = $_USER['uid'];&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    if (SEC_hasRights('links.admin')) {&lt;br /&gt;
        $result = DB_getItem($_TABLES['groups'], '*', &amp;quot;grp_name = 'lists Admin'&amp;quot;);&lt;br /&gt;
        if ($_CONF['listsarchive'] == 'optional') {&lt;br /&gt;
            $archive = $_CONF['listsarchivedefault'];&lt;br /&gt;
        } elseif ($_CONF['listsarchive'] == 'no') {&lt;br /&gt;
            $archive = 0;&lt;br /&gt;
        } else {     // $_CONF['listsarchive'] == 'yes'&lt;br /&gt;
            $archive = 1;&lt;br /&gt;
        }&lt;br /&gt;
        DB_save($_TABLES['lists'], 'ml_id, ml_name, ml_descr, html, archive, owner_id, group_id',&lt;br /&gt;
                &amp;quot;'&amp;quot; . COM_makeSid() . &amp;quot;', '&amp;quot; . $A['ml_name'] . &amp;quot;', '&amp;quot; . $A['ml_descr'] &lt;br /&gt;
              . &amp;quot;', &amp;quot; . $_CONF['listshtml'] . &amp;quot;, $archive, $owner_id, &amp;quot; . $result['grp_id']);&lt;br /&gt;
    } elseif ($_CONF['listssubmission'] == 1) {&lt;br /&gt;
        DB_save($_TABLES['listssubmission'],&lt;br /&gt;
                'ml_id, ml_name, ml_descr',&lt;br /&gt;
                &amp;quot;'&amp;quot; . COM_makeSid() . &amp;quot;', '&amp;quot; . $A['ml_name'] . &amp;quot;', '&amp;quot; &lt;br /&gt;
              . $A['ml_descr'] . &amp;quot;'&amp;quot;);&lt;br /&gt;
    } else {&lt;br /&gt;
        return false;&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    if (DB_error()) {&lt;br /&gt;
        return false;&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    return true;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
====plugin_moderationvalues_&amp;lt;plugin name&amp;gt;====&lt;br /&gt;
The '''''plugin_savesubmission''''' function takes data entered into&lt;br /&gt;
the submission form and saves it to the submission table.  Optionally, this function can use different logic for an admin or power user as seen in the Mailing Lists Plugin.  &lt;br /&gt;
In addition to saving the information to the plugin's submission table, it must also check data entered for validity.   Upon failure the function should return false or redirect to the submission form.  If successful, the function should redirect to a relevant page, or return true.  In Geeklog 1.3.7 the plugin API expects the function to do a redirect (COM_refresh()).  If it does not, a successful return from the function &lt;br /&gt;
will redirect the user back to the Geeklog home page.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
function plugin_moderationvalues_lists()&lt;br /&gt;
{&lt;br /&gt;
    global $_TABLES;&lt;br /&gt;
&lt;br /&gt;
    return array('ml_id', $_TABLES['lists'], 'ml_id, ml_name, ml_descr', $_TABLES['listssubmission']);&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
====plugin_itemlist_&amp;lt;plugin name&amp;gt;====&lt;br /&gt;
The '''''plugin_moderationvalues''''' function returns important information used by the Plugin API to handle plugin submissions.  It must return an array consisting of the main column id (ml_id), the main table name ($_TABLES['lists']), a comma separated list of columns that will be copied from the plugin submission table to the main table (ml_id, ml_name, ml_descr), and the name of the submission table ($_TABLE['listssubmission']).  This information is used to automatically&lt;br /&gt;
copy information from the plugin submission table to the plugin main table when a submission is approved.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
function plugin_itemlist_lists()&lt;br /&gt;
{&lt;br /&gt;
    global $_TABLES;&lt;br /&gt;
&lt;br /&gt;
    if (plugin_ismoderator_lists()) {&lt;br /&gt;
        $plugin = new Plugin();&lt;br /&gt;
        $plugin-&amp;gt;submissionlabel = 'Mailing List Submissions';&lt;br /&gt;
        $plugin-&amp;gt;getsubmissionssql = SELECT ml_id as id, ml_name, ml_descr FROM  &lt;br /&gt;
                                   . $_TABLES['listssubmission'];&lt;br /&gt;
        $plugin-&amp;gt;addSubmissionHeading('List Name');&lt;br /&gt;
        $plugin-&amp;gt;addSubmissionHeading('List Description');&lt;br /&gt;
&lt;br /&gt;
        return $plugin;&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
====plugin_submit_&amp;lt;plugin name&amp;gt;====&lt;br /&gt;
The function '''''plugin_itemlist''''' returns a Plugin() class containing information that will displayed on the moderation.php page.  The following member variables of the Plugin class must be filled out:&lt;br /&gt;
&lt;br /&gt;
* '''submissionlabel:''' The title that indicate the plugin submission section.&lt;br /&gt;
* '''getsubmissionsql:''' An SQL query that will select all the data that will be displayed in the plugin submission section.  NOTE: one item (the unique id column) must be labeled id ('as id').&lt;br /&gt;
* '''addSubmissionHeading():'''  This function must be called once for every field besides the one labeled id.  The parameter passed should be the column name to be displayed.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
function plugin_submit_lists()&lt;br /&gt;
{&lt;br /&gt;
    global $_CONF, $LANG12;&lt;br /&gt;
&lt;br /&gt;
    if ($_CONF['listssubmission'] == 0 &amp;amp;amp;&amp;amp;amp; !SEC_hasRights('lists.admin')) {&lt;br /&gt;
        return &amp;quot;Submission queue disabled for mailing lists&amp;quot;;&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    if ($_POST['mode'] == $LANG12[32]) { // preview&lt;br /&gt;
        $A = $_POST;&lt;br /&gt;
        $ml_id = $A['ml_id'];&lt;br /&gt;
    } else {&lt;br /&gt;
        $ml_id = COM_makesid();&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    $template = new Template($_CONF['path'] . &amp;quot;plugins/lists/templates/public&amp;quot;);&lt;br /&gt;
    $template-&amp;gt;set_file(array('form' =&amp;gt; 'submit_form.thtml'));&lt;br /&gt;
    $template-&amp;gt;set_var('site_url', $_CONF['site_url']);&lt;br /&gt;
    $template-&amp;gt;set_var('lang_name', 'List Name');&lt;br /&gt;
    $template-&amp;gt;set_var('ml_name', $A['ml_name']);&lt;br /&gt;
    $template-&amp;gt;set_var('lang_descr', 'Description');&lt;br /&gt;
    $template-&amp;gt;set_var('ml_descr', $A['ml_descr']);&lt;br /&gt;
    $template-&amp;gt;set_var('ml_id', $ml_id);&lt;br /&gt;
    $template-&amp;gt;set_var('lang_preview', $LANG12[32]);&lt;br /&gt;
    $template-&amp;gt;set_var('lang_save', $LANG12[8]);&lt;br /&gt;
&lt;br /&gt;
    return $template-&amp;gt;parse('output', 'form');&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
====plugin_moderationapprove_&amp;lt;plugin name&amp;gt; ====&lt;br /&gt;
The function '''''plugin_submit''''' creates HTML that contains the submission form for the plugin.  It is recommended to use the Geeklog template functionality as shown here to create the form.  See the section of this manual [[Using Templates and Language Files|on templates]] for more information.  When creating the form, be sure to include fields for each variable you would like the user to fill along with preview and submit buttons.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
function plugin_moderationapprove_lists($id)&lt;br /&gt;
{&lt;br /&gt;
    global $_TABLES, $_USER, $_CONF;&lt;br /&gt;
&lt;br /&gt;
    $result = DB_query(&amp;quot;SELECT * FROM &amp;quot; . $_TABLES['groups'] &lt;br /&gt;
                     . &amp;quot; WHERE grp_name = 'lists Admin'&amp;quot;);&lt;br /&gt;
    $group  = DB_fetchArray($result);&lt;br /&gt;
    if ($_CONF['listsarchive'] == 'optional') {&lt;br /&gt;
        $archive = $_CONF['listsarchivedefault'];&lt;br /&gt;
    } elseif ($_CONF['listsarchive'] == 'no') {&lt;br /&gt;
        $archive = 0;&lt;br /&gt;
    } else {     // $_CONF['listsarchive'] == 'yes'&lt;br /&gt;
        $archive = 1;&lt;br /&gt;
    }&lt;br /&gt;
    $sql = &amp;quot;UPDATE &amp;quot; . $_TABLES['lists'] . &amp;quot; SET owner_id = &amp;quot; . $_USER['uid'] &lt;br /&gt;
         . &amp;quot;, group_id = &amp;quot; . $group['grp_id'] . &amp;quot;, html = &amp;quot; . $_CONF['listshtml']&lt;br /&gt;
         . &amp;quot;, archive = $archive WHERE ml_id = '$id'&amp;quot;;&lt;br /&gt;
    $result = DB_query($sql);&lt;br /&gt;
&lt;br /&gt;
    if (DB_error()) {&lt;br /&gt;
       return 'Error';&lt;br /&gt;
    }&lt;br /&gt;
    return '';&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
====plugin_moderationdelete_&amp;lt;plugin name&amp;gt;====&lt;br /&gt;
Although the moderation.php script takes care of the work of actually moving data from the plugin submission table to the main plugin table, often times a plugin requires more to be done to the plugin tables or for other information to be updated.  Geeklog provides the function '''''plugin_moderationapprove''''' for these tasks.  In the case of the lists plugin, the main plugin table is updated with additional data that it is not desirable for a user to enter.  Instead this function takes care of placing that information into the table.  As of now the return value for this function is ignored.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
function plugin_moderationdelete_lists($id)&lt;br /&gt;
{&lt;br /&gt;
    global $_TABLES;&lt;br /&gt;
&lt;br /&gt;
    // these tables should not contain any rows with ml_id = $id&lt;br /&gt;
    // this is done 'just in case'&lt;br /&gt;
    DB_delete($_TABLES['listsubscriptions'], 'ml_id', $id);&lt;br /&gt;
    DB_delete($_TABLES['listarchive'], 'ml_id', $id);&lt;br /&gt;
    DB_delete($_TABLES['listpermissions'], 'ml_id', $id);&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Although the moderation.php script takes care of the work of actually removing data from the plugin submission table for a submission deletion, often times a plugin requires more to be done to the plugin tables or for other information to be updated.  Geeklog provides the function '''''plugin_moderationdelete''''' for these tasks.  In the case of the lists plugin, tables are checked for extraneous data (that should not exist in most cases) and that data is removed if found.  As of now the return value for this function is ignored.&lt;br /&gt;
&lt;br /&gt;
[[Category:Plugin Developers Handbook]] [[Category:Plugin Development]]&lt;/div&gt;</summary>
		<author><name>LWC</name></author>	</entry>

	<entry>
		<id>http://gwiki3.thatlinuxbox.com/index.php?title=Using_Geeklog%27s_Improved_Search_Engine&amp;diff=5473</id>
		<title>Using Geeklog's Improved Search Engine</title>
		<link rel="alternate" type="text/html" href="http://gwiki3.thatlinuxbox.com/index.php?title=Using_Geeklog%27s_Improved_Search_Engine&amp;diff=5473"/>
				<updated>2009-05-26T15:28:39Z</updated>
		
		<summary type="html">&lt;p&gt;LWC: /* Standard SQL Query */ Fixed&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;==Plugins' compatibility with old Geeklog versions==&lt;br /&gt;
If you want to make your plugin compatible with Geeklog v1.5 and below, you must also implement [[Using Geeklog's Search Engine]].&lt;br /&gt;
&lt;br /&gt;
==The functions==&lt;br /&gt;
Tying your plugin into Geeklogs search API is rather easy.  Easy, that is, if you know how to search &lt;br /&gt;
your plugins data already. The Geeklog search API provides a way for you to return the SQL query back to Geeklog which will be executed in the core and the results included in its search page.&lt;br /&gt;
&lt;br /&gt;
For the data in your plugin to be searched by Geeklog's search functions, there are two functions that you need to implement in your plugins function.inc:&lt;br /&gt;
&lt;br /&gt;
*plugin_searchtypes_{plugin_name}() returns to Geeklog the type(s) of search.&lt;br /&gt;
*plugin_dopluginsearch_{plugin_name}() returns the search SQL query back to Geeklog.&lt;br /&gt;
&lt;br /&gt;
Let's look at each of them in turn:&lt;br /&gt;
&lt;br /&gt;
=== plugin_searchtypes_{plugin_name}() ===&lt;br /&gt;
&lt;br /&gt;
This function takes no parameters and returns an associative array of the search type.  The normal code for this&lt;br /&gt;
function will make it all clear.  Normally the function looks like this:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;function plugin_searchtypes_{plugin_name}()&lt;br /&gt;
{&lt;br /&gt;
    global $LANG_PL00;&lt;br /&gt;
    $tmp['{plugin_name}']= $LANG_PL00['searchtype'];&lt;br /&gt;
    return $tmp;&lt;br /&gt;
}&amp;lt;/pre&amp;gt;&lt;br /&gt;
&amp;lt;sup&amp;gt;(don't forget to replace {plugin_name} with the actual name).&amp;lt;/sup&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Naturally all occurrences of plugin would be replaced with the name of your &lt;br /&gt;
plugin and the LANGUAGE varible $LANG_PL00 is just an example. Your Plugin needs &lt;br /&gt;
to use a unique variable name so replace PL00.&lt;br /&gt;
&lt;br /&gt;
The return array is of the format array['searchtype'] = 'Search Description', where searchtype &lt;br /&gt;
is returned to your plugin search routine and Description is displayed in the &lt;br /&gt;
Search Page Drop Down box.&lt;br /&gt;
&lt;br /&gt;
You can have multiple search types and descriptions.&lt;br /&gt;
&lt;br /&gt;
=== plugin_dopluginsearch_{plugin_name}() ===&lt;br /&gt;
This section will outline the method used to search a plugin's data.&lt;br /&gt;
&lt;br /&gt;
==== Input Parameters ====&lt;br /&gt;
The parameters that are passed to this function are as follows:&lt;br /&gt;
*$query -- a string containing the search term.&lt;br /&gt;
*$datestart -- starting date to begin search.&lt;br /&gt;
*$dateend -- ending date to end search.&lt;br /&gt;
*$topic -- topic item is assigned to.&lt;br /&gt;
*$type -- no longer used, deprecated.&lt;br /&gt;
*$author -- the user id of the author.&lt;br /&gt;
*$keyType -- search key type: 'all', 'phrase', 'any'.&lt;br /&gt;
*$page -- no longer used, deprecated.&lt;br /&gt;
*$perpage -- no longer used, deprecated.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Depending on your plugin, some of these criteria may be meaningless and thus ignored.  The function should then perform two basic operations:&lt;br /&gt;
#Build search SQL string using the input parameters.&lt;br /&gt;
#Return the query along with some plugin information.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==== Returned Values ====&lt;br /&gt;
The search API requires the following information to be returned by the plugin_dopluginsearch_{plugin_name}() function:&lt;br /&gt;
&lt;br /&gt;
===== Plugin Name =====&lt;br /&gt;
* A name to display to the user, i.e. 'My Plugin' (singular preferred)&lt;br /&gt;
* A name used locally to identify the plugin, i.e. 'myplugin'&lt;br /&gt;
&lt;br /&gt;
===== A Search Rank =====&lt;br /&gt;
* An integer between 1 and 5 based on how many result to extract from the query.&lt;br /&gt;
As all the results have been combined into a single list, the core needs to prioritise important plugins to non important ones. The higher the ranking the more results will be displayed to the user. A rank of 1 will show fewer results, where as a rank of 5 shows the most amount of results from the plugin. The rank is optional, if it's not provided it will default to 3.&lt;br /&gt;
Here is an example of Geeklog setup with three plugins, the different rank values will allow varying results from each plugin. The results page is set to display a total of 50 results.&lt;br /&gt;
    plugin      rank    results&lt;br /&gt;
    ---------------------------&lt;br /&gt;
    stories     5       23&lt;br /&gt;
    forums      4       18&lt;br /&gt;
    comments    2       9&lt;br /&gt;
&lt;br /&gt;
===== Standard SQL Query =====&lt;br /&gt;
* A string containing a single query.&lt;br /&gt;
* OR An array of two queries for both MSSQL and MySQL DBMS.&lt;br /&gt;
All SQL queries returned should be without the LIMIT and ORDER BY clauses. The SQL query must have the following column names and look like:&lt;br /&gt;
&amp;lt;pre&amp;gt;SELECT id, title, description, date, uid, hits, url FROM ... WHERE ...{space}&amp;lt;/pre&amp;gt;&lt;br /&gt;
If a column does not exist in the table then another value should be substituted, for example: '0' AS hits, ...&lt;br /&gt;
&lt;br /&gt;
======url======&lt;br /&gt;
The url is where to take the user when they have clicked a result. It should start with a single slash if the target is within the current domain. Otherwise the result with be printed, as is, in the href attribute of the link. For example this url belongs to the Geeklog site&lt;br /&gt;
&amp;lt;pre&amp;gt;CONCAT('/staticpages/index.php?page=', sp.sp_id) AS url&amp;lt;/pre&amp;gt;&lt;br /&gt;
However the Links plugin needs to direct users to external sites when clicked, so providing the url from the database will suffice.&lt;br /&gt;
&lt;br /&gt;
===== Full-Text SQL Query (optional) =====&lt;br /&gt;
* An array of two queries for both MSSQL and MySQL DBMS using the Full-Text search method.&lt;br /&gt;
This search method will take advantage of Full-Text indexes which will reduce search times. This should only be returned if the columns being searched have been properly indexed. The Full-Text SQL Query will only be executed if Full-Text searches have been enabled by the admin during the installation or upgrading process, otherwise the core will always fall back to the Standard SQL Query.&lt;br /&gt;
&lt;br /&gt;
==== The SearchCriteria() Class ====&lt;br /&gt;
The process of returning the values is done by initializing a SearchCriteria() object, setting the parameters for the search then returning the object. Here is an example:&lt;br /&gt;
&amp;lt;pre&amp;gt;$search = new SearchCriteria('myplugin', 'My Plugin');&lt;br /&gt;
$search-&amp;gt;setSQL($sql);&lt;br /&gt;
$search-&amp;gt;setFTSQL($ftsql);&lt;br /&gt;
$search-&amp;gt;setRank(4);&amp;lt;/pre&amp;gt;&lt;br /&gt;
This indicates that the 'myplugin' plugin supports Full-Text searches and will have a ranking of 4.&lt;br /&gt;
&lt;br /&gt;
===== buildSearchSQL() Function =====&lt;br /&gt;
As a lot of the plugins will be processing the same or similar SQL queries the buildSearchSQL() function has been provided to simplify things. This function will take four parameters then build the searching part of the SQL query. It will also return the Full-Text query strings should they be required. The parameters are:&lt;br /&gt;
*$keyType -- search key type: 'all', 'phrase', 'any'.&lt;br /&gt;
*$query -- the query string.&lt;br /&gt;
*$columns -- the column names to search.&lt;br /&gt;
*$sql -- the sql query to append to. (optional)&lt;br /&gt;
And an example of how it can be put to use:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
$sql = 'SELECT ... FROM ... WHERE ... ';&lt;br /&gt;
$columns = array('title','bodytext');&lt;br /&gt;
list($sql,$ftsql) = buildSearchSQL('any', 'my geeklog', $columns, $sql);&lt;br /&gt;
&lt;br /&gt;
// $sql =&amp;gt; SELECT ... FROM ... WHERE ... AND ((title LIKE '%my%' OR bodytext LIKE '%my%') OR  (title LIKE '%geeklog%' OR bodytext LIKE '%geeklog%'))&lt;br /&gt;
// $ftsql[mysql] =&amp;gt; SELECT ... FROM ... WHERE ... AND MATCH(title,bodytext) AGAINST ('my geeklog' IN BOOLEAN MODE)&lt;br /&gt;
// $ftsql[mssql] =&amp;gt; SELECT ... FROM ... WHERE ... AND CONTAINS((title,bodytext), '&amp;quot;my&amp;quot; OR &amp;quot;geeklog&amp;quot;')&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
A proper example of its use is at the bottom of the page.&lt;br /&gt;
&lt;br /&gt;
===== Enabling URL Rewrite =====&lt;br /&gt;
If the plugin requires the URL to be passed through the COM_buildUrl() function then it should set the setURLRewrite() function to true. For example:&lt;br /&gt;
&amp;lt;pre&amp;gt;$search = new SearchCriteria('myplugin', 'My Plugin');&lt;br /&gt;
$search-&amp;gt;setSQL($sql);&lt;br /&gt;
$search-&amp;gt;setURLRewrite(true);&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===== Returning Multiple Objects =====&lt;br /&gt;
In some cases a plugin may be required to search across two or more tables that have no relation with one another. To accommodate this they may return an array of SearchCriteria() objects, each with a different SQL query. To allow the user to differentiate between the results an array of names can be passed, each name will be a separate sub group and will be appended to one another using the separator from the configuration.&lt;br /&gt;
The following example shows how this works:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
// Search the main table&lt;br /&gt;
//   These results will be labelled 'My Plugin &amp;gt; Main'&lt;br /&gt;
$search_main = new SearchCriteria('myplugin', array('My Plugin', 'Main'));&lt;br /&gt;
$plugin_main-&amp;gt;setSQL($sql_main);&lt;br /&gt;
$plugin_main-&amp;gt;setFTSQL($ftsql_main);&lt;br /&gt;
$plugin_main-&amp;gt;setRank(4);&lt;br /&gt;
&lt;br /&gt;
// Search a sub tables&lt;br /&gt;
//   These results will be labelled 'My Plugin &amp;gt; Sub'&lt;br /&gt;
$search_sub = new SearchCriteria('myplugin', array('My Plugin', 'Sub'));&lt;br /&gt;
$search_sub-&amp;gt;setSQL($sql_sub);&lt;br /&gt;
$search_sub-&amp;gt;setFTSQL($ftsql_sub);&lt;br /&gt;
$search_sub-&amp;gt;setRank(4);&lt;br /&gt;
&lt;br /&gt;
// Return both objects&lt;br /&gt;
return array($search_main, $search_sub);&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
Note: The plugin identifier needs to stay the same across all objects, in this case 'myplugin'.&lt;br /&gt;
&lt;br /&gt;
==== A Working Example ====&lt;br /&gt;
This example searches the Stories. Although it's not a plugin, it puts to use everything discussed here so it's a good example of how to implement the API in your plugin.&lt;br /&gt;
&amp;lt;pre&amp;gt;function plugin_dopluginsearch_searchStories($query, $datestart, $dateend, $topic, $type, $author, $keyType, $page, $perpage)&lt;br /&gt;
{&lt;br /&gt;
    global $_TABLES, $_DB_dbms, $LANG09;&lt;br /&gt;
&lt;br /&gt;
    // Make sure the query is SQL safe&lt;br /&gt;
    $query = trim(addslashes($query));&lt;br /&gt;
&lt;br /&gt;
    // Build the first part of the query&lt;br /&gt;
    $sql = &amp;quot;SELECT&lt;br /&gt;
                s.sid AS id,&lt;br /&gt;
                s.title AS title,&lt;br /&gt;
                s.introtext AS description,&lt;br /&gt;
                UNIX_TIMESTAMP(s.date) AS date,&lt;br /&gt;
                s.uid AS uid,&lt;br /&gt;
                s.hits AS hits,&lt;br /&gt;
                CONCAT('/article.php?story=',s.sid) AS url &amp;quot;;&lt;br /&gt;
    $sql .= &amp;quot;FROM {$_TABLES['stories']} AS s, {$_TABLES['users']} AS u &amp;quot;;&lt;br /&gt;
    $sql .= &amp;quot;WHERE (draft_flag = 0) AND (date &amp;lt;= NOW()) AND (u.uid = s.uid) &amp;quot;;&lt;br /&gt;
    $sql .= COM_getPermSQL('AND') . COM_getTopicSQL('AND') . COM_getLangSQL('sid', 'AND') . ' ';&lt;br /&gt;
&lt;br /&gt;
    // If we are searching by date add that too&lt;br /&gt;
    if (!empty($datestart) &amp;amp;&amp;amp; !empty($dateend)) {&lt;br /&gt;
        $delim = substr($datestart, 4, 1);&lt;br /&gt;
        if (!empty($delim)) {&lt;br /&gt;
            $DS = explode($delim, $datestart);&lt;br /&gt;
            $DE = explode($delim, $dateend);&lt;br /&gt;
            $startdate = mktime(0,0,0,$DS[1],$DS[2],$DS[0]);&lt;br /&gt;
            $enddate = mktime(23,59,59,$DE[1],$DE[2],$DE[0]);&lt;br /&gt;
            $sql .= &amp;quot;AND (UNIX_TIMESTAMP(date) BETWEEN '$startdate' AND '$enddate') &amp;quot;;&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
    if (!empty($topic)) {&lt;br /&gt;
        $sql .= &amp;quot;AND (s.tid = '$topic') &amp;quot;;&lt;br /&gt;
    }&lt;br /&gt;
    if (!empty($author)) {&lt;br /&gt;
        $sql .= &amp;quot;AND (s.uid = '$author') &amp;quot;;&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    // Create a SearchCriteria instance with the name of the plugin&lt;br /&gt;
    $search = new SearchCriteria('stories', $LANG09[65]);&lt;br /&gt;
&lt;br /&gt;
    // These are the columns in the table that need searching&lt;br /&gt;
    $columns = array('introtext','bodytext','title');&lt;br /&gt;
&lt;br /&gt;
    // Get back the completed SQL query&lt;br /&gt;
    list($sql,$ftsql) = $search-&amp;gt;buildSearchSQL($keyType, $query, $columns, $sql);&lt;br /&gt;
&lt;br /&gt;
    // Set the Std. SQL Query&lt;br /&gt;
    $search-&amp;gt;setSQL($sql);&lt;br /&gt;
&lt;br /&gt;
    // Set the Full-Text Query, remember the columns _MUST_ be indexed first. If they are not then don't set this.&lt;br /&gt;
    $search-&amp;gt;setFTSQL($ftsql);&lt;br /&gt;
&lt;br /&gt;
    // Finally set a high ranking, enable URLRewrite and return the object.&lt;br /&gt;
    $search-&amp;gt;setRank(5);&lt;br /&gt;
    $search-&amp;gt;setURLRewrite(true);&lt;br /&gt;
    return $search;&lt;br /&gt;
}&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
For more examples, there's a forum post ({{forum|87624}}) with updated search functions for the [[FAQ Manager Plugin|FAQ Manager]], [[Forum Plugin|Forum]], and [[File Management Plugin|File Management]] plugins.&lt;br /&gt;
&lt;br /&gt;
[[Category:Plugin Development]]&lt;/div&gt;</summary>
		<author><name>LWC</name></author>	</entry>

	<entry>
		<id>http://gwiki3.thatlinuxbox.com/index.php?title=Using_Geeklog%27s_Improved_Search_Engine&amp;diff=5472</id>
		<title>Using Geeklog's Improved Search Engine</title>
		<link rel="alternate" type="text/html" href="http://gwiki3.thatlinuxbox.com/index.php?title=Using_Geeklog%27s_Improved_Search_Engine&amp;diff=5472"/>
				<updated>2009-05-26T12:33:16Z</updated>
		
		<summary type="html">&lt;p&gt;LWC: /* Plugins' compatibility with old Geeklog versions */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;==Plugins' compatibility with old Geeklog versions==&lt;br /&gt;
If you want to make your plugin compatible with Geeklog v1.5 and below, you must also implement [[Using Geeklog's Search Engine]].&lt;br /&gt;
&lt;br /&gt;
==The functions==&lt;br /&gt;
Tying your plugin into Geeklogs search API is rather easy.  Easy, that is, if you know how to search &lt;br /&gt;
your plugins data already. The Geeklog search API provides a way for you to return the SQL query back to Geeklog which will be executed in the core and the results included in its search page.&lt;br /&gt;
&lt;br /&gt;
For the data in your plugin to be searched by Geeklog's search functions, there are two functions that you need to implement in your plugins function.inc:&lt;br /&gt;
&lt;br /&gt;
*plugin_searchtypes_{plugin_name}() returns to Geeklog the type(s) of search.&lt;br /&gt;
*plugin_dopluginsearch_{plugin_name}() returns the search SQL query back to Geeklog.&lt;br /&gt;
&lt;br /&gt;
Let's look at each of them in turn:&lt;br /&gt;
&lt;br /&gt;
=== plugin_searchtypes_{plugin_name}() ===&lt;br /&gt;
&lt;br /&gt;
This function takes no parameters and returns an associative array of the search type.  The normal code for this&lt;br /&gt;
function will make it all clear.  Normally the function looks like this:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;function plugin_searchtypes_{plugin_name}()&lt;br /&gt;
{&lt;br /&gt;
    global $LANG_PL00;&lt;br /&gt;
    $tmp['{plugin_name}']= $LANG_PL00['searchtype'];&lt;br /&gt;
    return $tmp;&lt;br /&gt;
}&amp;lt;/pre&amp;gt;&lt;br /&gt;
&amp;lt;sup&amp;gt;(don't forget to replace {plugin_name} with the actual name).&amp;lt;/sup&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Naturally all occurrences of plugin would be replaced with the name of your &lt;br /&gt;
plugin and the LANGUAGE varible $LANG_PL00 is just an example. Your Plugin needs &lt;br /&gt;
to use a unique variable name so replace PL00.&lt;br /&gt;
&lt;br /&gt;
The return array is of the format array['searchtype'] = 'Search Description', where searchtype &lt;br /&gt;
is returned to your plugin search routine and Description is displayed in the &lt;br /&gt;
Search Page Drop Down box.&lt;br /&gt;
&lt;br /&gt;
You can have multiple search types and descriptions.&lt;br /&gt;
&lt;br /&gt;
=== plugin_dopluginsearch_{plugin_name}() ===&lt;br /&gt;
This section will outline the method used to search a plugin's data.&lt;br /&gt;
&lt;br /&gt;
==== Input Parameters ====&lt;br /&gt;
The parameters that are passed to this function are as follows:&lt;br /&gt;
*$query -- a string containing the search term.&lt;br /&gt;
*$datestart -- starting date to begin search.&lt;br /&gt;
*$dateend -- ending date to end search.&lt;br /&gt;
*$topic -- topic item is assigned to.&lt;br /&gt;
*$type -- no longer used, deprecated.&lt;br /&gt;
*$author -- the user id of the author.&lt;br /&gt;
*$keyType -- search key type: 'all', 'phrase', 'any'.&lt;br /&gt;
*$page -- no longer used, deprecated.&lt;br /&gt;
*$perpage -- no longer used, deprecated.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Depending on your plugin, some of these criteria may be meaningless and thus ignored.  The function should then perform two basic operations:&lt;br /&gt;
#Build search SQL string using the input parameters.&lt;br /&gt;
#Return the query along with some plugin information.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==== Returned Values ====&lt;br /&gt;
The search API requires the following information to be returned by the plugin_dopluginsearch_{plugin_name}() function:&lt;br /&gt;
&lt;br /&gt;
===== Plugin Name =====&lt;br /&gt;
* A name to display to the user, i.e. 'My Plugin' (singular preferred)&lt;br /&gt;
* A name used locally to identify the plugin, i.e. 'myplugin'&lt;br /&gt;
&lt;br /&gt;
===== A Search Rank =====&lt;br /&gt;
* An integer between 1 and 5 based on how many result to extract from the query.&lt;br /&gt;
As all the results have been combined into a single list, the core needs to prioritise important plugins to non important ones. The higher the ranking the more results will be displayed to the user. A rank of 1 will show fewer results, where as a rank of 5 shows the most amount of results from the plugin. The rank is optional, if it's not provided it will default to 3.&lt;br /&gt;
Here is an example of Geeklog setup with three plugins, the different rank values will allow varying results from each plugin. The results page is set to display a total of 50 results.&lt;br /&gt;
    plugin      rank    results&lt;br /&gt;
    ---------------------------&lt;br /&gt;
    stories     5       23&lt;br /&gt;
    forums      4       18&lt;br /&gt;
    comments    2       9&lt;br /&gt;
&lt;br /&gt;
===== Standard SQL Query =====&lt;br /&gt;
* A string containing a single query.&lt;br /&gt;
* OR An array of two queries for both MSSQL and MySQL DBMS.&lt;br /&gt;
All SQL queries returned should be without the LIMIT and ORDER BY clauses. The SQL query must have the following column names and look like:&lt;br /&gt;
&amp;lt;pre&amp;gt;SELECT id, title, description, date, user, hits, url FROM ... WHERE ...&amp;lt;/pre&amp;gt;&lt;br /&gt;
If a column does not exist in the table then another value should be substituted, for example: '0' AS hits, ...&lt;br /&gt;
&lt;br /&gt;
The url is where to take the user when they have clicked a result. It should start with a single slash if the target is within the current domain. Otherwise the result with be printed, as is, in the href attribute of the link. For example this url belongs to the Geeklog site&lt;br /&gt;
&amp;lt;pre&amp;gt;CONCAT('/staticpages/index.php?page=', sp.sp_id) AS url&amp;lt;/pre&amp;gt;&lt;br /&gt;
However the Links plugin needs to direct users to external sites when clicked, so providing the url from the database will suffice.&lt;br /&gt;
&lt;br /&gt;
===== Full-Text SQL Query (optional) =====&lt;br /&gt;
* An array of two queries for both MSSQL and MySQL DBMS using the Full-Text search method.&lt;br /&gt;
This search method will take advantage of Full-Text indexes which will reduce search times. This should only be returned if the columns being searched have been properly indexed. The Full-Text SQL Query will only be executed if Full-Text searches have been enabled by the admin during the installation or upgrading process, otherwise the core will always fall back to the Standard SQL Query.&lt;br /&gt;
&lt;br /&gt;
==== The SearchCriteria() Class ====&lt;br /&gt;
The process of returning the values is done by initializing a SearchCriteria() object, setting the parameters for the search then returning the object. Here is an example:&lt;br /&gt;
&amp;lt;pre&amp;gt;$search = new SearchCriteria('myplugin', 'My Plugin');&lt;br /&gt;
$search-&amp;gt;setSQL($sql);&lt;br /&gt;
$search-&amp;gt;setFTSQL($ftsql);&lt;br /&gt;
$search-&amp;gt;setRank(4);&amp;lt;/pre&amp;gt;&lt;br /&gt;
This indicates that the 'myplugin' plugin supports Full-Text searches and will have a ranking of 4.&lt;br /&gt;
&lt;br /&gt;
===== buildSearchSQL() Function =====&lt;br /&gt;
As a lot of the plugins will be processing the same or similar SQL queries the buildSearchSQL() function has been provided to simplify things. This function will take four parameters then build the searching part of the SQL query. It will also return the Full-Text query strings should they be required. The parameters are:&lt;br /&gt;
*$keyType -- search key type: 'all', 'phrase', 'any'.&lt;br /&gt;
*$query -- the query string.&lt;br /&gt;
*$columns -- the column names to search.&lt;br /&gt;
*$sql -- the sql query to append to. (optional)&lt;br /&gt;
And an example of how it can be put to use:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
$sql = 'SELECT ... FROM ... WHERE ... ';&lt;br /&gt;
$columns = array('title','bodytext');&lt;br /&gt;
list($sql,$ftsql) = buildSearchSQL('any', 'my geeklog', $columns, $sql);&lt;br /&gt;
&lt;br /&gt;
// $sql =&amp;gt; SELECT ... FROM ... WHERE ... AND ((title LIKE '%my%' OR bodytext LIKE '%my%') OR  (title LIKE '%geeklog%' OR bodytext LIKE '%geeklog%'))&lt;br /&gt;
// $ftsql[mysql] =&amp;gt; SELECT ... FROM ... WHERE ... AND MATCH(title,bodytext) AGAINST ('my geeklog' IN BOOLEAN MODE)&lt;br /&gt;
// $ftsql[mssql] =&amp;gt; SELECT ... FROM ... WHERE ... AND CONTAINS((title,bodytext), '&amp;quot;my&amp;quot; OR &amp;quot;geeklog&amp;quot;')&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
A proper example of its use is at the bottom of the page.&lt;br /&gt;
&lt;br /&gt;
===== Enabling URL Rewrite =====&lt;br /&gt;
If the plugin requires the URL to be passed through the COM_buildUrl() function then it should set the setURLRewrite() function to true. For example:&lt;br /&gt;
&amp;lt;pre&amp;gt;$search = new SearchCriteria('myplugin', 'My Plugin');&lt;br /&gt;
$search-&amp;gt;setSQL($sql);&lt;br /&gt;
$search-&amp;gt;setURLRewrite(true);&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===== Returning Multiple Objects =====&lt;br /&gt;
In some cases a plugin may be required to search across two or more tables that have no relation with one another. To accommodate this they may return an array of SearchCriteria() objects, each with a different SQL query. To allow the user to differentiate between the results an array of names can be passed, each name will be a separate sub group and will be appended to one another using the separator from the configuration.&lt;br /&gt;
The following example shows how this works:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
// Search the main table&lt;br /&gt;
//   These results will be labelled 'My Plugin &amp;gt; Main'&lt;br /&gt;
$search_main = new SearchCriteria('myplugin', array('My Plugin', 'Main'));&lt;br /&gt;
$plugin_main-&amp;gt;setSQL($sql_main);&lt;br /&gt;
$plugin_main-&amp;gt;setFTSQL($ftsql_main);&lt;br /&gt;
$plugin_main-&amp;gt;setRank(4);&lt;br /&gt;
&lt;br /&gt;
// Search a sub tables&lt;br /&gt;
//   These results will be labelled 'My Plugin &amp;gt; Sub'&lt;br /&gt;
$search_sub = new SearchCriteria('myplugin', array('My Plugin', 'Sub'));&lt;br /&gt;
$search_sub-&amp;gt;setSQL($sql_sub);&lt;br /&gt;
$search_sub-&amp;gt;setFTSQL($ftsql_sub);&lt;br /&gt;
$search_sub-&amp;gt;setRank(4);&lt;br /&gt;
&lt;br /&gt;
// Return both objects&lt;br /&gt;
return array($search_main, $search_sub);&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
Note: The plugin identifier needs to stay the same across all objects, in this case 'myplugin'.&lt;br /&gt;
&lt;br /&gt;
==== A Working Example ====&lt;br /&gt;
This example searches the Stories. Although it's not a plugin, it puts to use everything discussed here so it's a good example of how to implement the API in your plugin.&lt;br /&gt;
&amp;lt;pre&amp;gt;function plugin_dopluginsearch_searchStories($query, $datestart, $dateend, $topic, $type, $author, $keyType, $page, $perpage)&lt;br /&gt;
{&lt;br /&gt;
    global $_TABLES, $_DB_dbms, $LANG09;&lt;br /&gt;
&lt;br /&gt;
    // Make sure the query is SQL safe&lt;br /&gt;
    $query = trim(addslashes($query));&lt;br /&gt;
&lt;br /&gt;
    // Build the first part of the query&lt;br /&gt;
    $sql = &amp;quot;SELECT&lt;br /&gt;
                s.sid AS id,&lt;br /&gt;
                s.title AS title,&lt;br /&gt;
                s.introtext AS description,&lt;br /&gt;
                UNIX_TIMESTAMP(s.date) AS date,&lt;br /&gt;
                s.uid AS uid,&lt;br /&gt;
                s.hits AS hits,&lt;br /&gt;
                CONCAT('/article.php?story=',s.sid) AS url &amp;quot;;&lt;br /&gt;
    $sql .= &amp;quot;FROM {$_TABLES['stories']} AS s, {$_TABLES['users']} AS u &amp;quot;;&lt;br /&gt;
    $sql .= &amp;quot;WHERE (draft_flag = 0) AND (date &amp;lt;= NOW()) AND (u.uid = s.uid) &amp;quot;;&lt;br /&gt;
    $sql .= COM_getPermSQL('AND') . COM_getTopicSQL('AND') . COM_getLangSQL('sid', 'AND') . ' ';&lt;br /&gt;
&lt;br /&gt;
    // If we are searching by date add that too&lt;br /&gt;
    if (!empty($datestart) &amp;amp;&amp;amp; !empty($dateend)) {&lt;br /&gt;
        $delim = substr($datestart, 4, 1);&lt;br /&gt;
        if (!empty($delim)) {&lt;br /&gt;
            $DS = explode($delim, $datestart);&lt;br /&gt;
            $DE = explode($delim, $dateend);&lt;br /&gt;
            $startdate = mktime(0,0,0,$DS[1],$DS[2],$DS[0]);&lt;br /&gt;
            $enddate = mktime(23,59,59,$DE[1],$DE[2],$DE[0]);&lt;br /&gt;
            $sql .= &amp;quot;AND (UNIX_TIMESTAMP(date) BETWEEN '$startdate' AND '$enddate') &amp;quot;;&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
    if (!empty($topic)) {&lt;br /&gt;
        $sql .= &amp;quot;AND (s.tid = '$topic') &amp;quot;;&lt;br /&gt;
    }&lt;br /&gt;
    if (!empty($author)) {&lt;br /&gt;
        $sql .= &amp;quot;AND (s.uid = '$author') &amp;quot;;&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    // Create a SearchCriteria instance with the name of the plugin&lt;br /&gt;
    $search = new SearchCriteria('stories', $LANG09[65]);&lt;br /&gt;
&lt;br /&gt;
    // These are the columns in the table that need searching&lt;br /&gt;
    $columns = array('introtext','bodytext','title');&lt;br /&gt;
&lt;br /&gt;
    // Get back the completed SQL query&lt;br /&gt;
    list($sql,$ftsql) = $search-&amp;gt;buildSearchSQL($keyType, $query, $columns, $sql);&lt;br /&gt;
&lt;br /&gt;
    // Set the Std. SQL Query&lt;br /&gt;
    $search-&amp;gt;setSQL($sql);&lt;br /&gt;
&lt;br /&gt;
    // Set the Full-Text Query, remember the columns _MUST_ be indexed first. If they are not then don't set this.&lt;br /&gt;
    $search-&amp;gt;setFTSQL($ftsql);&lt;br /&gt;
&lt;br /&gt;
    // Finally set a high ranking, enable URLRewrite and return the object.&lt;br /&gt;
    $search-&amp;gt;setRank(5);&lt;br /&gt;
    $search-&amp;gt;setURLRewrite(true);&lt;br /&gt;
    return $search;&lt;br /&gt;
}&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
For more examples, there's a forum post ({{forum|87624}}) with updated search functions for the [[FAQ Manager Plugin|FAQ Manager]], [[Forum Plugin|Forum]], and [[File Management Plugin|File Management]] plugins.&lt;br /&gt;
&lt;br /&gt;
[[Category:Plugin Development]]&lt;/div&gt;</summary>
		<author><name>LWC</name></author>	</entry>

	<entry>
		<id>http://gwiki3.thatlinuxbox.com/index.php?title=Template:Forum&amp;diff=5471</id>
		<title>Template:Forum</title>
		<link rel="alternate" type="text/html" href="http://gwiki3.thatlinuxbox.com/index.php?title=Template:Forum&amp;diff=5471"/>
				<updated>2009-05-26T12:32:45Z</updated>
		
		<summary type="html">&lt;p&gt;LWC: /* Usage */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&amp;lt;includeonly&amp;gt;http://www.geeklog.net/forum/viewtopic.php?showtopic={{{1}}}&amp;lt;/includeonly&amp;gt;&amp;lt;noinclude&amp;gt;Supply an forum ID from the main site and get a link for it.&lt;br /&gt;
&lt;br /&gt;
==Usage==&lt;br /&gt;
&amp;lt;pre&amp;gt;&amp;lt;nowiki&amp;gt;{{forum|forumID}}&amp;lt;/nowiki&amp;gt;&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
For example, &amp;lt;nowiki&amp;gt;{{forum|9778}}&amp;lt;/nowiki&amp;gt; would display as:&lt;br /&gt;
&lt;br /&gt;
{{forum|9778}}&lt;br /&gt;
&amp;lt;/noinclude&amp;gt;&lt;/div&gt;</summary>
		<author><name>LWC</name></author>	</entry>

	<entry>
		<id>http://gwiki3.thatlinuxbox.com/index.php?title=Using_Geeklog%27s_Search_Engine&amp;diff=5470</id>
		<title>Using Geeklog's Search Engine</title>
		<link rel="alternate" type="text/html" href="http://gwiki3.thatlinuxbox.com/index.php?title=Using_Geeklog%27s_Search_Engine&amp;diff=5470"/>
				<updated>2009-05-26T12:26:37Z</updated>
		
		<summary type="html">&lt;p&gt;LWC: /* New method */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;==Old method==&lt;br /&gt;
This method is meant for Geeklog v1.5 and below.&lt;br /&gt;
&lt;br /&gt;
===The functions===&lt;br /&gt;
Tying your plugin into Geeklogs search API is rather easy.  Easy, that is, if you know how search your plugins data already.  The Geeklog search API provides a way for you to return your search results back to Geeklog to be included in its search results page.&lt;br /&gt;
&lt;br /&gt;
For the data in your plugin to be searched by Geeklogs search functions, there are two functions that you need to implement in your plugins function.inc:&lt;br /&gt;
&lt;br /&gt;
* plugin_searchtypes_{plugin_name}() returns to Geeklog the type(s) of search.&lt;br /&gt;
* plugin_dopluginsearch_{plugin_name}() returns the actual results to Geeklog.&lt;br /&gt;
&lt;br /&gt;
Let's look at each of them in turn:&lt;br /&gt;
&lt;br /&gt;
==== plugin_searchtypes_{plugin_name}() ====&lt;br /&gt;
&lt;br /&gt;
This function takes no parameters and returns an associative array of the search type.  The normal code for this&lt;br /&gt;
function will make it all clear.  Normally the function looks like this:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
function plugin_searchtypes_{plugin_name}() {&lt;br /&gt;
    global $LANG_PL00;&lt;br /&gt;
    $tmp['{plugin_name}']= $LANG_PL00['searchtype'];&lt;br /&gt;
    return $tmp;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&amp;lt;sup&amp;gt;(don't forget to replace {plugin_name} with the actual name).&amp;lt;/sup&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Naturally all occurrences of plugin would be replaced with the name of your plugin and the LANGUAGE varible $LANG_PL00 is just an example. Your Plugin needs to use a unique variable name so replace PL00.&lt;br /&gt;
&lt;br /&gt;
The return array is of the format array['searchtype'] = 'Search Description', where searchtype is returned to your plugin search routine and Description is displayed in the Search Page Drop Down box.&lt;br /&gt;
&lt;br /&gt;
You can have multiple search types and descriptions.&lt;br /&gt;
&lt;br /&gt;
==== plugin_dopluginsearch_{plugin_name}() ====&lt;br /&gt;
&lt;br /&gt;
This function is where the search is actually done.  It is passed a number of parameters that can be used in your search.  They are:&lt;br /&gt;
&lt;br /&gt;
* $query -- the actual items being searched for.&lt;br /&gt;
* $datestart -- starting date to begin search.&lt;br /&gt;
* $dateend -- ending date to end search.&lt;br /&gt;
* $topic -- topic item is assigned to.&lt;br /&gt;
* $type -- type of item (see searchtypes above).&lt;br /&gt;
* $author -- author of item.&lt;br /&gt;
&lt;br /&gt;
Depending on your plugin, some of these criteria may be meaningless and thus ignored.  Here is a brief overview of what your function should do.&lt;br /&gt;
&lt;br /&gt;
# Initialize plugin object&lt;br /&gt;
# Check to see if type is appropriate for this plugin -- if not, bail out.&lt;br /&gt;
# Get a list of all your items to search.&lt;br /&gt;
# Create Search object and Build search results header.&lt;br /&gt;
# Search each of your items in turn.&lt;br /&gt;
# If a match then add item to the results.&lt;br /&gt;
# When done set number of results and return search object&lt;br /&gt;
&lt;br /&gt;
Looking at the example code  should make all of this clear.  The search results are returned in a object of type Plugin.  You initialize the object by setting the Label and then setting the names of the columns you want returned.  This is done in typical object fashion with this construct: $plugin-&amp;gt;addSearch Heading.    &lt;br /&gt;
&lt;br /&gt;
The headings will vary according to what your plugin does, but should include a link to the item found.  After searching each of your items in turn; you add your search results to an array having the same number of items as the labels you set earlier.    &lt;br /&gt;
&lt;br /&gt;
Note:  your search should be case insensitive to be compatible with Geeklogs search.  This array will correspond to the column headings entered above.  In the example below, the array consists of the Title of the page, the url to the page (a link) and the number of hits.  This array is then added to the Plugin object as a row. &lt;br /&gt;
 &lt;br /&gt;
The following construct is used:  $plugin-&amp;gt;addSearchResult. &lt;br /&gt;
When you are done searching you set the number of rows found and the number searched to the plugin object and return it. The example below is from the External Pages Plugin.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
function plugin_dopluginsearch_external($query,$datestart,$dateend,$topic,$type,$author)&lt;br /&gt;
{&lt;br /&gt;
    global $_TABLES, $_CONF, $LANG_EX00;&lt;br /&gt;
&lt;br /&gt;
    if (empty($type)) {&lt;br /&gt;
        $type = 'all';&lt;br /&gt;
    }&lt;br /&gt;
      &lt;br /&gt;
    // Bail if we aren't supppose to do our search&lt;br /&gt;
    if ($type &amp;amp;lt;&amp;amp;gt; 'all' AND $type &amp;amp;lt;&amp;amp;gt; 'external') {&lt;br /&gt;
        $plugin_results = new Plugin();&lt;br /&gt;
        $plugin_results-&amp;amp;gt;plugin_name = 'external';&lt;br /&gt;
        $plugin_results-&amp;amp;gt;searchlabel = $LANG_EX00['externpages'] . $LANG_EX00['results'];&lt;br /&gt;
        return $plugin_results;&lt;br /&gt;
    }&lt;br /&gt;
      &lt;br /&gt;
    // Build search SQL - Modified to exclude static PHP pages from search.&lt;br /&gt;
    $sql = &amp;amp;quot;SELECT * from &amp;amp;quot; . $_TABLES['external'];&lt;br /&gt;
    $result = DB_query($sql);&lt;br /&gt;
    &lt;br /&gt;
    // OK, now create new plugin object and insert table header labels&lt;br /&gt;
    require_once($_CONF['path_system'] . 'classes/plugin.class.php');&lt;br /&gt;
    $plugin_results = new Plugin();&lt;br /&gt;
    $plugin_results-&amp;amp;gt;plugin_name = 'external';&lt;br /&gt;
    $plugin_results-&amp;amp;gt;searchlabel = $LANG_EX00['externpages'] . $LANG_EX00['results'];&lt;br /&gt;
    $plugin_results-&amp;amp;gt;addSearchHeading($LANG_EX00['titlemsg']);&lt;br /&gt;
    $plugin_results-&amp;amp;gt;addSearchHeading($LANG_EX00['urlmsg']);&lt;br /&gt;
    $plugin_results-&amp;amp;gt;addSearchHeading($LANG_EX00['hitsmsg']);&lt;br /&gt;
    $mycount = DB_numRows($result);&lt;br /&gt;
    // NOTE if any of your data items need to be links then add them here! &lt;br /&gt;
    // make sure data elements are in an array and in the same order as your&lt;br /&gt;
    // headings above!&lt;br /&gt;
    for ($i = 1; $i &amp;lt;= $mycount; $i++) {&lt;br /&gt;
        $A = DB_fetchArray($result);&lt;br /&gt;
&lt;br /&gt;
        if(SEC_hasAccess($A[owner_id],$A[group_id],$A[perm_owner],$A[perm_group],$A[perm_members],$A[perm_anon])){&lt;br /&gt;
            if (preg_match(&amp;quot;/^(http:\/\/)/i&amp;quot;,$A['url']) == 1) {&lt;br /&gt;
                $pth = $A['url'];&lt;br /&gt;
                $url = $A['url'];&lt;br /&gt;
            } else {&lt;br /&gt;
                $pth = $_CONF['path_html'] . $A['url'];&lt;br /&gt;
                $url = $_CONF['site_url'] . '/' . $A['url'];&lt;br /&gt;
            }&lt;br /&gt;
            $cnts = implode('',file($pth));&lt;br /&gt;
            if (stristr($cnts,$query) != '') {&lt;br /&gt;
                $rcnt++;&lt;br /&gt;
                $A['title'] = stripslashes($A['title']);&lt;br /&gt;
                $row = array($A['title'],&lt;br /&gt;
                      '&amp;lt;a href=&amp;quot;' . $url . '&amp;quot;&amp;gt;' . $A['url'] . &amp;quot;&amp;lt;/a&amp;gt;&amp;quot;,&lt;br /&gt;
                     $A['hits']);&lt;br /&gt;
                $plugin_results-&amp;gt;addSearchResult($row);&lt;br /&gt;
            }&lt;br /&gt;
        }&lt;br /&gt;
    &lt;br /&gt;
    }&lt;br /&gt;
    $plugin_results-&amp;gt;num_searchresults = $rcnt;&lt;br /&gt;
    $plugin_results-&amp;gt;num_itemssearched = DB_count($_TABLES['external']);&lt;br /&gt;
&lt;br /&gt;
    return $plugin_results;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==New method==&lt;br /&gt;
This method only works in Geeklog v1.6 and above.&lt;br /&gt;
&lt;br /&gt;
There is an updated API which makes use of the new and improved '''SearchCriteria()''' class. See [[Using Geeklog's Improved Search Engine]].&lt;br /&gt;
&lt;br /&gt;
[[Category:Plugin Developers Handbook]] [[Category:Plugin Development]]&lt;/div&gt;</summary>
		<author><name>LWC</name></author>	</entry>

	<entry>
		<id>http://gwiki3.thatlinuxbox.com/index.php?title=Using_Geeklog%27s_Improved_Search_Engine&amp;diff=5469</id>
		<title>Using Geeklog's Improved Search Engine</title>
		<link rel="alternate" type="text/html" href="http://gwiki3.thatlinuxbox.com/index.php?title=Using_Geeklog%27s_Improved_Search_Engine&amp;diff=5469"/>
				<updated>2009-05-26T12:22:26Z</updated>
		
		<summary type="html">&lt;p&gt;LWC: Formatted&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;==Plugins' compatibility with old Geeklog versions==&lt;br /&gt;
If you want to make your plugin compatible with Geeklog v1.5 and below, you must also implement [[Using Geeklog's Search Engine?]].&lt;br /&gt;
&lt;br /&gt;
==The functions==&lt;br /&gt;
Tying your plugin into Geeklogs search API is rather easy.  Easy, that is, if you know how to search &lt;br /&gt;
your plugins data already. The Geeklog search API provides a way for you to return the SQL query back to Geeklog which will be executed in the core and the results included in its search page.&lt;br /&gt;
&lt;br /&gt;
For the data in your plugin to be searched by Geeklog's search functions, there are two functions that you need to implement in your plugins function.inc:&lt;br /&gt;
&lt;br /&gt;
*plugin_searchtypes_{plugin_name}() returns to Geeklog the type(s) of search.&lt;br /&gt;
*plugin_dopluginsearch_{plugin_name}() returns the search SQL query back to Geeklog.&lt;br /&gt;
&lt;br /&gt;
Let's look at each of them in turn:&lt;br /&gt;
&lt;br /&gt;
=== plugin_searchtypes_{plugin_name}() ===&lt;br /&gt;
&lt;br /&gt;
This function takes no parameters and returns an associative array of the search type.  The normal code for this&lt;br /&gt;
function will make it all clear.  Normally the function looks like this:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;function plugin_searchtypes_{plugin_name}()&lt;br /&gt;
{&lt;br /&gt;
    global $LANG_PL00;&lt;br /&gt;
    $tmp['{plugin_name}']= $LANG_PL00['searchtype'];&lt;br /&gt;
    return $tmp;&lt;br /&gt;
}&amp;lt;/pre&amp;gt;&lt;br /&gt;
&amp;lt;sup&amp;gt;(don't forget to replace {plugin_name} with the actual name).&amp;lt;/sup&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Naturally all occurrences of plugin would be replaced with the name of your &lt;br /&gt;
plugin and the LANGUAGE varible $LANG_PL00 is just an example. Your Plugin needs &lt;br /&gt;
to use a unique variable name so replace PL00.&lt;br /&gt;
&lt;br /&gt;
The return array is of the format array['searchtype'] = 'Search Description', where searchtype &lt;br /&gt;
is returned to your plugin search routine and Description is displayed in the &lt;br /&gt;
Search Page Drop Down box.&lt;br /&gt;
&lt;br /&gt;
You can have multiple search types and descriptions.&lt;br /&gt;
&lt;br /&gt;
=== plugin_dopluginsearch_{plugin_name}() ===&lt;br /&gt;
This section will outline the method used to search a plugin's data.&lt;br /&gt;
&lt;br /&gt;
==== Input Parameters ====&lt;br /&gt;
The parameters that are passed to this function are as follows:&lt;br /&gt;
*$query -- a string containing the search term.&lt;br /&gt;
*$datestart -- starting date to begin search.&lt;br /&gt;
*$dateend -- ending date to end search.&lt;br /&gt;
*$topic -- topic item is assigned to.&lt;br /&gt;
*$type -- no longer used, deprecated.&lt;br /&gt;
*$author -- the user id of the author.&lt;br /&gt;
*$keyType -- search key type: 'all', 'phrase', 'any'.&lt;br /&gt;
*$page -- no longer used, deprecated.&lt;br /&gt;
*$perpage -- no longer used, deprecated.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Depending on your plugin, some of these criteria may be meaningless and thus ignored.  The function should then perform two basic operations:&lt;br /&gt;
#Build search SQL string using the input parameters.&lt;br /&gt;
#Return the query along with some plugin information.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==== Returned Values ====&lt;br /&gt;
The search API requires the following information to be returned by the plugin_dopluginsearch_{plugin_name}() function:&lt;br /&gt;
&lt;br /&gt;
===== Plugin Name =====&lt;br /&gt;
* A name to display to the user, i.e. 'My Plugin' (singular preferred)&lt;br /&gt;
* A name used locally to identify the plugin, i.e. 'myplugin'&lt;br /&gt;
&lt;br /&gt;
===== A Search Rank =====&lt;br /&gt;
* An integer between 1 and 5 based on how many result to extract from the query.&lt;br /&gt;
As all the results have been combined into a single list, the core needs to prioritise important plugins to non important ones. The higher the ranking the more results will be displayed to the user. A rank of 1 will show fewer results, where as a rank of 5 shows the most amount of results from the plugin. The rank is optional, if it's not provided it will default to 3.&lt;br /&gt;
Here is an example of Geeklog setup with three plugins, the different rank values will allow varying results from each plugin. The results page is set to display a total of 50 results.&lt;br /&gt;
    plugin      rank    results&lt;br /&gt;
    ---------------------------&lt;br /&gt;
    stories     5       23&lt;br /&gt;
    forums      4       18&lt;br /&gt;
    comments    2       9&lt;br /&gt;
&lt;br /&gt;
===== Standard SQL Query =====&lt;br /&gt;
* A string containing a single query.&lt;br /&gt;
* OR An array of two queries for both MSSQL and MySQL DBMS.&lt;br /&gt;
All SQL queries returned should be without the LIMIT and ORDER BY clauses. The SQL query must have the following column names and look like:&lt;br /&gt;
&amp;lt;pre&amp;gt;SELECT id, title, description, date, user, hits, url FROM ... WHERE ...&amp;lt;/pre&amp;gt;&lt;br /&gt;
If a column does not exist in the table then another value should be substituted, for example: '0' AS hits, ...&lt;br /&gt;
&lt;br /&gt;
The url is where to take the user when they have clicked a result. It should start with a single slash if the target is within the current domain. Otherwise the result with be printed, as is, in the href attribute of the link. For example this url belongs to the Geeklog site&lt;br /&gt;
&amp;lt;pre&amp;gt;CONCAT('/staticpages/index.php?page=', sp.sp_id) AS url&amp;lt;/pre&amp;gt;&lt;br /&gt;
However the Links plugin needs to direct users to external sites when clicked, so providing the url from the database will suffice.&lt;br /&gt;
&lt;br /&gt;
===== Full-Text SQL Query (optional) =====&lt;br /&gt;
* An array of two queries for both MSSQL and MySQL DBMS using the Full-Text search method.&lt;br /&gt;
This search method will take advantage of Full-Text indexes which will reduce search times. This should only be returned if the columns being searched have been properly indexed. The Full-Text SQL Query will only be executed if Full-Text searches have been enabled by the admin during the installation or upgrading process, otherwise the core will always fall back to the Standard SQL Query.&lt;br /&gt;
&lt;br /&gt;
==== The SearchCriteria() Class ====&lt;br /&gt;
The process of returning the values is done by initializing a SearchCriteria() object, setting the parameters for the search then returning the object. Here is an example:&lt;br /&gt;
&amp;lt;pre&amp;gt;$search = new SearchCriteria('myplugin', 'My Plugin');&lt;br /&gt;
$search-&amp;gt;setSQL($sql);&lt;br /&gt;
$search-&amp;gt;setFTSQL($ftsql);&lt;br /&gt;
$search-&amp;gt;setRank(4);&amp;lt;/pre&amp;gt;&lt;br /&gt;
This indicates that the 'myplugin' plugin supports Full-Text searches and will have a ranking of 4.&lt;br /&gt;
&lt;br /&gt;
===== buildSearchSQL() Function =====&lt;br /&gt;
As a lot of the plugins will be processing the same or similar SQL queries the buildSearchSQL() function has been provided to simplify things. This function will take four parameters then build the searching part of the SQL query. It will also return the Full-Text query strings should they be required. The parameters are:&lt;br /&gt;
*$keyType -- search key type: 'all', 'phrase', 'any'.&lt;br /&gt;
*$query -- the query string.&lt;br /&gt;
*$columns -- the column names to search.&lt;br /&gt;
*$sql -- the sql query to append to. (optional)&lt;br /&gt;
And an example of how it can be put to use:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
$sql = 'SELECT ... FROM ... WHERE ... ';&lt;br /&gt;
$columns = array('title','bodytext');&lt;br /&gt;
list($sql,$ftsql) = buildSearchSQL('any', 'my geeklog', $columns, $sql);&lt;br /&gt;
&lt;br /&gt;
// $sql =&amp;gt; SELECT ... FROM ... WHERE ... AND ((title LIKE '%my%' OR bodytext LIKE '%my%') OR  (title LIKE '%geeklog%' OR bodytext LIKE '%geeklog%'))&lt;br /&gt;
// $ftsql[mysql] =&amp;gt; SELECT ... FROM ... WHERE ... AND MATCH(title,bodytext) AGAINST ('my geeklog' IN BOOLEAN MODE)&lt;br /&gt;
// $ftsql[mssql] =&amp;gt; SELECT ... FROM ... WHERE ... AND CONTAINS((title,bodytext), '&amp;quot;my&amp;quot; OR &amp;quot;geeklog&amp;quot;')&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
A proper example of its use is at the bottom of the page.&lt;br /&gt;
&lt;br /&gt;
===== Enabling URL Rewrite =====&lt;br /&gt;
If the plugin requires the URL to be passed through the COM_buildUrl() function then it should set the setURLRewrite() function to true. For example:&lt;br /&gt;
&amp;lt;pre&amp;gt;$search = new SearchCriteria('myplugin', 'My Plugin');&lt;br /&gt;
$search-&amp;gt;setSQL($sql);&lt;br /&gt;
$search-&amp;gt;setURLRewrite(true);&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===== Returning Multiple Objects =====&lt;br /&gt;
In some cases a plugin may be required to search across two or more tables that have no relation with one another. To accommodate this they may return an array of SearchCriteria() objects, each with a different SQL query. To allow the user to differentiate between the results an array of names can be passed, each name will be a separate sub group and will be appended to one another using the separator from the configuration.&lt;br /&gt;
The following example shows how this works:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
// Search the main table&lt;br /&gt;
//   These results will be labelled 'My Plugin &amp;gt; Main'&lt;br /&gt;
$search_main = new SearchCriteria('myplugin', array('My Plugin', 'Main'));&lt;br /&gt;
$plugin_main-&amp;gt;setSQL($sql_main);&lt;br /&gt;
$plugin_main-&amp;gt;setFTSQL($ftsql_main);&lt;br /&gt;
$plugin_main-&amp;gt;setRank(4);&lt;br /&gt;
&lt;br /&gt;
// Search a sub tables&lt;br /&gt;
//   These results will be labelled 'My Plugin &amp;gt; Sub'&lt;br /&gt;
$search_sub = new SearchCriteria('myplugin', array('My Plugin', 'Sub'));&lt;br /&gt;
$search_sub-&amp;gt;setSQL($sql_sub);&lt;br /&gt;
$search_sub-&amp;gt;setFTSQL($ftsql_sub);&lt;br /&gt;
$search_sub-&amp;gt;setRank(4);&lt;br /&gt;
&lt;br /&gt;
// Return both objects&lt;br /&gt;
return array($search_main, $search_sub);&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
Note: The plugin identifier needs to stay the same across all objects, in this case 'myplugin'.&lt;br /&gt;
&lt;br /&gt;
==== A Working Example ====&lt;br /&gt;
This example searches the Stories. Although it's not a plugin, it puts to use everything discussed here so it's a good example of how to implement the API in your plugin.&lt;br /&gt;
&amp;lt;pre&amp;gt;function plugin_dopluginsearch_searchStories($query, $datestart, $dateend, $topic, $type, $author, $keyType, $page, $perpage)&lt;br /&gt;
{&lt;br /&gt;
    global $_TABLES, $_DB_dbms, $LANG09;&lt;br /&gt;
&lt;br /&gt;
    // Make sure the query is SQL safe&lt;br /&gt;
    $query = trim(addslashes($query));&lt;br /&gt;
&lt;br /&gt;
    // Build the first part of the query&lt;br /&gt;
    $sql = &amp;quot;SELECT&lt;br /&gt;
                s.sid AS id,&lt;br /&gt;
                s.title AS title,&lt;br /&gt;
                s.introtext AS description,&lt;br /&gt;
                UNIX_TIMESTAMP(s.date) AS date,&lt;br /&gt;
                s.uid AS uid,&lt;br /&gt;
                s.hits AS hits,&lt;br /&gt;
                CONCAT('/article.php?story=',s.sid) AS url &amp;quot;;&lt;br /&gt;
    $sql .= &amp;quot;FROM {$_TABLES['stories']} AS s, {$_TABLES['users']} AS u &amp;quot;;&lt;br /&gt;
    $sql .= &amp;quot;WHERE (draft_flag = 0) AND (date &amp;lt;= NOW()) AND (u.uid = s.uid) &amp;quot;;&lt;br /&gt;
    $sql .= COM_getPermSQL('AND') . COM_getTopicSQL('AND') . COM_getLangSQL('sid', 'AND') . ' ';&lt;br /&gt;
&lt;br /&gt;
    // If we are searching by date add that too&lt;br /&gt;
    if (!empty($datestart) &amp;amp;&amp;amp; !empty($dateend)) {&lt;br /&gt;
        $delim = substr($datestart, 4, 1);&lt;br /&gt;
        if (!empty($delim)) {&lt;br /&gt;
            $DS = explode($delim, $datestart);&lt;br /&gt;
            $DE = explode($delim, $dateend);&lt;br /&gt;
            $startdate = mktime(0,0,0,$DS[1],$DS[2],$DS[0]);&lt;br /&gt;
            $enddate = mktime(23,59,59,$DE[1],$DE[2],$DE[0]);&lt;br /&gt;
            $sql .= &amp;quot;AND (UNIX_TIMESTAMP(date) BETWEEN '$startdate' AND '$enddate') &amp;quot;;&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
    if (!empty($topic)) {&lt;br /&gt;
        $sql .= &amp;quot;AND (s.tid = '$topic') &amp;quot;;&lt;br /&gt;
    }&lt;br /&gt;
    if (!empty($author)) {&lt;br /&gt;
        $sql .= &amp;quot;AND (s.uid = '$author') &amp;quot;;&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    // Create a SearchCriteria instance with the name of the plugin&lt;br /&gt;
    $search = new SearchCriteria('stories', $LANG09[65]);&lt;br /&gt;
&lt;br /&gt;
    // These are the columns in the table that need searching&lt;br /&gt;
    $columns = array('introtext','bodytext','title');&lt;br /&gt;
&lt;br /&gt;
    // Get back the completed SQL query&lt;br /&gt;
    list($sql,$ftsql) = $search-&amp;gt;buildSearchSQL($keyType, $query, $columns, $sql);&lt;br /&gt;
&lt;br /&gt;
    // Set the Std. SQL Query&lt;br /&gt;
    $search-&amp;gt;setSQL($sql);&lt;br /&gt;
&lt;br /&gt;
    // Set the Full-Text Query, remember the columns _MUST_ be indexed first. If they are not then don't set this.&lt;br /&gt;
    $search-&amp;gt;setFTSQL($ftsql);&lt;br /&gt;
&lt;br /&gt;
    // Finally set a high ranking, enable URLRewrite and return the object.&lt;br /&gt;
    $search-&amp;gt;setRank(5);&lt;br /&gt;
    $search-&amp;gt;setURLRewrite(true);&lt;br /&gt;
    return $search;&lt;br /&gt;
}&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
For more examples, there's a forum post ({{forum|87624}}) with updated search functions for the [[FAQ Manager Plugin|FAQ Manager]], [[Forum Plugin|Forum]], and [[File Management Plugin|File Management]] plugins.&lt;br /&gt;
&lt;br /&gt;
[[Category:Plugin Development]]&lt;/div&gt;</summary>
		<author><name>LWC</name></author>	</entry>

	<entry>
		<id>http://gwiki3.thatlinuxbox.com/index.php?title=Using_Geeklog%27s_Improved_Search_Engine&amp;diff=5468</id>
		<title>Using Geeklog's Improved Search Engine</title>
		<link rel="alternate" type="text/html" href="http://gwiki3.thatlinuxbox.com/index.php?title=Using_Geeklog%27s_Improved_Search_Engine&amp;diff=5468"/>
				<updated>2009-05-26T12:17:07Z</updated>
		
		<summary type="html">&lt;p&gt;LWC: /* plugin_searchtypes_{plugin_name}() */ Fixed&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Tying your plugin into Geeklogs search API is rather easy.  Easy, that is, if you know how to search &lt;br /&gt;
your plugins data already. The Geeklog search API provides a way for you to return the SQL query back to Geeklog which will be executed in the core and the results included in its search page.&lt;br /&gt;
&lt;br /&gt;
For the data in your plugin to be searched by Geeklog's search functions, there are two functions that you need to implement in your plugins function.inc:&lt;br /&gt;
&lt;br /&gt;
*plugin_searchtypes_{plugin_name}() returns to Geeklog the type(s) of search.&lt;br /&gt;
*plugin_dopluginsearch_{plugin_name}() returns the search SQL query back to Geeklog.&lt;br /&gt;
&lt;br /&gt;
Let's look at each of them in turn:&lt;br /&gt;
&lt;br /&gt;
== plugin_searchtypes_{plugin_name}() ==&lt;br /&gt;
&lt;br /&gt;
This function takes no parameters and returns an associative array of the search type.  The normal code for this&lt;br /&gt;
function will make it all clear.  Normally the function looks like this:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;function plugin_searchtypes_{plugin_name}()&lt;br /&gt;
{&lt;br /&gt;
    global $LANG_PL00;&lt;br /&gt;
    $tmp['{plugin_name}']= $LANG_PL00['searchtype'];&lt;br /&gt;
    return $tmp;&lt;br /&gt;
}&amp;lt;/pre&amp;gt;&lt;br /&gt;
&amp;lt;sup&amp;gt;(don't forget to replace {plugin_name} with the actual name).&amp;lt;/sup&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Naturally all occurrences of plugin would be replaced with the name of your &lt;br /&gt;
plugin and the LANGUAGE varible $LANG_PL00 is just an example. Your Plugin needs &lt;br /&gt;
to use a unique variable name so replace PL00.&lt;br /&gt;
&lt;br /&gt;
The return array is of the format array['searchtype'] = 'Search Description', where searchtype &lt;br /&gt;
is returned to your plugin search routine and Description is displayed in the &lt;br /&gt;
Search Page Drop Down box.&lt;br /&gt;
&lt;br /&gt;
You can have multiple search types and descriptions.&lt;br /&gt;
&lt;br /&gt;
== plugin_dopluginsearch_{plugin_name}() ==&lt;br /&gt;
This section will outline the method used to search a plugin's data.&lt;br /&gt;
&lt;br /&gt;
=== Input Parameters ===&lt;br /&gt;
The parameters that are passed to this function are as follows:&lt;br /&gt;
*$query -- a string containing the search term.&lt;br /&gt;
*$datestart -- starting date to begin search.&lt;br /&gt;
*$dateend -- ending date to end search.&lt;br /&gt;
*$topic -- topic item is assigned to.&lt;br /&gt;
*$type -- no longer used, deprecated.&lt;br /&gt;
*$author -- the user id of the author.&lt;br /&gt;
*$keyType -- search key type: 'all', 'phrase', 'any'.&lt;br /&gt;
*$page -- no longer used, deprecated.&lt;br /&gt;
*$perpage -- no longer used, deprecated.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Depending on your plugin, some of these criteria may be meaningless and thus ignored.  The function should then perform two basic operations:&lt;br /&gt;
#Build search SQL string using the input parameters.&lt;br /&gt;
#Return the query along with some plugin information.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Returned Values ===&lt;br /&gt;
The search API requires the following information to be returned by the plugin_dopluginsearch_{plugin_name}() function:&lt;br /&gt;
&lt;br /&gt;
==== Plugin Name ====&lt;br /&gt;
* A name to display to the user, i.e. 'My Plugin' (singular preferred)&lt;br /&gt;
* A name used locally to identify the plugin, i.e. 'myplugin'&lt;br /&gt;
&lt;br /&gt;
==== A Search Rank ====&lt;br /&gt;
* An integer between 1 and 5 based on how many result to extract from the query.&lt;br /&gt;
As all the results have been combined into a single list, the core needs to prioritise important plugins to non important ones. The higher the ranking the more results will be displayed to the user. A rank of 1 will show fewer results, where as a rank of 5 shows the most amount of results from the plugin. The rank is optional, if it's not provided it will default to 3.&lt;br /&gt;
Here is an example of Geeklog setup with three plugins, the different rank values will allow varying results from each plugin. The results page is set to display a total of 50 results.&lt;br /&gt;
    plugin      rank    results&lt;br /&gt;
    ---------------------------&lt;br /&gt;
    stories     5       23&lt;br /&gt;
    forums      4       18&lt;br /&gt;
    comments    2       9&lt;br /&gt;
&lt;br /&gt;
==== Standard SQL Query ====&lt;br /&gt;
* A string containing a single query.&lt;br /&gt;
* OR An array of two queries for both MSSQL and MySQL DBMS.&lt;br /&gt;
All SQL queries returned should be without the LIMIT and ORDER BY clauses. The SQL query must have the following column names and look like:&lt;br /&gt;
&amp;lt;pre&amp;gt;SELECT id, title, description, date, user, hits, url FROM ... WHERE ...&amp;lt;/pre&amp;gt;&lt;br /&gt;
If a column does not exist in the table then another value should be substituted, for example: '0' AS hits, ...&lt;br /&gt;
&lt;br /&gt;
The url is where to take the user when they have clicked a result. It should start with a single slash if the target is within the current domain. Otherwise the result with be printed, as is, in the href attribute of the link. For example this url belongs to the Geeklog site&lt;br /&gt;
&amp;lt;pre&amp;gt;CONCAT('/staticpages/index.php?page=', sp.sp_id) AS url&amp;lt;/pre&amp;gt;&lt;br /&gt;
However the Links plugin needs to direct users to external sites when clicked, so providing the url from the database will suffice.&lt;br /&gt;
&lt;br /&gt;
==== Full-Text SQL Query (optional) ====&lt;br /&gt;
* An array of two queries for both MSSQL and MySQL DBMS using the Full-Text search method.&lt;br /&gt;
This search method will take advantage of Full-Text indexes which will reduce search times. This should only be returned if the columns being searched have been properly indexed. The Full-Text SQL Query will only be executed if Full-Text searches have been enabled by the admin during the installation or upgrading process, otherwise the core will always fall back to the Standard SQL Query.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== The SearchCriteria() Class ===&lt;br /&gt;
The process of returning the values is done by initializing a SearchCriteria() object, setting the parameters for the search then returning the object. Here is an example:&lt;br /&gt;
&amp;lt;pre&amp;gt;$search = new SearchCriteria('myplugin', 'My Plugin');&lt;br /&gt;
$search-&amp;gt;setSQL($sql);&lt;br /&gt;
$search-&amp;gt;setFTSQL($ftsql);&lt;br /&gt;
$search-&amp;gt;setRank(4);&amp;lt;/pre&amp;gt;&lt;br /&gt;
This indicates that the 'myplugin' plugin supports Full-Text searches and will have a ranking of 4.&lt;br /&gt;
&lt;br /&gt;
==== buildSearchSQL() Function ====&lt;br /&gt;
As a lot of the plugins will be processing the same or similar SQL queries the buildSearchSQL() function has been provided to simplify things. This function will take four parameters then build the searching part of the SQL query. It will also return the Full-Text query strings should they be required. The parameters are:&lt;br /&gt;
*$keyType -- search key type: 'all', 'phrase', 'any'.&lt;br /&gt;
*$query -- the query string.&lt;br /&gt;
*$columns -- the column names to search.&lt;br /&gt;
*$sql -- the sql query to append to. (optional)&lt;br /&gt;
And an example of how it can be put to use:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
$sql = 'SELECT ... FROM ... WHERE ... ';&lt;br /&gt;
$columns = array('title','bodytext');&lt;br /&gt;
list($sql,$ftsql) = buildSearchSQL('any', 'my geeklog', $columns, $sql);&lt;br /&gt;
&lt;br /&gt;
// $sql =&amp;gt; SELECT ... FROM ... WHERE ... AND ((title LIKE '%my%' OR bodytext LIKE '%my%') OR  (title LIKE '%geeklog%' OR bodytext LIKE '%geeklog%'))&lt;br /&gt;
// $ftsql[mysql] =&amp;gt; SELECT ... FROM ... WHERE ... AND MATCH(title,bodytext) AGAINST ('my geeklog' IN BOOLEAN MODE)&lt;br /&gt;
// $ftsql[mssql] =&amp;gt; SELECT ... FROM ... WHERE ... AND CONTAINS((title,bodytext), '&amp;quot;my&amp;quot; OR &amp;quot;geeklog&amp;quot;')&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
A proper example of its use is at the bottom of the page.&lt;br /&gt;
&lt;br /&gt;
==== Enabling URL Rewrite ====&lt;br /&gt;
If the plugin requires the URL to be passed through the COM_buildUrl() function then it should set the setURLRewrite() function to true. For example:&lt;br /&gt;
&amp;lt;pre&amp;gt;$search = new SearchCriteria('myplugin', 'My Plugin');&lt;br /&gt;
$search-&amp;gt;setSQL($sql);&lt;br /&gt;
$search-&amp;gt;setURLRewrite(true);&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Returning Multiple Objects ====&lt;br /&gt;
In some cases a plugin may be required to search across two or more tables that have no relation with one another. To accommodate this they may return an array of SearchCriteria() objects, each with a different SQL query. To allow the user to differentiate between the results an array of names can be passed, each name will be a separate sub group and will be appended to one another using the separator from the configuration.&lt;br /&gt;
The following example shows how this works:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
// Search the main table&lt;br /&gt;
//   These results will be labelled 'My Plugin &amp;gt; Main'&lt;br /&gt;
$search_main = new SearchCriteria('myplugin', array('My Plugin', 'Main'));&lt;br /&gt;
$plugin_main-&amp;gt;setSQL($sql_main);&lt;br /&gt;
$plugin_main-&amp;gt;setFTSQL($ftsql_main);&lt;br /&gt;
$plugin_main-&amp;gt;setRank(4);&lt;br /&gt;
&lt;br /&gt;
// Search a sub tables&lt;br /&gt;
//   These results will be labelled 'My Plugin &amp;gt; Sub'&lt;br /&gt;
$search_sub = new SearchCriteria('myplugin', array('My Plugin', 'Sub'));&lt;br /&gt;
$search_sub-&amp;gt;setSQL($sql_sub);&lt;br /&gt;
$search_sub-&amp;gt;setFTSQL($ftsql_sub);&lt;br /&gt;
$search_sub-&amp;gt;setRank(4);&lt;br /&gt;
&lt;br /&gt;
// Return both objects&lt;br /&gt;
return array($search_main, $search_sub);&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
Note: The plugin identifier needs to stay the same across all objects, in this case 'myplugin'.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== A Working Example ===&lt;br /&gt;
This example searches the Stories, although it's not a plugin it puts to use everything discussed here so it's a good example of how to implement the API in your plugin.&lt;br /&gt;
&amp;lt;pre&amp;gt;function plugin_dopluginsearch_searchStories($query, $datestart, $dateend, $topic, $type, $author, $keyType, $page, $perpage)&lt;br /&gt;
{&lt;br /&gt;
    global $_TABLES, $_DB_dbms, $LANG09;&lt;br /&gt;
&lt;br /&gt;
    // Make sure the query is SQL safe&lt;br /&gt;
    $query = trim(addslashes($query));&lt;br /&gt;
&lt;br /&gt;
    // Build the first part of the query&lt;br /&gt;
    $sql = &amp;quot;SELECT&lt;br /&gt;
                s.sid AS id,&lt;br /&gt;
                s.title AS title,&lt;br /&gt;
                s.introtext AS description,&lt;br /&gt;
                UNIX_TIMESTAMP(s.date) AS date,&lt;br /&gt;
                s.uid AS uid,&lt;br /&gt;
                s.hits AS hits,&lt;br /&gt;
                CONCAT('/article.php?story=',s.sid) AS url &amp;quot;;&lt;br /&gt;
    $sql .= &amp;quot;FROM {$_TABLES['stories']} AS s, {$_TABLES['users']} AS u &amp;quot;;&lt;br /&gt;
    $sql .= &amp;quot;WHERE (draft_flag = 0) AND (date &amp;lt;= NOW()) AND (u.uid = s.uid) &amp;quot;;&lt;br /&gt;
    $sql .= COM_getPermSQL('AND') . COM_getTopicSQL('AND') . COM_getLangSQL('sid', 'AND') . ' ';&lt;br /&gt;
&lt;br /&gt;
    // If we are searching by date add that too&lt;br /&gt;
    if (!empty($datestart) &amp;amp;&amp;amp; !empty($dateend)) {&lt;br /&gt;
        $delim = substr($datestart, 4, 1);&lt;br /&gt;
        if (!empty($delim)) {&lt;br /&gt;
            $DS = explode($delim, $datestart);&lt;br /&gt;
            $DE = explode($delim, $dateend);&lt;br /&gt;
            $startdate = mktime(0,0,0,$DS[1],$DS[2],$DS[0]);&lt;br /&gt;
            $enddate = mktime(23,59,59,$DE[1],$DE[2],$DE[0]);&lt;br /&gt;
            $sql .= &amp;quot;AND (UNIX_TIMESTAMP(date) BETWEEN '$startdate' AND '$enddate') &amp;quot;;&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
    if (!empty($topic)) {&lt;br /&gt;
        $sql .= &amp;quot;AND (s.tid = '$topic') &amp;quot;;&lt;br /&gt;
    }&lt;br /&gt;
    if (!empty($author)) {&lt;br /&gt;
        $sql .= &amp;quot;AND (s.uid = '$author') &amp;quot;;&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    // Create a SearchCriteria instance with the name of the plugin&lt;br /&gt;
    $search = new SearchCriteria('stories', $LANG09[65]);&lt;br /&gt;
&lt;br /&gt;
    // These are the columns in the table that need searching&lt;br /&gt;
    $columns = array('introtext','bodytext','title');&lt;br /&gt;
&lt;br /&gt;
    // Get back the completed SQL query&lt;br /&gt;
    list($sql,$ftsql) = $search-&amp;gt;buildSearchSQL($keyType, $query, $columns, $sql);&lt;br /&gt;
&lt;br /&gt;
    // Set the Std. SQL Query&lt;br /&gt;
    $search-&amp;gt;setSQL($sql);&lt;br /&gt;
&lt;br /&gt;
    // Set the Full-Text Query, remember the columns _MUST_ be indexed first. If they are not then don't set this.&lt;br /&gt;
    $search-&amp;gt;setFTSQL($ftsql);&lt;br /&gt;
&lt;br /&gt;
    // Finally set a high ranking, enable URLRewrite and return the object.&lt;br /&gt;
    $search-&amp;gt;setRank(5);&lt;br /&gt;
    $search-&amp;gt;setURLRewrite(true);&lt;br /&gt;
    return $search;&lt;br /&gt;
}&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
For more examples, there's a forum post ({{forum|87624}}) with updated search functions for the [[FAQ Manager Plugin|FAQ Manager]], [[Forum Plugin|Forum]], and [[File Management Plugin|File Management]] plugins.&lt;br /&gt;
&lt;br /&gt;
[[Category:Plugin Development]]&lt;/div&gt;</summary>
		<author><name>LWC</name></author>	</entry>

	<entry>
		<id>http://gwiki3.thatlinuxbox.com/index.php?title=Using_Geeklog%27s_Search_Engine&amp;diff=5467</id>
		<title>Using Geeklog's Search Engine</title>
		<link rel="alternate" type="text/html" href="http://gwiki3.thatlinuxbox.com/index.php?title=Using_Geeklog%27s_Search_Engine&amp;diff=5467"/>
				<updated>2009-05-26T12:16:30Z</updated>
		
		<summary type="html">&lt;p&gt;LWC: Formatted&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;==Old method==&lt;br /&gt;
This method is meant for Geeklog v1.5 and below.&lt;br /&gt;
&lt;br /&gt;
===The functions===&lt;br /&gt;
Tying your plugin into Geeklogs search API is rather easy.  Easy, that is, if you know how search your plugins data already.  The Geeklog search API provides a way for you to return your search results back to Geeklog to be included in its search results page.&lt;br /&gt;
&lt;br /&gt;
For the data in your plugin to be searched by Geeklogs search functions, there are two functions that you need to implement in your plugins function.inc:&lt;br /&gt;
&lt;br /&gt;
* plugin_searchtypes_{plugin_name}() returns to Geeklog the type(s) of search.&lt;br /&gt;
* plugin_dopluginsearch_{plugin_name}() returns the actual results to Geeklog.&lt;br /&gt;
&lt;br /&gt;
Let's look at each of them in turn:&lt;br /&gt;
&lt;br /&gt;
==== plugin_searchtypes_{plugin_name}() ====&lt;br /&gt;
&lt;br /&gt;
This function takes no parameters and returns an associative array of the search type.  The normal code for this&lt;br /&gt;
function will make it all clear.  Normally the function looks like this:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
function plugin_searchtypes_{plugin_name}() {&lt;br /&gt;
    global $LANG_PL00;&lt;br /&gt;
    $tmp['{plugin_name}']= $LANG_PL00['searchtype'];&lt;br /&gt;
    return $tmp;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&amp;lt;sup&amp;gt;(don't forget to replace {plugin_name} with the actual name).&amp;lt;/sup&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Naturally all occurrences of plugin would be replaced with the name of your plugin and the LANGUAGE varible $LANG_PL00 is just an example. Your Plugin needs to use a unique variable name so replace PL00.&lt;br /&gt;
&lt;br /&gt;
The return array is of the format array['searchtype'] = 'Search Description', where searchtype is returned to your plugin search routine and Description is displayed in the Search Page Drop Down box.&lt;br /&gt;
&lt;br /&gt;
You can have multiple search types and descriptions.&lt;br /&gt;
&lt;br /&gt;
==== plugin_dopluginsearch_{plugin_name}() ====&lt;br /&gt;
&lt;br /&gt;
This function is where the search is actually done.  It is passed a number of parameters that can be used in your search.  They are:&lt;br /&gt;
&lt;br /&gt;
* $query -- the actual items being searched for.&lt;br /&gt;
* $datestart -- starting date to begin search.&lt;br /&gt;
* $dateend -- ending date to end search.&lt;br /&gt;
* $topic -- topic item is assigned to.&lt;br /&gt;
* $type -- type of item (see searchtypes above).&lt;br /&gt;
* $author -- author of item.&lt;br /&gt;
&lt;br /&gt;
Depending on your plugin, some of these criteria may be meaningless and thus ignored.  Here is a brief overview of what your function should do.&lt;br /&gt;
&lt;br /&gt;
# Initialize plugin object&lt;br /&gt;
# Check to see if type is appropriate for this plugin -- if not, bail out.&lt;br /&gt;
# Get a list of all your items to search.&lt;br /&gt;
# Create Search object and Build search results header.&lt;br /&gt;
# Search each of your items in turn.&lt;br /&gt;
# If a match then add item to the results.&lt;br /&gt;
# When done set number of results and return search object&lt;br /&gt;
&lt;br /&gt;
Looking at the example code  should make all of this clear.  The search results are returned in a object of type Plugin.  You initialize the object by setting the Label and then setting the names of the columns you want returned.  This is done in typical object fashion with this construct: $plugin-&amp;gt;addSearch Heading.    &lt;br /&gt;
&lt;br /&gt;
The headings will vary according to what your plugin does, but should include a link to the item found.  After searching each of your items in turn; you add your search results to an array having the same number of items as the labels you set earlier.    &lt;br /&gt;
&lt;br /&gt;
Note:  your search should be case insensitive to be compatible with Geeklogs search.  This array will correspond to the column headings entered above.  In the example below, the array consists of the Title of the page, the url to the page (a link) and the number of hits.  This array is then added to the Plugin object as a row. &lt;br /&gt;
 &lt;br /&gt;
The following construct is used:  $plugin-&amp;gt;addSearchResult. &lt;br /&gt;
When you are done searching you set the number of rows found and the number searched to the plugin object and return it. The example below is from the External Pages Plugin.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
function plugin_dopluginsearch_external($query,$datestart,$dateend,$topic,$type,$author)&lt;br /&gt;
{&lt;br /&gt;
    global $_TABLES, $_CONF, $LANG_EX00;&lt;br /&gt;
&lt;br /&gt;
    if (empty($type)) {&lt;br /&gt;
        $type = 'all';&lt;br /&gt;
    }&lt;br /&gt;
      &lt;br /&gt;
    // Bail if we aren't supppose to do our search&lt;br /&gt;
    if ($type &amp;amp;lt;&amp;amp;gt; 'all' AND $type &amp;amp;lt;&amp;amp;gt; 'external') {&lt;br /&gt;
        $plugin_results = new Plugin();&lt;br /&gt;
        $plugin_results-&amp;amp;gt;plugin_name = 'external';&lt;br /&gt;
        $plugin_results-&amp;amp;gt;searchlabel = $LANG_EX00['externpages'] . $LANG_EX00['results'];&lt;br /&gt;
        return $plugin_results;&lt;br /&gt;
    }&lt;br /&gt;
      &lt;br /&gt;
    // Build search SQL - Modified to exclude static PHP pages from search.&lt;br /&gt;
    $sql = &amp;amp;quot;SELECT * from &amp;amp;quot; . $_TABLES['external'];&lt;br /&gt;
    $result = DB_query($sql);&lt;br /&gt;
    &lt;br /&gt;
    // OK, now create new plugin object and insert table header labels&lt;br /&gt;
    require_once($_CONF['path_system'] . 'classes/plugin.class.php');&lt;br /&gt;
    $plugin_results = new Plugin();&lt;br /&gt;
    $plugin_results-&amp;amp;gt;plugin_name = 'external';&lt;br /&gt;
    $plugin_results-&amp;amp;gt;searchlabel = $LANG_EX00['externpages'] . $LANG_EX00['results'];&lt;br /&gt;
    $plugin_results-&amp;amp;gt;addSearchHeading($LANG_EX00['titlemsg']);&lt;br /&gt;
    $plugin_results-&amp;amp;gt;addSearchHeading($LANG_EX00['urlmsg']);&lt;br /&gt;
    $plugin_results-&amp;amp;gt;addSearchHeading($LANG_EX00['hitsmsg']);&lt;br /&gt;
    $mycount = DB_numRows($result);&lt;br /&gt;
    // NOTE if any of your data items need to be links then add them here! &lt;br /&gt;
    // make sure data elements are in an array and in the same order as your&lt;br /&gt;
    // headings above!&lt;br /&gt;
    for ($i = 1; $i &amp;lt;= $mycount; $i++) {&lt;br /&gt;
        $A = DB_fetchArray($result);&lt;br /&gt;
&lt;br /&gt;
        if(SEC_hasAccess($A[owner_id],$A[group_id],$A[perm_owner],$A[perm_group],$A[perm_members],$A[perm_anon])){&lt;br /&gt;
            if (preg_match(&amp;quot;/^(http:\/\/)/i&amp;quot;,$A['url']) == 1) {&lt;br /&gt;
                $pth = $A['url'];&lt;br /&gt;
                $url = $A['url'];&lt;br /&gt;
            } else {&lt;br /&gt;
                $pth = $_CONF['path_html'] . $A['url'];&lt;br /&gt;
                $url = $_CONF['site_url'] . '/' . $A['url'];&lt;br /&gt;
            }&lt;br /&gt;
            $cnts = implode('',file($pth));&lt;br /&gt;
            if (stristr($cnts,$query) != '') {&lt;br /&gt;
                $rcnt++;&lt;br /&gt;
                $A['title'] = stripslashes($A['title']);&lt;br /&gt;
                $row = array($A['title'],&lt;br /&gt;
                      '&amp;lt;a href=&amp;quot;' . $url . '&amp;quot;&amp;gt;' . $A['url'] . &amp;quot;&amp;lt;/a&amp;gt;&amp;quot;,&lt;br /&gt;
                     $A['hits']);&lt;br /&gt;
                $plugin_results-&amp;gt;addSearchResult($row);&lt;br /&gt;
            }&lt;br /&gt;
        }&lt;br /&gt;
    &lt;br /&gt;
    }&lt;br /&gt;
    $plugin_results-&amp;gt;num_searchresults = $rcnt;&lt;br /&gt;
    $plugin_results-&amp;gt;num_itemssearched = DB_count($_TABLES['external']);&lt;br /&gt;
&lt;br /&gt;
    return $plugin_results;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==New method==&lt;br /&gt;
This method only works in Geeklog v1.6 and above.&lt;br /&gt;
&lt;br /&gt;
There is an updated API which makes use of the new and improved [[Using Geeklog's Improved Search Engine|SearchCriteria()]] class.&lt;br /&gt;
&lt;br /&gt;
[[Category:Plugin Developers Handbook]] [[Category:Plugin Development]]&lt;/div&gt;</summary>
		<author><name>LWC</name></author>	</entry>

	<entry>
		<id>http://gwiki3.thatlinuxbox.com/index.php?title=Using_Geeklog%27s_Improved_Search_Engine&amp;diff=5466</id>
		<title>Using Geeklog's Improved Search Engine</title>
		<link rel="alternate" type="text/html" href="http://gwiki3.thatlinuxbox.com/index.php?title=Using_Geeklog%27s_Improved_Search_Engine&amp;diff=5466"/>
				<updated>2009-05-26T12:13:06Z</updated>
		
		<summary type="html">&lt;p&gt;LWC: /* A Working Example */ Link&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Tying your plugin into Geeklogs search API is rather easy.  Easy, that is, if you know how to search &lt;br /&gt;
your plugins data already. The Geeklog search API provides a way for you to return the SQL query back to Geeklog which will be executed in the core and the results included in its search page.&lt;br /&gt;
&lt;br /&gt;
For the data in your plugin to be searched by Geeklog's search functions, there are two functions that you need to implement in your plugins function.inc:&lt;br /&gt;
&lt;br /&gt;
*plugin_searchtypes_{plugin_name}() returns to Geeklog the type(s) of search.&lt;br /&gt;
*plugin_dopluginsearch_{plugin_name}() returns the search SQL query back to Geeklog.&lt;br /&gt;
&lt;br /&gt;
Let's look at each of them in turn:&lt;br /&gt;
&lt;br /&gt;
== plugin_searchtypes_{plugin_name}() ==&lt;br /&gt;
&lt;br /&gt;
This function takes no parameters and returns an associative array of the search type.  The normal code for this&lt;br /&gt;
function will make it all clear.  Normally the function looks like this:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;function plugin_searchtypes_{plugin_name}()&lt;br /&gt;
{&lt;br /&gt;
    global $LANG_PL00;&lt;br /&gt;
    $tmp['searchtype']= $LANG_PL00['searchtype'];&lt;br /&gt;
    return $tmp;&lt;br /&gt;
}&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Naturally all occurrences of plugin would be replaced with the name of your &lt;br /&gt;
plugin and the LANGUAGE varible $LANG_PL00 is just an example. Your Plugin needs &lt;br /&gt;
to use a unique variable name so replace PL00.&lt;br /&gt;
&lt;br /&gt;
The return array is of the format array['searchtype'] = 'Search Description', where searchtype &lt;br /&gt;
is returned to your plugin search routine and Description is displayed in the &lt;br /&gt;
Search Page Drop Down box.&lt;br /&gt;
&lt;br /&gt;
You can have multiple search types and descriptions.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== plugin_dopluginsearch_{plugin_name}() ==&lt;br /&gt;
This section will outline the method used to search a plugin's data.&lt;br /&gt;
&lt;br /&gt;
=== Input Parameters ===&lt;br /&gt;
The parameters that are passed to this function are as follows:&lt;br /&gt;
*$query -- a string containing the search term.&lt;br /&gt;
*$datestart -- starting date to begin search.&lt;br /&gt;
*$dateend -- ending date to end search.&lt;br /&gt;
*$topic -- topic item is assigned to.&lt;br /&gt;
*$type -- no longer used, deprecated.&lt;br /&gt;
*$author -- the user id of the author.&lt;br /&gt;
*$keyType -- search key type: 'all', 'phrase', 'any'.&lt;br /&gt;
*$page -- no longer used, deprecated.&lt;br /&gt;
*$perpage -- no longer used, deprecated.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Depending on your plugin, some of these criteria may be meaningless and thus ignored.  The function should then perform two basic operations:&lt;br /&gt;
#Build search SQL string using the input parameters.&lt;br /&gt;
#Return the query along with some plugin information.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Returned Values ===&lt;br /&gt;
The search API requires the following information to be returned by the plugin_dopluginsearch_{plugin_name}() function:&lt;br /&gt;
&lt;br /&gt;
==== Plugin Name ====&lt;br /&gt;
* A name to display to the user, i.e. 'My Plugin' (singular preferred)&lt;br /&gt;
* A name used locally to identify the plugin, i.e. 'myplugin'&lt;br /&gt;
&lt;br /&gt;
==== A Search Rank ====&lt;br /&gt;
* An integer between 1 and 5 based on how many result to extract from the query.&lt;br /&gt;
As all the results have been combined into a single list, the core needs to prioritise important plugins to non important ones. The higher the ranking the more results will be displayed to the user. A rank of 1 will show fewer results, where as a rank of 5 shows the most amount of results from the plugin. The rank is optional, if it's not provided it will default to 3.&lt;br /&gt;
Here is an example of Geeklog setup with three plugins, the different rank values will allow varying results from each plugin. The results page is set to display a total of 50 results.&lt;br /&gt;
    plugin      rank    results&lt;br /&gt;
    ---------------------------&lt;br /&gt;
    stories     5       23&lt;br /&gt;
    forums      4       18&lt;br /&gt;
    comments    2       9&lt;br /&gt;
&lt;br /&gt;
==== Standard SQL Query ====&lt;br /&gt;
* A string containing a single query.&lt;br /&gt;
* OR An array of two queries for both MSSQL and MySQL DBMS.&lt;br /&gt;
All SQL queries returned should be without the LIMIT and ORDER BY clauses. The SQL query must have the following column names and look like:&lt;br /&gt;
&amp;lt;pre&amp;gt;SELECT id, title, description, date, user, hits, url FROM ... WHERE ...&amp;lt;/pre&amp;gt;&lt;br /&gt;
If a column does not exist in the table then another value should be substituted, for example: '0' AS hits, ...&lt;br /&gt;
&lt;br /&gt;
The url is where to take the user when they have clicked a result. It should start with a single slash if the target is within the current domain. Otherwise the result with be printed, as is, in the href attribute of the link. For example this url belongs to the Geeklog site&lt;br /&gt;
&amp;lt;pre&amp;gt;CONCAT('/staticpages/index.php?page=', sp.sp_id) AS url&amp;lt;/pre&amp;gt;&lt;br /&gt;
However the Links plugin needs to direct users to external sites when clicked, so providing the url from the database will suffice.&lt;br /&gt;
&lt;br /&gt;
==== Full-Text SQL Query (optional) ====&lt;br /&gt;
* An array of two queries for both MSSQL and MySQL DBMS using the Full-Text search method.&lt;br /&gt;
This search method will take advantage of Full-Text indexes which will reduce search times. This should only be returned if the columns being searched have been properly indexed. The Full-Text SQL Query will only be executed if Full-Text searches have been enabled by the admin during the installation or upgrading process, otherwise the core will always fall back to the Standard SQL Query.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== The SearchCriteria() Class ===&lt;br /&gt;
The process of returning the values is done by initializing a SearchCriteria() object, setting the parameters for the search then returning the object. Here is an example:&lt;br /&gt;
&amp;lt;pre&amp;gt;$search = new SearchCriteria('myplugin', 'My Plugin');&lt;br /&gt;
$search-&amp;gt;setSQL($sql);&lt;br /&gt;
$search-&amp;gt;setFTSQL($ftsql);&lt;br /&gt;
$search-&amp;gt;setRank(4);&amp;lt;/pre&amp;gt;&lt;br /&gt;
This indicates that the 'myplugin' plugin supports Full-Text searches and will have a ranking of 4.&lt;br /&gt;
&lt;br /&gt;
==== buildSearchSQL() Function ====&lt;br /&gt;
As a lot of the plugins will be processing the same or similar SQL queries the buildSearchSQL() function has been provided to simplify things. This function will take four parameters then build the searching part of the SQL query. It will also return the Full-Text query strings should they be required. The parameters are:&lt;br /&gt;
*$keyType -- search key type: 'all', 'phrase', 'any'.&lt;br /&gt;
*$query -- the query string.&lt;br /&gt;
*$columns -- the column names to search.&lt;br /&gt;
*$sql -- the sql query to append to. (optional)&lt;br /&gt;
And an example of how it can be put to use:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
$sql = 'SELECT ... FROM ... WHERE ... ';&lt;br /&gt;
$columns = array('title','bodytext');&lt;br /&gt;
list($sql,$ftsql) = buildSearchSQL('any', 'my geeklog', $columns, $sql);&lt;br /&gt;
&lt;br /&gt;
// $sql =&amp;gt; SELECT ... FROM ... WHERE ... AND ((title LIKE '%my%' OR bodytext LIKE '%my%') OR  (title LIKE '%geeklog%' OR bodytext LIKE '%geeklog%'))&lt;br /&gt;
// $ftsql[mysql] =&amp;gt; SELECT ... FROM ... WHERE ... AND MATCH(title,bodytext) AGAINST ('my geeklog' IN BOOLEAN MODE)&lt;br /&gt;
// $ftsql[mssql] =&amp;gt; SELECT ... FROM ... WHERE ... AND CONTAINS((title,bodytext), '&amp;quot;my&amp;quot; OR &amp;quot;geeklog&amp;quot;')&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
A proper example of its use is at the bottom of the page.&lt;br /&gt;
&lt;br /&gt;
==== Enabling URL Rewrite ====&lt;br /&gt;
If the plugin requires the URL to be passed through the COM_buildUrl() function then it should set the setURLRewrite() function to true. For example:&lt;br /&gt;
&amp;lt;pre&amp;gt;$search = new SearchCriteria('myplugin', 'My Plugin');&lt;br /&gt;
$search-&amp;gt;setSQL($sql);&lt;br /&gt;
$search-&amp;gt;setURLRewrite(true);&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Returning Multiple Objects ====&lt;br /&gt;
In some cases a plugin may be required to search across two or more tables that have no relation with one another. To accommodate this they may return an array of SearchCriteria() objects, each with a different SQL query. To allow the user to differentiate between the results an array of names can be passed, each name will be a separate sub group and will be appended to one another using the separator from the configuration.&lt;br /&gt;
The following example shows how this works:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
// Search the main table&lt;br /&gt;
//   These results will be labelled 'My Plugin &amp;gt; Main'&lt;br /&gt;
$search_main = new SearchCriteria('myplugin', array('My Plugin', 'Main'));&lt;br /&gt;
$plugin_main-&amp;gt;setSQL($sql_main);&lt;br /&gt;
$plugin_main-&amp;gt;setFTSQL($ftsql_main);&lt;br /&gt;
$plugin_main-&amp;gt;setRank(4);&lt;br /&gt;
&lt;br /&gt;
// Search a sub tables&lt;br /&gt;
//   These results will be labelled 'My Plugin &amp;gt; Sub'&lt;br /&gt;
$search_sub = new SearchCriteria('myplugin', array('My Plugin', 'Sub'));&lt;br /&gt;
$search_sub-&amp;gt;setSQL($sql_sub);&lt;br /&gt;
$search_sub-&amp;gt;setFTSQL($ftsql_sub);&lt;br /&gt;
$search_sub-&amp;gt;setRank(4);&lt;br /&gt;
&lt;br /&gt;
// Return both objects&lt;br /&gt;
return array($search_main, $search_sub);&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
Note: The plugin identifier needs to stay the same across all objects, in this case 'myplugin'.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== A Working Example ===&lt;br /&gt;
This example searches the Stories, although it's not a plugin it puts to use everything discussed here so it's a good example of how to implement the API in your plugin.&lt;br /&gt;
&amp;lt;pre&amp;gt;function plugin_dopluginsearch_searchStories($query, $datestart, $dateend, $topic, $type, $author, $keyType, $page, $perpage)&lt;br /&gt;
{&lt;br /&gt;
    global $_TABLES, $_DB_dbms, $LANG09;&lt;br /&gt;
&lt;br /&gt;
    // Make sure the query is SQL safe&lt;br /&gt;
    $query = trim(addslashes($query));&lt;br /&gt;
&lt;br /&gt;
    // Build the first part of the query&lt;br /&gt;
    $sql = &amp;quot;SELECT&lt;br /&gt;
                s.sid AS id,&lt;br /&gt;
                s.title AS title,&lt;br /&gt;
                s.introtext AS description,&lt;br /&gt;
                UNIX_TIMESTAMP(s.date) AS date,&lt;br /&gt;
                s.uid AS uid,&lt;br /&gt;
                s.hits AS hits,&lt;br /&gt;
                CONCAT('/article.php?story=',s.sid) AS url &amp;quot;;&lt;br /&gt;
    $sql .= &amp;quot;FROM {$_TABLES['stories']} AS s, {$_TABLES['users']} AS u &amp;quot;;&lt;br /&gt;
    $sql .= &amp;quot;WHERE (draft_flag = 0) AND (date &amp;lt;= NOW()) AND (u.uid = s.uid) &amp;quot;;&lt;br /&gt;
    $sql .= COM_getPermSQL('AND') . COM_getTopicSQL('AND') . COM_getLangSQL('sid', 'AND') . ' ';&lt;br /&gt;
&lt;br /&gt;
    // If we are searching by date add that too&lt;br /&gt;
    if (!empty($datestart) &amp;amp;&amp;amp; !empty($dateend)) {&lt;br /&gt;
        $delim = substr($datestart, 4, 1);&lt;br /&gt;
        if (!empty($delim)) {&lt;br /&gt;
            $DS = explode($delim, $datestart);&lt;br /&gt;
            $DE = explode($delim, $dateend);&lt;br /&gt;
            $startdate = mktime(0,0,0,$DS[1],$DS[2],$DS[0]);&lt;br /&gt;
            $enddate = mktime(23,59,59,$DE[1],$DE[2],$DE[0]);&lt;br /&gt;
            $sql .= &amp;quot;AND (UNIX_TIMESTAMP(date) BETWEEN '$startdate' AND '$enddate') &amp;quot;;&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
    if (!empty($topic)) {&lt;br /&gt;
        $sql .= &amp;quot;AND (s.tid = '$topic') &amp;quot;;&lt;br /&gt;
    }&lt;br /&gt;
    if (!empty($author)) {&lt;br /&gt;
        $sql .= &amp;quot;AND (s.uid = '$author') &amp;quot;;&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    // Create a SearchCriteria instance with the name of the plugin&lt;br /&gt;
    $search = new SearchCriteria('stories', $LANG09[65]);&lt;br /&gt;
&lt;br /&gt;
    // These are the columns in the table that need searching&lt;br /&gt;
    $columns = array('introtext','bodytext','title');&lt;br /&gt;
&lt;br /&gt;
    // Get back the completed SQL query&lt;br /&gt;
    list($sql,$ftsql) = $search-&amp;gt;buildSearchSQL($keyType, $query, $columns, $sql);&lt;br /&gt;
&lt;br /&gt;
    // Set the Std. SQL Query&lt;br /&gt;
    $search-&amp;gt;setSQL($sql);&lt;br /&gt;
&lt;br /&gt;
    // Set the Full-Text Query, remember the columns _MUST_ be indexed first. If they are not then don't set this.&lt;br /&gt;
    $search-&amp;gt;setFTSQL($ftsql);&lt;br /&gt;
&lt;br /&gt;
    // Finally set a high ranking, enable URLRewrite and return the object.&lt;br /&gt;
    $search-&amp;gt;setRank(5);&lt;br /&gt;
    $search-&amp;gt;setURLRewrite(true);&lt;br /&gt;
    return $search;&lt;br /&gt;
}&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
For more examples, there's a forum post ({{forum|87624}}) with updated search functions for the [[FAQ Manager Plugin|FAQ Manager]], [[Forum Plugin|Forum]], and [[File Management Plugin|File Management]] plugins.&lt;br /&gt;
&lt;br /&gt;
[[Category:Plugin Development]]&lt;/div&gt;</summary>
		<author><name>LWC</name></author>	</entry>

	<entry>
		<id>http://gwiki3.thatlinuxbox.com/index.php?title=Template:Forum&amp;diff=5465</id>
		<title>Template:Forum</title>
		<link rel="alternate" type="text/html" href="http://gwiki3.thatlinuxbox.com/index.php?title=Template:Forum&amp;diff=5465"/>
				<updated>2009-05-26T12:11:35Z</updated>
		
		<summary type="html">&lt;p&gt;LWC: New page: &amp;lt;includeonly&amp;gt;http://www.geeklog.net/forum/viewtopic.php?showtopic={{{1}}}&amp;lt;/includeonly&amp;gt;&amp;lt;noinclude&amp;gt;Supply an forum ID from the main site and get a link for it.  ==Usage== &amp;lt;pre&amp;gt;&amp;lt;nowiki&amp;gt;{{for...&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&amp;lt;includeonly&amp;gt;http://www.geeklog.net/forum/viewtopic.php?showtopic={{{1}}}&amp;lt;/includeonly&amp;gt;&amp;lt;noinclude&amp;gt;Supply an forum ID from the main site and get a link for it.&lt;br /&gt;
&lt;br /&gt;
==Usage==&lt;br /&gt;
&amp;lt;pre&amp;gt;&amp;lt;nowiki&amp;gt;{{forum|forumID}}&amp;lt;/nowiki&amp;gt;&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
For example, &amp;lt;nowiki&amp;gt;{{forum|2004063013542379}}&amp;lt;/nowiki&amp;gt; would display as:&lt;br /&gt;
&lt;br /&gt;
{{forum|2004063013542379}}&lt;br /&gt;
&amp;lt;/noinclude&amp;gt;&lt;/div&gt;</summary>
		<author><name>LWC</name></author>	</entry>

	<entry>
		<id>http://gwiki3.thatlinuxbox.com/index.php?title=Template:Article&amp;diff=5464</id>
		<title>Template:Article</title>
		<link rel="alternate" type="text/html" href="http://gwiki3.thatlinuxbox.com/index.php?title=Template:Article&amp;diff=5464"/>
				<updated>2009-05-26T12:08:51Z</updated>
		
		<summary type="html">&lt;p&gt;LWC: Switched&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&amp;lt;includeonly&amp;gt;http://www.geeklog.net/article.php/{{{1}}}&amp;lt;/includeonly&amp;gt;&amp;lt;noinclude&amp;gt;Supply an article ID from the main site and get a link for it.&lt;br /&gt;
&lt;br /&gt;
==Usage==&lt;br /&gt;
&amp;lt;pre&amp;gt;&amp;lt;nowiki&amp;gt;{{article|articleID}}&amp;lt;/nowiki&amp;gt;&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
For example, &amp;lt;nowiki&amp;gt;{{article|2004063013542379}}&amp;lt;/nowiki&amp;gt; would display as:&lt;br /&gt;
&lt;br /&gt;
{{article|2004063013542379}}&lt;br /&gt;
&amp;lt;/noinclude&amp;gt;&lt;/div&gt;</summary>
		<author><name>LWC</name></author>	</entry>

	<entry>
		<id>http://gwiki3.thatlinuxbox.com/index.php?title=Template:Main_site&amp;diff=5463</id>
		<title>Template:Main site</title>
		<link rel="alternate" type="text/html" href="http://gwiki3.thatlinuxbox.com/index.php?title=Template:Main_site&amp;diff=5463"/>
				<updated>2009-05-26T12:08:47Z</updated>
		
		<summary type="html">&lt;p&gt;LWC: Switched&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;#REDIRECT [[Template:Article]]&lt;/div&gt;</summary>
		<author><name>LWC</name></author>	</entry>

	<entry>
		<id>http://gwiki3.thatlinuxbox.com/index.php?title=Template:Main_site&amp;diff=5462</id>
		<title>Template:Main site</title>
		<link rel="alternate" type="text/html" href="http://gwiki3.thatlinuxbox.com/index.php?title=Template:Main_site&amp;diff=5462"/>
				<updated>2009-05-26T12:07:37Z</updated>
		
		<summary type="html">&lt;p&gt;LWC: Undo revision 5451 by LWC (Talk) This wiki doesn't support advanced parser functions&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&amp;lt;includeonly&amp;gt;http://www.geeklog.net/article.php/{{{1}}}&amp;lt;/includeonly&amp;gt;&amp;lt;noinclude&amp;gt;Supply an article ID from the main site and get a link for it.&lt;br /&gt;
&lt;br /&gt;
==Usage==&lt;br /&gt;
&amp;lt;pre&amp;gt;&amp;lt;nowiki&amp;gt;{{article|articleID}}&amp;lt;/nowiki&amp;gt;&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
For example, &amp;lt;nowiki&amp;gt;{{article|2004063013542379}}&amp;lt;/nowiki&amp;gt; would display as:&lt;br /&gt;
&lt;br /&gt;
{{article|2004063013542379}}&lt;br /&gt;
&amp;lt;/noinclude&amp;gt;&lt;/div&gt;</summary>
		<author><name>LWC</name></author>	</entry>

	<entry>
		<id>http://gwiki3.thatlinuxbox.com/index.php?title=Template:Main_site&amp;diff=5461</id>
		<title>Template:Main site</title>
		<link rel="alternate" type="text/html" href="http://gwiki3.thatlinuxbox.com/index.php?title=Template:Main_site&amp;diff=5461"/>
				<updated>2009-05-26T12:05:42Z</updated>
		
		<summary type="html">&lt;p&gt;LWC: Testing&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{#expr: 1 and -1 }}&lt;/div&gt;</summary>
		<author><name>LWC</name></author>	</entry>

	</feed>