mirror of
https://github.com/EGroupware/egroupware.git
synced 2024-12-11 17:20:53 +01:00
649 lines
21 KiB
Plaintext
649 lines
21 KiB
Plaintext
<!doctype linuxdoc system>
|
|
|
|
<article>
|
|
<!-- LyX 1.1 created this file. For more info see http://www.lyx.org/ -->
|
|
<title>
|
|
phpgwapi - VFS Class
|
|
</title>
|
|
<author>
|
|
Jason Wies
|
|
</author>
|
|
<date>
|
|
June 2001, February 2002
|
|
</date>
|
|
<abstract>
|
|
The VFS, or Virtual File System, handles all file system activity
|
|
for eGoupWare.
|
|
</abstract>
|
|
<sect>
|
|
Introduction and Purpose<label id="sec:introduction" >
|
|
<p>
|
|
The latest version of the VFS for eGoupWare combines actual
|
|
file system manipulation with fully integrated database support.
|
|
It features nearly transparent handling of files and directories,
|
|
as well as files inside and outside the virtual root. This document
|
|
is intended to provide API and application developers with a guide
|
|
to incorporating the VFS into their work.
|
|
</p>
|
|
<sect>
|
|
Basics<label id="sec:basics" >
|
|
<sect1>
|
|
Prerequisites<label id="sec:prerequisites" >
|
|
<p>
|
|
You must explicitly enable the VFS class. To do this, set 'enable_vfs_class'
|
|
to True in $GLOBALS['phpgw_info']['flags'].
|
|
An example:
|
|
</p>
|
|
<p>
|
|
<verb>
|
|
$GLOBALS['phpgw_info']['flags'] = array(
|
|
'currentapp' => 'phpwebhosting',
|
|
'noheader' => False,
|
|
'noappheader' => False,
|
|
'enable_vfs_class' => True,
|
|
'enable_browser_class' => True
|
|
);
|
|
</verb>
|
|
</p><sect1>
|
|
Concepts<label id="sec:concepts" >
|
|
<p>
|
|
The VFS in located in phpgwapi/inc/class.vfs_sql.inc.php. You
|
|
can look over it, but I don't suggest trying to understand how it
|
|
works. It isn't necessary to know its internals to use it, but you
|
|
may find the inline comments helpful. The basic things to keep in
|
|
mind:
|
|
</p>
|
|
<p>
|
|
<itemize>
|
|
<item>
|
|
Files and directories are synonymous in almost all cases
|
|
</itemize>
|
|
<p>
|
|
<verb>
|
|
$GLOBALS['phpgw']->vfs->mv (array(
|
|
'from' => 'file1',
|
|
'to' => 'dir/file2'
|
|
));
|
|
|
|
$GLOBALS['phpgw']->vfs->mv (array(
|
|
'from' => 'dir1',
|
|
'to' => 'dir/dir1'
|
|
));
|
|
|
|
$GLOBALS['phpgw']->vfs->rm (array(
|
|
'string' => 'file'
|
|
));
|
|
|
|
$GLOBALS['phpgw']->vfs->rm (array(
|
|
'string' => 'dir'
|
|
));
|
|
</verb>
|
|
</p><p>
|
|
All work as you would except them to. The major exception is:
|
|
</p>
|
|
<p>
|
|
<verb>
|
|
$GLOBALS['phpgw']->vfs->touch (array(
|
|
'string' => 'file'
|
|
));
|
|
</verb>
|
|
</p><p>
|
|
vs.
|
|
</p>
|
|
<p>
|
|
<verb>
|
|
$GLOBALS['phpgw']->vfs->mkdir (array(
|
|
'string' => 'dir'
|
|
));
|
|
|
|
</verb>
|
|
<p>
|
|
<itemize>
|
|
<item>
|
|
Users and groups are synonymous
|
|
</itemize>
|
|
</p><p>
|
|
As far as the actual paths are concerned, users and groups are
|
|
the same. /home/username works the same as /home/groupname.
|
|
</p>
|
|
<p>
|
|
<itemize>
|
|
<item>
|
|
You should never have to know the real paths of files
|
|
</itemize>
|
|
</p><p>
|
|
One of the VFS's responsibilities is to translate paths for you.
|
|
While you certainly <em>can</em> operate using full paths, it is much simpler
|
|
to use the virtual paths. For example, instead of using:
|
|
</p>
|
|
<p>
|
|
<verb>
|
|
$GLOBALS['phpgw']->vfs->cp (array(
|
|
'from' => '/var/www/egroupware/files/home/user/file1',
|
|
'to' => '/var/www/egroupware/files/home/user/file2',
|
|
'relatives' => array(
|
|
RELATIVE_NONE|VFS_REAL,
|
|
RELATIVE_NONE|VFS_REAL
|
|
)
|
|
));
|
|
</verb>
|
|
</p><p>
|
|
you might use
|
|
</p>
|
|
<p>
|
|
<verb>
|
|
$GLOBALS['phpgw']->vfs->cp (array(
|
|
'from' => '/home/user/file1',
|
|
'to' => '/home/user/file2',
|
|
'relatives' => array(
|
|
RELATIVE_NONE,
|
|
RELATIVE_NONE
|
|
)
|
|
));
|
|
</verb>
|
|
</p><p>
|
|
(We'll get to the RELATIVE's in a minute.)
|
|
</p>
|
|
<p>
|
|
Site administrators should be able to move their files dir around
|
|
on their system and know that everything will continue to work smoothly.
|
|
</p>
|
|
<p>
|
|
<itemize>
|
|
<item>
|
|
Relativity is <em>vital</em>
|
|
</itemize>
|
|
</p><p>
|
|
Relativity is a new feature in the VFS, and its importance cannot
|
|
be stressed enough. It will make your life much easier, especially
|
|
for file system intensive applications, but it will take some getting
|
|
used to. If something doesn't work right the first time, chances
|
|
are great it has to do with incorrect relativity settings. We will
|
|
deal with relativity in depth in the Relativity section.
|
|
</p>
|
|
<sect>
|
|
Basic Functions<label id="sec:basic_functions" >
|
|
<p>
|
|
These are two functions you'll need to know before we get into
|
|
relativity.
|
|
</p>
|
|
<sect1>
|
|
path_parts ()<label id="sec:path_parts" >
|
|
<p>
|
|
The job of path_parts () is to translate any given file location
|
|
into its many component parts for any relativity. The values passed
|
|
to path_parts () are:
|
|
</p>
|
|
<p>
|
|
<verb>
|
|
string
|
|
relatives
|
|
object
|
|
</verb>
|
|
</p><p>
|
|
'string' is the path you want to translate, 'relatives' is the
|
|
standard relativity array, and 'object' specifies how you would like
|
|
the return value: if 'object' is True, an object will be returned;
|
|
if 'object' is False, an array will be returned. I think you'll find
|
|
the object easier to deal with, and we'll be using it throughout
|
|
this document. The most important returned values (but not all) for
|
|
path_parts () are:
|
|
</p>
|
|
<p>
|
|
<verb>
|
|
fake_full_path
|
|
fake_leading_dirs
|
|
fake_extra_path
|
|
fake_name
|
|
real_full_path
|
|
real_leading_dirs
|
|
real_extra_path
|
|
real_name
|
|
</verb>
|
|
</p><p>
|
|
Just like you would think, fake_full_path contains the full virtual
|
|
path of 'string', and real_full_path contains the full real path
|
|
of 'string'. The fake_name and real_name variables should always
|
|
be the same, and contain the final file or directory name. The leading_dirs
|
|
contain everything except the name, and the extra_path is everything
|
|
from the / before "home" to the end of the leading_dirs. To better
|
|
illustrate, here is an example:
|
|
</p>
|
|
<p>
|
|
<verb>
|
|
$p = $GLOBALS['phpgw']->vfs->path_parts (array(
|
|
'string' => '/home/jason/dir/file',
|
|
'relatives' => array(
|
|
RELATIVE_NONE
|
|
)
|
|
));
|
|
</verb>
|
|
<p>
|
|
<itemize>
|
|
<item>
|
|
$p->fake_full_path - /home/jason/dir/file
|
|
<item>
|
|
$p->fake_leading_dirs - /home/jason/dir
|
|
<item>
|
|
$p->fake_extra_path - home/jason/dir
|
|
<item>
|
|
$p->fake_name - file
|
|
<item>
|
|
$p->real_full_path - /var/www/egroupware/files/home/jason/dir/file
|
|
<item>
|
|
$p->real_leading_dirs - /var/www/egroupware/files/home/jason/dir
|
|
|
|
<item>
|
|
$p->real_extra_path - home/jason/dir
|
|
<item>
|
|
$p->real_name - file
|
|
</itemize>
|
|
</p><p>
|
|
As you can see, path_parts () is a very useful function and will
|
|
save you from doing those darn substr ()'s yourself. For those of
|
|
you used to the prior VFS, note that <em>getabsolutepath () is depreciated</em>.
|
|
getabsolutepath () still exists (albeit in a much different form),
|
|
and is responsible for some of the path translation, but it is an
|
|
<em>internal</em> function only. Applications should only use path_parts ().
|
|
We have shown you how to use path_parts () so you can experiment
|
|
with it using different paths and relativities as we explore relativity.
|
|
</p>
|
|
<sect1>
|
|
cd ()<label id="sec:cd" >
|
|
<p>
|
|
Part of the overall goal for the VFS in eGoupWare is to give
|
|
the user a seamless experience during their session. For example,
|
|
if they upload a file using a file manager to the directory /home/my_group/project1,
|
|
and then go to download an email attachment, the default directory
|
|
will be /home/my_group/project1. This is accomplished using the cd
|
|
() function. Examples:
|
|
</p>
|
|
<p>
|
|
<verb>
|
|
/* cd to their home directory */
|
|
$GLOBALS['phpgw']->vfs->cd (array(
|
|
'string' => '/'
|
|
));
|
|
|
|
/* cd to /home/jason/dir */
|
|
$GLOBALS['phpgw']->vfs->cd (array(
|
|
'string' => '/home/jason/dir',
|
|
'relative' => False,
|
|
'relatives' => array(
|
|
RELATIVE_NONE
|
|
)
|
|
));
|
|
|
|
/* When following the above, cd's to /home/jason/dir/dir2 */
|
|
$GLOBALS['phpgw']->vfs->cd (array(
|
|
'string' => 'dir2',
|
|
'relative' => True
|
|
));
|
|
</verb>
|
|
</p><p>
|
|
If 'relative' is True, the 'string' is simply appended to the
|
|
current path. If you want to know what the current path is, use $GLOBALS['phpgw']->vfs->pwd
|
|
().
|
|
</p>
|
|
<p>
|
|
Now you're ready for relativity.
|
|
</p>
|
|
<sect>
|
|
Relativity<label id="sec:relativity" >
|
|
<p>
|
|
Ok, just one last thing before we get into relativity. You will
|
|
notice throughout the examples the use of $fakebase. $GLOBALS['phpgw']->vfs->fakebase
|
|
is by default '/home'. The old VFS was hard-coded to use '/home',
|
|
but the naming choice for this is now up to administrators. See the
|
|
<ref id="sec:fakebase" name="Fakebase directory (changing /home)" > section for more information. Throughout the rest of this document,
|
|
you will see $fakebase used in calls to the VFS, and /home
|
|
used in actual paths. <em>You should always use $fakebase when
|
|
making applications. </em>I suggest doing $fakebase = $GLOBALS['phpgw']->vfs->fakebase;
|
|
right off the bat to keep things neater.
|
|
</p>
|
|
<sect1>
|
|
What is it and how does it work?
|
|
<p>
|
|
One of the design challenges for a Virtual File System is to
|
|
try to figure out whether the calling application is referring to
|
|
a file inside or outside the virtual root, and if inside, exactly
|
|
where. To solve this problem, the eGoupWare VFS uses RELATIVE
|
|
defines that are used in bitmasks passed to each function. The result
|
|
is that any set of different relativities can be used in combination
|
|
with each other. Let's look at a few examples. Say you want to move
|
|
'logo.png' from the user's home directory to the current directory.
|
|
|
|
</p>
|
|
<p>
|
|
<verb>
|
|
$GLOBALS['phpgw']->vfs->mv (array(
|
|
'from' => 'logo.png',
|
|
'to' => 'logo.png',
|
|
'relatives' => array(
|
|
RELATIVE_USER,
|
|
RELATIVE_ALL
|
|
)
|
|
));
|
|
</verb>
|
|
</p><p>
|
|
RELATIVE_USER means relative to the user's home directory. RELATIVE_ALL
|
|
means relative to the current directory, as set by cd () and as reported
|
|
by pwd (). So if the current directory was "$fakebase/my_group/project1",
|
|
the call to mv () would be processed as:
|
|
</p>
|
|
<p>
|
|
<verb>
|
|
MOVE "$fakebase/jason/logo.png" TO "$fakebase/my_group/project1/logo.png"
|
|
</verb>
|
|
</p><p>
|
|
and the actual file system call would be:
|
|
</p>
|
|
<p>
|
|
<verb>
|
|
rename ('/var/www/egroupware/files/home/jason/logo.php', '/var/www/egroupware/files/home/my_group/project1/logo.png');
|
|
</verb>
|
|
</p><p>
|
|
Those used to the old VFS will note that you do not have to translate
|
|
the path beforehand. Let's look at another example. Suppose you were
|
|
moving an email attachment stored in eGoupWare's temporary directory
|
|
to the 'attachments' directory within the user's home directory (we're
|
|
assuming the attachments directory exists). Note that the temporary
|
|
directory is <em>outside</em> the virtual root.
|
|
</p>
|
|
<p>
|
|
<verb>
|
|
$GLOBALS['phpgw']->vfs->mv (array(
|
|
'from' => $GLOBALS['phpgw_info']['server']['temp_dir'] . '/' . $randomdir . '/' . $randomfile,
|
|
'to' => 'attachments/actual_name.ext',
|
|
'relatives' => array(
|
|
RELATIVE_NONE|VFS_REAL,
|
|
RELATIVE_USER
|
|
)
|
|
));
|
|
</verb>
|
|
</p><p>
|
|
$randomdir and $randomfile are what the directory
|
|
and file might be called before they are given a proper name by the
|
|
user, which is actual_name.ext in this example. RELATIVE_NONE is
|
|
the define for using full path names. However, RELATIVE_NONE is still
|
|
relative to the virtual root, so we pass along VFS_REAL as well,
|
|
to say that the file is <em>outside</em> the virtual root, somewhere else
|
|
in the file system. Once again, RELATIVE_USER means relative to the
|
|
user's home directory. So the actual file system call might look
|
|
like this (keep in mind that $randomdir and $randomfile
|
|
are just random strings):
|
|
</p>
|
|
<p>
|
|
<verb>
|
|
rename ('/var/www/egroupware/tmp/0ak5adftgh7/jX42sC9M', '/var/www/egroupware/files/home/jason/attachments/actual_name.ext');
|
|
</verb>
|
|
</p><p>
|
|
Of course you don't have to know that, nor should you be concerned
|
|
with it; you can take it for granted that the VFS will translate
|
|
the paths correctly. Let's take a look at one more example, this
|
|
time using the RELATIVE_USER_APP define. RELATIVE_USER_APP is used
|
|
to store quasi-hidden application files, similar to the Unix convention
|
|
of ˜/.appname. It simply appends .appname to the user's home
|
|
directory. For example, if you were making an HTML editor application
|
|
named 'htmledit', and wanted to keep a backup file in case something
|
|
goes wrong, you could use RELATIVE_USER_APP to store it:
|
|
</p>
|
|
<p>
|
|
<verb>
|
|
$GLOBALS['phpgw']->vfs->write (array(
|
|
'string' => 'file.name˜',
|
|
'relatives' => array(
|
|
RELATIVE_USER_APP
|
|
),
|
|
'content' => $contents
|
|
));
|
|
</verb>
|
|
</p><p>
|
|
This assumes that ˜/.htmledit exists of course. The backup
|
|
file "file.name˜" would then be written in $fakebase/jason/.htmledit/file.name˜.
|
|
Note that storing files like this might not be as good of a solution
|
|
as storing them in the temporary directory or in the database. But
|
|
it is there in case you need it.
|
|
</p>
|
|
<sect1>
|
|
Complete List<label id="sec:relatives_complete_list" >
|
|
<p>
|
|
Here is the complete list of RELATIVE defines, and what they
|
|
do:
|
|
</p>
|
|
<p>
|
|
<descrip>
|
|
<tag>
|
|
RELATIVE_ROOT</tag>Don't translate the path at all. Just prepends
|
|
a /. You'll probably want to use RELATIVE_NONE though, which handles
|
|
both virtual and real files.
|
|
<tag>
|
|
RELATIVE_USER</tag>User's home directory
|
|
<tag>
|
|
RELATIVE_CURR_USER</tag>Current user's home directory. If the
|
|
current directory is $fakebase/my_group/project1, this will
|
|
return is $fakebase/my_group
|
|
<tag>
|
|
RELATIVE_USER_APP</tag>Append .appname to the user's home directory,
|
|
where appname is the current application's appname
|
|
<tag>
|
|
RELATIVE_PATH</tag>DO NOT USE. Relative to the current directory,
|
|
used in RELATIVE_ALL
|
|
<tag>
|
|
RELATIVE_NONE</tag>Not relative to anything. Use this with VFS_REAL
|
|
for files outside the virtual root. Note that using RELATIVE_NONE
|
|
by itself still means relative to the virtual root
|
|
<tag>
|
|
RELATIVE_CURRENT</tag>An alias for the currently set RELATIVE
|
|
define, or RELATIVE_ALL if none is set (see the Defaults section)
|
|
<tag>
|
|
VFS_REAL</tag>File is outside of the virtual root. Usually used
|
|
with RELATIVE_NONE
|
|
<tag>
|
|
RELATIVE_ALL</tag>Relative to the current directory. Use RELATIVE_ALL<em>
|
|
</em>instead of RELATIVE_PATH
|
|
</descrip>
|
|
</p><sect1>
|
|
Defaults<label id="sec:relatives_defaults" >
|
|
<p>
|
|
You might be thinking to yourself that passing along RELATIVE
|
|
defines with every VFS call is overkill, especially if your application
|
|
always uses the same relativity. The default RELATIVE define for
|
|
all VFS calls is RELATIVE_CURRENT. RELATIVE_CURRENT itself defaults
|
|
to RELATIVE_ALL (relative to the current path), <em>unless</em> your application
|
|
sets a specific relativity. If your application requires most of
|
|
the work to be done outside of the virtual root, you may wish to
|
|
set RELATIVE_CURRENT to RELATIVE_NONE|VFS_REAL. set_relative () is
|
|
the function to do this. For example:
|
|
</p>
|
|
<p>
|
|
<verb>
|
|
$GLOBALS['phpgw']->vfs->set_relative (array(
|
|
'mask' => RELATIVE_NONE|VFS_REAL
|
|
));
|
|
|
|
$GLOBALS['phpgw']->vfs->read (array(
|
|
'string' => '/etc/passwd'
|
|
));
|
|
|
|
$GLOBALS['phpgw']->vfs->cp (array(
|
|
'from' => '/usr/include/stdio.h',
|
|
'to' => '/tmp/stdio.h'
|
|
));
|
|
|
|
$GLOBALS['phpgw']->vfs->cp (array(
|
|
'from' => '/usr/share/pixmaps/yes.xpm',
|
|
'to' => 'icons/yes.xpm',
|
|
'relatives' => array(
|
|
RELATIVE_CURRENT,
|
|
RELATIVE_USER
|
|
)
|
|
));
|
|
</verb>
|
|
</p><p>
|
|
You should notice that no relativity array is needed in the other
|
|
calls that refer to files outside the virtual root, but one is needed
|
|
for calls that include files inside the virtual root. Any RELATIVE
|
|
define can be set as the default and works in the same fashion. To
|
|
retrieve the currently set define, use get_relative (). Note that
|
|
the relativity is reset after each page request; that is, it's good
|
|
only for the life of the current page loading, and is not stored
|
|
in session management.
|
|
</p>
|
|
<sect>
|
|
Function reference<label id="sec:function_reference" >
|
|
<p>
|
|
To view the function reference for the VFS, use the doc/inlinedocparser.php
|
|
script that comes with eGoupWare, ie <url url="http://localhost/doc/inlinedocparser.php?fn=class.vfs_sql.inc.php" name="http://localhost/doc/inlinedocparser.php?fn=class.vfs_sql.inc.php">.
|
|
</p>
|
|
<sect>
|
|
Notes<label id="sec:notes" >
|
|
<sect1>
|
|
Database<label id="sec:database" >
|
|
<p>
|
|
Data about the files and directories within the virtual root
|
|
is kept in the SQL database. Currently, this information includes:
|
|
</p>
|
|
<p>
|
|
<itemize>
|
|
<item>
|
|
File ID (used internally, primary key for table)
|
|
<item>
|
|
Owner ID (phpGW account_id)
|
|
<item>
|
|
Created by ID (phpGW account_id)
|
|
<item>
|
|
Modified by ID (phpGW account_id)
|
|
<item>
|
|
Created (date)
|
|
<item>
|
|
Modified (date)
|
|
<item>
|
|
Size (bytes)
|
|
<item>
|
|
MIME type
|
|
<item>
|
|
Deleteable (Y/N/Other?)
|
|
<item>
|
|
Comment
|
|
<item>
|
|
App (appname of application that created the file)
|
|
<item>
|
|
Directory (directory the file or directory is in)
|
|
<item>
|
|
Name (name of file or directory)
|
|
<item>
|
|
Link directory (if the file or directory is linked, what the
|
|
actual directory is)
|
|
<item>
|
|
Link name (if the file or directory is linked, what the actual
|
|
name is)
|
|
<item>
|
|
Version (numeric version of the file)
|
|
</itemize>
|
|
</p><p>
|
|
The internal names of these (the database column names) are stored
|
|
in the $GLOBALS['phpgw']->vfs->attributes
|
|
array, which is useful for loops, and is guaranteed to be up-to-date.
|
|
</p>
|
|
<p>
|
|
Note that no information is kept about files outside the virtual
|
|
root. If a file is moved outside, all records of it are deleted from
|
|
the database (other than the journaling records). If a file is moved
|
|
into the virtual root, some information, specifically MIME-type,
|
|
is not always stored in the database. The vital information has defaults:
|
|
owner is based on where the file is being stored; size is correctly
|
|
read; deleteable is set to Y.
|
|
</p>
|
|
<sect1>
|
|
ACL support<label id="sec:acl_support" >
|
|
<p>
|
|
ACL support is built into the VFS. vfs->acl_check () does
|
|
the actual checking, and is called from all VFS functions as needed.
|
|
If the file or directory sent to acl_check () doesn't exist, the
|
|
permissions for the parent directory are used to determine access.
|
|
ACL checking can be overridden at any time by setting vfs->override_acl.
|
|
For example:
|
|
</p>
|
|
<p>
|
|
<verb>
|
|
$GLOBALS['phpgw']->vfs->override_acl = 1;
|
|
$GLOBALS['phpgw']->vfs->mkdir (array(
|
|
'string' => $GLOBALS['fakebase']. '/' . $group_array['account_name'],
|
|
'relatives' => array(
|
|
RELATIVE_NONE
|
|
)
|
|
));
|
|
$GLOBALS['phpgw']->vfs->override_acl = 0;
|
|
</verb>
|
|
</p><sect1>
|
|
Function aliases<label id="sec:function_aliases" >
|
|
<p>
|
|
You might have noticed there are some functions that just pass
|
|
the arguments on to other functions. These are provided in part because
|
|
of legacy and in part for convenience. You can use either. Here is
|
|
the list (alias -> actual):
|
|
</p>
|
|
<p>
|
|
<itemize>
|
|
<item>
|
|
copy -> cp
|
|
<item>
|
|
move -> rm
|
|
<item>
|
|
delete -> rm
|
|
<item>
|
|
dir -> ls
|
|
</itemize>
|
|
</p><sect1>
|
|
Fakebase directory (changing /home)<label id="sec:fakebase" >
|
|
<p>
|
|
The old VFS was hard-coded to use '/home' as the fake base directory,
|
|
even though the user never saw it. With the new system, crafty administrators
|
|
may wish to change '/home' to something else, say '/users' or '/public_html'.
|
|
The fake base directory name is stored in $GLOBALS['phpgw']->vfs->fakebase,
|
|
and changing it will transparently change it throughout the VFS and
|
|
all applications. However, this must be done <em>before</em> any data is in
|
|
the VFS database. If you wish to change it afterwords, you'll have
|
|
to manually update the database, replacing the old value with the
|
|
new value. <em>Application programmers need to recognize that /home is
|
|
not absolute, and use $GLOBALS['phpgw']->vfs->fakebase
|
|
instead</em>. I suggest setting $fakebase = $GLOBALS['phpgw']->vfs->fakebase;
|
|
right off the bat to keep things neater.
|
|
</p>
|
|
<sect>
|
|
About this Document
|
|
<sect1>
|
|
Copyright and License
|
|
<p>
|
|
Copyright (c) 2001, 2002 Jason Wies
|
|
</p>
|
|
<p>
|
|
Permission is granted to copy, distribute and/or modify this
|
|
document under the terms of the GNU Free Documentation License, Version
|
|
1.1 or any later version published by the Free Software Foundation;
|
|
with no Invarient Sections, with no Front-Cover Texts, and no Back-Cover
|
|
Texts.
|
|
</p>
|
|
<p>
|
|
A copy of the license is available at <url url="http://www.gnu.org/copyleft/fdl.html" name="http://www.gnu.org/copyleft/fdl.html">.
|
|
</p>
|
|
<sect1>
|
|
History
|
|
<p>
|
|
Original document released in June 2001 by Jason Wies.
|
|
</p>
|
|
<p>
|
|
Updated February 2002 to include arrayized parameters, single
|
|
quotes, and GLOBALS.
|
|
</p>
|
|
<sect1>
|
|
Contributing
|
|
<p>
|
|
Contributions are always welcome. Please send to the current
|
|
maintainer, Jason Wies,
|
|
</p>
|
|
|
|
|
|
</article>
|