mirror of
https://github.com/EGroupware/egroupware.git
synced 2024-12-23 23:29:31 +01:00
820 lines
20 KiB
Plaintext
820 lines
20 KiB
Plaintext
|
|
|
|
phpGroupWare Application Development
|
|
|
|
Dan Kuykendall <dan@kuykendall.org>
|
|
|
|
v0.9 29 September 2000
|
|
|
|
This document explains phpGroupWare's infrastructure and
|
|
API, along with what is required to integrate applications
|
|
into it.
|
|
|
|
|
|
|
|
1 Introduction
|
|
|
|
phpGroupWare is a web based groupware application framework
|
|
(API), for writing applications. Integrated applications
|
|
such as email, calendar, todo list, address book, and file
|
|
manager are included.
|
|
|
|
1.1 Overview of application writing
|
|
|
|
We have attempted to make writing application for phpGroupWare
|
|
as painless as possible. We hope any pain and suffering
|
|
is cause by making your application work, but not dealing
|
|
with phpGroupWare itself.
|
|
|
|
1.2 What does the phpGroupWare API provide?
|
|
|
|
The phpGroupWare API handles session management, user/group
|
|
management, has support for multiple databases, using the
|
|
PHPLIB database abstraction method, we support templates
|
|
using the PHPLIB Templates class, a file system interface,
|
|
and even a network i/o interface.
|
|
|
|
On top of these standard functions, phpGroupWare provides
|
|
several functions to give you the information you need about
|
|
the users environment, and to properly plug into phpGroupWare.
|
|
|
|
2 Guidelines
|
|
|
|
2.1 Requirements
|
|
|
|
These guidelines must be followed for any application that
|
|
wants considered for inclusion into phpGroupWare deluxe:
|
|
|
|
* It must run on PHP3 and PHP4.
|
|
|
|
* SQL statements must be compatible with both MySQL and PostgreSQL.
|
|
|
|
* It must use our default header.inc.php include.
|
|
|
|
* It must use our $phpgw_link($url) for all links (this is
|
|
for session support).
|
|
|
|
* It must use "post" for
|
|
forms.
|
|
|
|
* It must respect phpGW group rights and phpGW user permissions.
|
|
|
|
* It must use our directory structure, template support and
|
|
lang (multi-language) support.
|
|
|
|
* Where possible it should run on both Unix and NT platforms.
|
|
|
|
* For applications that do not meet these requirements, they
|
|
can be available to users via the phpGroupWare Apps project,
|
|
or whatever means the developers decide. If you need help
|
|
converting your application to templates and our lang
|
|
support, we will try to connect you with someone to help.
|
|
|
|
2.2 Writing/porting your application
|
|
|
|
Include files
|
|
|
|
Each PHP page you write will need to include the header.inc.php
|
|
along with a few variables.
|
|
This is done by putting this at the top of each PHP page.
|
|
Of course change application name to fit.
|
|
This include will provide the following things:
|
|
|
|
* The phpgwAPI - The phpGroupWare API will be loaded.
|
|
|
|
* The phpGW navbar will be loaded (by default, but can be
|
|
disabled until a later point.
|
|
|
|
* appname/inc/functions.inc.php - This file is loaded just
|
|
after the phpgwAPI and before any HTML code is generated.
|
|
This file should include all your application specific
|
|
functions.. You are welcome to include any additional
|
|
files you need from within this file.
|
|
|
|
* appname/inc/header.inc.php - This file is loaded just after
|
|
the system header/navbar, and allows developers to use
|
|
it for whatever they need to load.
|
|
|
|
* appname/inc/footer.inc.php - This file is loaded just before
|
|
the system footer, allowing developers to close connections
|
|
and whatever else they need.
|
|
|
|
* The phpGW footer will be loaded, which closes several connections.
|
|
|
|
3 Installing your application
|
|
|
|
3.1 Overview
|
|
|
|
It is fairly simple to add and delete applications to/from
|
|
phpGroupWare.
|
|
|
|
3.2 Automatic features
|
|
|
|
To make things easy for developers we go ahead and load the
|
|
following files.
|
|
|
|
* appname/inc/functions.inc.php - This file should include
|
|
all your application specific functions.
|
|
|
|
* appname/inc/header.inc.php - This file is loaded by $phpgw->common->header
|
|
just after the system header/navbar, and allows developers
|
|
to use it for whatever they need to load.
|
|
|
|
* appname/inc/footer.inc.php - This file is loaded by $phpgw->common->footer
|
|
just before the system footer, allowing developers to
|
|
close connections and whatever else they need.
|
|
|
|
3.3 Adding files, directories and icons.
|
|
|
|
You will need to create the following directories for your
|
|
code
|
|
(replace 'appname' with your application name)
|
|
|
|
|
|
`--appname
|
|
|
|
|--inc
|
|
|
|
| |--functions.inc.php
|
|
|
|
| |--header.inc.php
|
|
|
|
| |--hook_preferences.inc.php
|
|
|
|
| |--hook_admin.inc.php
|
|
|
|
| `--footer.inc.php
|
|
|
|
`--templates
|
|
|
|
| `--default
|
|
|
|
3.4 Making phpGroupWare aware of your application
|
|
|
|
To make the application aware of your application, add your
|
|
application details to the applications table. This can
|
|
be done via the GUI administration screen, or via a SQL
|
|
script.
|
|
|
|
3.5 Hooking into Administration page
|
|
|
|
When a user goes to the Administration page, it starts appname/inc/hook_admin.inc.php
|
|
for each application that is enabled, in alphabetical order
|
|
of application title. If the file exists, it is include()d
|
|
in the hopes it will display a selection of links to configure
|
|
that application.
|
|
|
|
Simple Example: Look at headlines/inc/hook_admin.inc.php
|
|
and admin/inc/hook_admin.inc.php for more examples.
|
|
|
|
Things to note:
|
|
|
|
* Links are relative to the admin/index.php file, not your
|
|
application's base directory. (so use $appname in your
|
|
link() calls)
|
|
|
|
* The file is brought in with include() so be careful to
|
|
not pollute the name-space too much
|
|
|
|
The standard $phpgw and $phpgw_info variables are in-scope,
|
|
as is $appname which corresponds to the application name
|
|
in the path.
|
|
|
|
There are 2 functions to coordinate the display of each application's
|
|
links, section_start() and section_end()
|
|
|
|
section_start
|
|
|
|
section_start($title,$icon_url) starts the section for your
|
|
application. $title is passed through lang() for you. $icon_url
|
|
should be page-relative to admin/index.php or an absolute
|
|
URL.
|
|
|
|
section_end
|
|
|
|
section_end() closes the section that was started with section_start().
|
|
|
|
3.6 Hooking into Preferences page
|
|
|
|
The mechanism to hook into the preferences page is identical
|
|
to the one used to hook into the administration page, however
|
|
it looks for appname/inc/hook_preferences.inc.php instead
|
|
of appname/inc/hook_admin.inc.php. The same functions and
|
|
variables are defined.
|
|
|
|
4 Infrastructure
|
|
|
|
4.1 Overview
|
|
|
|
phpGroupWare attempts to provide developers with a sound
|
|
directory structure to work from.
|
|
The directory layout may seem complex at first, but after
|
|
some use, you will see that it is designed to accommodate
|
|
a large number of applications and functions.
|
|
|
|
4.2 Directory tree
|
|
|
|
.--appname
|
|
|
|
| |--inc
|
|
|
|
| | |--functions.inc.php
|
|
|
|
| | |--header.inc.php
|
|
|
|
| | |--hook_preferences.ini.php
|
|
|
|
| | |--hook_home.inc.php
|
|
|
|
| | `--footer.inc.php
|
|
|
|
| |--manual
|
|
|
|
| |--setup
|
|
|
|
| | |--baseline.inc.php
|
|
|
|
| | |--droptables.inc.php
|
|
|
|
| | |--newtables.inc.php
|
|
|
|
| | |--upgradetables.inc.php
|
|
|
|
| | |--config.inc.php
|
|
|
|
| | `--register.inc.php
|
|
|
|
| `--templates
|
|
|
|
| | `--default
|
|
|
|
| | `--images
|
|
|
|
| |
|
|
`--navbar.gif
|
|
|
|
| |--preferences.php
|
|
|
|
|--docs (installation docs)
|
|
|
|
|--files
|
|
|
|
| |--groups
|
|
|
|
| `--users
|
|
|
|
`--phpgwapi
|
|
|
|
|--cron (phpgroupware's optional daemons)
|
|
|
|
|--doc (developers docs)
|
|
|
|
|--inc
|
|
|
|
| |--phpgw.inc.php
|
|
|
|
| |--phpgw_info.inc.php
|
|
|
|
| |--phpgw_common.inc.php
|
|
|
|
| `--etc..
|
|
|
|
|--manual
|
|
|
|
|--setup
|
|
|
|
| |--baseline.inc.php
|
|
|
|
| |--droptables.inc.php
|
|
|
|
| |--newtables.inc.php
|
|
|
|
| |--upgradetables.inc.php
|
|
|
|
| |--config.inc.php
|
|
|
|
| `--register.inc.php
|
|
|
|
|--templates
|
|
|
|
| |--default
|
|
|
|
| | `--images
|
|
|
|
| | |--home.gif
|
|
|
|
| | `--preferences.gif
|
|
|
|
| `--verilak
|
|
|
|
| `--images
|
|
|
|
|--home.gif
|
|
|
|
`--preferences.gif
|
|
|
|
`--themes
|
|
|
|
`--default.theme
|
|
|
|
4.3 Translations
|
|
|
|
The translations are now being done thru the database, and
|
|
will be configurable to use other mechanisms.
|
|
|
|
We are completing a program called Transy, which will provide
|
|
developers/translators a nice GUI for building and updating
|
|
translations.
|
|
|
|
In the mean time you will need to create a SQL script yourself
|
|
and name it lang.sql. You can copy the one in doc/lang.sql
|
|
and use it as a template.
|
|
|
|
5 The API
|
|
|
|
5.1 Introduction
|
|
|
|
phpGroupWare attempts to provide developers with a useful
|
|
API to handle common tasks.
|
|
|
|
To do this we have created a multi-dimensional class $phpgw->.
|
|
|
|
This allows for terrific code organization, and help developers
|
|
easily identify the file that the function is in. All the
|
|
files that are part of this class are in the inc/core directory
|
|
and are named to match the sub-class.
|
|
|
|
Example: $phpgw->send->msg() is in the inc/phpgwapi/phpgw_send.inc.php
|
|
file.
|
|
|
|
5.2 Basic functions
|
|
|
|
$phpgw->link
|
|
|
|
$phpgw->link($url)
|
|
Add support for session management. ALL links must use this,
|
|
that includes href's form actions and header location's.
|
|
|
|
If you are just doing a form action back to the same page,
|
|
you can use it without any parameters.
|
|
|
|
This function is right at the core of the class because it
|
|
is used so often, we wanted to save developers a few keystrokes.
|
|
Example:
|
|
|
|
5.3 Application Functions
|
|
|
|
$phpgw->common->phpgw_header
|
|
|
|
$phpgw->phpgw_header()
|
|
Print out the start of the HTML page, including the navigation
|
|
bar and includes appname/inc/header.php
|
|
|
|
$phpgw->common->phpgw_footer
|
|
|
|
$phpgw->phpgw_footer()
|
|
Prints the system footer, and includes appname/inc/footer.php
|
|
|
|
$phpgw->common->appsession
|
|
|
|
$phpgw->common->appsession($data)
|
|
Store important information session information that your
|
|
application needs.
|
|
$phpgw->appsession will return the value of your session
|
|
data is you leave the parameter empty [i.e. $phpgw->appsession("")],
|
|
otherwise it will store whatever data you send to it.
|
|
You can also store a comma delimited string and use explode()
|
|
to turn it back into an array when you receive the value
|
|
back.
|
|
|
|
Example:
|
|
|
|
5.4 File functions
|
|
|
|
$phpgw->vfs->read_file
|
|
|
|
$phpgw->vfs->read_file($file)
|
|
Returns the data from $file.
|
|
You must send the complete path to the file.
|
|
Example:
|
|
|
|
$phpgw->vfs->write_file
|
|
|
|
$phpgw->vfs->write_file($file, $contents)
|
|
Write data to $file.
|
|
You must send the complete path to the file.
|
|
Example:
|
|
|
|
$phpgw->vfs->read_userfile
|
|
|
|
$phpgw->vfs->read_userfile($file)
|
|
Returns the data from $file, which resides in the users
|
|
private dir.
|
|
Example:
|
|
|
|
$phpgw->vfs->write_userfile
|
|
|
|
$phpgw->write_userfile($file, $contents)
|
|
Writes data to $file, which resides in the users private
|
|
dir.
|
|
Example:
|
|
|
|
$phpgw->vfs->list_userfiles
|
|
|
|
$phpgw->vfs->list_userfiles()
|
|
Returns an array which has the list of files in the users
|
|
private dir.
|
|
Example:
|
|
|
|
5.5 Email/NNTP Functions
|
|
|
|
$phpgw->send->msg
|
|
|
|
$phpgw->msg->send($service, $to, $subject, $body, $msgtype,
|
|
$cc, $bcc)
|
|
Send a message via email or NNTP and returns any error codes.
|
|
Example:
|
|
|
|
6 Configuration Variables
|
|
|
|
6.1 Introduction
|
|
|
|
phpGroupWare attempt to provide developers with as much information
|
|
about the user, group, server, and application configuration
|
|
as possible.
|
|
|
|
To do this we provide a multi-dimensional array called '$phpgw_info[]',
|
|
which includes all the information about your environment.
|
|
|
|
Due to the multi-dimensional array approach. getting these
|
|
values is easy.
|
|
|
|
Here are some examples:
|
|
|
|
6.2 User information
|
|
|
|
$phpgw_info["user"]["userid"]
|
|
= The user ID.
|
|
|
|
$phpgw_info["user"]["sessionid"]
|
|
= The session ID
|
|
|
|
$phpgw_info["user"]["theme"]
|
|
= Selected theme
|
|
|
|
$phpgw_info["user"]["private_dir"]
|
|
= Users private dir. Use phpGroupWare core functions for
|
|
access to the files.
|
|
|
|
$phpgw_info["user"]["firstname"]
|
|
= Users first name
|
|
|
|
$phpgw_info["user"]["lastname"]
|
|
= Users last name
|
|
|
|
$phpgw_info["user"]["fullname"]
|
|
= Users Full Name
|
|
|
|
$phpgw_info["user"]["groups"]
|
|
= Groups the user is a member of
|
|
|
|
$phpgw_info["user"]["app_perms"]
|
|
= If the user has access to the current application
|
|
|
|
$phpgw_info["user"]["lastlogin"]
|
|
= Last time the user logged in.
|
|
|
|
$phpgw_info["user"]["lastloginfrom"]
|
|
= Where they logged in from the last time.
|
|
|
|
$phpgw_info["user"]["lastpasswd_change"]
|
|
= Last time they changed their password.
|
|
|
|
$phpgw_info["user"]["passwd"]
|
|
= Hashed password.
|
|
|
|
$phpgw_info["user"]["status"]
|
|
= If the user is enabled.
|
|
|
|
$phpgw_info["user"]["logintime"]
|
|
= Time they logged into their current session.
|
|
|
|
$phpgw_info["user"]["session_dla"]
|
|
= Last time they did anything in their current session
|
|
|
|
$phpgw_info["user"]["session_ip"]
|
|
= Current IP address
|
|
|
|
6.3 Group information
|
|
|
|
$phpgw_info["group"]["group_names"]
|
|
= List of groups.
|
|
|
|
6.4 Server information
|
|
|
|
$phpgw_info["server"]["server_root"]
|
|
= Main installation directory
|
|
|
|
$phpgw_info["server"]["include_root"]
|
|
= Location of the 'inc' directory.
|
|
|
|
$phpgw_info["server"]["temp_dir"]
|
|
= Directory that can be used for temporarily storing files
|
|
|
|
$phpgw_info["server"]["files_dir"]
|
|
= Directory er and group files are stored
|
|
|
|
$phpgw_info["server"]["common_include_dir"]
|
|
= Location of the core/shared include files.
|
|
|
|
$phpgw_info["server"]["template_dir"]
|
|
= Active template files directory. This is defaulted by
|
|
the server, and changeable by the user.
|
|
|
|
$phpgw_info["server"]["dir_separator"]
|
|
= Allows compatibility with WindowsNT directory format,
|
|
|
|
$phpgw_info["server"]["encrpytkey"]
|
|
= Key used for encryption functions
|
|
|
|
$phpgw_info["server"]["site_title"]
|
|
= Site Title will show in the title bar of each webpage.
|
|
|
|
$phpgw_info["server"]["webserver_url"]
|
|
= URL to phpGroupWare installation.
|
|
|
|
$phpgw_info["server"]["hostname"]
|
|
= Name of the server phpGroupWare is installed upon.
|
|
|
|
$phpgw_info["server"]["charset"]
|
|
= default charset, default:iso-8859-1
|
|
|
|
$phpgw_info["server"]["version"]
|
|
= phpGroupWare version.
|
|
|
|
6.5 Database information
|
|
|
|
It is unlikely you will need these, because $phpgw_info_db
|
|
will already be loaded as a database for you to use.
|
|
|
|
$phpgw_info["server"]["db_host"]
|
|
= Address of the database server. Usually this is set to
|
|
localhost.
|
|
|
|
$phpgw_info["server"]["db_name"]
|
|
= Database name.
|
|
|
|
$phpgw_info["server"]["db_user"]
|
|
= User name.
|
|
|
|
$phpgw_info["server"]["db_pass"]
|
|
= Password
|
|
|
|
$phpgw_info["server"]["db_type"]
|
|
= Type of database. Currently MySQL and PostgreSQL are supported.
|
|
|
|
6.6 Mail information
|
|
|
|
It is unlikely you will need these, because most email needs
|
|
are services thru core phpGroupWare functions.
|
|
|
|
$phpgw_info["server"]["mail_server"]
|
|
= Address of the IMAP server. Usually this is set to localhost.
|
|
|
|
$phpgw_info["server"]["mail_server_type"]
|
|
= IMAP or POP3
|
|
|
|
$phpgw_info["server"]["imap_server_type"]
|
|
= Cyrus or Uwash
|
|
|
|
$phpgw_info["server"]["imap_port"]
|
|
= This is usually 143, and should only be changed if there
|
|
is a good reason.
|
|
|
|
$phpgw_info["server"]["mail_suffix]
|
|
= This is the domain name, used to add to email address
|
|
|
|
$phpgw_info["server"]["mail_login_type"]
|
|
= This adds support for VMailMgr. Generally this should
|
|
be set to 'standard'.
|
|
|
|
$phpgw_info["server"]["smtp_server"]
|
|
= Address of the SMTP server. Usually this is set to localhost.
|
|
|
|
$phpgw_info["server"]["smtp_port"]
|
|
= This is usually 25, and should only be changed if there
|
|
is a good reason
|
|
|
|
6.7 NNTP information
|
|
|
|
$phpgw_info["server"]["nntp_server"]
|
|
= Address of the NNTP server.
|
|
|
|
$phpgw_info["server"]["nntp_port"]
|
|
= This is usually XX, and should only be changed if there
|
|
is a good reason.
|
|
|
|
$phpgw_info["server"]["nntp_sender"]
|
|
= Unknown
|
|
|
|
$phpgw_info["server"]["nntp_organization"]
|
|
= Unknown
|
|
|
|
$phpgw_info["server"]["nntp_admin"]
|
|
= Unknown
|
|
|
|
6.8 Application information
|
|
|
|
Each application has the following information available.
|
|
|
|
$phpgw_info["apps"]["appname"]["title"]
|
|
= The title of the application.
|
|
|
|
$phpgw_info["apps"]["appname"]["enabled"]
|
|
= If the application is enabled. True or False.
|
|
|
|
$phpgw_info["server"]["app_include_dir"]
|
|
= Location of the current application include files.
|
|
|
|
$phpgw_info["server"]["app_template_dir"]
|
|
= Location of the current application tpl files.
|
|
|
|
$phpgw_info["server"]["app_lang_dir"]
|
|
= Location of the current lang directory.
|
|
|
|
$phpgw_info["server"]["app_auth"]
|
|
= If the server and current user have access to current
|
|
application
|
|
|
|
$phpgw_info["server"]["app_current"]
|
|
= name of the current application.
|
|
|
|
7 Using Language Support
|
|
|
|
7.1 Overview
|
|
|
|
phpGroupWare is built using a multi-language support scheme.
|
|
This means the pages can be translated to other languages
|
|
very easily. Translations of text strings are stored in
|
|
the phpGroupWare database, and can be modified by the phpGroupWare
|
|
administrator.
|
|
|
|
7.2 How to use lang support
|
|
|
|
The lang() function is your application's interface to phpGroupWare's
|
|
internationalization support.
|
|
|
|
While developing your application, just wrap all your text
|
|
output with calls to lang(), as in the following code: This
|
|
will attempt to translate "The
|
|
counter is %1", and return a translated version
|
|
based on the current application and language in use. Note
|
|
how the position that $x will end up is controlled by the
|
|
format string, not by building up the string in your code.
|
|
This allows your application to be translated to languages
|
|
where the actual number is not placed at the end of the
|
|
string.
|
|
|
|
When a translation is not found, the original text will be
|
|
returned with a * after the string. This makes it easy to
|
|
develop your application, then go back and add missing translations
|
|
(identified by the *) later.
|
|
|
|
Without a specific translation in the lang table, the above
|
|
code will print: If the current user speaks Italian, they
|
|
string returned may instead be:
|
|
|
|
The lang function
|
|
|
|
|
|
|
|
$key
|
|
|
|
is the string to translate and may contain replacement
|
|
directives of the form %n.
|
|
|
|
|
|
$m1
|
|
|
|
is the first replacement value or may be an array of replacement
|
|
values (in which case $m2 and above are ignored).
|
|
|
|
$m2 - $m10
|
|
|
|
the 2nd through 10th replacement values if $m1 is not an
|
|
array.
|
|
|
|
The database is searched for rows with a lang.message_id
|
|
that matches $key. If a translation is not found, the original
|
|
$key is used. The translation engine then replaces all tokens
|
|
of the form %N with the Nth parameter (either $m1[N] or
|
|
$mN).
|
|
|
|
Adding translation data
|
|
|
|
An application called Transy is being developed to make this
|
|
easier, until then you can create the translation data manually.
|
|
|
|
The lang table
|
|
|
|
The translation class uses the lang table for all translations.
|
|
We are concerned with 4 of the columns to create a translation:
|
|
|
|
message_id
|
|
|
|
The key to identify the message (the $key passed to the
|
|
lang() function). This is written in English.
|
|
|
|
app_name
|
|
|
|
The application the translation applies to, or common if
|
|
it is common across multiple applications.
|
|
|
|
lang
|
|
|
|
The code for the language the translation is in.
|
|
|
|
content
|
|
|
|
The translated string.
|
|
|
|
lang.sql
|
|
|
|
Currently all applications, and the core phpGroupWare source
|
|
tree have a lang.sql file. This is the place to add translation
|
|
data. Just add lines of the form: translating the content
|
|
to reflect the message_id string in the lang language. If
|
|
the string is specific to your application, put your application
|
|
name in for app_name otherwise use the name common. The
|
|
message_id should be in lower case for a small increase
|
|
in speed.
|
|
|
|
7.3 Common return codes
|
|
|
|
If you browse through the phpGroupWare sources, you may notice
|
|
a pattern to the return codes used in the higher-level functions.
|
|
The codes used are partially documented in the doc/developers/CODES
|
|
file.
|
|
|
|
Codes are used as a simple way to communicate common error
|
|
and progress conditions back to the user. They are mapped
|
|
to a text string through the check_code() function, which
|
|
passes the strings through lang() before returning.
|
|
|
|
For example, calling Would print translated into the current
|
|
language.
|
|
|
|
8 Using Templates
|
|
|
|
8.1 Overview
|
|
|
|
phpGroupWare is built using a templates based design. This
|
|
means the display pages, stored in tpl files, can be translated
|
|
to other languages, made to look completely different.
|
|
|
|
8.2 How to use templates
|
|
|
|
Some instructions on using templates:
|
|
|
|
For Further info read the PHPLIBs documentation for their
|
|
template class. [http://phplib.netuse.de]
|
|
|
|
9 About this document
|
|
|
|
9.1 New versions
|
|
|
|
The newest version of this document can be found on our website
|
|
as lyx source, HTML, and text.
|
|
|
|
9.2 Comments
|
|
|
|
Comments on this HOWTO should be directed to the phpGroupWare
|
|
developers mailing list phpgroupware-developers@lists.sourceforge.net
|
|
|
|
To subscribe, go to _id=7305
|
|
|
|
9.3 History
|
|
|
|
This document was written by Dan Kuykendall.
|
|
|
|
2000-09-25 documentation on lang(), codes, administration
|
|
and preferences extension added by Steve Brown.
|
|
|
|
2001-01-08 fixed directory structure, minor layout changes,
|
|
imported to lyx source - Darryl VanDorp
|
|
|
|
9.4 Copyrights and Trademarks
|
|
|
|
Copyright (c) Dan Kuykendall. 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.
|
|
|
|
A copy of the license is available at [http://www.gnu.org/copyleft/gpl.html]
|
|
|
|
9.5 Acknowledgments and Thanks
|
|
|
|
Thanks to Joesph Engo for starting phpGroupWare (at the time
|
|
called webdistro). Thanks to all the developers and users
|
|
who contribute to making phpGroupWare such a success.
|