[Wiki] changed: Horde4/CodingStandards
Chuck Hagenbuch <[email protected]>
| Newsgroups | gmane.comp.horde.cvs |
|---|---|
| Message-ID | <[email protected]> |
chuck Sun, 28 Jun 2009 21:34:56 -0400 Modified page: http://wiki.horde.org/Horde4/CodingStandards New Revision: 1.3 Change log: link to h4 coding standards in cvs @@ -1,842 +1,3 @@ + Horde 4 Coding Standards -[[toc]] - -======================== - Horde Coding Standards -======================== - -:Last update: $Date: 2008/08/05 19:40:27 $ -:Revision: $Revision: 1.129 $ -:Authors: Jon Parise, Chuck Hagenbuch -:Contact: [email protected] - -.. contents:: Contents -.. section-numbering:: - -Indenting/Whitespace -==================== - -Use an indent of 4 spaces, with no tabs. Remove all trailing whitespace. If -using vim, the following .vimrc code will highlight trailing whitespace in -red:: - - highlight WhitespaceEOL ctermbg=red guibg=red - match WhitespaceEOL /\s\+$/ - - -Language Case -============= - -When working with PHP statements, constructs or keywords, lowercase text is -required. This does not apply to classes provided by PHP, which should be -written as they are in the PHP manual (e.g. `DOMDocument::createCDATASection`_) - -.. _DOMDocument::createCDATASection: http://us.php.net/manual/en/domdocument.createcdatasection.php - - -Control Structures -================== - -These include ``if``, ``for``, ``while``, ``switch``, etc. Here is an example -``if`` statement, since it is the most complicated of them:: - - if ((condition1) || (condition2)) { - action1; - } elseif ((condition3) && (condition4)) { - action2; - } else { - defaultaction; - } - -Multi-line if conditions are braced this way:: - - if ((condition1) || (condition2) || (condition3) || - (condition4)) { - action1; - } - -Control statements should have one space between the control keyword and -opening parenthesis, to distinguish them from function calls. - -Do not omit the curly braces under any circumstance. In the case of a large -number of short tests and actions, the following is acceptable:: - - if (condition) { action; } - if (condition 2) { action 2; } - ... - -For switch statements:: - - switch (condition) { - case 1: - action1; - break; - - case 2: - action2; - break; - - default: - defaultaction; - break; - } - - -Function Calls -============== - -Functions should be called with no spaces between the function name, the -opening parenthesis, and the first parameter; spaces between commas and each -parameter, and no space between the last parameter, the closing parenthesis, -and the semicolon. Here's an example:: - - $var = foo($bar, $baz, $quux); - -As displayed above, there should be one space on either side of an equals sign -used to assign the return value of a function to a variable. In the case of a -block of related assignments, more space may be inserted to promote -readability:: - - $short = foo($bar); - $long_variable = foo($baz); - -The "@" operator can be used to silence any errors that a function -call may generate. This should be used with caution, as it is both -slow and prone to pitfalls. For example, if you use it to silence -including a file that may not exist, the main goal - not throwing -warnings if the file isn't there - will be accomplished. But if the -file does exist but has a parse error, the entire script or page will -die with no warning. Because of problems like this, using "@" to -silence function calls should be avoided whenever possible. - -In place of "@", using error_reporting() appropriately around -code blocks that should not emit warnings is actually faster. - - -Function Definitions -==================== - -Function declarations follow the "BSD/Allman" convention:: - - function fooFunction($arg1, $arg2 = '') - { - if (condition) { - statement; - } - return $val; - } - -Arguments with default values go at the end of the argument list. Always -attempt to return a meaningful value from a function if one is appropriate. - -Functions used only in the current script/class (e.g. private or protected methods) -should begin with a ``_`` character (e.g. ``_exampleLibrary``). This helps -distinguish these private function calls from other, public function calls. - - -Class Definitions -================= - -Class definitions also follow the "BSD/Allman" convention:: - - class Some_Class - { - /** - * - */ - var $_variable; - - public function fooFunction() - { - statement; - } - - } - -Note the blank line at the end of the class definition. - - -Naming Libraries -================ - -Libraries (any file located in the ``lib/`` directory of the application) -should be named with capital letters at the beginning of each word. Use -studlycaps for naming; a session cache class would be stored in -``lib/SessionCache.php``. - -If the library/class is extended, the extending files should be stored in a -directory under ``lib/`` with the same name as the original library. -Subclasses follow the exact same naming requirements. - -Example -------- - -The "Example Library" library should be saved as ``lib/ExampleLibrary.php``. -Any file extending the library/class should be stored in the directory -``lib/ExampleLibrary/``. - - -Comments -======== - -Inline documentation for classes should follow the `phpDocumentor conventions`_. - -.. _phpDocumentor conventions: http://phpdoc.org/ - -Quick example for private variable definition for Horde:: - - /** - * Variable description. - * - * @var datatype - */ - -Quick example function definition for Horde:: - - /** - * The description of the function goes here. - * - * @param datatype $variablename Description of variable. - * @param datatype $variable2name Description of variable2. - * ... - * [Insert 2 spaces after the longest $variable definition, and then line - * up all descriptions with this description] - * - * @return datatype Description of return value. - * [Once again, insert 2 spaces after the datatype, and line up all - * subsequent lines, if any, with this character.] - * - * @since Horde x.x [Only if necessary - use if function is added to the - * current release versions to indicate that the function has not been - * available in previous versions.] - */ - - -Including Code -============== - -You should not explicitly include or require classes. Horde provides an -autoloader library, so the class should be autoloaded. This -will allow maximum flexibility in managing class libraries. - -For all other includes (configuration files, data files, etc.) use `include`_. - -.. _autoload: http://php.net/autoload -.. _include: http://php.net/include - - -PHP Code Tags -============= - -Always use ``<?php`` to delimit PHP code, not the ``<?`` shorthand. -This is required for PEAR compliance and is also the most portable way to -include PHP code on differing operating systems and setups. - -In templates, make sure to use this as well (``<?php echo $varname ?>``), as -the shortcut version (``<?= $var ?>``) does not work with `short_open_tag`_ -turned off. - -Files should never end with a closing closing '?>'. This is redundant and can -allow whitespace added to the end of a file to cause PHP to send headers early. - -.. _short_open_tag: http://www.php.net/manual/en/configuration.directives.php#ini.short-open-tag - - -Header Comment Blocks -===================== - -All source code files in the Horde distribution should contain the following -comment block as the header: - -Example for `LGPL`_'ed Horde code:: - - /** - * The Horde_Foo:: class provides an API for various foo - * techniques that can be used by Horde applications. - * - * Copyright 1999-2001 Original Author <[email protected]> - * Copyright 2001 Your Name <[email protected]> - * - * See the enclosed file COPYING for license information (LGPL). If you - * did not receive this file, see http://www.fsf.org/copyleft/lgpl.html. - * - * @author Original Author <[email protected]> - * @author Your Name <[email protected]> - * @since Horde 3.0 - * @category Horde - * @package Horde_Package - */ - -.. _LGPL: http://www.opensource.org/licenses/lgpl-license.php - -Example for `GPL`_'ed application code:: - - /** - * The App_Bar:: class contains all functions related to handling - * bars in App. - * - * $Horde - * - * Copyright 1999-2001 Original Author <[email protected]> - * Copyright 2001 Your Name <[email protected]> - * - * See the enclosed file COPYING for license information (GPL). If you - * did not receive this file, see http://www.fsf.org/copyleft/gpl.html. - * - * @author Original Author <[email protected]> - * @author Your Name <[email protected]> - * @since App 1.0 - * @category Horde - * @package app - */ - - -.. _GPL: http://www.opensource.org/licenses/gpl-license.php - -There's no hard rule to determine when a new code contributer should be added -to the list of authors for a given source file. In general, their changes -should fall into the "substantial" category (meaning somewhere around 10% to -20% of code changes). Exceptions could be made for rewriting functions or -contributing new logic. - -Simple code reorganization or bug fixes would not justify the addition of a -new individual to the list of authors. - - -Example URLs -============ - -Use ``example.com`` for all example URLs, per `RFC 2606`_. - -.. _RFC 2606: http://www.faqs.org/rfcs/rfc2606.html - - -php.ini settings -================ - -All Horde code should work with `register_globals`_ disabled. This means -using ``$_COOKIE``, ``$_SESSION``, ``$_SERVER`` and ``$_ENV`` to access all -cookie, session, server and environment data, respectively. By the same token, -all Horde code should also work with `register_globals`_ enabled. Since -applications can be expected to store data in $_SESSION['application'] it is -therefor important that applications NOT register $GLOBALS in their own -application name. For instance the application "foo" may create and use -$_SESSION['foo'] but not $GLOBALS['foo']. Failing this rule may cause problems -on PHP installations on which `register_globals`_ is enabled. - -To retrieve posted data (in the global ``$_GET`` and ``$_POST`` variables), -you should normally use `Util::getFormData()`_ which will automatically run -`Util::dispelMagicQuotes()`_. This will ensure that all Horde code will work -regardless of the setting of `magic_quotes_gpc`_. The only time you should not -use `Util::getFormData()`_ is if you want to directly access a GET or POST -variable instead; in this case, you should use `Util::getGet()`_ or -`Util::getPost()`_ respectively. - -All Horde code should work with `error_reporting`_ = E_ALL. Failure to do so -would result in ugly output, error logs getting filled with lots of warning -messages, or even downright broken scripts. - -No Horde code should assume that '.' is in the include path. Always specify -'./' in front of a filename when you are including a file in the same -directory. - -.. _register_globals: http://www.php.net/manual/en/security.registerglobals.php -.. _magic_quotes_gpc: http://www.php.net/manual/en/ref.info.php#ini.magic-quotes-gpc -.. _error_reporting: http://www.php.net/manual/en/ref.errorfunc.php#ini.error-reporting -.. _Util::getFormData(): http://dev.horde.org/api/framework/Horde_Util/Util.html#methodgetFormData -.. _Util::dispelMagicQuotes(): http://dev.horde.org/api/framework/Horde_Util/Util.html#methoddispelMagicQuotes -.. _Util::getGet(): http://dev.horde.org/api/framework/Horde_Util/Util.html#methodgetGet -.. _Util::getPost(): http://dev.horde.org/api/framework/Horde_Util/Util.html#methodgetPost - - -XHTML 1.0 Compliance -==================== - -All tag names and parameters must be lower case including javascript event -handlers:: - - <font color="#ffffff">...</font> - <a href="http://example.com" onmouseover="status=''" onmouseout="status=''">...</a> - -All tag parameters must be of a valid parameter="value" form (numeric values -must also be surrounded by quotes). For parameters that had no value in HTML, -the parameter name is the value. For example:: - - <input type="checkbox" checked="checked" /> - <select name="example"> - <option selected="selected" value="1">Example</option> - </select> - <td nowrap="nowrap">Example</td> - -All tags must be properly closed. Tags where closing is forbidden must end -with a space and a slash:: - - <br /> - <hr /> - <img src="example.gif" alt="Example" /> - <input type="submit" value="Example" /> - -All form definitions must be on their own line and either fully defined within -a ``<td></td>`` pair or be outside table tags. Forms must also always have an -action parameter:: - - <form method="post" action="http://example.com/example.cgi"> - <table> - <tr><td>example</td></tr> - </table> - </form> - - <table> - <tr><td> - <form action="javascript:void(0)" onsubmit="return false;"> - </form> - </td></tr> - </table> - -All JavaScript tags must have a valid type parameter:: - - <script type="text/javascript"> - ... - </script> - -Nothing may appear after ``</html>``, therefore include any common footers -after all other output. - -All images must have an ``alt`` attribute:: - - <img src="example.gif" alt="<?php echo _("Example") ?>" /> - <?php echo Horde::img('example.gif', _("Example")) ?> (On the HEAD branch) - <?php echo Horde::img('example.gif', 'alt="' . _("Example") . '"') ?> (On the RELENG_2 branch) - -Input fields of type "image" do not allow the border attribute and may render -with a border on some browsers. Use the following instead:: - - <a href="" onclick="document.formname.submit(); return false;"><?php echo Horde::img("example.gif", _("Example")) ?></a> - - -Database Naming Conventions -=========================== - -All database tables used by Horde resources and Horde applications need to -make sure that their table and field names work in all databases. Many -databases reserve words like 'uid', 'user', etc. for internal use, and forbid -words that are SQL keywords (select, where, etc.). Also, all names should be -lowercase, with underscores ('_') to separate words, to avoid case sensitivity -issues. - -A good way to do this for field names is to make the field name -tablename_fieldname. - -Other general guidelines: Table names should be plural (users); field names -should be singular (user_name). - -Try to use portable data types and avoid RDBMS specific SQL scripts as much as -possible. Portable types are INTEGER, SMALLINT, NUMERIC(4,0) (for TINYINT), -NUMERIC(p,s), VARCHAR(n), CHAR(n), FLOAT, and REAL. See -http://home.fnal.gov/~dbox/SQL_API_Portability.html and -http://builder.com.com/5100-6388-1045051.html for more information. - -In SQL queries, keywords should be capitalized. - -In table creation statements, SQL keywords and datatypes should be -capitalized. Also, 'DEFAULT' constraints should be listed before 'NOT -NULL' constraints for maximum portability. - -Regular Expression Use -====================== - -Always use the `preg_`_ functions instead of `ereg_`_ (and -`preg_split()`_ instead of `split()`_); they are included in PHP by default -and faster than `ereg_`_; `ereg_`_ is also deprecated in PHP 5.3+. - -**NEVER** use a regular expression to match or replace a static string. -`explode()`_ (in place of `split()`_), `str_replace()`_, `strpos()`_, or -`strtr()`_ do the job much more efficiently. - -In addition, when doing replacement or regex matching on large -strings, if you don't know if the target string contains the text to -be matched or replaced, it is often a performance win to use -`strpos()`_ to check first. Then, only if the text to be matched or -replaced is present, go ahead and do the more memory intensive string -manipulation. - -.. _preg_: http://www.php.net/manual/en/ref.pcre.php -.. _ereg_: http://www.php.net/manual/en/ref.regex.php -.. _preg_split(): http://www.php.net/manual/en/function.preg-split.php -.. _split(): http://www.php.net/manual/en/function.split.php -.. _explode(): http://www.php.net/manual/en/function.explode.php -.. _str_replace(): http://www.php.net/manual/en/function.str-replace.php -.. _strpos(): http://www.php.net/manual/en/function.strpos.php -.. _strtr(): http://www.php.net/manual/en/function.strtr.php - - -Parameter Passing -================= - -Parameters should be passed by value wherever semantically possible. -This practice takes full advantage of reference counting. - -.. Note:: The `ternary operator`_ automatically returns a copy of its operands, - so don't use it with objects unless you are sure you want to return an - object copy. - -.. _`ternary operator`: http://www.php.net/manual/en/language.operators.comparison.php#language.operators.comparison.ternary - - -Long Lines -========== - -The optimal line length is 80 characters, including comments. The maximum line -length is 100 characters unless this severely impacts the clarity of the -code. When deciding where to wrap, aim for readability, understanding that -different developers will have different views on this. Always wrap comments. - - -Line Breaks -=========== - -Only use UNIX style of linebreak (``\n``), not Windows/DOS/Mac style -(``\r\n``). - -Using vim, to convert from DOS style type:: - - :set ff=unix - -Using vi, to convert from DOS style type:: - - :g/^M/s///g - -(Note that the ``^M`` is a control character, and to reproduce it when you -type in the vi command you have to pad it first using the special ``^V`` -character.) - - -Private Variables -================= - -Variables used exclusively within a class should begin with a underscore ('_') -character. An example class variable definition: ``protected $_variablename;`` - - -Array Definitions -================= - -When defining arrays, or nested arrays, use the following format, where -indentation is noted via the closing parenthesis characters:: - - $arrayname['index'] = array( - 'name1' => 'value1', - 'name2' => array( - 'subname1' => 'subvalue1', - 'subname2' => 'subvalue2' - ), - ); - -The only exception should be for empty or short arrays that fit on one line, -which may be written as:: - - $arrayname['index'] = array(); - - -Internationalization (I18n) -=========================== - -Mark all strings presented to the user as gettext strings by calling the -gettext shortcut function (``_()``):: - - echo _("Hello world"); - -Don't use the gettext functions for strings that will be written to a log file -or otherwise presented to the administrator. - -The String:: class contains several string manipulation methods that are, as -opposed to their PHP equivalents, locale and charset safe. - -Use String::convertCharset() if you need to convert between different -character set encodings (for example, between user input and a storage backend -or data from an external source and the user interface). You don't need to -care if the character sets are really different. - -Use the String::lower() and String::upper() methods without a second -parameter if you need to perform a locale-independent string conversion. -That's the case for all strings that are further processed or interpreted by -code. Use these methods with the second parameter set to true for strings -that need to be converted correctly according to the current (or specified) -character set. - -Use the other String:: equivalents of PHP string functions to manipulate -strings correctly according to the current (or specified) character set but -use the PHP functions for code/machine processed strings. - - -Error checking -============== - -Horde code should use `PEAR_Error`_ objects to return most error conditions -from library calls, and many times we will simply pass back a `PEAR_Error`_ -object generated by an underlying library (such as Mail or PEAR DB). - -For these cases, use the following style of code block to check for success -after any call which could generate an error condition:: - - $result = $something->call('may error'); - if (is_a($result, 'PEAR_Error')) { - // Handle error condition. - } else { - // Succeeded. - } - -Note that `is_a()`_ checks for subclasses of the named class, as well, so if -the object you get back is really a `DB_Error`_ object, this will still catch -it (since `DB_Error`_ extends `PEAR_Error`_). - -Calling PEAR::isError() results in the same behavior, but is_a() -accomplishes the same result with a single native PHP function call. - -.. _PEAR_Error: http://pear.php.net/manual/en/core.pear.pear-error.php -.. _DB_Error: http://pear.php.net/manual/en/package.database.db.db-error.php -.. _is_a(): http://www.php.net/manual/en/function.is-a.php - - -Existence checking -================== - -Often you'll need to check whether or not a variable or property exists. -There are several cases here: - -a. If you need to know if a variable exists at all and is not ``null``, use - `isset()`_:: - - // Check to see if $param is defined. - if (isset($param)) { - // $param may be false, but it's there. - } - -b. If you need to know if a variable exists AND has a non-empty value (not - ``null``, 0, ``false``, empty string or undefined), use !empty():: - - // Make sure that $answer exists, is not an empty string, and is - // not 0: - if (!empty($answer)) { - // $answer has some non-false content. - } else { - // (bool)$answer would be false. - } - -As pointed out in the comment of the else clause, `empty()`_ essentially does -the same check as `isset()`_ -- is this variable defined in the current scope? --- and then, if it is, returns what the variable would evaluate to as a -boolean. This means that 0, while potentially valid input, is "empty" - so if -0 is valid data for your case, don't use !empty(). - -c. If you want to know if a variable is a non-empty string, including 0, you - have to use `strlen()`_. This only works with strings or scalars that - automatically cast to strings without problems:: - - // Make sure that $str is a non-empty string. $str must exist, so add an - // additional check with isset() if necessary. - if (strlen($str)) { - // $str has a non-zero length. - } else { - // $str is an empty string '', or null. - } - -d. If you know you are working with a mixed variable then using just - `isset()`_ and `empty()`_ could cause unexpected results, for example if - testing for a key and the variable is actually a string:: - - $foo = 'bar'; - if (isset($foo['somekey'])) { - // This will evaluate to TRUE! - } - -If you know that there is a possibility of a mixed type variable the solution -in this case would be to add an `is_array()`_ check in the ``if()`` statement. - -e. Use `array_key_exists()`_ when you want to check if an array key is defined - even if it has a value of ``null``:: - - // Make sure we have a charset parameter. Value could also be null. - if (!array_key_exists('charset', $params)) { - Horde::fatal('Incomplete configuration.'); - } - -Please note that `array_key_exists()`_ is a performance hit (25%-100%) and -should only be used when necessary. Instead try to use !empty() or -`isset()`_ instead. - -.. _isset(): http://www.php.net/manual/en/function.isset.php -.. _empty(): http://www.php.net/manual/en/function.empty.php -.. _strlen(): http://www.php.net/manual/en/function.strlen.php -.. _is_array(): http://www.php.net/manual/en/function.is-array.php -.. _array_key_exists(): http://www.php.net/manual/en/function.array-key-exists.php - - -Quotes -====== - -You should always use single quote (') characters around strings, except where -double quote (") characters are required. All literal strings should be in -single quotes. A comparison of single and double quote usage follows: - -Single Quotes: - * Variables in the string are not parsed or expanded. - * New line symbols can be included as literal line ends (not recommended). - * To include a single quote character, escape it with a ``\`` (backslash) - character, as in: ``echo 'Here\'s an example';`` - * To specify a ``\`` (backslash) character, double it: ``echo 'c:\\temp';`` - -Double Quotes: - * Parses and expands variables in the string. - * Uses advanced (`sprintf`_-style) escape sequences like ``\n``, ``\$``, - ``\t``, etc. - * Should be used in the gettext shortcut ``_("")`` format. - * Use with care, as many correct looking strings are really invalid. - -The following are all incorrect:: - - echo "Today is the $date['day'] of $date['month']" - $_SESSION[index] = $_SESSION["old_index"]; - -.. _sprintf: http://www.php.net/sprintf - - -define() -======== - -`define()`_ is a somewhat slow function in PHP (as of PHP -4.3.x) so excessive use is discouraged. - -Using `define()`_ in classes should be OK - we will sacrifice a tiny bit of -speed for readability of code. `define()`_ should NOT be used for actionIDs - -use a plain old string instead. For anything else, use your best judgment. - -Additionally, every constant should be prefixed with ``HORDE_``, its package -name, or the application name. - -.. _define(): http://www.php.net/manual/en/function.define.php - - -Security Considerations -======================= - -The following are a non-exhaustive list of features/functions to take -special care with: - -PHP Code Execution: -------------------- - -require, include, require_once, include_once - Carefully audit any -variables used in these functions, and check the source of any -constants as well. - -eval and create_function - Obvious danger if user input is supplied to -it in uncontrolled conditions. - -preg_replace - The /e modifier causes the replacement string to be -evaluated as PHP code. - -Command Execution: ------------------- - -exec - Executes a specified command and returns the last line of output. - -passthru - Executes a specified command and writes the output to STDOUT. - -`` (backticks) - Executes the specified command and returns all the -output in an array. - -system - Like passthru() but doesn't handle binary data. - -popen - Executes a specified command and connects its output or input -stream to a PHP file descriptor. - -File Disclosure: ----------------- - -File functions which can be potentially used to open remote or -unintended files: fopen, readfile, file, file_get_contents. - - -Optimizations -============= - -The following optimizations should be used, if possible: - -extension_loaded() ------------------- -This appears to be an expensive PHP call. Use Util::extensionExists() -instead, which will cache the results of the call. - -Concatenate strings -------------------- -Building a string with concatenation (the "." operator) using -single-quoted strings and variables is faster than using an -interpolated string (a string inside double quotes with variables -inside the string itself). In addition, concatenation is easier to -read and audit for logic and security problems. - -Loops ------ -Make sure that you do not continue to define the same variable within a -loop. Instead, declare the variable a single time before the loop is run. - -Additionally, for large amounts of data, do not use foreach() loops, as PHP -will make an additional copy in memory of every element of the array when -traversing. Instead, use either array_shift, a for() loop, or the -next()/each() functions. (NOTE: As of PHP 5, it is possible to indicate that -the values should be provided to the interior of the loop by reference, -thereby eliminating the need to create a copy of the value.) - -Array ------ -Avoid frequent array accesses. If you use an array or an array member in a -loop, assign it to a variable first:: - - $a = array('x' => 'y'); - $entries = array(...); - - $length = count($entries); - $x = $a['x']; - for ($i = 0; $i < $length; ++$i) { - echo $x; - } - -Don't use array_unique(). The following is reported to be 20 times faster:: - - $unique = array_keys(array_flip($foo)); - -Even better, if possible rework the algorithm to store the unique data in the -key and then call array_keys($foo) to return the unique list. - -User defined functions ----------------------- -User defined functions are more expensive than "regular" functions. Use them -only if they improve the code readability more then regular functions. - -Dynamically created functions (eval and create_function) --------------------------------------------------------- -Code executed with eval, and functions created with create_function, -are essentially PHP code that the engine has to parse every time it is -run. This code is impossible to cache with an opcode cache, and even -without one is slower than regular PHP code. Because they also have -security risks, they should be avoided if at all possible. - -Disk I/O --------- -Disk read and write operations are slow. If possible read and write files in -large chunks. According to the PHP documentation, file_get_contents() is -potentially much faster than using fopen()/fread()/fclose(). - - -STDIN/STDOUT/STDERR -=================== - -To access either STDIN, STDOUT, or STDERR, the following code should be used:: - - while (!feof([STDIN|STDOUT|STDERR])) { - $line = fgets([STDIN|STDOUT|STDERR]); - // process $line here - } - +This document is now in the main Horde docs/ directory: http://cvs.horde.org/co.php/horde/docs/CODING_STANDARDS -- To unsubscribe, mail: [email protected]