+ $squirrelmail_plugin_hooks['loading_prefs']['demo']
+ = 'demo_load_prefs';
+
+ Assuming the function demo_load_prefs() calls another function
+ elsewhere called demo_load_prefs_do(), that function just needs to
+ pull out any all all preferences you'll be needing elsewhere:
+
+ global $data_dir, $username, $pref_value;
+ $pref_value = getPref($data_dir, $username, 'pref_name', 'default value');
+
+ Remember to globalize each preference, or this code is useless.
+
+
+Internationalization
+--------------------
+
+Although this document may only be available in English, we sure hope that you
+are thinking about making your plugin useful to the thousands of non-English
+speaking SquirrelMail users out there! It is almost rude not to do so, and
+it isn't much trouble, either. This document will only describe how you can
+accomplish the internationalization of a plugin. For more general information
+about PHP and SquirrelMail translation facilities, see:
+
+http://www.squirrelmail.org/wiki/wiki.php?LanguageTranslation
+
+The unofficial way to internationalize a plugin is to put all plugin output
+into the proper format but to rely on the SquirrelMail translation facilities
+for all the rest. If the plugin were really to get translated, you'd need
+to make sure that all output strings for your plugin are either added to or
+already exist in the main SquirrelMail locale files.
+
+The better way to make sure your plugin is translated is to create your own
+locale files and what is called a "gettext domain" (see the link above for
+more information).
+
+There are three basic steps to getting your plugins internationalized: put
+all output into the proper format, switch gettext domains and create locale
+files.
+
+ 1. Putting plugin output into the correct format is quite easy. The hard
+ part is making sure you catch every last echo statement. You need to
+ echo text like this:
+
+ echo _("Hello");
+
+ So, even in the HTML segments of your plugin files, you need to do this:
+
+ <input type="submit" value="<?php echo _("Submit") ?>">
+
+ You can put any text you want inside of the quotes (you MUST use double
+ quotes!), including HTML tags, etc. What you should think carefully
+ about is that some languages may use different word ordering, so this
+ might be problematic:
+
+ echo _("I want to eat a ") . $fruitName . _(" before noon");
+
+ Because some languages (Japanese, for instance) would need to translate
+ such a sentence to "Before noon " . $fruitName . " I want to eat", but
+ with the format above, they are stuck having to translate each piece
+ separately. You might want to reword your original sentence:
+
+ echo _("This is what I want to eat before noon: ") . $fruitName;
+
+ 2. By default, the SquirrelMail gettext domain is always in use. That
+ means that any text in the format described above will be translated
+ using the locale files found in the main SquirrelMail locale directory.
+ Unless your plugin produces no output or only output that is in fact
+ translated under the default SquirrelMail domain, you need to create
+ your own gettext domain. The PHP for doing so is very simple. At
+ the top of any file that produces any output, place the following code
+ (again, using "demo" as the plugin name):
+
+ bindtextdomain('demo', SM_PATH . 'plugins/demo/locale');
+ textdomain('demo');
+
+ Now all output will be translated using your own custom locale files.
+ Please be sure to switch back to the SquirrelMail domain at the end
+ of the file, or many of the other SquirrelMail files may misbehave:
+
+ bindtextdomain('squirrelmail', SM_PATH . 'locale');
+ textdomain('squirrelmail');
+
+ Note that if, in the middle of your plugin file, you use any
+ SquirrelMail functions that send output to the browser, you'll need
+ to temporarily switch back to the SquirrelMail domain:
+
+ bindtextdomain('squirrelmail', SM_PATH . 'locale');
+ textdomain('squirrelmail');
+ displayPageHeader($color, 'None');
+ bindtextdomain('demo', SM_PATH . 'plugins/demo/locale');
+ textdomain('demo');
+
+ Note that technically speaking, you only need to have one bindtextdomain
+ call per file, you should always use it before every textdomain call,
+ since PHP installations without gettext compiled into them will not
+ function properly if you do not.
+
+ 3. Finally, you just need to create your own locale. You should create
+ a directory structure like this in the plugin directory:
+
+ demo
+ |
+ ------locale
+ |
+ ------de_DE
+ | |
+ | ------LC_MESSAGES
+ |
+ ------ja_JP
+ |
+ ------LC_MESSAGES
+
+ Create a directories such as de_DE for each language (de_DE is German,
+ ja_JP is Japanese, etc. - check the SquirrelMail locale directory for
+ a fairly comprehensive listing). Inside of each LC_MESSAGES directory
+ you should place two files, one with your translations in it, called
+ <plugin name>.po (in this case, "demo.po"), and one that is a compiled
+ version of the ".po" file, called <plugin name>.mo (in this case,
+ "demo.mo"). On most linux systems, there is a tool you can use to pull
+ out most of the strings that you need to have translated from your PHP
+ files into a sample .po file:
+
+ xgettext --keyword=_ -d <plugin name> -s -C *.php
+
+ --keyword option tells xgettext what your strings are enclosed in
+ -d is the domain of your plugin which should be the plugin's name
+ -s tells xgettext to sort the results and remove duplicate strings
+ -C means you are translating a file with C/C++ type syntax (ie. PHP)
+ *.php is all the files you want translations for
+
+ Note, however, that this will not always pick up all strings, so you
+ should double-check manually. Of course, it's easiest if you just keep
+ track of all your strings as you are coding your plugin. Your .po file
+ will now look something like:
+
+ # SOME DESCRIPTIVE TITLE.
+ # Copyright (C) YEAR Free Software Foundation, Inc.
+ # FIRST AUTHOR <EMAIL@ADDRESS>, YEAR.
+ #
+ #, fuzzy
+ msgid ""
+ msgstr ""
+ "Project-Id-Version: PACKAGE VERSION\n"
+ "POT-Creation-Date: 2003-06-18 11:22-0600\n"
+ "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
+ "Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
+ "Language-Team: LANGUAGE <LL@li.org>\n"
+ "MIME-Version: 1.0\n"
+ "Content-Type: text/plain; charset=CHARSET\n"
+ "Content-Transfer-Encoding: ENCODING\n"
+
+ #: functions.php:45
+ msgid "Hello"
+ msgstr ""
+
+ #: functions.php:87
+ msgid "Favorite Color"
+ msgstr ""
+
+ You should change the header to look something more like:
+
+ # Copyright (c) 1999-2003 The Squirrelmail Development Team
+ # Roland Bauerschmidt <rb@debian.org>, 1999.
+ msgid ""
+ msgstr ""
+ "Project-Id-Version: $Id: squirrelmail.po,v 1.10 2003/06/04 15:01:59
+ philippe_mingo Exp $\n"
+ "POT-Creation-Date: 2003-01-21 19:21+0100\n"
+ "PO-Revision-Date: 2003-01-21 21:01+0100\n"
+ "Last-Translator: Juergen Edner <juergen.edner@epost.de>\n"
+ "Language-Team: German <squirrelmail-i18n@lists.squirrelmail.net>\n"
+ "MIME-Version: 1.0\n"
+ "Content-Type: text/plain; charset=ISO-8859-1\n"
+ "Content-Transfer-Encoding: 8bit\n"
+
+ The most important thing to change here is the charset on the next to
+ last line. You'll want to keep a master copy of the .po file and make
+ a copy for each language you have a translation for. You'll need to
+ translate each string in the .po file:
+
+ msgid "Hello"
+ msgstr "Guten Tag"
+
+ After you're done translating, you can create the .mo file very simply
+ by running the following command (available on most linux systems):
+
+ msgfmt -o <plugin name>.mo <plugin name>.po
+
+ In the case of the "demo" plugin:
+
+ msgfmt -o demo.mo demo.po
+
+ Please be sure that the .po and .mo files both are named exactly the
+ same as the domain you bound in step 2 above and everything else works
+ automatically. In SquirrelMail, go to Options -> Display Preferences
+ and change your Language setting to see the translations in action!
+
+
+
+Documenting the Code (Optional)
+-------------------------------
+
+If you wish, you can use phpdoc (Javadoc-style) comments, when documenting your
+code.
+
+If you follow the standards that are followed between Squirrelmail core &
+plugin developers, the resulted documentation can be included with the rest of
+the Squirrelmail code & API documentation. Specifically, in the page-level
+docblock, declare the package to be 'plugins', and the subpackage to be the
+name of your plugin. For instance:
+
+/**
+ * demo.php
+ *
+ * Copyright (c) 2003 My Name <my-email-address>
+ * Licensed under the GNU GPL. For full terms see the file COPYING.
+ *
+ * @package plugins
+ * @subpackage demo
+ */
+
+The rest is up to you. Try to follow some common sense and document what is
+really needed. Documenting the code properly can be a big help not only to
+yourself, but to those who will take a look at your code, fix the bugs and even
+improve it, in the true open-source spirit that Squirrelmail was built upon.
+
+For more information about phpdocumentor and how to write proper-tagged
+comments, you are directed at:
+
+http://phpdocu.sourceforge.net/
+
+
+
+PLUGIN STANDARDS AND REQUIREMENTS
+=================================
+
+The SquirrelMail project has some important goals, such as avoiding the
+use of JavaScript, avoiding non-standard HTML tags, keeping file sizes
+small and providing the fastest webmail client on the Internet. As such,
+we'd like it if plugin authors coded with the same goals in mind that the
+core developers do. Common sense is always a good tool to have in your
+programming repertoire, but below is an outline of some standards that we
+ask you as a plugin developer to meet. Depending upon how far you bend
+these rules, we may not want to post your plugin on the SquirrelMail
+website... and of course, no one really wants your efforts to go to waste
+and for the SquirrelMail community to miss out on a potentially useful
+plugin, so please try to follow these guidelines as closely as possible.
+
+
+Small setup.php
+---------------
+
+In order for SquirrelMail to remain fast and lean, we are now asking
+that all plugin authors remove all unnecessary functionality from setup.php
+and refactor it into another file. There are a few ways to accomplish
+this, none of which are difficult. At a minimum, you'll want to have the
+squirrelmail_plugin_init_<plugin name>() function in setup.php, and naturally,
+you'll need functions that are merely stubs for each hook that you are using.
+One (but not the only) way to do it is:
+
+ function squirrelmail_plugin_init_demo()
+ {
+ global $squirrelmail_plugin_hooks;
+ $squirrelmail_plugin_hooks['generic_header']['demo'] = 'plugin_demo_header';
+ }
+ function plugin_demo_header()
+ {
+ include_once(SM_PATH . 'plugins/demo/functions.php');
+ plugin_demo_header_do();
+ }
+
+
+Internationalization
+--------------------
+
+Q: What is more disappointing to users in France who would make good
+ use of your plugin than learning that it is written entirely in English?
+A: Learning that they cannot send you a French translation file for your
+ plugin.
+
+There are thousands of users out there whose native tongue is not English,
+and when you develop your plugin without going through the three simple steps
+needed to internationalize it, you are effectively writing them all off.
+PLEASE consider internationalizing your plugin!
+
+
+Developing with E_ALL
+---------------------
+
+When you are developing your plugin, you should always have error reporting
+turned all the way up. You can do this by changing two settings in your
+php.ini and restarting your web server:
+
+ display_errors = On
+ error_reporting = E_ALL
+
+This way, you'll be sure to see all Notices, Warnings and Errors that your
+code generates (it's OK, really, it happens to the best of us... except me!).
+Please make sure to fix them all before you release the plugin.
+
+
+Compatibility with register_globals=Off
+---------------------------------------
+
+Most sensible systems administrators now run their PHP systems with the
+setting "register_globals" as OFF. This is a prudent security setting,
+and as the SquirrelMail core code has long since been upgraded to work
+in such an environment, we are now requiring that all plugins do the same.
+Compatibility with this setting amounts to little more than explicitly
+gathering any and all variables you sent from a <form> tag as GET or POST
+values instead of just assuming that they will be placed in the global
+scope automatically. There is nothing more to do than this:
+
+ global $favorite_color;
+ sqgetGlobalVar('favorite_color', $favorite_color, SQ_FORM);
+
+
+Extra Blank Lines
+-----------------
+
+It may seem innocuous, but if you have any blank lines either before the
+first <?php tag or after the last ?> tag in any of your plugin files, you
+you will break SquirrelMail in ways that may seem entirely unrelated. For
+instance, this will often cause a line feed character to be included with
+email attachments when they are viewed or downloaded, rendering them useless!
+
+
+include_once
+------------
+
+When including files, please make sure to use the include_once() function
+and NOT include(), require(), or require_once(), since these all are much
+less efficient than include_once() and can have a cumulative effect on
+SquirrelMail performance.
+
+
+Version Reporting
+-----------------
+
+In order for systems administrators to keep better track of your plugin and
+get upgrades more efficiently, you are requested to make version information
+available to SquirrelMail in a format that it understands. There are two
+ways to do this. Presently, we are asking that you do both, since we are
+still in a transition period between the two. This is painless, so please
+be sure to include it:
+
+ 1. Create a file called "version" in the plugin directory. That file
+ should have only two lines: the first line should have the name of
+ the plugin as named on the SquirrelMail web site (this is often a
+ prettified version of the plugin directory name), the second line
+ must have the version and nothing more. So for our "demo" plugin,
+ whose name on the web site might be something like "Demo Favorite
+ Colors", the file plugins/demo/version should have these two lines:
+
+ Demo Favorite Colors
+ 1.0
+
+ 2. In setup.php, you should have a function called <plugin name>_version().
+ That function should return the version of your plugin. For the "demo"
+ plugin, that should look like this:
+
+ function demo_version()
+ {
+ return '1.0';
+ }
+
+
+Configuration Files
+-------------------
+
+It is common to need a configuration file that holds some variables that
+are set up at install time. For ease of installation and maintenance, you
+should place all behavioral settings in a config file, isolated from the
+rest of your plugin code. A typical file name to use is "config.php". If
+you are using such a file, you should NOT include a file called "config.php"
+in your plugin distribution, but instead a copy of that file called
+"config.php.sample". This helps systems administrators avoid overwriting
+the "config.php" files and losing all of their setup information when they
+upgrade your plugin.
+
+
+Session Variables
+-----------------
+
+In the past, there have been some rather serious issues with PHP sessions
+and SquirrelMail, and certain people have worked long and hard to ensure
+that these problems no longer occur in an extremely wide variety of OS/PHP/
+web server environments. Thus, if you need to place any values into the
+user's session, there are some built-in SquirrelMail functions that you are
+strongly encouraged to make use of. Using them also makes your job easier.
+
+ 1. To place a variable into the session:
+
+ global $favorite_color;
+ $favoriteColor = 'green';
+ sqsession_register($favorite_color, 'favorite_color');
+
+ Strictly speaking, globalizing the variable shouldn't be necessary,
+ but certain versions of PHP seem to behave more predictably if you do.
+
+ 2. To retrieve a variable from the session:
+
+ global $favorite_color;
+ sqgetGlobalVar('favorite_color', $favorite_color, SQ_SESSION);
+
+ 3. You can also check for the presence of a variable in the session:
+
+ if (sqsession_is_registered('favorite_color'))
+ // do something important
+
+ 4. To remove a variable from the session:
+
+ global $favorite_color;
+ sqsession_unregister('favorite_color');
+
+ Strictly speaking, globalizing the variable shouldn't be necessary,
+ but certain versions of PHP seem to behave more predictably if you do.
+
+
+Form Variables
+--------------
+
+You are also encouraged to use SquirrelMail's built-in facilities to
+retrieve variables from POST and GET submissions. This is also much
+easier on you and makes sure that all PHP installations are accounted
+for (such as those that don't make the $_POST array automatically
+global, etc.):
+
+ global $favorite_color;
+ sqgetGlobalVar('favorite_color', $favorite_color, SQ_FORM);
+
+
+Files In Plugin Directory
+-------------------------
+
+There are a few files that you should make sure to include when you build
+your final plugin distribution:
+
+ 1. A copy of the file index.php from the main plugins directory. When
+ working in your plugin directory, just copy it in like this:
+
+ $ cp ../index.php .
+
+ This will redirect anyone who tries to browse to your plugin directory
+ to somewhere more appropriate. If you create other directories under
+ your plugin directory, you may copy the file there as well to be extra
+ safe. If you are storing sensitive configuration files or other data
+ in such a directory, you could even include a .htaccess file with the
+ contents "Deny From All" that will disallow access to that directory
+ entirely (when the target system is running the Apache web server).
+ Keep in mind that not all web servers will honor an .htaccess file, so
+ don't depend on it for security. Make sure not to put such a file in
+ your main plugin directory!
+
+ 2. A file that describes your plugin and offers detailed instructions for
+ configuration or help with troubleshooting, etc. This file is usually
+ entitled "README". Some useful sections to include might be:
+
+ Plugin Name and Author
+ Current Version
+ Plugin Features
+ Detailed Plugin Description
+ How-to for Plugin Configuration
+ Change Log
+ Future Ideas/Enhancements/To Do List
+
+ 3. A file that explains how to install your plugin. This file is typically
+ called "INSTALL". If you do not require any special installation
+ actions, you can probably copy one from another plugin or use this as
+ a template:
+
+ Installing the Demo Plugin
+ ==========================
+
+ 1) Start with untaring the file into the plugins directory.
+ Here is a example for the 1.0 version of the Demo plugin.
+
+ $ cd plugins
+ $ tar -zxvf demo-1.0-1.4.0.tar.gz
+
+ 2) Change into the demo directory, copy config.php.sample
+ to config.php and edit config.php, making adjustments as
+ you deem necessary. For more detailed explanations about
+ each of these parameters, consult the README file.
+
+ $ cd demo
+ $ cp config.php.sample config.php
+ $ vi config.php
+
+
+ 3) Then go to your config directory and run conf.pl. Choose
+ option 8 and move the plugin from the "Available Plugins"
+ category to the "Installed Plugins" category. Save and exit.
+
+ $ cd ../../config/
+ $ ./conf.pl
+
+
+ Upgrading the Demo Plugin
+ =========================
+
+ 1) Start with untaring the file into the plugins directory.
+ Here is a example for the 3.1 version of the demo plugin.
+
+ $ cd plugins
+ $ tar -zxvf demo-3.1-1.4.0.tar.gz
+
+
+ 2) Change into the demo directory, check your config.php
+ file against the new version, to see if there are any new
+ settings that you must add to your config.php file.
+
+ $ diff -Nau config.php config.php.sample
+
+ Or simply replace your config.php file with the provided sample
+ and reconfigure the plugin from scratch (see step 2 under the
+ installation procedure above).
+
+
+COMPATIBILITY WITH OLDER VERSIONS OF SQUIRRELMAIL
+=================================================
+
+Whenever new versions of SquirrelMail are released, there is always a
+considerable lag time before it is widely adopted. During that transitional
+time, especially when the new SquirrelMail version contains any architectural
+and/or functional changes, plugin developers are put in a unique and very
+difficult position. That is, there will be people running both the old and
+new versions of SquirrelMail who want to use your plugin, and you will
+probably want to accomodate them both.
+
+The easiest way to keep both sides happy is to keep two different versions
+of your pluign up to date, one that runs under the older SquirrelMail, and
+one that requires the newest SquirrelMail. This is inconvenient, however,
+especially if you are continuing to develop the plugin. Depending on the
+changes the SquirrelMail has implemented in the new version, you may be able
+to include code that can auto-sense SquirrelMail version and make adjustments
+on the fly. There is a function available to you for determining the
+SquirrelMail version called check_sm_version() and it can be used as such:
+
+ check_sm_version(1, 4, 0)
+
+This will return TRUE if the SquirrelMail being used is at least 1.4.0, and
+FALSE otherwise.
+
+As this document is written, we are in a transition period between versions
+1.2.11 and 1.4.0. There is a plugin called "Compatibilty" that is intended
+for use by plugin authors so they can develop one version of their plugin
+and seamlessly support both 1.2.x and 1.4.x SquirrelMail installations. For
+more information about how to use the "Compatibility" plugin, download it and
+read its README file or see:
+
+ http://www.squirrelmail.org/wiki/wiki.php?PluginUpgrading
+
+
+REQUESTING NEW HOOKS
+====================
+
+It's impossible to foresee all of the places where hooks might be useful
+(it's also impossible to put in hooks everywhere!), so you might need to
+negotiate the insertion of a new hook to make your plugin work. In order
+to do so, you should post such a request to the squirrelmail-devel mailing
+list.
+
+
+HOW TO RELEASE YOUR PLUGIN
+==========================
+
+As long as you've consulted the list of plugin standards and done your
+best to follow them, there's little standing in the way of great fame as an
+official SquirrelMail plugin developer.
+
+ 1. Make a distribution file. There is a convenient Perl script in
+ the plugins directory that will help you do this:
+
+ make_archive.pl -v demo 1.0 1.4.0
+
+ -v is optional and indicates that the script should run in verbose mode
+ demo is the name of your plugin
+ 1.0 is the version of your plugin
+ 1.4.0 is the version of SquirrelMail that is required to run your plugin
+
+ You can also create the distribution file manually in most *nix
+ environments by running this command from the plugins directory (NOT
+ your plugin directory):
+
+ $ tar czvf demo-1.0-1.4.0.tar.gz demo
+
+ Where "demo" is the name of your plugin, "1.0" is the version of
+ your plugin, and "1.4.0" is the version of SquirrelMail required
+ to use your plugin.
+
+ 2. Consult the SquirrelMail web site for contact information for the
+ Plugins Team Leaders, to whom you should make your request. If they
+ do not respond, you should feel free to ask for help contacting them
+ on the squirrelmail-plugins mailing list.
+
+ http://www.squirrelmail.org/wiki/wiki.php?SquirrelMailLeadership
+