[20845] update phpgwapi

Sigurd Nes <[email protected]>
Newsgroups gmane.comp.web.phpgroupware.cvs
Message-ID <[email protected]>
Revision: 20845
          http://svn.sv.gnu.org/viewvc/?view=rev&root=phpgroupware&revision=20845
Author:   sigurdne
Date:     2009-11-20 10:28:10 +0000 (Fri, 20 Nov 2009)
Log Message:
-----------
update phpgwapi

Modified Paths:
--------------
    people/sigurdne/modules/phpgwapi/trunk/cron/asyncservices.php
    people/sigurdne/modules/phpgwapi/trunk/doc/coding_standard.txt
    people/sigurdne/modules/phpgwapi/trunk/doc/generate-class-country.php
    people/sigurdne/modules/phpgwapi/trunk/doc/ldap/README
    people/sigurdne/modules/phpgwapi/trunk/doc/ldap/phpgroupware.schema
    people/sigurdne/modules/phpgwapi/trunk/doc/soap/README
    people/sigurdne/modules/phpgwapi/trunk/doc/vfs/webdav.txt
    people/sigurdne/modules/phpgwapi/trunk/inc/accounts/class.accounts_.inc.php
    people/sigurdne/modules/phpgwapi/trunk/inc/accounts/class.accounts_ldap.inc.php
    people/sigurdne/modules/phpgwapi/trunk/inc/accounts/class.accounts_sql.inc.php
    people/sigurdne/modules/phpgwapi/trunk/inc/accounts/class.accounts_sqlldap.inc.php
    people/sigurdne/modules/phpgwapi/trunk/inc/auth/class.auth_.inc.php
    people/sigurdne/modules/phpgwapi/trunk/inc/auth/class.auth_ads.inc.php
    people/sigurdne/modules/phpgwapi/trunk/inc/auth/class.auth_exchange.inc.php
    people/sigurdne/modules/phpgwapi/trunk/inc/auth/class.auth_http.inc.php
    people/sigurdne/modules/phpgwapi/trunk/inc/auth/class.auth_ldap.inc.php
    people/sigurdne/modules/phpgwapi/trunk/inc/auth/class.auth_mail.inc.php
    people/sigurdne/modules/phpgwapi/trunk/inc/auth/class.auth_nis.inc.php
    people/sigurdne/modules/phpgwapi/trunk/inc/auth/class.auth_ntlm.inc.php
    people/sigurdne/modules/phpgwapi/trunk/inc/auth/class.auth_remoteuser.inc.php
    people/sigurdne/modules/phpgwapi/trunk/inc/auth/class.auth_sql.inc.php
    people/sigurdne/modules/phpgwapi/trunk/inc/auth/class.auth_sqlssl.inc.php
    people/sigurdne/modules/phpgwapi/trunk/inc/class.Template.inc.php
    people/sigurdne/modules/phpgwapi/trunk/inc/class.Template_experimental.inc.php
    people/sigurdne/modules/phpgwapi/trunk/inc/class.account.inc.php
    people/sigurdne/modules/phpgwapi/trunk/inc/class.acl.inc.php
    people/sigurdne/modules/phpgwapi/trunk/inc/class.applications.inc.php
    people/sigurdne/modules/phpgwapi/trunk/inc/class.arrayfunctions.inc.php
    people/sigurdne/modules/phpgwapi/trunk/inc/class.asyncservice.inc.php
    people/sigurdne/modules/phpgwapi/trunk/inc/class.bojsaddressbook.inc.php
    people/sigurdne/modules/phpgwapi/trunk/inc/class.browser.inc.php
    people/sigurdne/modules/phpgwapi/trunk/inc/class.cache.inc.php
    people/sigurdne/modules/phpgwapi/trunk/inc/class.calendar_holidays.inc.php
    people/sigurdne/modules/phpgwapi/trunk/inc/class.categories.inc.php
    people/sigurdne/modules/phpgwapi/trunk/inc/class.clientsniffer.inc.php
    people/sigurdne/modules/phpgwapi/trunk/inc/class.common.inc.php
    people/sigurdne/modules/phpgwapi/trunk/inc/class.config.inc.php
    people/sigurdne/modules/phpgwapi/trunk/inc/class.contact_accounts.inc.php
    people/sigurdne/modules/phpgwapi/trunk/inc/class.contact_addr.inc.php
    people/sigurdne/modules/phpgwapi/trunk/inc/class.contact_addr_type.inc.php
    people/sigurdne/modules/phpgwapi/trunk/inc/class.contact_categories.inc.php
    people/sigurdne/modules/phpgwapi/trunk/inc/class.contact_central.inc.php
    people/sigurdne/modules/phpgwapi/trunk/inc/class.contact_comm.inc.php
    people/sigurdne/modules/phpgwapi/trunk/inc/class.contact_comm_descr.inc.php
    people/sigurdne/modules/phpgwapi/trunk/inc/class.contact_comm_type.inc.php
    people/sigurdne/modules/phpgwapi/trunk/inc/class.contact_note.inc.php
    people/sigurdne/modules/phpgwapi/trunk/inc/class.contact_note_type.inc.php
    people/sigurdne/modules/phpgwapi/trunk/inc/class.contact_org.inc.php
    people/sigurdne/modules/phpgwapi/trunk/inc/class.contact_org_person.inc.php
    people/sigurdne/modules/phpgwapi/trunk/inc/class.contact_others.inc.php
    people/sigurdne/modules/phpgwapi/trunk/inc/class.contact_person.inc.php
    people/sigurdne/modules/phpgwapi/trunk/inc/class.contact_types.inc.php
    people/sigurdne/modules/phpgwapi/trunk/inc/class.contacts.inc.php
    people/sigurdne/modules/phpgwapi/trunk/inc/class.contacts_shared.inc.php
    people/sigurdne/modules/phpgwapi/trunk/inc/class.contacts_sql.inc.php
    people/sigurdne/modules/phpgwapi/trunk/inc/class.country.inc.php
    people/sigurdne/modules/phpgwapi/trunk/inc/class.crypto.inc.php
    people/sigurdne/modules/phpgwapi/trunk/inc/class.css.inc.php
    people/sigurdne/modules/phpgwapi/trunk/inc/class.csstooltip.inc.php
    people/sigurdne/modules/phpgwapi/trunk/inc/class.custom_fields.inc.php
    people/sigurdne/modules/phpgwapi/trunk/inc/class.data_cleaner.inc.php
    people/sigurdne/modules/phpgwapi/trunk/inc/class.datetime.inc.php
    people/sigurdne/modules/phpgwapi/trunk/inc/class.db.inc.php
    people/sigurdne/modules/phpgwapi/trunk/inc/class.error.inc.php
    people/sigurdne/modules/phpgwapi/trunk/inc/class.errorlog.inc.php
    people/sigurdne/modules/phpgwapi/trunk/inc/class.excel.inc.php
    people/sigurdne/modules/phpgwapi/trunk/inc/class.excelreader.inc.php
    people/sigurdne/modules/phpgwapi/trunk/inc/class.gdbutton.inc.php
    people/sigurdne/modules/phpgwapi/trunk/inc/class.gdgraph.inc.php
    people/sigurdne/modules/phpgwapi/trunk/inc/class.gdimage.inc.php
    people/sigurdne/modules/phpgwapi/trunk/inc/class.globally_denied.inc.php
    people/sigurdne/modules/phpgwapi/trunk/inc/class.historylog.inc.php
    people/sigurdne/modules/phpgwapi/trunk/inc/class.hooks.inc.php
    people/sigurdne/modules/phpgwapi/trunk/inc/class.html2text.inc.php
    people/sigurdne/modules/phpgwapi/trunk/inc/class.http.inc.php
    people/sigurdne/modules/phpgwapi/trunk/inc/class.http_dav_client.inc.php
    people/sigurdne/modules/phpgwapi/trunk/inc/class.http_svn_client.inc.php
    people/sigurdne/modules/phpgwapi/trunk/inc/class.interlink.inc.php
    people/sigurdne/modules/phpgwapi/trunk/inc/class.interserver.inc.php
    people/sigurdne/modules/phpgwapi/trunk/inc/class.ipc_.inc.php
    people/sigurdne/modules/phpgwapi/trunk/inc/class.ipc_manager.inc.php
    people/sigurdne/modules/phpgwapi/trunk/inc/class.js.inc.php
    people/sigurdne/modules/phpgwapi/trunk/inc/class.jscal.inc.php
    people/sigurdne/modules/phpgwapi/trunk/inc/class.jscalendar.inc.php
    people/sigurdne/modules/phpgwapi/trunk/inc/class.listbox.inc.php
    people/sigurdne/modules/phpgwapi/trunk/inc/class.locations.inc.php
    people/sigurdne/modules/phpgwapi/trunk/inc/class.log.inc.php
    people/sigurdne/modules/phpgwapi/trunk/inc/class.log_message.inc.php
    people/sigurdne/modules/phpgwapi/trunk/inc/class.mail2array.inc.php
    people/sigurdne/modules/phpgwapi/trunk/inc/class.mailer_smtp.inc.php
    people/sigurdne/modules/phpgwapi/trunk/inc/class.matrixview.inc.php
    people/sigurdne/modules/phpgwapi/trunk/inc/class.menu.inc.php
    people/sigurdne/modules/phpgwapi/trunk/inc/class.menu_apps.inc.php
    people/sigurdne/modules/phpgwapi/trunk/inc/class.menutree.inc.php
    people/sigurdne/modules/phpgwapi/trunk/inc/class.mime_magic.inc.php
    people/sigurdne/modules/phpgwapi/trunk/inc/class.net_http_client.inc.php
    people/sigurdne/modules/phpgwapi/trunk/inc/class.network.inc.php
    people/sigurdne/modules/phpgwapi/trunk/inc/class.nextmatchs.inc.php
    people/sigurdne/modules/phpgwapi/trunk/inc/class.nextmatchs_xslt.inc.php
    people/sigurdne/modules/phpgwapi/trunk/inc/class.object_factory.inc.php
    people/sigurdne/modules/phpgwapi/trunk/inc/class.ofphpgwapi.inc.php
    people/sigurdne/modules/phpgwapi/trunk/inc/class.pdf.inc.php
    people/sigurdne/modules/phpgwapi/trunk/inc/class.phpgw.inc.php
    people/sigurdne/modules/phpgwapi/trunk/inc/class.ping.inc.php
    people/sigurdne/modules/phpgwapi/trunk/inc/class.portalbox.inc.php
    people/sigurdne/modules/phpgwapi/trunk/inc/class.preferences.inc.php
    people/sigurdne/modules/phpgwapi/trunk/inc/class.resultbox.inc.php
    people/sigurdne/modules/phpgwapi/trunk/inc/class.richtext.inc.php
    people/sigurdne/modules/phpgwapi/trunk/inc/class.rssparser.inc.php
    people/sigurdne/modules/phpgwapi/trunk/inc/class.sbox.inc.php
    people/sigurdne/modules/phpgwapi/trunk/inc/class.sbox2.inc.php
    people/sigurdne/modules/phpgwapi/trunk/inc/class.schema_proc.inc.php
    people/sigurdne/modules/phpgwapi/trunk/inc/class.schema_proc_array.inc.php
    people/sigurdne/modules/phpgwapi/trunk/inc/class.schema_proc_mssql.inc.php
    people/sigurdne/modules/phpgwapi/trunk/inc/class.schema_proc_mysql.inc.php
    people/sigurdne/modules/phpgwapi/trunk/inc/class.schema_proc_oracle.inc.php
    people/sigurdne/modules/phpgwapi/trunk/inc/class.schema_proc_pgsql.inc.php
    people/sigurdne/modules/phpgwapi/trunk/inc/class.schema_proc_sapdb.inc.php
    people/sigurdne/modules/phpgwapi/trunk/inc/class.send.inc.php
    people/sigurdne/modules/phpgwapi/trunk/inc/class.service.inc.php
    people/sigurdne/modules/phpgwapi/trunk/inc/class.service_contacts.inc.php
    people/sigurdne/modules/phpgwapi/trunk/inc/class.service_notes.inc.php
    people/sigurdne/modules/phpgwapi/trunk/inc/class.service_schedule.inc.php
    people/sigurdne/modules/phpgwapi/trunk/inc/class.session_handler_db.inc.php
    people/sigurdne/modules/phpgwapi/trunk/inc/class.sessions.inc.php
    people/sigurdne/modules/phpgwapi/trunk/inc/class.setup.inc.php
    people/sigurdne/modules/phpgwapi/trunk/inc/class.setup_detection.inc.php
    people/sigurdne/modules/phpgwapi/trunk/inc/class.setup_html.inc.php
    people/sigurdne/modules/phpgwapi/trunk/inc/class.setup_process.inc.php
    people/sigurdne/modules/phpgwapi/trunk/inc/class.setup_translation.inc.php
    people/sigurdne/modules/phpgwapi/trunk/inc/class.shm.inc.php
    people/sigurdne/modules/phpgwapi/trunk/inc/class.soap_client.inc.php
    people/sigurdne/modules/phpgwapi/trunk/inc/class.sql.inc.php
    people/sigurdne/modules/phpgwapi/trunk/inc/class.sql_builder.inc.php
    people/sigurdne/modules/phpgwapi/trunk/inc/class.sql_criteria.inc.php
    people/sigurdne/modules/phpgwapi/trunk/inc/class.sql_entity.inc.php
    people/sigurdne/modules/phpgwapi/trunk/inc/class.translation.inc.php
    people/sigurdne/modules/phpgwapi/trunk/inc/class.ui_tools.inc.php
    people/sigurdne/modules/phpgwapi/trunk/inc/class.uijsaddressbook.inc.php
    people/sigurdne/modules/phpgwapi/trunk/inc/class.utilities.inc.php
    people/sigurdne/modules/phpgwapi/trunk/inc/class.validator.inc.php
    people/sigurdne/modules/phpgwapi/trunk/inc/class.vcard.inc.php
    people/sigurdne/modules/phpgwapi/trunk/inc/class.vfs.inc.php
    people/sigurdne/modules/phpgwapi/trunk/inc/class.vfs_dav.inc.php
    people/sigurdne/modules/phpgwapi/trunk/inc/class.vfs_shared.inc.php
    people/sigurdne/modules/phpgwapi/trunk/inc/class.vfs_sql.inc.php
    people/sigurdne/modules/phpgwapi/trunk/inc/class.xmlrpc_client.inc.php
    people/sigurdne/modules/phpgwapi/trunk/inc/class.xmltool.inc.php
    people/sigurdne/modules/phpgwapi/trunk/inc/class.xslttemplates.inc.php
    people/sigurdne/modules/phpgwapi/trunk/inc/class.yui.inc.php
    people/sigurdne/modules/phpgwapi/trunk/inc/common_functions.inc.php
    people/sigurdne/modules/phpgwapi/trunk/inc/footer.inc.php
    people/sigurdne/modules/phpgwapi/trunk/inc/functions.inc.php
    people/sigurdne/modules/phpgwapi/trunk/inc/phpmailer/ChangeLog.txt
    people/sigurdne/modules/phpgwapi/trunk/inc/phpmailer/README
    people/sigurdne/modules/phpgwapi/trunk/inc/phpmailer/class.phpmailer.php
    people/sigurdne/modules/phpgwapi/trunk/inc/phpmailer/class.smtp.php
    people/sigurdne/modules/phpgwapi/trunk/inc/phpmailer/docs/faq.html
    people/sigurdne/modules/phpgwapi/trunk/inc/phpmailer/language/phpmailer.lang-br.php
    people/sigurdne/modules/phpgwapi/trunk/inc/phpmailer/language/phpmailer.lang-ca.php
    people/sigurdne/modules/phpgwapi/trunk/inc/phpmailer/language/phpmailer.lang-cz.php
    people/sigurdne/modules/phpgwapi/trunk/inc/phpmailer/language/phpmailer.lang-de.php
    people/sigurdne/modules/phpgwapi/trunk/inc/phpmailer/language/phpmailer.lang-dk.php
    people/sigurdne/modules/phpgwapi/trunk/inc/phpmailer/language/phpmailer.lang-en.php
    people/sigurdne/modules/phpgwapi/trunk/inc/phpmailer/language/phpmailer.lang-es.php
    people/sigurdne/modules/phpgwapi/trunk/inc/phpmailer/language/phpmailer.lang-fi.php
    people/sigurdne/modules/phpgwapi/trunk/inc/phpmailer/language/phpmailer.lang-fo.php
    people/sigurdne/modules/phpgwapi/trunk/inc/phpmailer/language/phpmailer.lang-fr.php
    people/sigurdne/modules/phpgwapi/trunk/inc/phpmailer/language/phpmailer.lang-hu.php
    people/sigurdne/modules/phpgwapi/trunk/inc/phpmailer/language/phpmailer.lang-it.php
    people/sigurdne/modules/phpgwapi/trunk/inc/phpmailer/language/phpmailer.lang-ja.php
    people/sigurdne/modules/phpgwapi/trunk/inc/phpmailer/language/phpmailer.lang-nl.php
    people/sigurdne/modules/phpgwapi/trunk/inc/phpmailer/language/phpmailer.lang-no.php
    people/sigurdne/modules/phpgwapi/trunk/inc/phpmailer/language/phpmailer.lang-pl.php
    people/sigurdne/modules/phpgwapi/trunk/inc/phpmailer/language/phpmailer.lang-ro.php
    people/sigurdne/modules/phpgwapi/trunk/inc/phpmailer/language/phpmailer.lang-ru.php
    people/sigurdne/modules/phpgwapi/trunk/inc/phpmailer/language/phpmailer.lang-se.php
    people/sigurdne/modules/phpgwapi/trunk/inc/phpmailer/language/phpmailer.lang-tr.php
    people/sigurdne/modules/phpgwapi/trunk/inc/phpmailer/test/phpunit.php
    people/sigurdne/modules/phpgwapi/trunk/inc/soap_functions.inc.php
    people/sigurdne/modules/phpgwapi/trunk/inc/sso/create_account.php
    people/sigurdne/modules/phpgwapi/trunk/inc/sso/create_mapping.php
    people/sigurdne/modules/phpgwapi/trunk/inc/sso/include_login.inc.php
    people/sigurdne/modules/phpgwapi/trunk/inc/sso/login_server.php
    people/sigurdne/modules/phpgwapi/trunk/js/core/base.js
    people/sigurdne/modules/phpgwapi/trunk/js/sarissa/doc/DOMParser.html
    people/sigurdne/modules/phpgwapi/trunk/js/sarissa/doc/Document.html
    people/sigurdne/modules/phpgwapi/trunk/js/sarissa/doc/Element.html
    people/sigurdne/modules/phpgwapi/trunk/js/sarissa/doc/GLOBALS.html
    people/sigurdne/modules/phpgwapi/trunk/js/sarissa/doc/Sarissa.html
    people/sigurdne/modules/phpgwapi/trunk/js/sarissa/doc/XMLDocument.html
    people/sigurdne/modules/phpgwapi/trunk/js/sarissa/doc/XMLHttpRequest.html
    people/sigurdne/modules/phpgwapi/trunk/js/sarissa/doc/XMLSerializer.html
    people/sigurdne/modules/phpgwapi/trunk/js/sarissa/doc/XSLTProcessor.html
    people/sigurdne/modules/phpgwapi/trunk/js/tabs/tabs.js
    people/sigurdne/modules/phpgwapi/trunk/setup/default_records.inc.php
    people/sigurdne/modules/phpgwapi/trunk/setup/phpgw_nl.lang
    people/sigurdne/modules/phpgwapi/trunk/setup/phpgw_no.lang
    people/sigurdne/modules/phpgwapi/trunk/setup/phpgw_sv.lang
    people/sigurdne/modules/phpgwapi/trunk/setup/setup.inc.php
    people/sigurdne/modules/phpgwapi/trunk/setup/tables_current.inc.php
    people/sigurdne/modules/phpgwapi/trunk/setup/tables_update.inc.php
    people/sigurdne/modules/phpgwapi/trunk/templates/base/categories.xsl
    people/sigurdne/modules/phpgwapi/trunk/templates/base/config.tpl
    people/sigurdne/modules/phpgwapi/trunk/templates/base/css/base.css
    people/sigurdne/modules/phpgwapi/trunk/templates/base/css/login.css
    people/sigurdne/modules/phpgwapi/trunk/templates/base/login.tpl
    people/sigurdne/modules/phpgwapi/trunk/templates/base/msgbox.xsl
    people/sigurdne/modules/phpgwapi/trunk/templates/base/nextmatchs.tpl
    people/sigurdne/modules/phpgwapi/trunk/templates/base/nextmatchs.xsl
    people/sigurdne/modules/phpgwapi/trunk/templates/desktop/css/desktop.css
    people/sigurdne/modules/phpgwapi/trunk/templates/desktop/head.inc.php
    people/sigurdne/modules/phpgwapi/trunk/templates/desktop/navbar.inc.php
    people/sigurdne/modules/phpgwapi/trunk/templates/idots/css/idots.css
    people/sigurdne/modules/phpgwapi/trunk/templates/idots/head.inc.php
    people/sigurdne/modules/phpgwapi/trunk/templates/idots/navbar.inc.php
    people/sigurdne/modules/phpgwapi/trunk/templates/idots/navbar.tpl
    people/sigurdne/modules/phpgwapi/trunk/templates/idsociety/css/base.css
    people/sigurdne/modules/phpgwapi/trunk/templates/idsociety/navbar.inc.php
    people/sigurdne/modules/phpgwapi/trunk/templates/linux-at-work.de/css/base.css
    people/sigurdne/modules/phpgwapi/trunk/templates/linux-at-work.de/navbar.inc.php
    people/sigurdne/modules/phpgwapi/trunk/templates/probusiness/css/styles.css
    people/sigurdne/modules/phpgwapi/trunk/templates/probusiness/head.inc.php
    people/sigurdne/modules/phpgwapi/trunk/templates/probusiness/head.tpl
    people/sigurdne/modules/phpgwapi/trunk/templates/probusiness/navbar.inc.php
    people/sigurdne/modules/phpgwapi/trunk/templates/simple/css/simple.css
    people/sigurdne/modules/phpgwapi/trunk/templates/simple/head.inc.php
    people/sigurdne/modules/phpgwapi/trunk/templates/simple/head.tpl
    people/sigurdne/modules/phpgwapi/trunk/templates/simple/navbar.inc.php
    people/sigurdne/modules/phpgwapi/trunk/templates/verdilak/css/styles.css
    people/sigurdne/modules/phpgwapi/trunk/templates/verdilak/head.inc.php
    people/sigurdne/modules/phpgwapi/trunk/templates/verdilak/navbar.inc.php
    people/sigurdne/modules/phpgwapi/trunk/templates/verdilak/navbar.tpl

Added Paths:
-----------
    people/sigurdne/modules/phpgwapi/trunk/inc/class.Services_JSON.inc.php
    people/sigurdne/modules/phpgwapi/trunk/inc/class.accounts_popup.inc.php
    people/sigurdne/modules/phpgwapi/trunk/inc/class.custom_functions.inc.php
    people/sigurdne/modules/phpgwapi/trunk/inc/class.ms_exchange.inc.php
    people/sigurdne/modules/phpgwapi/trunk/inc/class.pclzip.inc.php
    people/sigurdne/modules/phpgwapi/trunk/inc/class.template_portico.inc.php
    people/sigurdne/modules/phpgwapi/trunk/inc/class.xml.inc.php
    people/sigurdne/modules/phpgwapi/trunk/inc/class.yuical.inc.php
    people/sigurdne/modules/phpgwapi/trunk/inc/exchange/
    people/sigurdne/modules/phpgwapi/trunk/inc/exchange/class_http.php
    people/sigurdne/modules/phpgwapi/trunk/inc/exchange/class_xml.php
    people/sigurdne/modules/phpgwapi/trunk/inc/exchange/example.php
    people/sigurdne/modules/phpgwapi/trunk/inc/exchange/example_xml.php
    people/sigurdne/modules/phpgwapi/trunk/inc/exchange/image_cache.php
    people/sigurdne/modules/phpgwapi/trunk/inc/exchange/rss_example.php
    people/sigurdne/modules/phpgwapi/trunk/inc/exchange/sample.xml
    people/sigurdne/modules/phpgwapi/trunk/inc/phpmailer/class.pop3.php
    people/sigurdne/modules/phpgwapi/trunk/inc/phpmailer/codeworxtech.html
    people/sigurdne/modules/phpgwapi/trunk/inc/phpmailer/docs/pop3_article.txt
    people/sigurdne/modules/phpgwapi/trunk/inc/phpmailer/docs/use_gmail.txt
    people/sigurdne/modules/phpgwapi/trunk/inc/phpmailer/examples/
    people/sigurdne/modules/phpgwapi/trunk/inc/phpmailer/examples/contents.html
    people/sigurdne/modules/phpgwapi/trunk/inc/phpmailer/examples/images/
    people/sigurdne/modules/phpgwapi/trunk/inc/phpmailer/examples/images/bkgrnd.gif
    people/sigurdne/modules/phpgwapi/trunk/inc/phpmailer/examples/images/phpmailer.gif
    people/sigurdne/modules/phpgwapi/trunk/inc/phpmailer/examples/images/phpmailer.png
    people/sigurdne/modules/phpgwapi/trunk/inc/phpmailer/examples/images/phpmailer_mini.gif
    people/sigurdne/modules/phpgwapi/trunk/inc/phpmailer/examples/index.html
    people/sigurdne/modules/phpgwapi/trunk/inc/phpmailer/examples/pop3_before_smtp_test.php
    people/sigurdne/modules/phpgwapi/trunk/inc/phpmailer/examples/test_gmail.php
    people/sigurdne/modules/phpgwapi/trunk/inc/phpmailer/examples/test_mail.php
    people/sigurdne/modules/phpgwapi/trunk/inc/phpmailer/examples/test_sendmail.php
    people/sigurdne/modules/phpgwapi/trunk/inc/phpmailer/examples/test_smtp.php
    people/sigurdne/modules/phpgwapi/trunk/inc/phpmailer/language/phpmailer.lang-et.php
    people/sigurdne/modules/phpgwapi/trunk/js/core/formatdate.js
    people/sigurdne/modules/phpgwapi/trunk/js/fckeditor/
    people/sigurdne/modules/phpgwapi/trunk/js/fckeditor/_documentation.html
    people/sigurdne/modules/phpgwapi/trunk/js/fckeditor/_samples/
    people/sigurdne/modules/phpgwapi/trunk/js/fckeditor/_samples/_plugins/
    people/sigurdne/modules/phpgwapi/trunk/js/fckeditor/_samples/_plugins/findreplace/
    people/sigurdne/modules/phpgwapi/trunk/js/fckeditor/_samples/_plugins/findreplace/fckplugin.js
    people/sigurdne/modules/phpgwapi/trunk/js/fckeditor/_samples/_plugins/findreplace/find.gif
    people/sigurdne/modules/phpgwapi/trunk/js/fckeditor/_samples/_plugins/findreplace/find.html
    people/sigurdne/modules/phpgwapi/trunk/js/fckeditor/_samples/_plugins/findreplace/lang/
    people/sigurdne/modules/phpgwapi/trunk/js/fckeditor/_samples/_plugins/findreplace/lang/en.js
    people/sigurdne/modules/phpgwapi/trunk/js/fckeditor/_samples/_plugins/findreplace/lang/fr.js
    people/sigurdne/modules/phpgwapi/trunk/js/fckeditor/_samples/_plugins/findreplace/lang/it.js
    people/sigurdne/modules/phpgwapi/trunk/js/fckeditor/_samples/_plugins/findreplace/replace.gif
    people/sigurdne/modules/phpgwapi/trunk/js/fckeditor/_samples/_plugins/findreplace/replace.html
    people/sigurdne/modules/phpgwapi/trunk/js/fckeditor/_samples/_plugins/samples/
    people/sigurdne/modules/phpgwapi/trunk/js/fckeditor/_samples/_plugins/samples/fckplugin.js
    people/sigurdne/modules/phpgwapi/trunk/js/fckeditor/_samples/default.html
    people/sigurdne/modules/phpgwapi/trunk/js/fckeditor/_samples/html/
    people/sigurdne/modules/phpgwapi/trunk/js/fckeditor/_samples/html/sample01.html
    people/sigurdne/modules/phpgwapi/trunk/js/fckeditor/_samples/html/sample02.html
    people/sigurdne/modules/phpgwapi/trunk/js/fckeditor/_samples/html/sample03.html
    people/sigurdne/modules/phpgwapi/trunk/js/fckeditor/_samples/html/sample04.html
    people/sigurdne/modules/phpgwapi/trunk/js/fckeditor/_samples/html/sample05.html
    people/sigurdne/modules/phpgwapi/trunk/js/fckeditor/_samples/html/sample06.config.js
    people/sigurdne/modules/phpgwapi/trunk/js/fckeditor/_samples/html/sample06.html
    people/sigurdne/modules/phpgwapi/trunk/js/fckeditor/_samples/html/sample07.html
    people/sigurdne/modules/phpgwapi/trunk/js/fckeditor/_samples/html/sample08.html
    people/sigurdne/modules/phpgwapi/trunk/js/fckeditor/_samples/html/sample09.html
    people/sigurdne/modules/phpgwapi/trunk/js/fckeditor/_samples/html/sample10.html
    people/sigurdne/modules/phpgwapi/trunk/js/fckeditor/_samples/html/sample11.html
    people/sigurdne/modules/phpgwapi/trunk/js/fckeditor/_samples/html/sample11_frame.html
    people/sigurdne/modules/phpgwapi/trunk/js/fckeditor/_samples/html/sampleposteddata.asp
    people/sigurdne/modules/phpgwapi/trunk/js/fckeditor/_samples/html/sampleposteddata.html
    people/sigurdne/modules/phpgwapi/trunk/js/fckeditor/_samples/sample.css
    people/sigurdne/modules/phpgwapi/trunk/js/fckeditor/_samples/sampleslist.html
    people/sigurdne/modules/phpgwapi/trunk/js/fckeditor/_testcases/
    people/sigurdne/modules/phpgwapi/trunk/js/fckeditor/_testcases/001.html
    people/sigurdne/modules/phpgwapi/trunk/js/fckeditor/_testcases/002.html
    people/sigurdne/modules/phpgwapi/trunk/js/fckeditor/_testcases/003.html
    people/sigurdne/modules/phpgwapi/trunk/js/fckeditor/_testcases/004.html
    people/sigurdne/modules/phpgwapi/trunk/js/fckeditor/_testcases/005.html
    people/sigurdne/modules/phpgwapi/trunk/js/fckeditor/_testcases/006.html
    people/sigurdne/modules/phpgwapi/trunk/js/fckeditor/_testcases/007.html
    people/sigurdne/modules/phpgwapi/trunk/js/fckeditor/_testcases/008.html
    people/sigurdne/modules/phpgwapi/trunk/js/fckeditor/_testcases/009.html
    people/sigurdne/modules/phpgwapi/trunk/js/fckeditor/_testcases/010.html
    people/sigurdne/modules/phpgwapi/trunk/js/fckeditor/_testcases/sampleposteddata.asp
    people/sigurdne/modules/phpgwapi/trunk/js/fckeditor/_testcases/testcases.css
    people/sigurdne/modules/phpgwapi/trunk/js/fckeditor/_whatsnew.html
    people/sigurdne/modules/phpgwapi/trunk/js/fckeditor/editor/
    people/sigurdne/modules/phpgwapi/trunk/js/fckeditor/editor/_source/
    people/sigurdne/modules/phpgwapi/trunk/js/fckeditor/editor/_source/classes/
    people/sigurdne/modules/phpgwapi/trunk/js/fckeditor/editor/_source/classes/fckcontextmenu.js
    people/sigurdne/modules/phpgwapi/trunk/js/fckeditor/editor/_source/classes/fckcontextmenugroup.js
    people/sigurdne/modules/phpgwapi/trunk/js/fckeditor/editor/_source/classes/fckcontextmenuitem.js
    people/sigurdne/modules/phpgwapi/trunk/js/fckeditor/editor/_source/classes/fckcontextmenuseparator.js
    people/sigurdne/modules/phpgwapi/trunk/js/fckeditor/editor/_source/classes/fckeditingarea.js
    people/sigurdne/modules/phpgwapi/trunk/js/fckeditor/editor/_source/classes/fckevents.js
    people/sigurdne/modules/phpgwapi/trunk/js/fckeditor/editor/_source/classes/fckicon.js
    people/sigurdne/modules/phpgwapi/trunk/js/fckeditor/editor/_source/classes/fckiecleanup.js
    people/sigurdne/modules/phpgwapi/trunk/js/fckeditor/editor/_source/classes/fckmenublock.js
    people/sigurdne/modules/phpgwapi/trunk/js/fckeditor/editor/_source/classes/fckmenublockpanel.js
    people/sigurdne/modules/phpgwapi/trunk/js/fckeditor/editor/_source/classes/fckmenuitem.js
    people/sigurdne/modules/phpgwapi/trunk/js/fckeditor/editor/_source/classes/fckpanel.js
    people/sigurdne/modules/phpgwapi/trunk/js/fckeditor/editor/_source/classes/fckpanel_gecko.js
    people/sigurdne/modules/phpgwapi/trunk/js/fckeditor/editor/_source/classes/fckpanel_ie.js
    people/sigurdne/modules/phpgwapi/trunk/js/fckeditor/editor/_source/classes/fckplugin.js
    people/sigurdne/modules/phpgwapi/trunk/js/fckeditor/editor/_source/classes/fckspecialcombo.js
    people/sigurdne/modules/phpgwapi/trunk/js/fckeditor/editor/_source/classes/fckstyledef.js
    people/sigurdne/modules/phpgwapi/trunk/js/fckeditor/editor/_source/classes/fckstyledef_gecko.js
    people/sigurdne/modules/phpgwapi/trunk/js/fckeditor/editor/_source/classes/fckstyledef_ie.js
    people/sigurdne/modules/phpgwapi/trunk/js/fckeditor/editor/_source/classes/fckstylesloader.js
    people/sigurdne/modules/phpgwapi/trunk/js/fckeditor/editor/_source/classes/fcktoolbar.js
    people/sigurdne/modules/phpgwapi/trunk/js/fckeditor/editor/_source/classes/fcktoolbarbreak_gecko.js
    people/sigurdne/modules/phpgwapi/trunk/js/fckeditor/editor/_source/classes/fcktoolbarbreak_ie.js
    people/sigurdne/modules/phpgwapi/trunk/js/fckeditor/editor/_source/classes/fcktoolbarbutton.js
    people/sigurdne/modules/phpgwapi/trunk/js/fckeditor/editor/_source/classes/fcktoolbarbuttonui.js
    people/sigurdne/modules/phpgwapi/trunk/js/fckeditor/editor/_source/classes/fcktoolbarfontformatcombo.js
    people/sigurdne/modules/phpgwapi/trunk/js/fckeditor/editor/_source/classes/fcktoolbarfontscombo.js
    people/sigurdne/modules/phpgwapi/trunk/js/fckeditor/editor/_source/classes/fcktoolbarfontsizecombo.js
    people/sigurdne/modules/phpgwapi/trunk/js/fckeditor/editor/_source/classes/fcktoolbarpanelbutton.js
    people/sigurdne/modules/phpgwapi/trunk/js/fckeditor/editor/_source/classes/fcktoolbarspecialcombo.js
    people/sigurdne/modules/phpgwapi/trunk/js/fckeditor/editor/_source/classes/fcktoolbarstylecombo.js
    people/sigurdne/modules/phpgwapi/trunk/js/fckeditor/editor/_source/classes/fckxml_gecko.js
    people/sigurdne/modules/phpgwapi/trunk/js/fckeditor/editor/_source/classes/fckxml_ie.js
    people/sigurdne/modules/phpgwapi/trunk/js/fckeditor/editor/_source/commandclasses/
    people/sigurdne/modules/phpgwapi/trunk/js/fckeditor/editor/_source/commandclasses/fck_othercommands.js
    people/sigurdne/modules/phpgwapi/trunk/js/fckeditor/editor/_source/commandclasses/fckfitwindow.js
    people/sigurdne/modules/phpgwapi/trunk/js/fckeditor/editor/_source/commandclasses/fcknamedcommand.js
    people/sigurdne/modules/phpgwapi/trunk/js/fckeditor/editor/_source/commandclasses/fckpasteplaintextcommand.js
    people/sigurdne/modules/phpgwapi/trunk/js/fckeditor/editor/_source/commandclasses/fckpastewordcommand.js
    people/sigurdne/modules/phpgwapi/trunk/js/fckeditor/editor/_source/commandclasses/fckspellcheckcommand_gecko.js
    people/sigurdne/modules/phpgwapi/trunk/js/fckeditor/editor/_source/commandclasses/fckspellcheckcommand_ie.js
    people/sigurdne/modules/phpgwapi/trunk/js/fckeditor/editor/_source/commandclasses/fckstylecommand.js
    people/sigurdne/modules/phpgwapi/trunk/js/fckeditor/editor/_source/commandclasses/fcktablecommand.js
    people/sigurdne/modules/phpgwapi/trunk/js/fckeditor/editor/_source/commandclasses/fcktextcolorcommand.js
    people/sigurdne/modules/phpgwapi/trunk/js/fckeditor/editor/_source/globals/
    people/sigurdne/modules/phpgwapi/trunk/js/fckeditor/editor/_source/globals/fck_constants.js
    people/sigurdne/modules/phpgwapi/trunk/js/fckeditor/editor/_source/globals/fckeditorapi.js
    people/sigurdne/modules/phpgwapi/trunk/js/fckeditor/editor/_source/internals/
    people/sigurdne/modules/phpgwapi/trunk/js/fckeditor/editor/_source/internals/fck.js
    people/sigurdne/modules/phpgwapi/trunk/js/fckeditor/editor/_source/internals/fck_1.js
    people/sigurdne/modules/phpgwapi/trunk/js/fckeditor/editor/_source/internals/fck_1_gecko.js
    people/sigurdne/modules/phpgwapi/trunk/js/fckeditor/editor/_source/internals/fck_1_ie.js
    people/sigurdne/modules/phpgwapi/trunk/js/fckeditor/editor/_source/internals/fck_2.js
    people/sigurdne/modules/phpgwapi/trunk/js/fckeditor/editor/_source/internals/fck_2_gecko.js
    people/sigurdne/modules/phpgwapi/trunk/js/fckeditor/editor/_source/internals/fck_2_ie.js
    people/sigurdne/modules/phpgwapi/trunk/js/fckeditor/editor/_source/internals/fck_contextmenu.js
    people/sigurdne/modules/phpgwapi/trunk/js/fckeditor/editor/_source/internals/fck_last.js
    people/sigurdne/modules/phpgwapi/trunk/js/fckeditor/editor/_source/internals/fck_onload.js
    people/sigurdne/modules/phpgwapi/trunk/js/fckeditor/editor/_source/internals/fckbrowserinfo.js
    people/sigurdne/modules/phpgwapi/trunk/js/fckeditor/editor/_source/internals/fckcodeformatter.js
    people/sigurdne/modules/phpgwapi/trunk/js/fckeditor/editor/_source/internals/fckcommands.js
    people/sigurdne/modules/phpgwapi/trunk/js/fckeditor/editor/_source/internals/fckconfig.js
    people/sigurdne/modules/phpgwapi/trunk/js/fckeditor/editor/_source/internals/fckcontextmenu.js
    people/sigurdne/modules/phpgwapi/trunk/js/fckeditor/editor/_source/internals/fckcoreextensions.js
    people/sigurdne/modules/phpgwapi/trunk/js/fckeditor/editor/_source/internals/fckdebug.js
    people/sigurdne/modules/phpgwapi/trunk/js/fckeditor/editor/_source/internals/fckdialog.js
    people/sigurdne/modules/phpgwapi/trunk/js/fckeditor/editor/_source/internals/fckdialog_gecko.js
    people/sigurdne/modules/phpgwapi/trunk/js/fckeditor/editor/_source/internals/fckdialog_ie.js
    people/sigurdne/modules/phpgwapi/trunk/js/fckeditor/editor/_source/internals/fckdocumentprocessor.js
    people/sigurdne/modules/phpgwapi/trunk/js/fckeditor/editor/_source/internals/fcklanguagemanager.js
    people/sigurdne/modules/phpgwapi/trunk/js/fckeditor/editor/_source/internals/fcknamespace.js
    people/sigurdne/modules/phpgwapi/trunk/js/fckeditor/editor/_source/internals/fckplugins.js
    people/sigurdne/modules/phpgwapi/trunk/js/fckeditor/editor/_source/internals/fckregexlib.js
    people/sigurdne/modules/phpgwapi/trunk/js/fckeditor/editor/_source/internals/fckscriptloader.js
    people/sigurdne/modules/phpgwapi/trunk/js/fckeditor/editor/_source/internals/fckselection.js
    people/sigurdne/modules/phpgwapi/trunk/js/fckeditor/editor/_source/internals/fckselection_gecko.js
    people/sigurdne/modules/phpgwapi/trunk/js/fckeditor/editor/_source/internals/fckselection_ie.js
    people/sigurdne/modules/phpgwapi/trunk/js/fckeditor/editor/_source/internals/fcktablehandler.js
    people/sigurdne/modules/phpgwapi/trunk/js/fckeditor/editor/_source/internals/fcktablehandler_gecko.js
    people/sigurdne/modules/phpgwapi/trunk/js/fckeditor/editor/_source/internals/fcktablehandler_ie.js
    people/sigurdne/modules/phpgwapi/trunk/js/fckeditor/editor/_source/internals/fcktoolbaritems.js
    people/sigurdne/modules/phpgwapi/trunk/js/fckeditor/editor/_source/internals/fcktoolbarset.js
    people/sigurdne/modules/phpgwapi/trunk/js/fckeditor/editor/_source/internals/fcktools.js
    people/sigurdne/modules/phpgwapi/trunk/js/fckeditor/editor/_source/internals/fcktools_gecko.js
    people/sigurdne/modules/phpgwapi/trunk/js/fckeditor/editor/_source/internals/fcktools_ie.js
    people/sigurdne/modules/phpgwapi/trunk/js/fckeditor/editor/_source/internals/fckundo_gecko.js
    people/sigurdne/modules/phpgwapi/trunk/js/fckeditor/editor/_source/internals/fckundo_ie.js
    people/sigurdne/modules/phpgwapi/trunk/js/fckeditor/editor/_source/internals/fckurlparams.js
    people/sigurdne/modules/phpgwapi/trunk/js/fckeditor/editor/_source/internals/fckxhtml.js
    people/sigurdne/modules/phpgwapi/trunk/js/fckeditor/editor/_source/internals/fckxhtml_gecko.js
    people/sigurdne/modules/phpgwapi/trunk/js/fckeditor/editor/_source/internals/fckxhtml_ie.js
    people/sigurdne/modules/phpgwapi/trunk/js/fckeditor/editor/_source/internals/fckxhtmlentities.js
    people/sigurdne/modules/phpgwapi/trunk/js/fckeditor/editor/css/
    people/sigurdne/modules/phpgwapi/trunk/js/fckeditor/editor/css/behaviors/
    people/sigurdne/modules/phpgwapi/trunk/js/fckeditor/editor/css/behaviors/disablehandles.htc
    people/sigurdne/modules/phpgwapi/trunk/js/fckeditor/editor/css/behaviors/hiddenfield.gif
    people/sigurdne/modules/phpgwapi/trunk/js/fckeditor/editor/css/behaviors/hiddenfield.htc
    people/sigurdne/modules/phpgwapi/trunk/js/fckeditor/editor/css/behaviors/showtableborders.htc
    people/sigurdne/modules/phpgwapi/trunk/js/fckeditor/editor/css/fck_editorarea.css
    people/sigurdne/modules/phpgwapi/trunk/js/fckeditor/editor/css/fck_internal.css
    people/sigurdne/modules/phpgwapi/trunk/js/fckeditor/editor/css/fck_showtableborders_gecko.css
    people/sigurdne/modules/phpgwapi/trunk/js/fckeditor/editor/css/images/
    people/sigurdne/modules/phpgwapi/trunk/js/fckeditor/editor/css/images/fck_anchor.gif
    people/sigurdne/modules/phpgwapi/trunk/js/fckeditor/editor/css/images/fck_flashlogo.gif
    people/sigurdne/modules/phpgwapi/trunk/js/fckeditor/editor/css/images/fck_pagebreak.gif
    people/sigurdne/modules/phpgwapi/trunk/js/fckeditor/editor/dialog/
    people/sigurdne/modules/phpgwapi/trunk/js/fckeditor/editor/dialog/common/
    people/sigurdne/modules/phpgwapi/trunk/js/fckeditor/editor/dialog/common/fck_dialog_common.css
    people/sigurdne/modules/phpgwapi/trunk/js/fckeditor/editor/dialog/common/fck_dialog_common.js
    people/sigurdne/modules/phpgwapi/trunk/js/fckeditor/editor/dialog/common/fcknumericfield.htc
    people/sigurdne/modules/phpgwapi/trunk/js/fckeditor/editor/dialog/common/images/
    people/sigurdne/modules/phpgwapi/trunk/js/fckeditor/editor/dialog/common/images/locked.gif
    people/sigurdne/modules/phpgwapi/trunk/js/fckeditor/editor/dialog/common/images/reset.gif
    people/sigurdne/modules/phpgwapi/trunk/js/fckeditor/editor/dialog/common/images/unlocked.gif
    people/sigurdne/modules/phpgwapi/trunk/js/fckeditor/editor/dialog/common/moz-bindings.xml
    people/sigurdne/modules/phpgwapi/trunk/js/fckeditor/editor/dialog/fck_about/
    people/sigurdne/modules/phpgwapi/trunk/js/fckeditor/editor/dialog/fck_about/lgpl.html
    people/sigurdne/modules/phpgwapi/trunk/js/fckeditor/editor/dialog/fck_about/logo_fckeditor.gif
    people/sigurdne/modules/phpgwapi/trunk/js/fckeditor/editor/dialog/fck_about/logo_fredck.gif
    people/sigurdne/modules/phpgwapi/trunk/js/fckeditor/editor/dialog/fck_about.html
    people/sigurdne/modules/phpgwapi/trunk/js/fckeditor/editor/dialog/fck_anchor.html
    people/sigurdne/modules/phpgwapi/trunk/js/fckeditor/editor/dialog/fck_button.html
    people/sigurdne/modules/phpgwapi/trunk/js/fckeditor/editor/dialog/fck_checkbox.html
    people/sigurdne/modules/phpgwapi/trunk/js/fckeditor/editor/dialog/fck_colorselector.html
    people/sigurdne/modules/phpgwapi/trunk/js/fckeditor/editor/dialog/fck_docprops/
    people/sigurdne/modules/phpgwapi/trunk/js/fckeditor/editor/dialog/fck_docprops/fck_document_preview.html
    people/sigurdne/modules/phpgwapi/trunk/js/fckeditor/editor/dialog/fck_docprops.html
    people/sigurdne/modules/phpgwapi/trunk/js/fckeditor/editor/dialog/fck_find.html
    people/sigurdne/modules/phpgwapi/trunk/js/fckeditor/editor/dialog/fck_flash/
    people/sigurdne/modules/phpgwapi/trunk/js/fckeditor/editor/dialog/fck_flash/fck_flash.js
    people/sigurdne/modules/phpgwapi/trunk/js/fckeditor/editor/dialog/fck_flash/fck_flash_preview.html
    people/sigurdne/modules/phpgwapi/trunk/js/fckeditor/editor/dialog/fck_flash.html
    people/sigurdne/modules/phpgwapi/trunk/js/fckeditor/editor/dialog/fck_form.html
    people/sigurdne/modules/phpgwapi/trunk/js/fckeditor/editor/dialog/fck_hiddenfield.html
    people/sigurdne/modules/phpgwapi/trunk/js/fckeditor/editor/dialog/fck_image/
    people/sigurdne/modules/phpgwapi/trunk/js/fckeditor/editor/dialog/fck_image/fck_image.js
    people/sigurdne/modules/phpgwapi/trunk/js/fckeditor/editor/dialog/fck_image/fck_image_preview.html
    people/sigurdne/modules/phpgwapi/trunk/js/fckeditor/editor/dialog/fck_image.html
    people/sigurdne/modules/phpgwapi/trunk/js/fckeditor/editor/dialog/fck_link/
    people/sigurdne/modules/phpgwapi/trunk/js/fckeditor/editor/dialog/fck_link/fck_link.js
    people/sigurdne/modules/phpgwapi/trunk/js/fckeditor/editor/dialog/fck_link.html
    people/sigurdne/modules/phpgwapi/trunk/js/fckeditor/editor/dialog/fck_listprop.html
    people/sigurdne/modules/phpgwapi/trunk/js/fckeditor/editor/dialog/fck_paste.html
    people/sigurdne/modules/phpgwapi/trunk/js/fckeditor/editor/dialog/fck_radiobutton.html
    people/sigurdne/modules/phpgwapi/trunk/js/fckeditor/editor/dialog/fck_replace.html
    people/sigurdne/modules/phpgwapi/trunk/js/fckeditor/editor/dialog/fck_select/
    people/sigurdne/modules/phpgwapi/trunk/js/fckeditor/editor/dialog/fck_select/fck_select.js
    people/sigurdne/modules/phpgwapi/trunk/js/fckeditor/editor/dialog/fck_select.html
    people/sigurdne/modules/phpgwapi/trunk/js/fckeditor/editor/dialog/fck_smiley.html
    people/sigurdne/modules/phpgwapi/trunk/js/fckeditor/editor/dialog/fck_source.html
    people/sigurdne/modules/phpgwapi/trunk/js/fckeditor/editor/dialog/fck_specialchar.html
    people/sigurdne/modules/phpgwapi/trunk/js/fckeditor/editor/dialog/fck_spellerpages/
    people/sigurdne/modules/phpgwapi/trunk/js/fckeditor/editor/dialog/fck_spellerpages/spellerpages/
    people/sigurdne/modules/phpgwapi/trunk/js/fckeditor/editor/dialog/fck_spellerpages/spellerpages/controlWindow.js
    people/sigurdne/modules/phpgwapi/trunk/js/fckeditor/editor/dialog/fck_spellerpages/spellerpages/controls.html
    people/sigurdne/modules/phpgwapi/trunk/js/fckeditor/editor/dialog/fck_spellerpages/spellerpages/server-scripts/
    people/sigurdne/modules/phpgwapi/trunk/js/fckeditor/editor/dialog/fck_spellerpages/spellerpages/server-scripts/spellchecker.cfm
    people/sigurdne/modules/phpgwapi/trunk/js/fckeditor/editor/dialog/fck_spellerpages/spellerpages/server-scripts/spellchecker.php
    people/sigurdne/modules/phpgwapi/trunk/js/fckeditor/editor/dialog/fck_spellerpages/spellerpages/server-scripts/spellchecker.pl
    people/sigurdne/modules/phpgwapi/trunk/js/fckeditor/editor/dialog/fck_spellerpages/spellerpages/spellChecker.js
    people/sigurdne/modules/phpgwapi/trunk/js/fckeditor/editor/dialog/fck_spellerpages/spellerpages/spellchecker.html
    people/sigurdne/modules/phpgwapi/trunk/js/fckeditor/editor/dialog/fck_spellerpages/spellerpages/spellerStyle.css
    people/sigurdne/modules/phpgwapi/trunk/js/fckeditor/editor/dialog/fck_spellerpages/spellerpages/wordWindow.js
    people/sigurdne/modules/phpgwapi/trunk/js/fckeditor/editor/dialog/fck_spellerpages.html
    people/sigurdne/modules/phpgwapi/trunk/js/fckeditor/editor/dialog/fck_table.html
    people/sigurdne/modules/phpgwapi/trunk/js/fckeditor/editor/dialog/fck_tablecell.html
    people/sigurdne/modules/phpgwapi/trunk/js/fckeditor/editor/dialog/fck_template/
    people/sigurdne/modules/phpgwapi/trunk/js/fckeditor/editor/dialog/fck_template/images/
    people/sigurdne/modules/phpgwapi/trunk/js/fckeditor/editor/dialog/fck_template/images/template1.gif
    people/sigurdne/modules/phpgwapi/trunk/js/fckeditor/editor/dialog/fck_template/images/template2.gif
    people/sigurdne/modules/phpgwapi/trunk/js/fckeditor/editor/dialog/fck_template/images/template3.gif
    people/sigurdne/modules/phpgwapi/trunk/js/fckeditor/editor/dialog/fck_template.html
    people/sigurdne/modules/phpgwapi/trunk/js/fckeditor/editor/dialog/fck_textarea.html
    people/sigurdne/modules/phpgwapi/trunk/js/fckeditor/editor/dialog/fck_textfield.html
    people/sigurdne/modules/phpgwapi/trunk/js/fckeditor/editor/dialog/fck_universalkey/
    people/sigurdne/modules/phpgwapi/trunk/js/fckeditor/editor/dialog/fck_universalkey/00.gif
    people/sigurdne/modules/phpgwapi/trunk/js/fckeditor/editor/dialog/fck_universalkey/data.js
    people/sigurdne/modules/phpgwapi/trunk/js/fckeditor/editor/dialog/fck_universalkey/diacritic.js
    people/sigurdne/modules/phpgwapi/trunk/js/fckeditor/editor/dialog/fck_universalkey/dialogue.js
    people/sigurdne/modules/phpgwapi/trunk/js/fckeditor/editor/dialog/fck_universalkey/fck_universalkey.css
    people/sigurdne/modules/phpgwapi/trunk/js/fckeditor/editor/dialog/fck_universalkey/keyboard_layout.gif
    people/sigurdne/modules/phpgwapi/trunk/js/fckeditor/editor/dialog/fck_universalkey/multihexa.js
    people/sigurdne/modules/phpgwapi/trunk/js/fckeditor/editor/dialog/fck_universalkey.html
    people/sigurdne/modules/phpgwapi/trunk/js/fckeditor/editor/fckblank.html
    people/sigurdne/modules/phpgwapi/trunk/js/fckeditor/editor/fckdebug.html
    people/sigurdne/modules/phpgwapi/trunk/js/fckeditor/editor/fckdialog.html
    people/sigurdne/modules/phpgwapi/trunk/js/fckeditor/editor/fckdocument.html
    people/sigurdne/modules/phpgwapi/trunk/js/fckeditor/editor/fckeditor.html
    people/sigurdne/modules/phpgwapi/trunk/js/fckeditor/editor/fckeditor.original.html
    people/sigurdne/modules/phpgwapi/trunk/js/fckeditor/editor/filemanager/
    people/sigurdne/modules/phpgwapi/trunk/js/fckeditor/editor/filemanager/browser/
    people/sigurdne/modules/phpgwapi/trunk/js/fckeditor/editor/filemanager/browser/default/
    people/sigurdne/modules/phpgwapi/trunk/js/fckeditor/editor/filemanager/browser/default/browser.css
    people/sigurdne/modules/phpgwapi/trunk/js/fckeditor/editor/filemanager/browser/default/browser.html
    people/sigurdne/modules/phpgwapi/trunk/js/fckeditor/editor/filemanager/browser/default/connectors/
    people/sigurdne/modules/phpgwapi/trunk/js/fckeditor/editor/filemanager/browser/default/connectors/asp/
    people/sigurdne/modules/phpgwapi/trunk/js/fckeditor/editor/filemanager/browser/default/connectors/asp/basexml.asp
    people/sigurdne/modules/phpgwapi/trunk/js/fckeditor/editor/filemanager/browser/default/connectors/asp/class_upload.asp
    people/sigurdne/modules/phpgwapi/trunk/js/fckeditor/editor/filemanager/browser/default/connectors/asp/commands.asp
    people/sigurdne/modules/phpgwapi/trunk/js/fckeditor/editor/filemanager/browser/default/connectors/asp/config.asp
    people/sigurdne/modules/phpgwapi/trunk/js/fckeditor/editor/filemanager/browser/default/connectors/asp/connector.asp
    people/sigurdne/modules/phpgwapi/trunk/js/fckeditor/editor/filemanager/browser/default/connectors/asp/io.asp
    people/sigurdne/modules/phpgwapi/trunk/js/fckeditor/editor/filemanager/browser/default/connectors/asp/util.asp
    people/sigurdne/modules/phpgwapi/trunk/js/fckeditor/editor/filemanager/browser/default/connectors/aspx/
    people/sigurdne/modules/phpgwapi/trunk/js/fckeditor/editor/filemanager/browser/default/connectors/aspx/connector.aspx
    people/sigurdne/modules/phpgwapi/trunk/js/fckeditor/editor/filemanager/browser/default/connectors/cfm/
    people/sigurdne/modules/phpgwapi/trunk/js/fckeditor/editor/filemanager/browser/default/connectors/cfm/config.cfm
    people/sigurdne/modules/phpgwapi/trunk/js/fckeditor/editor/filemanager/browser/default/connectors/cfm/connector.cfm
    people/sigurdne/modules/phpgwapi/trunk/js/fckeditor/editor/filemanager/browser/default/connectors/lasso/
    people/sigurdne/modules/phpgwapi/trunk/js/fckeditor/editor/filemanager/browser/default/connectors/lasso/config.lasso
    people/sigurdne/modules/phpgwapi/trunk/js/fckeditor/editor/filemanager/browser/default/connectors/lasso/connector.lasso
    people/sigurdne/modules/phpgwapi/trunk/js/fckeditor/editor/filemanager/browser/default/connectors/perl/
    people/sigurdne/modules/phpgwapi/trunk/js/fckeditor/editor/filemanager/browser/default/connectors/perl/basexml.pl
    people/sigurdne/modules/phpgwapi/trunk/js/fckeditor/editor/filemanager/browser/default/connectors/perl/commands.pl
    people/sigurdne/modules/phpgwapi/trunk/js/fckeditor/editor/filemanager/browser/default/connectors/perl/connector.cgi
    people/sigurdne/modules/phpgwapi/trunk/js/fckeditor/editor/filemanager/browser/default/connectors/perl/io.pl
    people/sigurdne/modules/phpgwapi/trunk/js/fckeditor/editor/filemanager/browser/default/connectors/perl/upload_fck.pl
    people/sigurdne/modules/phpgwapi/trunk/js/fckeditor/editor/filemanager/browser/default/connectors/perl/util.pl
    people/sigurdne/modules/phpgwapi/trunk/js/fckeditor/editor/filemanager/browser/default/connectors/php/
    people/sigurdne/modules/phpgwapi/trunk/js/fckeditor/editor/filemanager/browser/default/connectors/php/basexml.php
    people/sigurdne/modules/phpgwapi/trunk/js/fckeditor/editor/filemanager/browser/default/connectors/php/commands.php
    people/sigurdne/modules/phpgwapi/trunk/js/fckeditor/editor/filemanager/browser/default/connectors/php/config.php
    people/sigurdne/modules/phpgwapi/trunk/js/fckeditor/editor/filemanager/browser/default/connectors/php/connector.php
    people/sigurdne/modules/phpgwapi/trunk/js/fckeditor/editor/filemanager/browser/default/connectors/php/io.php
    people/sigurdne/modules/phpgwapi/trunk/js/fckeditor/editor/filemanager/browser/default/connectors/php/util.php
    people/sigurdne/modules/phpgwapi/trunk/js/fckeditor/editor/filemanager/browser/default/connectors/py/
    people/sigurdne/modules/phpgwapi/trunk/js/fckeditor/editor/filemanager/browser/default/connectors/py/connector.py
    people/sigurdne/modules/phpgwapi/trunk/js/fckeditor/editor/filemanager/browser/default/connectors/test.html
    people/sigurdne/modules/phpgwapi/trunk/js/fckeditor/editor/filemanager/browser/default/frmactualfolder.html
    people/sigurdne/modules/phpgwapi/trunk/js/fckeditor/editor/filemanager/browser/default/frmcreatefolder.html
    people/sigurdne/modules/phpgwapi/trunk/js/fckeditor/editor/filemanager/browser/default/frmfolders.html
    people/sigurdne/modules/phpgwapi/trunk/js/fckeditor/editor/filemanager/browser/default/frmresourceslist.html
    people/sigurdne/modules/phpgwapi/trunk/js/fckeditor/editor/filemanager/browser/default/frmresourcetype.html
    people/sigurdne/modules/phpgwapi/trunk/js/fckeditor/editor/filemanager/browser/default/frmupload.html
    people/sigurdne/modules/phpgwapi/trunk/js/fckeditor/editor/filemanager/browser/default/images/
    people/sigurdne/modules/phpgwapi/trunk/js/fckeditor/editor/filemanager/browser/default/images/ButtonArrow.gif
    people/sigurdne/modules/phpgwapi/trunk/js/fckeditor/editor/filemanager/browser/default/images/Folder.gif
    people/sigurdne/modules/phpgwapi/trunk/js/fckeditor/editor/filemanager/browser/default/images/Folder32.gif
    people/sigurdne/modules/phpgwapi/trunk/js/fckeditor/editor/filemanager/browser/default/images/FolderOpened.gif
    people/sigurdne/modules/phpgwapi/trunk/js/fckeditor/editor/filemanager/browser/default/images/FolderOpened32.gif
    people/sigurdne/modules/phpgwapi/trunk/js/fckeditor/editor/filemanager/browser/default/images/FolderUp.gif
    people/sigurdne/modules/phpgwapi/trunk/js/fckeditor/editor/filemanager/browser/default/images/icons/
    people/sigurdne/modules/phpgwapi/trunk/js/fckeditor/editor/filemanager/browser/default/images/icons/32/
    people/sigurdne/modules/phpgwapi/trunk/js/fckeditor/editor/filemanager/browser/default/images/icons/32/ai.gif
    people/sigurdne/modules/phpgwapi/trunk/js/fckeditor/editor/filemanager/browser/default/images/icons/32/avi.gif
    people/sigurdne/modules/phpgwapi/trunk/js/fckeditor/editor/filemanager/browser/default/images/icons/32/bmp.gif
    people/sigurdne/modules/phpgwapi/trunk/js/fckeditor/editor/filemanager/browser/default/images/icons/32/cs.gif
    people/sigurdne/modules/phpgwapi/trunk/js/fckeditor/editor/filemanager/browser/default/images/icons/32/default.icon.gif
    people/sigurdne/modules/phpgwapi/trunk/js/fckeditor/editor/filemanager/browser/default/images/icons/32/dll.gif
    people/sigurdne/modules/phpgwapi/trunk/js/fckeditor/editor/filemanager/browser/default/images/icons/32/doc.gif
    people/sigurdne/modules/phpgwapi/trunk/js/fckeditor/editor/filemanager/browser/default/images/icons/32/exe.gif
    people/sigurdne/modules/phpgwapi/trunk/js/fckeditor/editor/filemanager/browser/default/images/icons/32/fla.gif
    people/sigurdne/modules/phpgwapi/trunk/js/fckeditor/editor/filemanager/browser/default/images/icons/32/gif.gif
    people/sigurdne/modules/phpgwapi/trunk/js/fckeditor/editor/filemanager/browser/default/images/icons/32/htm.gif
    people/sigurdne/modules/phpgwapi/trunk/js/fckeditor/editor/filemanager/browser/default/images/icons/32/html.gif
    people/sigurdne/modules/phpgwapi/trunk/js/fckeditor/editor/filemanager/browser/default/images/icons/32/jpg.gif
    people/sigurdne/modules/phpgwapi/trunk/js/fckeditor/editor/filemanager/browser/default/images/icons/32/js.gif
    people/sigurdne/modules/phpgwapi/trunk/js/fckeditor/editor/filemanager/browser/default/images/icons/32/mdb.gif
    people/sigurdne/modules/phpgwapi/trunk/js/fckeditor/editor/filemanager/browser/default/images/icons/32/mp3.gif
    people/sigurdne/modules/phpgwapi/trunk/js/fckeditor/editor/filemanager/browser/default/images/icons/32/pdf.gif
    people/sigurdne/modules/phpgwapi/trunk/js/fckeditor/editor/filemanager/browser/default/images/icons/32/ppt.gif
    people/sigurdne/modules/phpgwapi/trunk/js/fckeditor/editor/filemanager/browser/default/images/icons/32/rdp.gif
    people/sigurdne/modules/phpgwapi/trunk/js/fckeditor/editor/filemanager/browser/default/images/icons/32/swf.gif
    people/sigurdne/modules/phpgwapi/trunk/js/fckeditor/editor/filemanager/browser/default/images/icons/32/swt.gif
    people/sigurdne/modules/phpgwapi/trunk/js/fckeditor/editor/filemanager/browser/default/images/icons/32/txt.gif
    people/sigurdne/modules/phpgwapi/trunk/js/fckeditor/editor/filemanager/browser/default/images/icons/32/vsd.gif
    people/sigurdne/modules/phpgwapi/trunk/js/fckeditor/editor/filemanager/browser/default/images/icons/32/xls.gif
    people/sigurdne/modules/phpgwapi/trunk/js/fckeditor/editor/filemanager/browser/default/images/icons/32/xml.gif
    people/sigurdne/modules/phpgwapi/trunk/js/fckeditor/editor/filemanager/browser/default/images/icons/32/zip.gif
    people/sigurdne/modules/phpgwapi/trunk/js/fckeditor/editor/filemanager/browser/default/images/icons/ai.gif
    people/sigurdne/modules/phpgwapi/trunk/js/fckeditor/editor/filemanager/browser/default/images/icons/avi.gif
    people/sigurdne/modules/phpgwapi/trunk/js/fckeditor/editor/filemanager/browser/default/images/icons/bmp.gif
    people/sigurdne/modules/phpgwapi/trunk/js/fckeditor/editor/filemanager/browser/default/images/icons/cs.gif
    people/sigurdne/modules/phpgwapi/trunk/js/fckeditor/editor/filemanager/browser/default/images/icons/default.icon.gif
    people/sigurdne/modules/phpgwapi/trunk/js/fckeditor/editor/filemanager/browser/default/images/icons/dll.gif
    people/sigurdne/modules/phpgwapi/trunk/js/fckeditor/editor/filemanager/browser/default/images/icons/doc.gif
    people/sigurdne/modules/phpgwapi/trunk/js/fckeditor/editor/filemanager/browser/default/images/icons/exe.gif
    people/sigurdne/modules/phpgwapi/trunk/js/fckeditor/editor/filemanager/browser/default/images/icons/fla.gif
    people/sigurdne/modules/phpgwapi/trunk/js/fckeditor/editor/filemanager/browser/default/images/icons/gif.gif
    people/sigurdne/modules/phpgwapi/trunk/js/fckeditor/editor/filemanager/browser/default/images/icons/htm.gif
    people/sigurdne/modules/phpgwapi/trunk/js/fckeditor/editor/filemanager/browser/default/images/icons/html.gif
    people/sigurdne/modules/phpgwapi/trunk/js/fckeditor/editor/filemanager/browser/default/images/icons/jpg.gif
    people/sigurdne/modules/phpgwapi/trunk/js/fckeditor/editor/filemanager/browser/default/images/icons/js.gif
    people/sigurdne/modules/phpgwapi/trunk/js/fckeditor/editor/filemanager/browser/default/images/icons/mdb.gif
    people/sigurdne/modules/phpgwapi/trunk/js/fckeditor/editor/filemanager/browser/default/images/icons/mp3.gif
    people/sigurdne/modules/phpgwapi/trunk/js/fckeditor/editor/filemanager/browser/default/images/icons/pdf.gif
    people/sigurdne/modules/phpgwapi/trunk/js/fckeditor/editor/filemanager/browser/default/images/icons/ppt.gif
    people/sigurdne/modules/phpgwapi/trunk/js/fckeditor/editor/filemanager/browser/default/images/icons/rdp.gif
    people/sigurdne/modules/phpgwapi/trunk/js/fckeditor/editor/filemanager/browser/default/images/icons/swf.gif
    people/sigurdne/modules/phpgwapi/trunk/js/fckeditor/editor/filemanager/browser/default/images/icons/swt.gif
    people/sigurdne/modules/phpgwapi/trunk/js/fckeditor/editor/filemanager/browser/default/images/icons/txt.gif
    people/sigurdne/modules/phpgwapi/trunk/js/fckeditor/editor/filemanager/browser/default/images/icons/vsd.gif
    people/sigurdne/modules/phpgwapi/trunk/js/fckeditor/editor/filemanager/browser/default/images/icons/xls.gif
    people/sigurdne/modules/phpgwapi/trunk/js/fckeditor/editor/filemanager/browser/default/images/icons/xml.gif
    people/sigurdne/modules/phpgwapi/trunk/js/fckeditor/editor/filemanager/browser/default/images/icons/zip.gif
    people/sigurdne/modules/phpgwapi/trunk/js/fckeditor/editor/filemanager/browser/default/images/spacer.gif
    people/sigurdne/modules/phpgwapi/trunk/js/fckeditor/editor/filemanager/browser/default/js/
    people/sigurdne/modules/phpgwapi/trunk/js/fckeditor/editor/filemanager/browser/default/js/common.js
    people/sigurdne/modules/phpgwapi/trunk/js/fckeditor/editor/filemanager/browser/default/js/fckxml.js
    people/sigurdne/modules/phpgwapi/trunk/js/fckeditor/editor/filemanager/upload/
    people/sigurdne/modules/phpgwapi/trunk/js/fckeditor/editor/filemanager/upload/asp/
    people/sigurdne/modules/phpgwapi/trunk/js/fckeditor/editor/filemanager/upload/asp/class_upload.asp
    people/sigurdne/modules/phpgwapi/trunk/js/fckeditor/editor/filemanager/upload/asp/config.asp
    people/sigurdne/modules/phpgwapi/trunk/js/fckeditor/editor/filemanager/upload/asp/io.asp
    people/sigurdne/modules/phpgwapi/trunk/js/fckeditor/editor/filemanager/upload/asp/upload.asp
    people/sigurdne/modules/phpgwapi/trunk/js/fckeditor/editor/filemanager/upload/aspx/
    people/sigurdne/modules/phpgwapi/trunk/js/fckeditor/editor/filemanager/upload/aspx/upload.aspx
    people/sigurdne/modules/phpgwapi/trunk/js/fckeditor/editor/filemanager/upload/cfm/
    people/sigurdne/modules/phpgwapi/trunk/js/fckeditor/editor/filemanager/upload/cfm/config.cfm
    people/sigurdne/modules/phpgwapi/trunk/js/fckeditor/editor/filemanager/upload/cfm/upload.cfm
    people/sigurdne/modules/phpgwapi/trunk/js/fckeditor/editor/filemanager/upload/lasso/
    people/sigurdne/modules/phpgwapi/trunk/js/fckeditor/editor/filemanager/upload/lasso/config.lasso
    people/sigurdne/modules/phpgwapi/trunk/js/fckeditor/editor/filemanager/upload/lasso/upload.lasso
    people/sigurdne/modules/phpgwapi/trunk/js/fckeditor/editor/filemanager/upload/php/
    people/sigurdne/modules/phpgwapi/trunk/js/fckeditor/editor/filemanager/upload/php/config.php
    people/sigurdne/modules/phpgwapi/trunk/js/fckeditor/editor/filemanager/upload/php/upload.php
    people/sigurdne/modules/phpgwapi/trunk/js/fckeditor/editor/filemanager/upload/php/util.php
    people/sigurdne/modules/phpgwapi/trunk/js/fckeditor/editor/filemanager/upload/test.html
    people/sigurdne/modules/phpgwapi/trunk/js/fckeditor/editor/images/
    people/sigurdne/modules/phpgwapi/trunk/js/fckeditor/editor/images/anchor.gif
    people/sigurdne/modules/phpgwapi/trunk/js/fckeditor/editor/images/arrow_ltr.gif
    people/sigurdne/modules/phpgwapi/trunk/js/fckeditor/editor/images/arrow_rtl.gif
    people/sigurdne/modules/phpgwapi/trunk/js/fckeditor/editor/images/smiley/
    people/sigurdne/modules/phpgwapi/trunk/js/fckeditor/editor/images/smiley/msn/
    people/sigurdne/modules/phpgwapi/trunk/js/fckeditor/editor/images/smiley/msn/angel_smile.gif
    people/sigurdne/modules/phpgwapi/trunk/js/fckeditor/editor/images/smiley/msn/angry_smile.gif
    people/sigurdne/modules/phpgwapi/trunk/js/fckeditor/editor/images/smiley/msn/broken_heart.gif
    people/sigurdne/modules/phpgwapi/trunk/js/fckeditor/editor/images/smiley/msn/cake.gif
    people/sigurdne/modules/phpgwapi/trunk/js/fckeditor/editor/images/smiley/msn/confused_smile.gif
    people/sigurdne/modules/phpgwapi/trunk/js/fckeditor/editor/images/smiley/msn/cry_smile.gif
    people/sigurdne/modules/phpgwapi/trunk/js/fckeditor/editor/images/smiley/msn/devil_smile.gif
    people/sigurdne/modules/phpgwapi/trunk/js/fckeditor/editor/images/smiley/msn/embaressed_smile.gif
    people/sigurdne/modules/phpgwapi/trunk/js/fckeditor/editor/images/smiley/msn/envelope.gif
    people/sigurdne/modules/phpgwapi/trunk/js/fckeditor/editor/images/smiley/msn/heart.gif
    people/sigurdne/modules/phpgwapi/trunk/js/fckeditor/editor/images/smiley/msn/kiss.gif
    people/sigurdne/modules/phpgwapi/trunk/js/fckeditor/editor/images/smiley/msn/lightbulb.gif
    people/sigurdne/modules/phpgwapi/trunk/js/fckeditor/editor/images/smiley/msn/omg_smile.gif
    people/sigurdne/modules/phpgwapi/trunk/js/fckeditor/editor/images/smiley/msn/regular_smile.gif
    people/sigurdne/modules/phpgwapi/trunk/js/fckeditor/editor/images/smiley/msn/sad_smile.gif
    people/sigurdne/modules/phpgwapi/trunk/js/fckeditor/editor/images/smiley/msn/shades_smile.gif
    people/sigurdne/modules/phpgwapi/trunk/js/fckeditor/editor/images/smiley/msn/teeth_smile.gif
    people/sigurdne/modules/phpgwapi/trunk/js/fckeditor/editor/images/smiley/msn/thumbs_down.gif
    people/sigurdne/modules/phpgwapi/trunk/js/fckeditor/editor/images/smiley/msn/thumbs_up.gif
    people/sigurdne/modules/phpgwapi/trunk/js/fckeditor/editor/images/smiley/msn/tounge_smile.gif
    people/sigurdne/modules/phpgwapi/trunk/js/fckeditor/editor/images/smiley/msn/whatchutalkingabout_smile.gif
    people/sigurdne/modules/phpgwapi/trunk/js/fckeditor/editor/images/smiley/msn/wink_smile.gif
    people/sigurdne/modules/phpgwapi/trunk/js/fckeditor/editor/images/spacer.gif
    people/sigurdne/modules/phpgwapi/trunk/js/fckeditor/editor/js/
    people/sigurdne/modules/phpgwapi/trunk/js/fckeditor/editor/js/fck_startup.js
    people/sigurdne/modules/phpgwapi/trunk/js/fckeditor/editor/js/fckeditorcode_gecko.js
    people/sigurdne/modules/phpgwapi/trunk/js/fckeditor/editor/js/fckeditorcode_gecko_1.js
    people/sigurdne/modules/phpgwapi/trunk/js/fckeditor/editor/js/fckeditorcode_gecko_2.js
    people/sigurdne/modules/phpgwapi/trunk/js/fckeditor/editor/js/fckeditorcode_ie.js
    people/sigurdne/modules/phpgwapi/trunk/js/fckeditor/editor/js/fckeditorcode_ie_1.js
    people/sigurdne/modules/phpgwapi/trunk/js/fckeditor/editor/js/fckeditorcode_ie_2.js
    people/sigurdne/modules/phpgwapi/trunk/js/fckeditor/editor/lang/
    people/sigurdne/modules/phpgwapi/trunk/js/fckeditor/editor/lang/_getfontformat.html
    people/sigurdne/modules/phpgwapi/trunk/js/fckeditor/editor/lang/_translationstatus.txt
    people/sigurdne/modules/phpgwapi/trunk/js/fckeditor/editor/lang/ar.js
    people/sigurdne/modules/phpgwapi/trunk/js/fckeditor/editor/lang/bg.js
    people/sigurdne/modules/phpgwapi/trunk/js/fckeditor/editor/lang/bn.js
    people/sigurdne/modules/phpgwapi/trunk/js/fckeditor/editor/lang/bs.js
    people/sigurdne/modules/phpgwapi/trunk/js/fckeditor/editor/lang/ca.js
    people/sigurdne/modules/phpgwapi/trunk/js/fckeditor/editor/lang/cs.js
    people/sigurdne/modules/phpgwapi/trunk/js/fckeditor/editor/lang/da.js
    people/sigurdne/modules/phpgwapi/trunk/js/fckeditor/editor/lang/de.js
    people/sigurdne/modules/phpgwapi/trunk/js/fckeditor/editor/lang/el.js
    people/sigurdne/modules/phpgwapi/trunk/js/fckeditor/editor/lang/en-au.js
    people/sigurdne/modules/phpgwapi/trunk/js/fckeditor/editor/lang/en-ca.js
    people/sigurdne/modules/phpgwapi/trunk/js/fckeditor/editor/lang/en-uk.js
    people/sigurdne/modules/phpgwapi/trunk/js/fckeditor/editor/lang/en.js
    people/sigurdne/modules/phpgwapi/trunk/js/fckeditor/editor/lang/eo.js
    people/sigurdne/modules/phpgwapi/trunk/js/fckeditor/editor/lang/es.js
    people/sigurdne/modules/phpgwapi/trunk/js/fckeditor/editor/lang/et.js
    people/sigurdne/modules/phpgwapi/trunk/js/fckeditor/editor/lang/eu.js
    people/sigurdne/modules/phpgwapi/trunk/js/fckeditor/editor/lang/fa.js
    people/sigurdne/modules/phpgwapi/trunk/js/fckeditor/editor/lang/fcklanguagemanager.js
    people/sigurdne/modules/phpgwapi/trunk/js/fckeditor/editor/lang/fi.js
    people/sigurdne/modules/phpgwapi/trunk/js/fckeditor/editor/lang/fo.js
    people/sigurdne/modules/phpgwapi/trunk/js/fckeditor/editor/lang/fr.js
    people/sigurdne/modules/phpgwapi/trunk/js/fckeditor/editor/lang/gl.js
    people/sigurdne/modules/phpgwapi/trunk/js/fckeditor/editor/lang/he.js
    people/sigurdne/modules/phpgwapi/trunk/js/fckeditor/editor/lang/hi.js
    people/sigurdne/modules/phpgwapi/trunk/js/fckeditor/editor/lang/hr.js
    people/sigurdne/modules/phpgwapi/trunk/js/fckeditor/editor/lang/hu.js
    people/sigurdne/modules/phpgwapi/trunk/js/fckeditor/editor/lang/it.js
    people/sigurdne/modules/phpgwapi/trunk/js/fckeditor/editor/lang/ja.js
    people/sigurdne/modules/phpgwapi/trunk/js/fckeditor/editor/lang/km.js
    people/sigurdne/modules/phpgwapi/trunk/js/fckeditor/editor/lang/ko.js
    people/sigurdne/modules/phpgwapi/trunk/js/fckeditor/editor/lang/lt.js
    people/sigurdne/modules/phpgwapi/trunk/js/fckeditor/editor/lang/lv.js
    people/sigurdne/modules/phpgwapi/trunk/js/fckeditor/editor/lang/mn.js
    people/sigurdne/modules/phpgwapi/trunk/js/fckeditor/editor/lang/ms.js
    people/sigurdne/modules/phpgwapi/trunk/js/fckeditor/editor/lang/nl.js
    people/sigurdne/modules/phpgwapi/trunk/js/fckeditor/editor/lang/no.js
    people/sigurdne/modules/phpgwapi/trunk/js/fckeditor/editor/lang/pl.js
    people/sigurdne/modules/phpgwapi/trunk/js/fckeditor/editor/lang/pt-br.js
    people/sigurdne/modules/phpgwapi/trunk/js/fckeditor/editor/lang/pt.js
    people/sigurdne/modules/phpgwapi/trunk/js/fckeditor/editor/lang/ro.js
    people/sigurdne/modules/phpgwapi/trunk/js/fckeditor/editor/lang/ru.js
    people/sigurdne/modules/phpgwapi/trunk/js/fckeditor/editor/lang/sk.js
    people/sigurdne/modules/phpgwapi/trunk/js/fckeditor/editor/lang/sl.js
    people/sigurdne/modules/phpgwapi/trunk/js/fckeditor/editor/lang/sr-latn.js
    people/sigurdne/modules/phpgwapi/trunk/js/fckeditor/editor/lang/sr.js
    people/sigurdne/modules/phpgwapi/trunk/js/fckeditor/editor/lang/sv.js
    people/sigurdne/modules/phpgwapi/trunk/js/fckeditor/editor/lang/th.js
    people/sigurdne/modules/phpgwapi/trunk/js/fckeditor/editor/lang/tr.js
    people/sigurdne/modules/phpgwapi/trunk/js/fckeditor/editor/lang/uk.js
    people/sigurdne/modules/phpgwapi/trunk/js/fckeditor/editor/lang/vi.js
    people/sigurdne/modules/phpgwapi/trunk/js/fckeditor/editor/lang/zh-cn.js
    people/sigurdne/modules/phpgwapi/trunk/js/fckeditor/editor/lang/zh.js
    people/sigurdne/modules/phpgwapi/trunk/js/fckeditor/editor/plugins/
    people/sigurdne/modules/phpgwapi/trunk/js/fckeditor/editor/plugins/autogrow/
    people/sigurdne/modules/phpgwapi/trunk/js/fckeditor/editor/plugins/autogrow/fckplugin.js
    people/sigurdne/modules/phpgwapi/trunk/js/fckeditor/editor/plugins/placeholder/
    people/sigurdne/modules/phpgwapi/trunk/js/fckeditor/editor/plugins/placeholder/fck_placeholder.html
    people/sigurdne/modules/phpgwapi/trunk/js/fckeditor/editor/plugins/placeholder/fckplugin.js
    people/sigurdne/modules/phpgwapi/trunk/js/fckeditor/editor/plugins/placeholder/lang/
    people/sigurdne/modules/phpgwapi/trunk/js/fckeditor/editor/plugins/placeholder/lang/de.js
    people/sigurdne/modules/phpgwapi/trunk/js/fckeditor/editor/plugins/placeholder/lang/en.js
    people/sigurdne/modules/phpgwapi/trunk/js/fckeditor/editor/plugins/placeholder/lang/fr.js
    people/sigurdne/modules/phpgwapi/trunk/js/fckeditor/editor/plugins/placeholder/lang/it.js
    people/sigurdne/modules/phpgwapi/trunk/js/fckeditor/editor/plugins/placeholder/lang/pl.js
    people/sigurdne/modules/phpgwapi/trunk/js/fckeditor/editor/plugins/placeholder/placeholder.gif
    people/sigurdne/modules/phpgwapi/trunk/js/fckeditor/editor/plugins/simplecommands/
    people/sigurdne/modules/phpgwapi/trunk/js/fckeditor/editor/plugins/simplecommands/fckplugin.js
    people/sigurdne/modules/phpgwapi/trunk/js/fckeditor/editor/plugins/tablecommands/
    people/sigurdne/modules/phpgwapi/trunk/js/fckeditor/editor/plugins/tablecommands/fckplugin.js
    people/sigurdne/modules/phpgwapi/trunk/js/fckeditor/editor/skins/
    people/sigurdne/modules/phpgwapi/trunk/js/fckeditor/editor/skins/default/
    people/sigurdne/modules/phpgwapi/trunk/js/fckeditor/editor/skins/default/fck_contextmenu.css
    people/sigurdne/modules/phpgwapi/trunk/js/fckeditor/editor/skins/default/fck_dialog.css
    people/sigurdne/modules/phpgwapi/trunk/js/fckeditor/editor/skins/default/fck_editor.css
    people/sigurdne/modules/phpgwapi/trunk/js/fckeditor/editor/skins/default/fck_strip.gif
    people/sigurdne/modules/phpgwapi/trunk/js/fckeditor/editor/skins/default/images/
    people/sigurdne/modules/phpgwapi/trunk/js/fckeditor/editor/skins/default/images/toolbar.arrowright.gif
    people/sigurdne/modules/phpgwapi/trunk/js/fckeditor/editor/skins/default/images/toolbar.buttonarrow.gif
    people/sigurdne/modules/phpgwapi/trunk/js/fckeditor/editor/skins/default/images/toolbar.collapse.gif
    people/sigurdne/modules/phpgwapi/trunk/js/fckeditor/editor/skins/default/images/toolbar.end.gif
    people/sigurdne/modules/phpgwapi/trunk/js/fckeditor/editor/skins/default/images/toolbar.expand.gif
    people/sigurdne/modules/phpgwapi/trunk/js/fckeditor/editor/skins/default/images/toolbar.separator.gif
    people/sigurdne/modules/phpgwapi/trunk/js/fckeditor/editor/skins/default/images/toolbar.start.gif
    people/sigurdne/modules/phpgwapi/trunk/js/fckeditor/editor/skins/default/toolbar/
    people/sigurdne/modules/phpgwapi/trunk/js/fckeditor/editor/skins/default/toolbar/about.gif
    people/sigurdne/modules/phpgwapi/trunk/js/fckeditor/editor/skins/default/toolbar/anchor.gif
    people/sigurdne/modules/phpgwapi/trunk/js/fckeditor/editor/skins/default/toolbar/bgcolor.gif
    people/sigurdne/modules/phpgwapi/trunk/js/fckeditor/editor/skins/default/toolbar/bold.gif
    people/sigurdne/modules/phpgwapi/trunk/js/fckeditor/editor/skins/default/toolbar/bulletedlist.gif
    people/sigurdne/modules/phpgwapi/trunk/js/fckeditor/editor/skins/default/toolbar/button.gif
    people/sigurdne/modules/phpgwapi/trunk/js/fckeditor/editor/skins/default/toolbar/checkbox.gif
    people/sigurdne/modules/phpgwapi/trunk/js/fckeditor/editor/skins/default/toolbar/copy.gif
    people/sigurdne/modules/phpgwapi/trunk/js/fckeditor/editor/skins/default/toolbar/cut.gif
    people/sigurdne/modules/phpgwapi/trunk/js/fckeditor/editor/skins/default/toolbar/docprops.gif
    people/sigurdne/modules/phpgwapi/trunk/js/fckeditor/editor/skins/default/toolbar/find.gif
    people/sigurdne/modules/phpgwapi/trunk/js/fckeditor/editor/skins/default/toolbar/flash.gif
    people/sigurdne/modules/phpgwapi/trunk/js/fckeditor/editor/skins/default/toolbar/form.gif
    people/sigurdne/modules/phpgwapi/trunk/js/fckeditor/editor/skins/default/toolbar/hiddenfield.gif
    people/sigurdne/modules/phpgwapi/trunk/js/fckeditor/editor/skins/default/toolbar/image.gif
    people/sigurdne/modules/phpgwapi/trunk/js/fckeditor/editor/skins/default/toolbar/imagebutton.gif
    people/sigurdne/modules/phpgwapi/trunk/js/fckeditor/editor/skins/default/toolbar/indent.gif
    people/sigurdne/modules/phpgwapi/trunk/js/fckeditor/editor/skins/default/toolbar/inserthorizontalrule.gif
    people/sigurdne/modules/phpgwapi/trunk/js/fckeditor/editor/skins/default/toolbar/insertorderedlist.gif
    people/sigurdne/modules/phpgwapi/trunk/js/fckeditor/editor/skins/default/toolbar/insertunorderedlist.gif
    people/sigurdne/modules/phpgwapi/trunk/js/fckeditor/editor/skins/default/toolbar/italic.gif
    people/sigurdne/modules/phpgwapi/trunk/js/fckeditor/editor/skins/default/toolbar/justifycenter.gif
    people/sigurdne/modules/phpgwapi/trunk/js/fckeditor/editor/skins/default/toolbar/justifyfull.gif
    people/sigurdne/modules/phpgwapi/trunk/js/fckeditor/editor/skins/default/toolbar/justifyleft.gif
    people/sigurdne/modules/phpgwapi/trunk/js/fckeditor/editor/skins/default/toolbar/justifyright.gif
    people/sigurdne/modules/phpgwapi/trunk/js/fckeditor/editor/skins/default/toolbar/link.gif
    people/sigurdne/modules/phpgwapi/trunk/js/fckeditor/editor/skins/default/toolbar/newpage.gif
    people/sigurdne/modules/phpgwapi/trunk/js/fckeditor/editor/skins/default/toolbar/numberedlist.gif
    people/sigurdne/modules/phpgwapi/trunk/js/fckeditor/editor/skins/default/toolbar/outdent.gif
    people/sigurdne/modules/phpgwapi/trunk/js/fckeditor/editor/skins/default/toolbar/pagebreak.gif
    people/sigurdne/modules/phpgwapi/trunk/js/fckeditor/editor/skins/default/toolbar/paste.gif
    people/sigurdne/modules/phpgwapi/trunk/js/fckeditor/editor/skins/default/toolbar/pastetext.gif
    people/sigurdne/modules/phpgwapi/trunk/js/fckeditor/editor/skins/default/toolbar/pasteword.gif
    people/sigurdne/modules/phpgwapi/trunk/js/fckeditor/editor/skins/default/toolbar/preview.gif
    people/sigurdne/modules/phpgwapi/trunk/js/fckeditor/editor/skins/default/toolbar/print.gif
    people/sigurdne/modules/phpgwapi/trunk/js/fckeditor/editor/skins/default/toolbar/radio.gif
    people/sigurdne/modules/phpgwapi/trunk/js/fckeditor/editor/skins/default/toolbar/redo.gif
    people/sigurdne/modules/phpgwapi/trunk/js/fckeditor/editor/skins/default/toolbar/removeformat.gif
    people/sigurdne/modules/phpgwapi/trunk/js/fckeditor/editor/skins/default/toolbar/replace.gif
    people/sigurdne/modules/phpgwapi/trunk/js/fckeditor/editor/skins/default/toolbar/save.gif
    people/sigurdne/modules/phpgwapi/trunk/js/fckeditor/editor/skins/default/toolbar/select.gif
    people/sigurdne/modules/phpgwapi/trunk/js/fckeditor/editor/skins/default/toolbar/selectall.gif
    people/sigurdne/modules/phpgwapi/trunk/js/fckeditor/editor/skins/default/toolbar/showdetails.gif
    people/sigurdne/modules/phpgwapi/trunk/js/fckeditor/editor/skins/default/toolbar/showtableborders.gif
    people/sigurdne/modules/phpgwapi/trunk/js/fckeditor/editor/skins/default/toolbar/smiley.gif
    people/sigurdne/modules/phpgwapi/trunk/js/fckeditor/editor/skins/default/toolbar/source.gif
    people/sigurdne/modules/phpgwapi/trunk/js/fckeditor/editor/skins/default/toolbar/specialchar.gif
    people/sigurdne/modules/phpgwapi/trunk/js/fckeditor/editor/skins/default/toolbar/spellcheck.gif
    people/sigurdne/modules/phpgwapi/trunk/js/fckeditor/editor/skins/default/toolbar/strikethrough.gif
    people/sigurdne/modules/phpgwapi/trunk/js/fckeditor/editor/skins/default/toolbar/subscript.gif
    people/sigurdne/modules/phpgwapi/trunk/js/fckeditor/editor/skins/default/toolbar/superscript.gif
    people/sigurdne/modules/phpgwapi/trunk/js/fckeditor/editor/skins/default/toolbar/table.gif
    people/sigurdne/modules/phpgwapi/trunk/js/fckeditor/editor/skins/default/toolbar/tablecell.gif
    people/sigurdne/modules/phpgwapi/trunk/js/fckeditor/editor/skins/default/toolbar/tabledeletecells.gif
    people/sigurdne/modules/phpgwapi/trunk/js/fckeditor/editor/skins/default/toolbar/tabledeletecolumns.gif
    people/sigurdne/modules/phpgwapi/trunk/js/fckeditor/editor/skins/default/toolbar/tabledeleterows.gif
    people/sigurdne/modules/phpgwapi/trunk/js/fckeditor/editor/skins/default/toolbar/tableinsertcell.gif
    people/sigurdne/modules/phpgwapi/trunk/js/fckeditor/editor/skins/default/toolbar/tableinsertcolumn.gif
    people/sigurdne/modules/phpgwapi/trunk/js/fckeditor/editor/skins/default/toolbar/tableinsertrow.gif
    people/sigurdne/modules/phpgwapi/trunk/js/fckeditor/editor/skins/default/toolbar/tablemergecells.gif
    people/sigurdne/modules/phpgwapi/trunk/js/fckeditor/editor/skins/default/toolbar/tablesplitcell.gif
    people/sigurdne/modules/phpgwapi/trunk/js/fckeditor/editor/skins/default/toolbar/templates.gif
    people/sigurdne/modules/phpgwapi/trunk/js/fckeditor/editor/skins/default/toolbar/textarea.gif
    people/sigurdne/modules/phpgwapi/trunk/js/fckeditor/editor/skins/default/toolbar/textcolor.gif
    people/sigurdne/modules/phpgwapi/trunk/js/fckeditor/editor/skins/default/toolbar/textfield.gif
    people/sigurdne/modules/phpgwapi/trunk/js/fckeditor/editor/skins/default/toolbar/underline.gif
    people/sigurdne/modules/phpgwapi/trunk/js/fckeditor/editor/skins/default/toolbar/undo.gif
    people/sigurdne/modules/phpgwapi/trunk/js/fckeditor/editor/skins/default/toolbar/universalkey.gif
    people/sigurdne/modules/phpgwapi/trunk/js/fckeditor/editor/skins/default/toolbar/unlink.gif
    people/sigurdne/modules/phpgwapi/trunk/js/fckeditor/editor/skins/default/toolbar/unorderedlist.gif
    people/sigurdne/modules/phpgwapi/trunk/js/fckeditor/editor/skins/office2003/
    people/sigurdne/modules/phpgwapi/trunk/js/fckeditor/editor/skins/office2003/fck_contextmenu.css
    people/sigurdne/modules/phpgwapi/trunk/js/fckeditor/editor/skins/office2003/fck_dialog.css
    people/sigurdne/modules/phpgwapi/trunk/js/fckeditor/editor/skins/office2003/fck_editor.css
    people/sigurdne/modules/phpgwapi/trunk/js/fckeditor/editor/skins/office2003/fck_strip.gif
    people/sigurdne/modules/phpgwapi/trunk/js/fckeditor/editor/skins/office2003/images/
    people/sigurdne/modules/phpgwapi/trunk/js/fckeditor/editor/skins/office2003/images/office.start.gif
    people/sigurdne/modules/phpgwapi/trunk/js/fckeditor/editor/skins/office2003/images/toolbar.arrowright.gif
    people/sigurdne/modules/phpgwapi/trunk/js/fckeditor/editor/skins/office2003/images/toolbar.bg.gif
    people/sigurdne/modules/phpgwapi/trunk/js/fckeditor/editor/skins/office2003/images/toolbar.buttonarrow.gif
    people/sigurdne/modules/phpgwapi/trunk/js/fckeditor/editor/skins/office2003/images/toolbar.collapse.gif
    people/sigurdne/modules/phpgwapi/trunk/js/fckeditor/editor/skins/office2003/images/toolbar.end.gif
    people/sigurdne/modules/phpgwapi/trunk/js/fckeditor/editor/skins/office2003/images/toolbar.expand.gif
    people/sigurdne/modules/phpgwapi/trunk/js/fckeditor/editor/skins/office2003/images/toolbar.separator.gif
    people/sigurdne/modules/phpgwapi/trunk/js/fckeditor/editor/skins/office2003/images/toolbar.start.gif
    people/sigurdne/modules/phpgwapi/trunk/js/fckeditor/editor/skins/office2003/toolbar/
    people/sigurdne/modules/phpgwapi/trunk/js/fckeditor/editor/skins/office2003/toolbar/about.gif
    people/sigurdne/modules/phpgwapi/trunk/js/fckeditor/editor/skins/office2003/toolbar/anchor.gif
    people/sigurdne/modules/phpgwapi/trunk/js/fckeditor/editor/skins/office2003/toolbar/bgcolor.gif
    people/sigurdne/modules/phpgwapi/trunk/js/fckeditor/editor/skins/office2003/toolbar/bold.gif
    people/sigurdne/modules/phpgwapi/trunk/js/fckeditor/editor/skins/office2003/toolbar/bulletedlist.gif
    people/sigurdne/modules/phpgwapi/trunk/js/fckeditor/editor/skins/office2003/toolbar/button.gif
    people/sigurdne/modules/phpgwapi/trunk/js/fckeditor/editor/skins/office2003/toolbar/checkbox.gif
    people/sigurdne/modules/phpgwapi/trunk/js/fckeditor/editor/skins/office2003/toolbar/copy.gif
    people/sigurdne/modules/phpgwapi/trunk/js/fckeditor/editor/skins/office2003/toolbar/cut.gif
    people/sigurdne/modules/phpgwapi/trunk/js/fckeditor/editor/skins/office2003/toolbar/docprops.gif
    people/sigurdne/modules/phpgwapi/trunk/js/fckeditor/editor/skins/office2003/toolbar/find.gif
    people/sigurdne/modules/phpgwapi/trunk/js/fckeditor/editor/skins/office2003/toolbar/flash.gif
    people/sigurdne/modules/phpgwapi/trunk/js/fckeditor/editor/skins/office2003/toolbar/fontstyleadv.gif
    people/sigurdne/modules/phpgwapi/trunk/js/fckeditor/editor/skins/office2003/toolbar/form.gif
    people/sigurdne/modules/phpgwapi/trunk/js/fckeditor/editor/skins/office2003/toolbar/hidden.gif
    people/sigurdne/modules/phpgwapi/trunk/js/fckeditor/editor/skins/office2003/toolbar/hiddenfield.gif
    people/sigurdne/modules/phpgwapi/trunk/js/fckeditor/editor/skins/office2003/toolbar/image.gif
    people/sigurdne/modules/phpgwapi/trunk/js/fckeditor/editor/skins/office2003/toolbar/imagebutton.gif
    people/sigurdne/modules/phpgwapi/trunk/js/fckeditor/editor/skins/office2003/toolbar/indent.gif
    people/sigurdne/modules/phpgwapi/trunk/js/fckeditor/editor/skins/office2003/toolbar/input.gif
    people/sigurdne/modules/phpgwapi/trunk/js/fckeditor/editor/skins/office2003/toolbar/inserthorizontalrule.gif
    people/sigurdne/modules/phpgwapi/trunk/js/fckeditor/editor/skins/office2003/toolbar/insertorderedlist.gif
    people/sigurdne/modules/phpgwapi/trunk/js/fckeditor/editor/skins/office2003/toolbar/insertunorderedlist.gif
    people/sigurdne/modules/phpgwapi/trunk/js/fckeditor/editor/skins/office2003/toolbar/italic.gif
    people/sigurdne/modules/phpgwapi/trunk/js/fckeditor/editor/skins/office2003/toolbar/justifycenter.gif
    people/sigurdne/modules/phpgwapi/trunk/js/fckeditor/editor/skins/office2003/toolbar/justifyfull.gif
    people/sigurdne/modules/phpgwapi/trunk/js/fckeditor/editor/skins/office2003/toolbar/justifyleft.gif
    people/sigurdne/modules/phpgwapi/trunk/js/fckeditor/editor/skins/office2003/toolbar/justifyright.gif
    people/sigurdne/modules/phpgwapi/trunk/js/fckeditor/editor/skins/office2003/toolbar/link.gif
    people/sigurdne/modules/phpgwapi/trunk/js/fckeditor/editor/skins/office2003/toolbar/mail.gif
    people/sigurdne/modules/phpgwapi/trunk/js/fckeditor/editor/skins/office2003/toolbar/new.gif
    people/sigurdne/modules/phpgwapi/trunk/js/fckeditor/editor/skins/office2003/toolbar/newpage.gif
    people/sigurdne/modules/phpgwapi/trunk/js/fckeditor/editor/skins/office2003/toolbar/numberedlist.gif
    people/sigurdne/modules/phpgwapi/trunk/js/fckeditor/editor/skins/office2003/toolbar/open.gif
    people/sigurdne/modules/phpgwapi/trunk/js/fckeditor/editor/skins/office2003/toolbar/outdent.gif
    people/sigurdne/modules/phpgwapi/trunk/js/fckeditor/editor/skins/office2003/toolbar/pagebreak.gif
    people/sigurdne/modules/phpgwapi/trunk/js/fckeditor/editor/skins/office2003/toolbar/paste.gif
    people/sigurdne/modules/phpgwapi/trunk/js/fckeditor/editor/skins/office2003/toolbar/pastetext.gif
    people/sigurdne/modules/phpgwapi/trunk/js/fckeditor/editor/skins/office2003/toolbar/pasteword.gif
    people/sigurdne/modules/phpgwapi/trunk/js/fckeditor/editor/skins/office2003/toolbar/preview.gif
    people/sigurdne/modules/phpgwapi/trunk/js/fckeditor/editor/skins/office2003/toolbar/print.gif
    people/sigurdne/modules/phpgwapi/trunk/js/fckeditor/editor/skins/office2003/toolbar/radio.gif
    people/sigurdne/modules/phpgwapi/trunk/js/fckeditor/editor/skins/office2003/toolbar/redo.gif
    people/sigurdne/modules/phpgwapi/trunk/js/fckeditor/editor/skins/office2003/toolbar/removeformat.gif
    people/sigurdne/modules/phpgwapi/trunk/js/fckeditor/editor/skins/office2003/toolbar/replace.gif
    people/sigurdne/modules/phpgwapi/trunk/js/fckeditor/editor/skins/office2003/toolbar/save.gif
    people/sigurdne/modules/phpgwapi/trunk/js/fckeditor/editor/skins/office2003/toolbar/select.gif
    people/sigurdne/modules/phpgwapi/trunk/js/fckeditor/editor/skins/office2003/toolbar/selectall.gif
    people/sigurdne/modules/phpgwapi/trunk/js/fckeditor/editor/skins/office2003/toolbar/showdetails.gif
    people/sigurdne/modules/phpgwapi/trunk/js/fckeditor/editor/skins/office2003/toolbar/showtableborders.gif
    people/sigurdne/modules/phpgwapi/trunk/js/fckeditor/editor/skins/office2003/toolbar/smiley.gif
    people/sigurdne/modules/phpgwapi/trunk/js/fckeditor/editor/skins/office2003/toolbar/source.gif
    people/sigurdne/modules/phpgwapi/trunk/js/fckeditor/editor/skins/office2003/toolbar/specialchar.gif
    people/sigurdne/modules/phpgwapi/trunk/js/fckeditor/editor/skins/office2003/toolbar/spellcheck.gif
    people/sigurdne/modules/phpgwapi/trunk/js/fckeditor/editor/skins/office2003/toolbar/strikethrough.gif
    people/sigurdne/modules/phpgwapi/trunk/js/fckeditor/editor/skins/office2003/toolbar/subscript.gif
    people/sigurdne/modules/phpgwapi/trunk/js/fckeditor/editor/skins/office2003/toolbar/superscript.gif
    people/sigurdne/modules/phpgwapi/trunk/js/fckeditor/editor/skins/office2003/toolbar/table.gif
    people/sigurdne/modules/phpgwapi/trunk/js/fckeditor/editor/skins/office2003/toolbar/tablecell.gif
    people/sigurdne/modules/phpgwapi/trunk/js/fckeditor/editor/skins/office2003/toolbar/tabledeletecells.gif
    people/sigurdne/modules/phpgwapi/trunk/js/fckeditor/editor/skins/office2003/toolbar/tabledeletecolumns.gif
    people/sigurdne/modules/phpgwapi/trunk/js/fckeditor/editor/skins/office2003/toolbar/tabledeleterows.gif
    people/sigurdne/modules/phpgwapi/trunk/js/fckeditor/editor/skins/office2003/toolbar/tableinsertcell.gif
    people/sigurdne/modules/phpgwapi/trunk/js/fckeditor/editor/skins/office2003/toolbar/tableinsertcolumn.gif
    people/sigurdne/modules/phpgwapi/trunk/js/fckeditor/editor/skins/office2003/toolbar/tableinsertrow.gif
    people/sigurdne/modules/phpgwapi/trunk/js/fckeditor/editor/skins/office2003/toolbar/tablemergecells.gif
    people/sigurdne/modules/phpgwapi/trunk/js/fckeditor/editor/skins/office2003/toolbar/tablesplitcell.gif
    people/sigurdne/modules/phpgwapi/trunk/js/fckeditor/editor/skins/office2003/toolbar/templates.gif
    people/sigurdne/modules/phpgwapi/trunk/js/fckeditor/editor/skins/office2003/toolbar/textarea.gif
    people/sigurdne/modules/phpgwapi/trunk/js/fckeditor/editor/skins/office2003/toolbar/textcolor.gif
    people/sigurdne/modules/phpgwapi/trunk/js/fckeditor/editor/skins/office2003/toolbar/textfield.gif
    people/sigurdne/modules/phpgwapi/trunk/js/fckeditor/editor/skins/office2003/toolbar/underline.gif
    people/sigurdne/modules/phpgwapi/trunk/js/fckeditor/editor/skins/office2003/toolbar/undo.gif
    people/sigurdne/modules/phpgwapi/trunk/js/fckeditor/editor/skins/office2003/toolbar/universalkey.gif
    people/sigurdne/modules/phpgwapi/trunk/js/fckeditor/editor/skins/office2003/toolbar/unlink.gif
    people/sigurdne/modules/phpgwapi/trunk/js/fckeditor/editor/skins/office2003/toolbar/unorderedlist.gif
    people/sigurdne/modules/phpgwapi/trunk/js/fckeditor/editor/skins/silver/
    people/sigurdne/modules/phpgwapi/trunk/js/fckeditor/editor/skins/silver/fck_contextmenu.css
    people/sigurdne/modules/phpgwapi/trunk/js/fckeditor/editor/skins/silver/fck_dialog.css
    people/sigurdne/modules/phpgwapi/trunk/js/fckeditor/editor/skins/silver/fck_editor.css
    people/sigurdne/modules/phpgwapi/trunk/js/fckeditor/editor/skins/silver/fck_strip.gif
    people/sigurdne/modules/phpgwapi/trunk/js/fckeditor/editor/skins/silver/images/
    people/sigurdne/modules/phpgwapi/trunk/js/fckeditor/editor/skins/silver/images/toolbar.arrowright.gif
    people/sigurdne/modules/phpgwapi/trunk/js/fckeditor/editor/skins/silver/images/toolbar.buttonarrow.gif
    people/sigurdne/modules/phpgwapi/trunk/js/fckeditor/editor/skins/silver/images/toolbar.buttonbg.gif
    people/sigurdne/modules/phpgwapi/trunk/js/fckeditor/editor/skins/silver/images/toolbar.collapse.gif
    people/sigurdne/modules/phpgwapi/trunk/js/fckeditor/editor/skins/silver/images/toolbar.end.gif
    people/sigurdne/modules/phpgwapi/trunk/js/fckeditor/editor/skins/silver/images/toolbar.expand.gif
    people/sigurdne/modules/phpgwapi/trunk/js/fckeditor/editor/skins/silver/images/toolbar.separator.gif
    people/sigurdne/modules/phpgwapi/trunk/js/fckeditor/editor/skins/silver/images/toolbar.start.gif
    people/sigurdne/modules/phpgwapi/trunk/js/fckeditor/editor/skins/silver/toolbar/
    people/sigurdne/modules/phpgwapi/trunk/js/fckeditor/editor/skins/silver/toolbar/about.gif
    people/sigurdne/modules/phpgwapi/trunk/js/fckeditor/editor/skins/silver/toolbar/anchor.gif
    people/sigurdne/modules/phpgwapi/trunk/js/fckeditor/editor/skins/silver/toolbar/bgcolor.gif
    people/sigurdne/modules/phpgwapi/trunk/js/fckeditor/editor/skins/silver/toolbar/bold.gif
    people/sigurdne/modules/phpgwapi/trunk/js/fckeditor/editor/skins/silver/toolbar/bulletedlist.gif
    people/sigurdne/modules/phpgwapi/trunk/js/fckeditor/editor/skins/silver/toolbar/button.gif
    people/sigurdne/modules/phpgwapi/trunk/js/fckeditor/editor/skins/silver/toolbar/checkbox.gif
    people/sigurdne/modules/phpgwapi/trunk/js/fckeditor/editor/skins/silver/toolbar/copy.gif
    people/sigurdne/modules/phpgwapi/trunk/js/fckeditor/editor/skins/silver/toolbar/cut.gif
    people/sigurdne/modules/phpgwapi/trunk/js/fckeditor/editor/skins/silver/toolbar/docprops.gif
    people/sigurdne/modules/phpgwapi/trunk/js/fckeditor/editor/skins/silver/toolbar/find.gif
    people/sigurdne/modules/phpgwapi/trunk/js/fckeditor/editor/skins/silver/toolbar/flash.gif
    people/sigurdne/modules/phpgwapi/trunk/js/fckeditor/editor/skins/silver/toolbar/form.gif
    people/sigurdne/modules/phpgwapi/trunk/js/fckeditor/editor/skins/silver/toolbar/hiddenfield.gif
    people/sigurdne/modules/phpgwapi/trunk/js/fckeditor/editor/skins/silver/toolbar/image.gif
    people/sigurdne/modules/phpgwapi/trunk/js/fckeditor/editor/skins/silver/toolbar/imagebutton.gif
    people/sigurdne/modules/phpgwapi/trunk/js/fckeditor/editor/skins/silver/toolbar/indent.gif
    people/sigurdne/modules/phpgwapi/trunk/js/fckeditor/editor/skins/silver/toolbar/inserthorizontalrule.gif
    people/sigurdne/modules/phpgwapi/trunk/js/fckeditor/editor/skins/silver/toolbar/insertorderedlist.gif
    people/sigurdne/modules/phpgwapi/trunk/js/fckeditor/editor/skins/silver/toolbar/insertunorderedlist.gif
    people/sigurdne/modules/phpgwapi/trunk/js/fckeditor/editor/skins/silver/toolbar/italic.gif
    people/sigurdne/modules/phpgwapi/trunk/js/fckeditor/editor/skins/silver/toolbar/justifycenter.gif
    people/sigurdne/modules/phpgwapi/trunk/js/fckeditor/editor/skins/silver/toolbar/justifyfull.gif
    people/sigurdne/modules/phpgwapi/trunk/js/fckeditor/editor/skins/silver/toolbar/justifyleft.gif
    people/sigurdne/modules/phpgwapi/trunk/js/fckeditor/editor/skins/silver/toolbar/justifyright.gif
    people/sigurdne/modules/phpgwapi/trunk/js/fckeditor/editor/skins/silver/toolbar/link.gif
    people/sigurdne/modules/phpgwapi/trunk/js/fckeditor/editor/skins/silver/toolbar/newpage.gif
    people/sigurdne/modules/phpgwapi/trunk/js/fckeditor/editor/skins/silver/toolbar/numberedlist.gif
    people/sigurdne/modules/phpgwapi/trunk/js/fckeditor/editor/skins/silver/toolbar/outdent.gif
    people/sigurdne/modules/phpgwapi/trunk/js/fckeditor/editor/skins/silver/toolbar/pagebreak.gif
    people/sigurdne/modules/phpgwapi/trunk/js/fckeditor/editor/skins/silver/toolbar/paste.gif
    people/sigurdne/modules/phpgwapi/trunk/js/fckeditor/editor/skins/silver/toolbar/pastetext.gif
    people/sigurdne/modules/phpgwapi/trunk/js/fckeditor/editor/skins/silver/toolbar/pasteword.gif
    people/sigurdne/modules/phpgwapi/trunk/js/fckeditor/editor/skins/silver/toolbar/preview.gif
    people/sigurdne/modules/phpgwapi/trunk/js/fckeditor/editor/skins/silver/toolbar/print.gif
    people/sigurdne/modules/phpgwapi/trunk/js/fckeditor/editor/skins/silver/toolbar/radio.gif
    people/sigurdne/modules/phpgwapi/trunk/js/fckeditor/editor/skins/silver/toolbar/redo.gif
    people/sigurdne/modules/phpgwapi/trunk/js/fckeditor/editor/skins/silver/toolbar/removeformat.gif
    people/sigurdne/modules/phpgwapi/trunk/js/fckeditor/editor/skins/silver/toolbar/replace.gif
    people/sigurdne/modules/phpgwapi/trunk/js/fckeditor/editor/skins/silver/toolbar/save.gif
    people/sigurdne/modules/phpgwapi/trunk/js/fckeditor/editor/skins/silver/toolbar/select.gif
    people/sigurdne/modules/phpgwapi/trunk/js/fckeditor/editor/skins/silver/toolbar/selectall.gif
    people/sigurdne/modules/phpgwapi/trunk/js/fckeditor/editor/skins/silver/toolbar/showdetails.gif
    people/sigurdne/modules/phpgwapi/trunk/js/fckeditor/editor/skins/silver/toolbar/showtableborders.gif
    people/sigurdne/modules/phpgwapi/trunk/js/fckeditor/editor/skins/silver/toolbar/smiley.gif
    people/sigurdne/modules/phpgwapi/trunk/js/fckeditor/editor/skins/silver/toolbar/source.gif
    people/sigurdne/modules/phpgwapi/trunk/js/fckeditor/editor/skins/silver/toolbar/specialchar.gif
    people/sigurdne/modules/phpgwapi/trunk/js/fckeditor/editor/skins/silver/toolbar/spellcheck.gif
    people/sigurdne/modules/phpgwapi/trunk/js/fckeditor/editor/skins/silver/toolbar/strikethrough.gif
    people/sigurdne/modules/phpgwapi/trunk/js/fckeditor/editor/skins/silver/toolbar/subscript.gif
    people/sigurdne/modules/phpgwapi/trunk/js/fckeditor/editor/skins/silver/toolbar/superscript.gif
    people/sigurdne/modules/phpgwapi/trunk/js/fckeditor/editor/skins/silver/toolbar/table.gif
    people/sigurdne/modules/phpgwapi/trunk/js/fckeditor/editor/skins/silver/toolbar/tablecell.gif
    people/sigurdne/modules/phpgwapi/trunk/js/fckeditor/editor/skins/silver/toolbar/tabledeletecells.gif
    people/sigurdne/modules/phpgwapi/trunk/js/fckeditor/editor/skins/silver/toolbar/tabledeletecolumns.gif
    people/sigurdne/modules/phpgwapi/trunk/js/fckeditor/editor/skins/silver/toolbar/tabledeleterows.gif
    people/sigurdne/modules/phpgwapi/trunk/js/fckeditor/editor/skins/silver/toolbar/tableinsertcell.gif
    people/sigurdne/modules/phpgwapi/trunk/js/fckeditor/editor/skins/silver/toolbar/tableinsertcolumn.gif
    people/sigurdne/modules/phpgwapi/trunk/js/fckeditor/editor/skins/silver/toolbar/tableinsertrow.gif
    people/sigurdne/modules/phpgwapi/trunk/js/fckeditor/editor/skins/silver/toolbar/tablemergecells.gif
    people/sigurdne/modules/phpgwapi/trunk/js/fckeditor/editor/skins/silver/toolbar/tablesplitcell.gif
    people/sigurdne/modules/phpgwapi/trunk/js/fckeditor/editor/skins/silver/toolbar/templates.gif
    people/sigurdne/modules/phpgwapi/trunk/js/fckeditor/editor/skins/silver/toolbar/textarea.gif
    people/sigurdne/modules/phpgwapi/trunk/js/fckeditor/editor/skins/silver/toolbar/textcolor.gif
    people/sigurdne/modules/phpgwapi/trunk/js/fckeditor/editor/skins/silver/toolbar/textfield.gif
    people/sigurdne/modules/phpgwapi/trunk/js/fckeditor/editor/skins/silver/toolbar/underline.gif
    people/sigurdne/modules/phpgwapi/trunk/js/fckeditor/editor/skins/silver/toolbar/undo.gif
    people/sigurdne/modules/phpgwapi/trunk/js/fckeditor/editor/skins/silver/toolbar/universalkey.gif
    people/sigurdne/modules/phpgwapi/trunk/js/fckeditor/editor/skins/silver/toolbar/unlink.gif
    people/sigurdne/modules/phpgwapi/trunk/js/fckeditor/editor/skins/silver/toolbar/unorderedlist.gif
    people/sigurdne/modules/phpgwapi/trunk/js/fckeditor/fckconfig.js
    people/sigurdne/modules/phpgwapi/trunk/js/fckeditor/fckeditor.js
    people/sigurdne/modules/phpgwapi/trunk/js/fckeditor/fckeditor.pl
    people/sigurdne/modules/phpgwapi/trunk/js/fckeditor/fckstyles.xml
    people/sigurdne/modules/phpgwapi/trunk/js/fckeditor/fcktemplates.xml
    people/sigurdne/modules/phpgwapi/trunk/js/fckeditor/htaccess.txt
    people/sigurdne/modules/phpgwapi/trunk/js/fckeditor/license.txt
    people/sigurdne/modules/phpgwapi/trunk/js/tinymce/
    people/sigurdne/modules/phpgwapi/trunk/js/tinymce/blank.htm
    people/sigurdne/modules/phpgwapi/trunk/js/tinymce/classes/
    people/sigurdne/modules/phpgwapi/trunk/js/tinymce/classes/TinyMCE_Array.class.js
    people/sigurdne/modules/phpgwapi/trunk/js/tinymce/classes/TinyMCE_Cleanup.class.js
    people/sigurdne/modules/phpgwapi/trunk/js/tinymce/classes/TinyMCE_Control.class.js
    people/sigurdne/modules/phpgwapi/trunk/js/tinymce/classes/TinyMCE_DOMUtils.class.js
    people/sigurdne/modules/phpgwapi/trunk/js/tinymce/classes/TinyMCE_Debug.class.js
    people/sigurdne/modules/phpgwapi/trunk/js/tinymce/classes/TinyMCE_Engine.class.js
    people/sigurdne/modules/phpgwapi/trunk/js/tinymce/classes/TinyMCE_Event.class.js
    people/sigurdne/modules/phpgwapi/trunk/js/tinymce/classes/TinyMCE_ForceParagraphs.class.js
    people/sigurdne/modules/phpgwapi/trunk/js/tinymce/classes/TinyMCE_Layer.class.js
    people/sigurdne/modules/phpgwapi/trunk/js/tinymce/classes/TinyMCE_Menu.class.js
    people/sigurdne/modules/phpgwapi/trunk/js/tinymce/classes/TinyMCE_Popup.class.js
    people/sigurdne/modules/phpgwapi/trunk/js/tinymce/classes/TinyMCE_Selection.class.js
    people/sigurdne/modules/phpgwapi/trunk/js/tinymce/classes/TinyMCE_URL.class.js
    people/sigurdne/modules/phpgwapi/trunk/js/tinymce/classes/TinyMCE_UndoRedo.class.js
    people/sigurdne/modules/phpgwapi/trunk/js/tinymce/langs/
    people/sigurdne/modules/phpgwapi/trunk/js/tinymce/langs/en.js
    people/sigurdne/modules/phpgwapi/trunk/js/tinymce/langs/readme.txt
    people/sigurdne/modules/phpgwapi/trunk/js/tinymce/license.txt
    people/sigurdne/modules/phpgwapi/trunk/js/tinymce/other/
    people/sigurdne/modules/phpgwapi/trunk/js/tinymce/other/JSTrim.config
    people/sigurdne/modules/phpgwapi/trunk/js/tinymce/other/JSTrim.exe
    people/sigurdne/modules/phpgwapi/trunk/js/tinymce/other/JSTrim_mono.exe
    people/sigurdne/modules/phpgwapi/trunk/js/tinymce/other/changelog
    people/sigurdne/modules/phpgwapi/trunk/js/tinymce/other/docs/
    people/sigurdne/modules/phpgwapi/trunk/js/tinymce/other/docs/about.html
    people/sigurdne/modules/phpgwapi/trunk/js/tinymce/other/docs/compatiblity_chart.html
    people/sigurdne/modules/phpgwapi/trunk/js/tinymce/other/docs/credits.html
    people/sigurdne/modules/phpgwapi/trunk/js/tinymce/other/docs/css/
    people/sigurdne/modules/phpgwapi/trunk/js/tinymce/other/docs/css/screen.css
    people/sigurdne/modules/phpgwapi/trunk/js/tinymce/other/docs/customization_language_packs.html
    people/sigurdne/modules/phpgwapi/trunk/js/tinymce/other/docs/customization_plugins.html
    people/sigurdne/modules/phpgwapi/trunk/js/tinymce/other/docs/customization_themes.html
    people/sigurdne/modules/phpgwapi/trunk/js/tinymce/other/docs/faq.html
    people/sigurdne/modules/phpgwapi/trunk/js/tinymce/other/docs/images/
    people/sigurdne/modules/phpgwapi/trunk/js/tinymce/other/docs/images/moxiecode.gif
    people/sigurdne/modules/phpgwapi/trunk/js/tinymce/other/docs/index.html
    people/sigurdne/modules/phpgwapi/trunk/js/tinymce/other/docs/installation_example_00.html
    people/sigurdne/modules/phpgwapi/trunk/js/tinymce/other/docs/installation_example_01.html
    people/sigurdne/modules/phpgwapi/trunk/js/tinymce/other/docs/installation_example_02.html
    people/sigurdne/modules/phpgwapi/trunk/js/tinymce/other/docs/installation_example_03.html
    people/sigurdne/modules/phpgwapi/trunk/js/tinymce/other/docs/installing.html
    people/sigurdne/modules/phpgwapi/trunk/js/tinymce/other/docs/license.html
    people/sigurdne/modules/phpgwapi/trunk/js/tinymce/other/docs/option_accessibility_focus.html
    people/sigurdne/modules/phpgwapi/trunk/js/tinymce/other/docs/option_accessibility_warnings.html
    people/sigurdne/modules/phpgwapi/trunk/js/tinymce/other/docs/option_add_form_submit_trigger.html
    people/sigurdne/modules/phpgwapi/trunk/js/tinymce/other/docs/option_add_unload_trigger.html
    people/sigurdne/modules/phpgwapi/trunk/js/tinymce/other/docs/option_apply_source_formatting.html
    people/sigurdne/modules/phpgwapi/trunk/js/tinymce/other/docs/option_ask.html
    people/sigurdne/modules/phpgwapi/trunk/js/tinymce/other/docs/option_auto_focus.html
    people/sigurdne/modules/phpgwapi/trunk/js/tinymce/other/docs/option_auto_reset_designmode.html
    people/sigurdne/modules/phpgwapi/trunk/js/tinymce/other/docs/option_auto_resize.html
    people/sigurdne/modules/phpgwapi/trunk/js/tinymce/other/docs/option_browsers.html
    people/sigurdne/modules/phpgwapi/trunk/js/tinymce/other/docs/option_button_tile_map.html
    people/sigurdne/modules/phpgwapi/trunk/js/tinymce/other/docs/option_cleanup.html
    people/sigurdne/modules/phpgwapi/trunk/js/tinymce/other/docs/option_cleanup_callback.html
    people/sigurdne/modules/phpgwapi/trunk/js/tinymce/other/docs/option_cleanup_on_startup.html
    people/sigurdne/modules/phpgwapi/trunk/js/tinymce/other/docs/option_content_css.html
    people/sigurdne/modules/phpgwapi/trunk/js/tinymce/other/docs/option_convert_fonts_to_spans.html
    people/sigurdne/modules/phpgwapi/trunk/js/tinymce/other/docs/option_convert_newlines_to_brs.html
    people/sigurdne/modules/phpgwapi/trunk/js/tinymce/other/docs/option_convert_urls.html
    people/sigurdne/modules/phpgwapi/trunk/js/tinymce/other/docs/option_custom_shortcuts.html
    people/sigurdne/modules/phpgwapi/trunk/js/tinymce/other/docs/option_custom_undo_redo.html
    people/sigurdne/modules/phpgwapi/trunk/js/tinymce/other/docs/option_custom_undo_redo_keyboard_shortcuts.html
    people/sigurdne/modules/phpgwapi/trunk/js/tinymce/other/docs/option_custom_undo_redo_levels.html
    people/sigurdne/modules/phpgwapi/trunk/js/tinymce/other/docs/option_custom_undo_redo_restore_selection.html
    people/sigurdne/modules/phpgwapi/trunk/js/tinymce/other/docs/option_debug.html
    people/sigurdne/modules/phpgwapi/trunk/js/tinymce/other/docs/option_dialog_type.html
    people/sigurdne/modules/phpgwapi/trunk/js/tinymce/other/docs/option_directionality.html
    people/sigurdne/modules/phpgwapi/trunk/js/tinymce/other/docs/option_docs_language.html
    people/sigurdne/modules/phpgwapi/trunk/js/tinymce/other/docs/option_doctype.html
    people/sigurdne/modules/phpgwapi/trunk/js/tinymce/other/docs/option_document_base_url.html
    people/sigurdne/modules/phpgwapi/trunk/js/tinymce/other/docs/option_editor_css.html
    people/sigurdne/modules/phpgwapi/trunk/js/tinymce/other/docs/option_editor_deselector.html
    people/sigurdne/modules/phpgwapi/trunk/js/tinymce/other/docs/option_editor_selector.html
    people/sigurdne/modules/phpgwapi/trunk/js/tinymce/other/docs/option_elements.html
    people/sigurdne/modules/phpgwapi/trunk/js/tinymce/other/docs/option_encoding.html
    people/sigurdne/modules/phpgwapi/trunk/js/tinymce/other/docs/option_entities.html
    people/sigurdne/modules/phpgwapi/trunk/js/tinymce/other/docs/option_entity_encoding.html
    people/sigurdne/modules/phpgwapi/trunk/js/tinymce/other/docs/option_event_elements.html
    people/sigurdne/modules/phpgwapi/trunk/js/tinymce/other/docs/option_execcommand_callback.html
    people/sigurdne/modules/phpgwapi/trunk/js/tinymce/other/docs/option_extended_valid_elements.html
    people/sigurdne/modules/phpgwapi/trunk/js/tinymce/other/docs/option_external_image_list_url.html
    people/sigurdne/modules/phpgwapi/trunk/js/tinymce/other/docs/option_external_link_list_url.html
    people/sigurdne/modules/phpgwapi/trunk/js/tinymce/other/docs/option_file_browser_callback.html
    people/sigurdne/modules/phpgwapi/trunk/js/tinymce/other/docs/option_fix_content_duplication.html
    people/sigurdne/modules/phpgwapi/trunk/js/tinymce/other/docs/option_fix_list_elements.html
    people/sigurdne/modules/phpgwapi/trunk/js/tinymce/other/docs/option_fix_table_elements.html
    people/sigurdne/modules/phpgwapi/trunk/js/tinymce/other/docs/option_focus_alert.html
    people/sigurdne/modules/phpgwapi/trunk/js/tinymce/other/docs/option_font_size_classes.html
    people/sigurdne/modules/phpgwapi/trunk/js/tinymce/other/docs/option_font_size_style_values.html
    people/sigurdne/modules/phpgwapi/trunk/js/tinymce/other/docs/option_force_br_newlines.html
    people/sigurdne/modules/phpgwapi/trunk/js/tinymce/other/docs/option_force_hex_style_colors.html
    people/sigurdne/modules/phpgwapi/trunk/js/tinymce/other/docs/option_force_p_newlines.html
    people/sigurdne/modules/phpgwapi/trunk/js/tinymce/other/docs/option_handle_event_callback.html
    people/sigurdne/modules/phpgwapi/trunk/js/tinymce/other/docs/option_height.html
    people/sigurdne/modules/phpgwapi/trunk/js/tinymce/other/docs/option_init_instance_callback.html
    people/sigurdne/modules/phpgwapi/trunk/js/tinymce/other/docs/option_inline_styles.html
    people/sigurdne/modules/phpgwapi/trunk/js/tinymce/other/docs/option_insertimage_callback.html
    people/sigurdne/modules/phpgwapi/trunk/js/tinymce/other/docs/option_insertlink_callback.html
    people/sigurdne/modules/phpgwapi/trunk/js/tinymce/other/docs/option_invalid_elements.html
    people/sigurdne/modules/phpgwapi/trunk/js/tinymce/other/docs/option_language.html
    people/sigurdne/modules/phpgwapi/trunk/js/tinymce/other/docs/option_merge_styles_invalid_parents.html
    people/sigurdne/modules/phpgwapi/trunk/js/tinymce/other/docs/option_mode.html
    people/sigurdne/modules/phpgwapi/trunk/js/tinymce/other/docs/option_nowrap.html
    people/sigurdne/modules/phpgwapi/trunk/js/tinymce/other/docs/option_object_resizing.html
    people/sigurdne/modules/phpgwapi/trunk/js/tinymce/other/docs/option_onchange_callback.html
    people/sigurdne/modules/phpgwapi/trunk/js/tinymce/other/docs/option_oninit.html
    people/sigurdne/modules/phpgwapi/trunk/js/tinymce/other/docs/option_onpageload.html
    people/sigurdne/modules/phpgwapi/trunk/js/tinymce/other/docs/option_plugins.html
    people/sigurdne/modules/phpgwapi/trunk/js/tinymce/other/docs/option_popups_css.html
    people/sigurdne/modules/phpgwapi/trunk/js/tinymce/other/docs/option_preformatted.html
    people/sigurdne/modules/phpgwapi/trunk/js/tinymce/other/docs/option_relative_urls.html
    people/sigurdne/modules/phpgwapi/trunk/js/tinymce/other/docs/option_remove_linebreaks.html
    people/sigurdne/modules/phpgwapi/trunk/js/tinymce/other/docs/option_remove_script_host.html
    people/sigurdne/modules/phpgwapi/trunk/js/tinymce/other/docs/option_save_callback.html
    people/sigurdne/modules/phpgwapi/trunk/js/tinymce/other/docs/option_setupcontent_callback.html
    people/sigurdne/modules/phpgwapi/trunk/js/tinymce/other/docs/option_submit_patch.html
    people/sigurdne/modules/phpgwapi/trunk/js/tinymce/other/docs/option_table_inline_editing.html
    people/sigurdne/modules/phpgwapi/trunk/js/tinymce/other/docs/option_textarea_trigger.html
    people/sigurdne/modules/phpgwapi/trunk/js/tinymce/other/docs/option_theme.html
    people/sigurdne/modules/phpgwapi/trunk/js/tinymce/other/docs/option_theme_advanced_blockformats.html
    people/sigurdne/modules/phpgwapi/trunk/js/tinymce/other/docs/option_theme_advanced_buttons_n.html
    people/sigurdne/modules/phpgwapi/trunk/js/tinymce/other/docs/option_theme_advanced_buttons_n_add.html
    people/sigurdne/modules/phpgwapi/trunk/js/tinymce/other/docs/option_theme_advanced_buttons_n_add_before.html
    people/sigurdne/modules/phpgwapi/trunk/js/tinymce/other/docs/option_theme_advanced_container.html
    people/sigurdne/modules/phpgwapi/trunk/js/tinymce/other/docs/option_theme_advanced_container_align.html
    people/sigurdne/modules/phpgwapi/trunk/js/tinymce/other/docs/option_theme_advanced_container_class.html
    people/sigurdne/modules/phpgwapi/trunk/js/tinymce/other/docs/option_theme_advanced_containers.html
    people/sigurdne/modules/phpgwapi/trunk/js/tinymce/other/docs/option_theme_advanced_containers_default_align.html
    people/sigurdne/modules/phpgwapi/trunk/js/tinymce/other/docs/option_theme_advanced_containers_default_class.html
    people/sigurdne/modules/phpgwapi/trunk/js/tinymce/other/docs/option_theme_advanced_custom_layout.html
    people/sigurdne/modules/phpgwapi/trunk/js/tinymce/other/docs/option_theme_advanced_disable.html
    people/sigurdne/modules/phpgwapi/trunk/js/tinymce/other/docs/option_theme_advanced_fonts.html
    people/sigurdne/modules/phpgwapi/trunk/js/tinymce/other/docs/option_theme_advanced_layout_manager.html
    people/sigurdne/modules/phpgwapi/trunk/js/tinymce/other/docs/option_theme_advanced_link_targets.html
    people/sigurdne/modules/phpgwapi/trunk/js/tinymce/other/docs/option_theme_advanced_path.html
    people/sigurdne/modules/phpgwapi/trunk/js/tinymce/other/docs/option_theme_advanced_path_location.html
    people/sigurdne/modules/phpgwapi/trunk/js/tinymce/other/docs/option_theme_advanced_resize_horizontal.html
    people/sigurdne/modules/phpgwapi/trunk/js/tinymce/other/docs/option_theme_advanced_resizing.html
    people/sigurdne/modules/phpgwapi/trunk/js/tinymce/other/docs/option_theme_advanced_resizing_use_cookie.html
    people/sigurdne/modules/phpgwapi/trunk/js/tinymce/other/docs/option_theme_advanced_source_editor_height.html
    people/sigurdne/modules/phpgwapi/trunk/js/tinymce/other/docs/option_theme_advanced_source_editor_width.html
    people/sigurdne/modules/phpgwapi/trunk/js/tinymce/other/docs/option_theme_advanced_statusbar_location.html
    people/sigurdne/modules/phpgwapi/trunk/js/tinymce/other/docs/option_theme_advanced_styles.html
    people/sigurdne/modules/phpgwapi/trunk/js/tinymce/other/docs/option_theme_advanced_toolbar_align.html
    people/sigurdne/modules/phpgwapi/trunk/js/tinymce/other/docs/option_theme_advanced_toolbar_location.html
    people/sigurdne/modules/phpgwapi/trunk/js/tinymce/other/docs/option_trim_span_elements.html
    people/sigurdne/modules/phpgwapi/trunk/js/tinymce/other/docs/option_urlconverter_callback.html
    people/sigurdne/modules/phpgwapi/trunk/js/tinymce/other/docs/option_valid_elements.html
    people/sigurdne/modules/phpgwapi/trunk/js/tinymce/other/docs/option_verify_css_classes.html
    people/sigurdne/modules/phpgwapi/trunk/js/tinymce/other/docs/option_verify_html.html
    people/sigurdne/modules/phpgwapi/trunk/js/tinymce/other/docs/option_visual.html
    people/sigurdne/modules/phpgwapi/trunk/js/tinymce/other/docs/option_visual_table_class.html
    people/sigurdne/modules/phpgwapi/trunk/js/tinymce/other/docs/option_width.html
    people/sigurdne/modules/phpgwapi/trunk/js/tinymce/other/docs/plugin_advhr.html
    people/sigurdne/modules/phpgwapi/trunk/js/tinymce/other/docs/plugin_advimage.html
    people/sigurdne/modules/phpgwapi/trunk/js/tinymce/other/docs/plugin_advlink.html
    people/sigurdne/modules/phpgwapi/trunk/js/tinymce/other/docs/plugin_autosave.html
    people/sigurdne/modules/phpgwapi/trunk/js/tinymce/other/docs/plugin_contextmenu.html
    people/sigurdne/modules/phpgwapi/trunk/js/tinymce/other/docs/plugin_directionality.html
    people/sigurdne/modules/phpgwapi/trunk/js/tinymce/other/docs/plugin_emotions.html
    people/sigurdne/modules/phpgwapi/trunk/js/tinymce/other/docs/plugin_flash.html
    people/sigurdne/modules/phpgwapi/trunk/js/tinymce/other/docs/plugin_fullpage.html
    people/sigurdne/modules/phpgwapi/trunk/js/tinymce/other/docs/plugin_fullscreen.html
    people/sigurdne/modules/phpgwapi/trunk/js/tinymce/other/docs/plugin_iespell.html
    people/sigurdne/modules/phpgwapi/trunk/js/tinymce/other/docs/plugin_inlinepopups.html
    people/sigurdne/modules/phpgwapi/trunk/js/tinymce/other/docs/plugin_insertdatetime.html
    people/sigurdne/modules/phpgwapi/trunk/js/tinymce/other/docs/plugin_noneditable.html
    people/sigurdne/modules/phpgwapi/trunk/js/tinymce/other/docs/plugin_paste.html
    people/sigurdne/modules/phpgwapi/trunk/js/tinymce/other/docs/plugin_preview.html
    people/sigurdne/modules/phpgwapi/trunk/js/tinymce/other/docs/plugin_print.html
    people/sigurdne/modules/phpgwapi/trunk/js/tinymce/other/docs/plugin_save.html
    people/sigurdne/modules/phpgwapi/trunk/js/tinymce/other/docs/plugin_searchreplace.html
    people/sigurdne/modules/phpgwapi/trunk/js/tinymce/other/docs/plugin_spellchecker.html
    people/sigurdne/modules/phpgwapi/trunk/js/tinymce/other/docs/plugin_table.html
    people/sigurdne/modules/phpgwapi/trunk/js/tinymce/other/docs/plugin_zoom.html
    people/sigurdne/modules/phpgwapi/trunk/js/tinymce/other/docs/reference_buttons.html
    people/sigurdne/modules/phpgwapi/trunk/js/tinymce/other/docs/reference_configuration.html
    people/sigurdne/modules/phpgwapi/trunk/js/tinymce/other/docs/reference_javascript_functions.html
    people/sigurdne/modules/phpgwapi/trunk/js/tinymce/other/docs/reference_plugins.html
    people/sigurdne/modules/phpgwapi/trunk/js/tinymce/other/docs/tinymce_api/
    people/sigurdne/modules/phpgwapi/trunk/js/tinymce/other/docs/tinymce_api/GLOBALS.html
    people/sigurdne/modules/phpgwapi/trunk/js/tinymce/other/docs/tinymce_api/TinyMCE_Cleanup.html
    people/sigurdne/modules/phpgwapi/trunk/js/tinymce/other/docs/tinymce_api/TinyMCE_Control.html
    people/sigurdne/modules/phpgwapi/trunk/js/tinymce/other/docs/tinymce_api/TinyMCE_Engine.html
    people/sigurdne/modules/phpgwapi/trunk/js/tinymce/other/docs/tinymce_api/TinyMCE_Layer.html
    people/sigurdne/modules/phpgwapi/trunk/js/tinymce/other/docs/tinymce_api/TinyMCE_Popup.html
    people/sigurdne/modules/phpgwapi/trunk/js/tinymce/other/docs/tinymce_api/TinyMCE_Selection.html
    people/sigurdne/modules/phpgwapi/trunk/js/tinymce/other/docs/tinymce_api/TinyMCE_UndoRedo.html
    people/sigurdne/modules/phpgwapi/trunk/js/tinymce/other/docs/tinymce_api/allclasses-frame.html
    people/sigurdne/modules/phpgwapi/trunk/js/tinymce/other/docs/tinymce_api/allclasses-noframe.html
    people/sigurdne/modules/phpgwapi/trunk/js/tinymce/other/docs/tinymce_api/help-doc.html
    people/sigurdne/modules/phpgwapi/trunk/js/tinymce/other/docs/tinymce_api/index-all.html
    people/sigurdne/modules/phpgwapi/trunk/js/tinymce/other/docs/tinymce_api/index.html
    people/sigurdne/modules/phpgwapi/trunk/js/tinymce/other/docs/tinymce_api/overview-TinyMCE_Array.class.js.html
    people/sigurdne/modules/phpgwapi/trunk/js/tinymce/other/docs/tinymce_api/overview-TinyMCE_Cleanup.class.js.html
    people/sigurdne/modules/phpgwapi/trunk/js/tinymce/other/docs/tinymce_api/overview-TinyMCE_Control.class.js.html
    people/sigurdne/modules/phpgwapi/trunk/js/tinymce/other/docs/tinymce_api/overview-TinyMCE_DOMUtils.class.js.html
    people/sigurdne/modules/phpgwapi/trunk/js/tinymce/other/docs/tinymce_api/overview-TinyMCE_Debug.class.js.html
    people/sigurdne/modules/phpgwapi/trunk/js/tinymce/other/docs/tinymce_api/overview-TinyMCE_Engine.class.js.html
    people/sigurdne/modules/phpgwapi/trunk/js/tinymce/other/docs/tinymce_api/overview-TinyMCE_Event.class.js.html
    people/sigurdne/modules/phpgwapi/trunk/js/tinymce/other/docs/tinymce_api/overview-TinyMCE_ForceParagraphs.class.js.html
    people/sigurdne/modules/phpgwapi/trunk/js/tinymce/other/docs/tinymce_api/overview-TinyMCE_Layer.class.js.html
    people/sigurdne/modules/phpgwapi/trunk/js/tinymce/other/docs/tinymce_api/overview-TinyMCE_Menu.class.js.html
    people/sigurdne/modules/phpgwapi/trunk/js/tinymce/other/docs/tinymce_api/overview-TinyMCE_Popup.class.js.html
    people/sigurdne/modules/phpgwapi/trunk/js/tinymce/other/docs/tinymce_api/overview-TinyMCE_Selection.class.js.html
    people/sigurdne/modules/phpgwapi/trunk/js/tinymce/other/docs/tinymce_api/overview-TinyMCE_URL.class.js.html
    people/sigurdne/modules/phpgwapi/trunk/js/tinymce/other/docs/tinymce_api/overview-TinyMCE_UndoRedo.class.js.html
    people/sigurdne/modules/phpgwapi/trunk/js/tinymce/other/docs/tinymce_api/overview-frame.html
    people/sigurdne/modules/phpgwapi/trunk/js/tinymce/other/docs/tinymce_api/overview-summary-TinyMCE_Array.class.js.html
    people/sigurdne/modules/phpgwapi/trunk/js/tinymce/other/docs/tinymce_api/overview-summary-TinyMCE_Cleanup.class.js.html
    people/sigurdne/modules/phpgwapi/trunk/js/tinymce/other/docs/tinymce_api/overview-summary-TinyMCE_Control.class.js.html
    people/sigurdne/modules/phpgwapi/trunk/js/tinymce/other/docs/tinymce_api/overview-summary-TinyMCE_DOMUtils.class.js.html
    people/sigurdne/modules/phpgwapi/trunk/js/tinymce/other/docs/tinymce_api/overview-summary-TinyMCE_Debug.class.js.html
    people/sigurdne/modules/phpgwapi/trunk/js/tinymce/other/docs/tinymce_api/overview-summary-TinyMCE_Engine.class.js.html
    people/sigurdne/modules/phpgwapi/trunk/js/tinymce/other/docs/tinymce_api/overview-summary-TinyMCE_Event.class.js.html
    people/sigurdne/modules/phpgwapi/trunk/js/tinymce/other/docs/tinymce_api/overview-summary-TinyMCE_ForceParagraphs.class.js.html
    people/sigurdne/modules/phpgwapi/trunk/js/tinymce/other/docs/tinymce_api/overview-summary-TinyMCE_Layer.class.js.html
    people/sigurdne/modules/phpgwapi/trunk/js/tinymce/other/docs/tinymce_api/overview-summary-TinyMCE_Menu.class.js.html
    people/sigurdne/modules/phpgwapi/trunk/js/tinymce/other/docs/tinymce_api/overview-summary-TinyMCE_Popup.class.js.html
    people/sigurdne/modules/phpgwapi/trunk/js/tinymce/other/docs/tinymce_api/overview-summary-TinyMCE_Selection.class.js.html
    people/sigurdne/modules/phpgwapi/trunk/js/tinymce/other/docs/tinymce_api/overview-summary-TinyMCE_URL.class.js.html
    people/sigurdne/modules/phpgwapi/trunk/js/tinymce/other/docs/tinymce_api/overview-summary-TinyMCE_UndoRedo.class.js.html
    people/sigurdne/modules/phpgwapi/trunk/js/tinymce/other/docs/tinymce_api/overview-summary.html
    people/sigurdne/modules/phpgwapi/trunk/js/tinymce/other/docs/tinymce_api/overview-tree.html
    people/sigurdne/modules/phpgwapi/trunk/js/tinymce/other/docs/tinymce_api/stylesheet.css
    people/sigurdne/modules/phpgwapi/trunk/js/tinymce/other/examples/
    people/sigurdne/modules/phpgwapi/trunk/js/tinymce/other/examples/example_advanced.css
    people/sigurdne/modules/phpgwapi/trunk/js/tinymce/other/examples/example_advanced.htm
    people/sigurdne/modules/phpgwapi/trunk/js/tinymce/other/examples/example_flash_list.js
    people/sigurdne/modules/phpgwapi/trunk/js/tinymce/other/examples/example_full.css
    people/sigurdne/modules/phpgwapi/trunk/js/tinymce/other/examples/example_full.htm
    people/sigurdne/modules/phpgwapi/trunk/js/tinymce/other/examples/example_image_list.js
    people/sigurdne/modules/phpgwapi/trunk/js/tinymce/other/examples/example_link_list.js
    people/sigurdne/modules/phpgwapi/trunk/js/tinymce/other/examples/example_simple.htm
    people/sigurdne/modules/phpgwapi/trunk/js/tinymce/other/examples/example_word.css
    people/sigurdne/modules/phpgwapi/trunk/js/tinymce/other/examples/example_word.htm
    people/sigurdne/modules/phpgwapi/trunk/js/tinymce/other/examples/logo.jpg
    people/sigurdne/modules/phpgwapi/trunk/js/tinymce/other/examples/logo_over.jpg
    people/sigurdne/modules/phpgwapi/trunk/js/tinymce/other/examples/testcases/
    people/sigurdne/modules/phpgwapi/trunk/js/tinymce/other/examples/testcases/absolute_urls.htm
    people/sigurdne/modules/phpgwapi/trunk/js/tinymce/other/examples/testcases/ask_mode.htm
    people/sigurdne/modules/phpgwapi/trunk/js/tinymce/other/examples/testcases/cleanup.htm
    people/sigurdne/modules/phpgwapi/trunk/js/tinymce/other/examples/testcases/dump.php
    people/sigurdne/modules/phpgwapi/trunk/js/tinymce/other/examples/testcases/external_plugin.htm
    people/sigurdne/modules/phpgwapi/trunk/js/tinymce/other/examples/testcases/flash/
    people/sigurdne/modules/phpgwapi/trunk/js/tinymce/other/examples/testcases/flash/flash1.swf
    people/sigurdne/modules/phpgwapi/trunk/js/tinymce/other/examples/testcases/hide_show_div.htm
    people/sigurdne/modules/phpgwapi/trunk/js/tinymce/other/examples/testcases/images/
    people/sigurdne/modules/phpgwapi/trunk/js/tinymce/other/examples/testcases/images/gotmoxie.png
    people/sigurdne/modules/phpgwapi/trunk/js/tinymce/other/examples/testcases/index.htm
    people/sigurdne/modules/phpgwapi/trunk/js/tinymce/other/examples/testcases/inlinepopups.htm
    people/sigurdne/modules/phpgwapi/trunk/js/tinymce/other/examples/testcases/media.htm
    people/sigurdne/modules/phpgwapi/trunk/js/tinymce/other/examples/testcases/multiple_configs.htm
    people/sigurdne/modules/phpgwapi/trunk/js/tinymce/other/examples/testcases/multiple_instances.htm
    people/sigurdne/modules/phpgwapi/trunk/js/tinymce/other/examples/testcases/prototype.htm
    people/sigurdne/modules/phpgwapi/trunk/js/tinymce/other/examples/testcases/prototype.js
    people/sigurdne/modules/phpgwapi/trunk/js/tinymce/other/examples/testcases/relative_urls.htm
    people/sigurdne/modules/phpgwapi/trunk/js/tinymce/other/examples/testcases/selectors.htm
    people/sigurdne/modules/phpgwapi/trunk/js/tinymce/other/examples/testcases/tables.htm
    people/sigurdne/modules/phpgwapi/trunk/js/tinymce/other/examples/testcases/test/
    people/sigurdne/modules/phpgwapi/trunk/js/tinymce/other/examples/testcases/test/css/
    people/sigurdne/modules/phpgwapi/trunk/js/tinymce/other/examples/testcases/test/css/content.css
    people/sigurdne/modules/phpgwapi/trunk/js/tinymce/other/examples/testcases/test/editor_plugin.js
    people/sigurdne/modules/phpgwapi/trunk/js/tinymce/other/examples/testcases/test/editor_plugin_src.js
    people/sigurdne/modules/phpgwapi/trunk/js/tinymce/other/examples/testcases/test/images/
    people/sigurdne/modules/phpgwapi/trunk/js/tinymce/other/examples/testcases/test/images/test.gif
    people/sigurdne/modules/phpgwapi/trunk/js/tinymce/other/examples/testcases/test/langs/
    people/sigurdne/modules/phpgwapi/trunk/js/tinymce/other/examples/testcases/test/langs/en.js
    people/sigurdne/modules/phpgwapi/trunk/js/tinymce/other/examples/testcases/toggle_editor.htm
    people/sigurdne/modules/phpgwapi/trunk/js/tinymce/other/examples/testcases/xhtml.htm
    people/sigurdne/modules/phpgwapi/trunk/js/tinymce/other/jsdoc.bat
    people/sigurdne/modules/phpgwapi/trunk/js/tinymce/other/readme
    people/sigurdne/modules/phpgwapi/trunk/js/tinymce/plugins/
    people/sigurdne/modules/phpgwapi/trunk/js/tinymce/plugins/_template/
    people/sigurdne/modules/phpgwapi/trunk/js/tinymce/plugins/_template/editor_plugin.js
    people/sigurdne/modules/phpgwapi/trunk/js/tinymce/plugins/_template/editor_plugin_src.js
    people/sigurdne/modules/phpgwapi/trunk/js/tinymce/plugins/_template/images/
    people/sigurdne/modules/phpgwapi/trunk/js/tinymce/plugins/_template/images/template.gif
    people/sigurdne/modules/phpgwapi/trunk/js/tinymce/plugins/_template/langs/
    people/sigurdne/modules/phpgwapi/trunk/js/tinymce/plugins/_template/langs/en.js
    people/sigurdne/modules/phpgwapi/trunk/js/tinymce/plugins/_template/popup.htm
    people/sigurdne/modules/phpgwapi/trunk/js/tinymce/plugins/_template/readme.txt
    people/sigurdne/modules/phpgwapi/trunk/js/tinymce/plugins/advhr/
    people/sigurdne/modules/phpgwapi/trunk/js/tinymce/plugins/advhr/css/
    people/sigurdne/modules/phpgwapi/trunk/js/tinymce/plugins/advhr/css/advhr.css
    people/sigurdne/modules/phpgwapi/trunk/js/tinymce/plugins/advhr/editor_plugin.js
    people/sigurdne/modules/phpgwapi/trunk/js/tinymce/plugins/advhr/editor_plugin_src.js
    people/sigurdne/modules/phpgwapi/trunk/js/tinymce/plugins/advhr/images/
    people/sigurdne/modules/phpgwapi/trunk/js/tinymce/plugins/advhr/images/advhr.gif
    people/sigurdne/modules/phpgwapi/trunk/js/tinymce/plugins/advhr/jscripts/
    people/sigurdne/modules/phpgwapi/trunk/js/tinymce/plugins/advhr/jscripts/rule.js
    people/sigurdne/modules/phpgwapi/trunk/js/tinymce/plugins/advhr/langs/
    people/sigurdne/modules/phpgwapi/trunk/js/tinymce/plugins/advhr/langs/en.js
    people/sigurdne/modules/phpgwapi/trunk/js/tinymce/plugins/advhr/readme.txt
    people/sigurdne/modules/phpgwapi/trunk/js/tinymce/plugins/advhr/rule.htm
    people/sigurdne/modules/phpgwapi/trunk/js/tinymce/plugins/advimage/
    people/sigurdne/modules/phpgwapi/trunk/js/tinymce/plugins/advimage/css/
    people/sigurdne/modules/phpgwapi/trunk/js/tinymce/plugins/advimage/css/advimage.css
    people/sigurdne/modules/phpgwapi/trunk/js/tinymce/plugins/advimage/editor_plugin.js
    people/sigurdne/modules/phpgwapi/trunk/js/tinymce/plugins/advimage/editor_plugin_src.js
    people/sigurdne/modules/phpgwapi/trunk/js/tinymce/plugins/advimage/image.htm
    people/sigurdne/modules/phpgwapi/trunk/js/tinymce/plugins/advimage/images/
    people/sigurdne/modules/phpgwapi/trunk/js/tinymce/plugins/advimage/images/sample.gif
    people/sigurdne/modules/phpgwapi/trunk/js/tinymce/plugins/advimage/jscripts/
    people/sigurdne/modules/phpgwapi/trunk/js/tinymce/plugins/advimage/jscripts/functions.js
    people/sigurdne/modules/phpgwapi/trunk/js/tinymce/plugins/advimage/langs/
    people/sigurdne/modules/phpgwapi/trunk/js/tinymce/plugins/advimage/langs/en.js
    people/sigurdne/modules/phpgwapi/trunk/js/tinymce/plugins/advimage/readme.txt
    people/sigurdne/modules/phpgwapi/trunk/js/tinymce/plugins/advlink/
    people/sigurdne/modules/phpgwapi/trunk/js/tinymce/plugins/advlink/css/
    people/sigurdne/modules/phpgwapi/trunk/js/tinymce/plugins/advlink/css/advlink.css
    people/sigurdne/modules/phpgwapi/trunk/js/tinymce/plugins/advlink/editor_plugin.js
    people/sigurdne/modules/phpgwapi/trunk/js/tinymce/plugins/advlink/editor_plugin_src.js
    people/sigurdne/modules/phpgwapi/trunk/js/tinymce/plugins/advlink/jscripts/
    people/sigurdne/modules/phpgwapi/trunk/js/tinymce/plugins/advlink/jscripts/functions.js
    people/sigurdne/modules/phpgwapi/trunk/js/tinymce/plugins/advlink/langs/
    people/sigurdne/modules/phpgwapi/trunk/js/tinymce/plugins/advlink/langs/en.js
    people/sigurdne/modules/phpgwapi/trunk/js/tinymce/plugins/advlink/link.htm
    people/sigurdne/modules/phpgwapi/trunk/js/tinymce/plugins/advlink/readme.txt
    people/sigurdne/modules/phpgwapi/trunk/js/tinymce/plugins/autosave/
    people/sigurdne/modules/phpgwapi/trunk/js/tinymce/plugins/autosave/editor_plugin.js
    people/sigurdne/modules/phpgwapi/trunk/js/tinymce/plugins/autosave/editor_plugin_src.js
    people/sigurdne/modules/phpgwapi/trunk/js/tinymce/plugins/autosave/langs/
    people/sigurdne/modules/phpgwapi/trunk/js/tinymce/plugins/autosave/langs/en.js
    people/sigurdne/modules/phpgwapi/trunk/js/tinymce/plugins/autosave/readme.txt
    people/sigurdne/modules/phpgwapi/trunk/js/tinymce/plugins/cleanup/
    people/sigurdne/modules/phpgwapi/trunk/js/tinymce/plugins/cleanup/editor_plugin_src.js
    people/sigurdne/modules/phpgwapi/trunk/js/tinymce/plugins/cleanup/readme.txt
    people/sigurdne/modules/phpgwapi/trunk/js/tinymce/plugins/contextmenu/
    people/sigurdne/modules/phpgwapi/trunk/js/tinymce/plugins/contextmenu/css/
    people/sigurdne/modules/phpgwapi/trunk/js/tinymce/plugins/contextmenu/css/contextmenu.css
    people/sigurdne/modules/phpgwapi/trunk/js/tinymce/plugins/contextmenu/editor_plugin.js
    people/sigurdne/modules/phpgwapi/trunk/js/tinymce/plugins/contextmenu/editor_plugin_src.js
    people/sigurdne/modules/phpgwapi/trunk/js/tinymce/plugins/contextmenu/images/
    people/sigurdne/modules/phpgwapi/trunk/js/tinymce/plugins/contextmenu/images/spacer.gif
    people/sigurdne/modules/phpgwapi/trunk/js/tinymce/plugins/contextmenu/readme.txt
    people/sigurdne/modules/phpgwapi/trunk/js/tinymce/plugins/directionality/
    people/sigurdne/modules/phpgwapi/trunk/js/tinymce/plugins/directionality/editor_plugin.js
    people/sigurdne/modules/phpgwapi/trunk/js/tinymce/plugins/directionality/editor_plugin_src.js
    people/sigurdne/modules/phpgwapi/trunk/js/tinymce/plugins/directionality/images/
    people/sigurdne/modules/phpgwapi/trunk/js/tinymce/plugins/directionality/images/ltr.gif
    people/sigurdne/modules/phpgwapi/trunk/js/tinymce/plugins/directionality/images/rtl.gif
    people/sigurdne/modules/phpgwapi/trunk/js/tinymce/plugins/directionality/langs/
    people/sigurdne/modules/phpgwapi/trunk/js/tinymce/plugins/directionality/langs/en.js
    people/sigurdne/modules/phpgwapi/trunk/js/tinymce/plugins/directionality/readme.txt
    people/sigurdne/modules/phpgwapi/trunk/js/tinymce/plugins/emotions/
    people/sigurdne/modules/phpgwapi/trunk/js/tinymce/plugins/emotions/editor_plugin.js
    people/sigurdne/modules/phpgwapi/trunk/js/tinymce/plugins/emotions/editor_plugin_src.js
    people/sigurdne/modules/phpgwapi/trunk/js/tinymce/plugins/emotions/emotions.htm
    people/sigurdne/modules/phpgwapi/trunk/js/tinymce/plugins/emotions/images/
    people/sigurdne/modules/phpgwapi/trunk/js/tinymce/plugins/emotions/images/emotions.gif
    people/sigurdne/modules/phpgwapi/trunk/js/tinymce/plugins/emotions/images/readme.txt
    people/sigurdne/modules/phpgwapi/trunk/js/tinymce/plugins/emotions/images/smiley-cool.gif
    people/sigurdne/modules/phpgwapi/trunk/js/tinymce/plugins/emotions/images/smiley-cry.gif
    people/sigurdne/modules/phpgwapi/trunk/js/tinymce/plugins/emotions/images/smiley-embarassed.gif
    people/sigurdne/modules/phpgwapi/trunk/js/tinymce/plugins/emotions/images/smiley-foot-in-mouth.gif
    people/sigurdne/modules/phpgwapi/trunk/js/tinymce/plugins/emotions/images/smiley-frown.gif
    people/sigurdne/modules/phpgwapi/trunk/js/tinymce/plugins/emotions/images/smiley-innocent.gif
    people/sigurdne/modules/phpgwapi/trunk/js/tinymce/plugins/emotions/images/smiley-kiss.gif
    people/sigurdne/modules/phpgwapi/trunk/js/tinymce/plugins/emotions/images/smiley-laughing.gif
    people/sigurdne/modules/phpgwapi/trunk/js/tinymce/plugins/emotions/images/smiley-money-mouth.gif
    people/sigurdne/modules/phpgwapi/trunk/js/tinymce/plugins/emotions/images/smiley-sealed.gif
    people/sigurdne/modules/phpgwapi/trunk/js/tinymce/plugins/emotions/images/smiley-smile.gif
    people/sigurdne/modules/phpgwapi/trunk/js/tinymce/plugins/emotions/images/smiley-surprised.gif
    people/sigurdne/modules/phpgwapi/trunk/js/tinymce/plugins/emotions/images/smiley-tongue-out.gif
    people/sigurdne/modules/phpgwapi/trunk/js/tinymce/plugins/emotions/images/smiley-undecided.gif
    people/sigurdne/modules/phpgwapi/trunk/js/tinymce/plugins/emotions/images/smiley-wink.gif
    people/sigurdne/modules/phpgwapi/trunk/js/tinymce/plugins/emotions/images/smiley-yell.gif
    people/sigurdne/modules/phpgwapi/trunk/js/tinymce/plugins/emotions/jscripts/
    people/sigurdne/modules/phpgwapi/trunk/js/tinymce/plugins/emotions/jscripts/functions.js
    people/sigurdne/modules/phpgwapi/trunk/js/tinymce/plugins/emotions/langs/
    people/sigurdne/modules/phpgwapi/trunk/js/tinymce/plugins/emotions/langs/en.js
    people/sigurdne/modules/phpgwapi/trunk/js/tinymce/plugins/emotions/readme.txt
    people/sigurdne/modules/phpgwapi/trunk/js/tinymce/plugins/flash/
    people/sigurdne/modules/phpgwapi/trunk/js/tinymce/plugins/flash/css/
    people/sigurdne/modules/phpgwapi/trunk/js/tinymce/plugins/flash/css/content.css
    people/sigurdne/modules/phpgwapi/trunk/js/tinymce/plugins/flash/css/flash.css
    people/sigurdne/modules/phpgwapi/trunk/js/tinymce/plugins/flash/editor_plugin.js
    people/sigurdne/modules/phpgwapi/trunk/js/tinymce/plugins/flash/editor_plugin_src.js
    people/sigurdne/modules/phpgwapi/trunk/js/tinymce/plugins/flash/flash.htm
    people/sigurdne/modules/phpgwapi/trunk/js/tinymce/plugins/flash/images/
    people/sigurdne/modules/phpgwapi/trunk/js/tinymce/plugins/flash/images/flash.gif
    people/sigurdne/modules/phpgwapi/trunk/js/tinymce/plugins/flash/jscripts/
    people/sigurdne/modules/phpgwapi/trunk/js/tinymce/plugins/flash/jscripts/flash.js
    people/sigurdne/modules/phpgwapi/trunk/js/tinymce/plugins/flash/langs/
    people/sigurdne/modules/phpgwapi/trunk/js/tinymce/plugins/flash/langs/en.js
    people/sigurdne/modules/phpgwapi/trunk/js/tinymce/plugins/flash/readme.txt
    people/sigurdne/modules/phpgwapi/trunk/js/tinymce/plugins/fullpage/
    people/sigurdne/modules/phpgwapi/trunk/js/tinymce/plugins/fullpage/blank.htm
    people/sigurdne/modules/phpgwapi/trunk/js/tinymce/plugins/fullpage/css/
    people/sigurdne/modules/phpgwapi/trunk/js/tinymce/plugins/fullpage/css/fullpage.css
    people/sigurdne/modules/phpgwapi/trunk/js/tinymce/plugins/fullpage/editor_plugin.js
    people/sigurdne/modules/phpgwapi/trunk/js/tinymce/plugins/fullpage/editor_plugin_src.js
    people/sigurdne/modules/phpgwapi/trunk/js/tinymce/plugins/fullpage/fullpage.htm
    people/sigurdne/modules/phpgwapi/trunk/js/tinymce/plugins/fullpage/images/
    people/sigurdne/modules/phpgwapi/trunk/js/tinymce/plugins/fullpage/images/add.gif
    people/sigurdne/modules/phpgwapi/trunk/js/tinymce/plugins/fullpage/images/fullpage.gif
    people/sigurdne/modules/phpgwapi/trunk/js/tinymce/plugins/fullpage/images/move_down.gif
    people/sigurdne/modules/phpgwapi/trunk/js/tinymce/plugins/fullpage/images/move_up.gif
    people/sigurdne/modules/phpgwapi/trunk/js/tinymce/plugins/fullpage/images/remove.gif
    people/sigurdne/modules/phpgwapi/trunk/js/tinymce/plugins/fullpage/jscripts/
    people/sigurdne/modules/phpgwapi/trunk/js/tinymce/plugins/fullpage/jscripts/fullpage.js
    people/sigurdne/modules/phpgwapi/trunk/js/tinymce/plugins/fullpage/langs/
    people/sigurdne/modules/phpgwapi/trunk/js/tinymce/plugins/fullpage/langs/en.js
    people/sigurdne/modules/phpgwapi/trunk/js/tinymce/plugins/fullscreen/
    people/sigurdne/modules/phpgwapi/trunk/js/tinymce/plugins/fullscreen/editor_plugin.js
    people/sigurdne/modules/phpgwapi/trunk/js/tinymce/plugins/fullscreen/editor_plugin_src.js
    people/sigurdne/modules/phpgwapi/trunk/js/tinymce/plugins/fullscreen/fullscreen.htm
    people/sigurdne/modules/phpgwapi/trunk/js/tinymce/plugins/fullscreen/images/
    people/sigurdne/modules/phpgwapi/trunk/js/tinymce/plugins/fullscreen/images/fullscreen.gif
    people/sigurdne/modules/phpgwapi/trunk/js/tinymce/plugins/fullscreen/langs/
    people/sigurdne/modules/phpgwapi/trunk/js/tinymce/plugins/fullscreen/langs/en.js
    people/sigurdne/modules/phpgwapi/trunk/js/tinymce/plugins/fullscreen/readme.txt
    people/sigurdne/modules/phpgwapi/trunk/js/tinymce/plugins/iespell/
    people/sigurdne/modules/phpgwapi/trunk/js/tinymce/plugins/iespell/editor_plugin.js
    people/sigurdne/modules/phpgwapi/trunk/js/tinymce/plugins/iespell/editor_plugin_src.js
    people/sigurdne/modules/phpgwapi/trunk/js/tinymce/plugins/iespell/images/
    people/sigurdne/modules/phpgwapi/trunk/js/tinymce/plugins/iespell/images/iespell.gif
    people/sigurdne/modules/phpgwapi/trunk/js/tinymce/plugins/iespell/langs/
    people/sigurdne/modules/phpgwapi/trunk/js/tinymce/plugins/iespell/langs/en.js
    people/sigurdne/modules/phpgwapi/trunk/js/tinymce/plugins/iespell/readme.txt
    people/sigurdne/modules/phpgwapi/trunk/js/tinymce/plugins/inlinepopups/
    people/sigurdne/modules/phpgwapi/trunk/js/tinymce/plugins/inlinepopups/css/
    people/sigurdne/modules/phpgwapi/trunk/js/tinymce/plugins/inlinepopups/css/inlinepopup.css
    people/sigurdne/modules/phpgwapi/trunk/js/tinymce/plugins/inlinepopups/editor_plugin.js
    people/sigurdne/modules/phpgwapi/trunk/js/tinymce/plugins/inlinepopups/editor_plugin_src.js
    people/sigurdne/modules/phpgwapi/trunk/js/tinymce/plugins/inlinepopups/images/
    people/sigurdne/modules/phpgwapi/trunk/js/tinymce/plugins/inlinepopups/images/spacer.gif
    people/sigurdne/modules/phpgwapi/trunk/js/tinymce/plugins/inlinepopups/images/window_close.gif
    people/sigurdne/modules/phpgwapi/trunk/js/tinymce/plugins/inlinepopups/images/window_maximize.gif
    people/sigurdne/modules/phpgwapi/trunk/js/tinymce/plugins/inlinepopups/images/window_minimize.gif
    people/sigurdne/modules/phpgwapi/trunk/js/tinymce/plugins/inlinepopups/images/window_resize.gif
    people/sigurdne/modules/phpgwapi/trunk/js/tinymce/plugins/inlinepopups/jscripts/
    people/sigurdne/modules/phpgwapi/trunk/js/tinymce/plugins/inlinepopups/jscripts/mcwindows.js
    people/sigurdne/modules/phpgwapi/trunk/js/tinymce/plugins/insertdatetime/
    people/sigurdne/modules/phpgwapi/trunk/js/tinymce/plugins/insertdatetime/editor_plugin.js
    people/sigurdne/modules/phpgwapi/trunk/js/tinymce/plugins/insertdatetime/editor_plugin_src.js
    people/sigurdne/modules/phpgwapi/trunk/js/tinymce/plugins/insertdatetime/images/
    people/sigurdne/modules/phpgwapi/trunk/js/tinymce/plugins/insertdatetime/images/insertdate.gif
    people/sigurdne/modules/phpgwapi/trunk/js/tinymce/plugins/insertdatetime/images/inserttime.gif
    people/sigurdne/modules/phpgwapi/trunk/js/tinymce/plugins/insertdatetime/langs/
    people/sigurdne/modules/phpgwapi/trunk/js/tinymce/plugins/insertdatetime/langs/en.js
    people/sigurdne/modules/phpgwapi/trunk/js/tinymce/plugins/insertdatetime/readme.txt
    people/sigurdne/modules/phpgwapi/trunk/js/tinymce/plugins/noneditable/
    people/sigurdne/modules/phpgwapi/trunk/js/tinymce/plugins/noneditable/css/
    people/sigurdne/modules/phpgwapi/trunk/js/tinymce/plugins/noneditable/css/noneditable.css
    people/sigurdne/modules/phpgwapi/trunk/js/tinymce/plugins/noneditable/editor_plugin.js
    people/sigurdne/modules/phpgwapi/trunk/js/tinymce/plugins/noneditable/editor_plugin_src.js
    people/sigurdne/modules/phpgwapi/trunk/js/tinymce/plugins/noneditable/readme.txt
    people/sigurdne/modules/phpgwapi/trunk/js/tinymce/plugins/paste/
    people/sigurdne/modules/phpgwapi/trunk/js/tinymce/plugins/paste/blank.htm
    people/sigurdne/modules/phpgwapi/trunk/js/tinymce/plugins/paste/css/
    people/sigurdne/modules/phpgwapi/trunk/js/tinymce/plugins/paste/css/blank.css
    people/sigurdne/modules/phpgwapi/trunk/js/tinymce/plugins/paste/css/pasteword.css
    people/sigurdne/modules/phpgwapi/trunk/js/tinymce/plugins/paste/editor_plugin.js
    people/sigurdne/modules/phpgwapi/trunk/js/tinymce/plugins/paste/editor_plugin_src.js
    people/sigurdne/modules/phpgwapi/trunk/js/tinymce/plugins/paste/images/
    people/sigurdne/modules/phpgwapi/trunk/js/tinymce/plugins/paste/images/pastetext.gif
    people/sigurdne/modules/phpgwapi/trunk/js/tinymce/plugins/paste/images/pasteword.gif
    people/sigurdne/modules/phpgwapi/trunk/js/tinymce/plugins/paste/images/selectall.gif
    people/sigurdne/modules/phpgwapi/trunk/js/tinymce/plugins/paste/jscripts/
    people/sigurdne/modules/phpgwapi/trunk/js/tinymce/plugins/paste/jscripts/pastetext.js
    people/sigurdne/modules/phpgwapi/trunk/js/tinymce/plugins/paste/jscripts/pasteword.js
    people/sigurdne/modules/phpgwapi/trunk/js/tinymce/plugins/paste/langs/
    people/sigurdne/modules/phpgwapi/trunk/js/tinymce/plugins/paste/langs/en.js
    people/sigurdne/modules/phpgwapi/trunk/js/tinymce/plugins/paste/pastetext.htm
    people/sigurdne/modules/phpgwapi/trunk/js/tinymce/plugins/paste/pasteword.htm
    people/sigurdne/modules/phpgwapi/trunk/js/tinymce/plugins/paste/readme.txt
    people/sigurdne/modules/phpgwapi/trunk/js/tinymce/plugins/preview/
    people/sigurdne/modules/phpgwapi/trunk/js/tinymce/plugins/preview/editor_plugin.js
    people/sigurdne/modules/phpgwapi/trunk/js/tinymce/plugins/preview/editor_plugin_src.js
    people/sigurdne/modules/phpgwapi/trunk/js/tinymce/plugins/preview/example.html
    people/sigurdne/modules/phpgwapi/trunk/js/tinymce/plugins/preview/images/
    people/sigurdne/modules/phpgwapi/trunk/js/tinymce/plugins/preview/images/preview.gif
    people/sigurdne/modules/phpgwapi/trunk/js/tinymce/plugins/preview/langs/
    people/sigurdne/modules/phpgwapi/trunk/js/tinymce/plugins/preview/langs/en.js
    people/sigurdne/modules/phpgwapi/trunk/js/tinymce/plugins/preview/readme.txt
    people/sigurdne/modules/phpgwapi/trunk/js/tinymce/plugins/print/
    people/sigurdne/modules/phpgwapi/trunk/js/tinymce/plugins/print/editor_plugin.js
    people/sigurdne/modules/phpgwapi/trunk/js/tinymce/plugins/print/editor_plugin_src.js
    people/sigurdne/modules/phpgwapi/trunk/js/tinymce/plugins/print/images/
    people/sigurdne/modules/phpgwapi/trunk/js/tinymce/plugins/print/images/print.gif
    people/sigurdne/modules/phpgwapi/trunk/js/tinymce/plugins/print/langs/
    people/sigurdne/modules/phpgwapi/trunk/js/tinymce/plugins/print/langs/en.js
    people/sigurdne/modules/phpgwapi/trunk/js/tinymce/plugins/print/readme.txt
    people/sigurdne/modules/phpgwapi/trunk/js/tinymce/plugins/readme.txt
    people/sigurdne/modules/phpgwapi/trunk/js/tinymce/plugins/save/
    people/sigurdne/modules/phpgwapi/trunk/js/tinymce/plugins/save/editor_plugin.js
    people/sigurdne/modules/phpgwapi/trunk/js/tinymce/plugins/save/editor_plugin_src.js
    people/sigurdne/modules/phpgwapi/trunk/js/tinymce/plugins/save/images/
    people/sigurdne/modules/phpgwapi/trunk/js/tinymce/plugins/save/images/save.gif
    people/sigurdne/modules/phpgwapi/trunk/js/tinymce/plugins/save/langs/
    people/sigurdne/modules/phpgwapi/trunk/js/tinymce/plugins/save/langs/en.js
    people/sigurdne/modules/phpgwapi/trunk/js/tinymce/plugins/save/readme.txt
    people/sigurdne/modules/phpgwapi/trunk/js/tinymce/plugins/searchreplace/
    people/sigurdne/modules/phpgwapi/trunk/js/tinymce/plugins/searchreplace/editor_plugin.js
    people/sigurdne/modules/phpgwapi/trunk/js/tinymce/plugins/searchreplace/editor_plugin_src.js
    people/sigurdne/modules/phpgwapi/trunk/js/tinymce/plugins/searchreplace/images/
    people/sigurdne/modules/phpgwapi/trunk/js/tinymce/plugins/searchreplace/images/replace.gif
    people/sigurdne/modules/phpgwapi/trunk/js/tinymce/plugins/searchreplace/images/search.gif
    people/sigurdne/modules/phpgwapi/trunk/js/tinymce/plugins/searchreplace/jscripts/
    people/sigurdne/modules/phpgwapi/trunk/js/tinymce/plugins/searchreplace/jscripts/replace.js
    people/sigurdne/modules/phpgwapi/trunk/js/tinymce/plugins/searchreplace/jscripts/search.js
    people/sigurdne/modules/phpgwapi/trunk/js/tinymce/plugins/searchreplace/langs/
    people/sigurdne/modules/phpgwapi/trunk/js/tinymce/plugins/searchreplace/langs/en.js
    people/sigurdne/modules/phpgwapi/trunk/js/tinymce/plugins/searchreplace/readme.txt
    people/sigurdne/modules/phpgwapi/trunk/js/tinymce/plugins/searchreplace/replace.htm
    people/sigurdne/modules/phpgwapi/trunk/js/tinymce/plugins/searchreplace/search.htm
    people/sigurdne/modules/phpgwapi/trunk/js/tinymce/plugins/table/
    people/sigurdne/modules/phpgwapi/trunk/js/tinymce/plugins/table/cell.htm
    people/sigurdne/modules/phpgwapi/trunk/js/tinymce/plugins/table/css/
    people/sigurdne/modules/phpgwapi/trunk/js/tinymce/plugins/table/css/cell.css
    people/sigurdne/modules/phpgwapi/trunk/js/tinymce/plugins/table/css/row.css
    people/sigurdne/modules/phpgwapi/trunk/js/tinymce/plugins/table/css/table.css
    people/sigurdne/modules/phpgwapi/trunk/js/tinymce/plugins/table/editor_plugin.js
    people/sigurdne/modules/phpgwapi/trunk/js/tinymce/plugins/table/editor_plugin_src.js
    people/sigurdne/modules/phpgwapi/trunk/js/tinymce/plugins/table/images/
    people/sigurdne/modules/phpgwapi/trunk/js/tinymce/plugins/table/images/buttons.gif
    people/sigurdne/modules/phpgwapi/trunk/js/tinymce/plugins/table/images/table.gif
    people/sigurdne/modules/phpgwapi/trunk/js/tinymce/plugins/table/images/table_cell_props.gif
    people/sigurdne/modules/phpgwapi/trunk/js/tinymce/plugins/table/images/table_delete.gif
    people/sigurdne/modules/phpgwapi/trunk/js/tinymce/plugins/table/images/table_delete_col.gif
    people/sigurdne/modules/phpgwapi/trunk/js/tinymce/plugins/table/images/table_delete_row.gif
    people/sigurdne/modules/phpgwapi/trunk/js/tinymce/plugins/table/images/table_insert_col_after.gif
    people/sigurdne/modules/phpgwapi/trunk/js/tinymce/plugins/table/images/table_insert_col_before.gif
    people/sigurdne/modules/phpgwapi/trunk/js/tinymce/plugins/table/images/table_insert_row_after.gif
    people/sigurdne/modules/phpgwapi/trunk/js/tinymce/plugins/table/images/table_insert_row_before.gif
    people/sigurdne/modules/phpgwapi/trunk/js/tinymce/plugins/table/images/table_merge_cells.gif
    people/sigurdne/modules/phpgwapi/trunk/js/tinymce/plugins/table/images/table_row_props.gif
    people/sigurdne/modules/phpgwapi/trunk/js/tinymce/plugins/table/images/table_split_cells.gif
    people/sigurdne/modules/phpgwapi/trunk/js/tinymce/plugins/table/jscripts/
    people/sigurdne/modules/phpgwapi/trunk/js/tinymce/plugins/table/jscripts/cell.js
    people/sigurdne/modules/phpgwapi/trunk/js/tinymce/plugins/table/jscripts/merge_cells.js
    people/sigurdne/modules/phpgwapi/trunk/js/tinymce/plugins/table/jscripts/row.js
    people/sigurdne/modules/phpgwapi/trunk/js/tinymce/plugins/table/jscripts/table.js
    people/sigurdne/modules/phpgwapi/trunk/js/tinymce/plugins/table/langs/
    people/sigurdne/modules/phpgwapi/trunk/js/tinymce/plugins/table/langs/en.js
    people/sigurdne/modules/phpgwapi/trunk/js/tinymce/plugins/table/merge_cells.htm
    people/sigurdne/modules/phpgwapi/trunk/js/tinymce/plugins/table/readme.txt
    people/sigurdne/modules/phpgwapi/trunk/js/tinymce/plugins/table/row.htm
    people/sigurdne/modules/phpgwapi/trunk/js/tinymce/plugins/table/table.htm
    people/sigurdne/modules/phpgwapi/trunk/js/tinymce/plugins/zoom/
    people/sigurdne/modules/phpgwapi/trunk/js/tinymce/plugins/zoom/editor_plugin.js
    people/sigurdne/modules/phpgwapi/trunk/js/tinymce/plugins/zoom/editor_plugin_src.js
    people/sigurdne/modules/phpgwapi/trunk/js/tinymce/plugins/zoom/readme.txt
    people/sigurdne/modules/phpgwapi/trunk/js/tinymce/readme
    people/sigurdne/modules/phpgwapi/trunk/js/tinymce/themes/
    people/sigurdne/modules/phpgwapi/trunk/js/tinymce/themes/advanced/
    people/sigurdne/modules/phpgwapi/trunk/js/tinymce/themes/advanced/about.htm
    people/sigurdne/modules/phpgwapi/trunk/js/tinymce/themes/advanced/anchor.htm
    people/sigurdne/modules/phpgwapi/trunk/js/tinymce/themes/advanced/charmap.htm
    people/sigurdne/modules/phpgwapi/trunk/js/tinymce/themes/advanced/color_picker.htm
    people/sigurdne/modules/phpgwapi/trunk/js/tinymce/themes/advanced/css/
    people/sigurdne/modules/phpgwapi/trunk/js/tinymce/themes/advanced/css/editor_content.css
    people/sigurdne/modules/phpgwapi/trunk/js/tinymce/themes/advanced/css/editor_popup.css
    people/sigurdne/modules/phpgwapi/trunk/js/tinymce/themes/advanced/css/editor_ui.css
    people/sigurdne/modules/phpgwapi/trunk/js/tinymce/themes/advanced/docs/
    people/sigurdne/modules/phpgwapi/trunk/js/tinymce/themes/advanced/docs/en/
    people/sigurdne/modules/phpgwapi/trunk/js/tinymce/themes/advanced/docs/en/about.htm
    people/sigurdne/modules/phpgwapi/trunk/js/tinymce/themes/advanced/docs/en/common_buttons.htm
    people/sigurdne/modules/phpgwapi/trunk/js/tinymce/themes/advanced/docs/en/create_accessible_content.htm
    people/sigurdne/modules/phpgwapi/trunk/js/tinymce/themes/advanced/docs/en/images/
    people/sigurdne/modules/phpgwapi/trunk/js/tinymce/themes/advanced/docs/en/images/insert_anchor_window.gif
    people/sigurdne/modules/phpgwapi/trunk/js/tinymce/themes/advanced/docs/en/images/insert_image_window.gif
    people/sigurdne/modules/phpgwapi/trunk/js/tinymce/themes/advanced/docs/en/images/insert_link_window.gif
    people/sigurdne/modules/phpgwapi/trunk/js/tinymce/themes/advanced/docs/en/images/insert_table_window.gif
    people/sigurdne/modules/phpgwapi/trunk/js/tinymce/themes/advanced/docs/en/index.htm
    people/sigurdne/modules/phpgwapi/trunk/js/tinymce/themes/advanced/docs/en/insert_anchor_button.htm
    people/sigurdne/modules/phpgwapi/trunk/js/tinymce/themes/advanced/docs/en/insert_image_button.htm
    people/sigurdne/modules/phpgwapi/trunk/js/tinymce/themes/advanced/docs/en/insert_link_button.htm
    people/sigurdne/modules/phpgwapi/trunk/js/tinymce/themes/advanced/docs/en/insert_table_button.htm
    people/sigurdne/modules/phpgwapi/trunk/js/tinymce/themes/advanced/docs/en/style.css
    people/sigurdne/modules/phpgwapi/trunk/js/tinymce/themes/advanced/editor_template.js
    people/sigurdne/modules/phpgwapi/trunk/js/tinymce/themes/advanced/editor_template_src.js
    people/sigurdne/modules/phpgwapi/trunk/js/tinymce/themes/advanced/image.htm
    people/sigurdne/modules/phpgwapi/trunk/js/tinymce/themes/advanced/images/
    people/sigurdne/modules/phpgwapi/trunk/js/tinymce/themes/advanced/images/anchor.gif
    people/sigurdne/modules/phpgwapi/trunk/js/tinymce/themes/advanced/images/anchor_symbol.gif
    people/sigurdne/modules/phpgwapi/trunk/js/tinymce/themes/advanced/images/backcolor.gif
    people/sigurdne/modules/phpgwapi/trunk/js/tinymce/themes/advanced/images/bold.gif
    people/sigurdne/modules/phpgwapi/trunk/js/tinymce/themes/advanced/images/bold_de_se.gif
    people/sigurdne/modules/phpgwapi/trunk/js/tinymce/themes/advanced/images/bold_es.gif
    people/sigurdne/modules/phpgwapi/trunk/js/tinymce/themes/advanced/images/bold_fr.gif
    people/sigurdne/modules/phpgwapi/trunk/js/tinymce/themes/advanced/images/bold_ru.gif
    people/sigurdne/modules/phpgwapi/trunk/js/tinymce/themes/advanced/images/bold_tw.gif
    people/sigurdne/modules/phpgwapi/trunk/js/tinymce/themes/advanced/images/browse.gif
    people/sigurdne/modules/phpgwapi/trunk/js/tinymce/themes/advanced/images/bullist.gif
    people/sigurdne/modules/phpgwapi/trunk/js/tinymce/themes/advanced/images/button_menu.gif
    people/sigurdne/modules/phpgwapi/trunk/js/tinymce/themes/advanced/images/buttons.gif
    people/sigurdne/modules/phpgwapi/trunk/js/tinymce/themes/advanced/images/cancel_button_bg.gif
    people/sigurdne/modules/phpgwapi/trunk/js/tinymce/themes/advanced/images/charmap.gif
    people/sigurdne/modules/phpgwapi/trunk/js/tinymce/themes/advanced/images/cleanup.gif
    people/sigurdne/modules/phpgwapi/trunk/js/tinymce/themes/advanced/images/close.gif
    people/sigurdne/modules/phpgwapi/trunk/js/tinymce/themes/advanced/images/code.gif
    people/sigurdne/modules/phpgwapi/trunk/js/tinymce/themes/advanced/images/color.gif
    people/sigurdne/modules/phpgwapi/trunk/js/tinymce/themes/advanced/images/copy.gif
    people/sigurdne/modules/phpgwapi/trunk/js/tinymce/themes/advanced/images/custom_1.gif
    people/sigurdne/modules/phpgwapi/trunk/js/tinymce/themes/advanced/images/cut.gif
    people/sigurdne/modules/phpgwapi/trunk/js/tinymce/themes/advanced/images/forecolor.gif
    people/sigurdne/modules/phpgwapi/trunk/js/tinymce/themes/advanced/images/help.gif
    people/sigurdne/modules/phpgwapi/trunk/js/tinymce/themes/advanced/images/hr.gif
    people/sigurdne/modules/phpgwapi/trunk/js/tinymce/themes/advanced/images/image.gif
    people/sigurdne/modules/phpgwapi/trunk/js/tinymce/themes/advanced/images/indent.gif
    people/sigurdne/modules/phpgwapi/trunk/js/tinymce/themes/advanced/images/insert_button_bg.gif
    people/sigurdne/modules/phpgwapi/trunk/js/tinymce/themes/advanced/images/italic.gif
    people/sigurdne/modules/phpgwapi/trunk/js/tinymce/themes/advanced/images/italic_de_se.gif
    people/sigurdne/modules/phpgwapi/trunk/js/tinymce/themes/advanced/images/italic_es.gif
    people/sigurdne/modules/phpgwapi/trunk/js/tinymce/themes/advanced/images/italic_ru.gif
    people/sigurdne/modules/phpgwapi/trunk/js/tinymce/themes/advanced/images/italic_tw.gif
    people/sigurdne/modules/phpgwapi/trunk/js/tinymce/themes/advanced/images/justifycenter.gif
    people/sigurdne/modules/phpgwapi/trunk/js/tinymce/themes/advanced/images/justifyfull.gif
    people/sigurdne/modules/phpgwapi/trunk/js/tinymce/themes/advanced/images/justifyleft.gif
    people/sigurdne/modules/phpgwapi/trunk/js/tinymce/themes/advanced/images/justifyright.gif
    people/sigurdne/modules/phpgwapi/trunk/js/tinymce/themes/advanced/images/link.gif
    people/sigurdne/modules/phpgwapi/trunk/js/tinymce/themes/advanced/images/menu_check.gif
    people/sigurdne/modules/phpgwapi/trunk/js/tinymce/themes/advanced/images/newdocument.gif
    people/sigurdne/modules/phpgwapi/trunk/js/tinymce/themes/advanced/images/numlist.gif
    people/sigurdne/modules/phpgwapi/trunk/js/tinymce/themes/advanced/images/opacity.png
    people/sigurdne/modules/phpgwapi/trunk/js/tinymce/themes/advanced/images/outdent.gif
    people/sigurdne/modules/phpgwapi/trunk/js/tinymce/themes/advanced/images/paste.gif
    people/sigurdne/modules/phpgwapi/trunk/js/tinymce/themes/advanced/images/redo.gif
    people/sigurdne/modules/phpgwapi/trunk/js/tinymce/themes/advanced/images/removeformat.gif
    people/sigurdne/modules/phpgwapi/trunk/js/tinymce/themes/advanced/images/separator.gif
    people/sigurdne/modules/phpgwapi/trunk/js/tinymce/themes/advanced/images/spacer.gif
    people/sigurdne/modules/phpgwapi/trunk/js/tinymce/themes/advanced/images/statusbar_resize.gif
    people/sigurdne/modules/phpgwapi/trunk/js/tinymce/themes/advanced/images/strikethrough.gif
    people/sigurdne/modules/phpgwapi/trunk/js/tinymce/themes/advanced/images/sub.gif
    people/sigurdne/modules/phpgwapi/trunk/js/tinymce/themes/advanced/images/sup.gif
    people/sigurdne/modules/phpgwapi/trunk/js/tinymce/themes/advanced/images/underline.gif
    people/sigurdne/modules/phpgwapi/trunk/js/tinymce/themes/advanced/images/underline_es.gif
    people/sigurdne/modules/phpgwapi/trunk/js/tinymce/themes/advanced/images/underline_fr.gif
    people/sigurdne/modules/phpgwapi/trunk/js/tinymce/themes/advanced/images/underline_ru.gif
    people/sigurdne/modules/phpgwapi/trunk/js/tinymce/themes/advanced/images/underline_tw.gif
    people/sigurdne/modules/phpgwapi/trunk/js/tinymce/themes/advanced/images/undo.gif
    people/sigurdne/modules/phpgwapi/trunk/js/tinymce/themes/advanced/images/unlink.gif
    people/sigurdne/modules/phpgwapi/trunk/js/tinymce/themes/advanced/images/visualaid.gif
    people/sigurdne/modules/phpgwapi/trunk/js/tinymce/themes/advanced/images/xp/
    people/sigurdne/modules/phpgwapi/trunk/js/tinymce/themes/advanced/images/xp/tab_bg.gif
    people/sigurdne/modules/phpgwapi/trunk/js/tinymce/themes/advanced/images/xp/tab_end.gif
    people/sigurdne/modules/phpgwapi/trunk/js/tinymce/themes/advanced/images/xp/tab_sel_bg.gif
    people/sigurdne/modules/phpgwapi/trunk/js/tinymce/themes/advanced/images/xp/tab_sel_end.gif
    people/sigurdne/modules/phpgwapi/trunk/js/tinymce/themes/advanced/images/xp/tabs_bg.gif
    people/sigurdne/modules/phpgwapi/trunk/js/tinymce/themes/advanced/jscripts/
    people/sigurdne/modules/phpgwapi/trunk/js/tinymce/themes/advanced/jscripts/about.js
    people/sigurdne/modules/phpgwapi/trunk/js/tinymce/themes/advanced/jscripts/anchor.js
    people/sigurdne/modules/phpgwapi/trunk/js/tinymce/themes/advanced/jscripts/charmap.js
    people/sigurdne/modules/phpgwapi/trunk/js/tinymce/themes/advanced/jscripts/color_picker.js
    people/sigurdne/modules/phpgwapi/trunk/js/tinymce/themes/advanced/jscripts/image.js
    people/sigurdne/modules/phpgwapi/trunk/js/tinymce/themes/advanced/jscripts/link.js
    people/sigurdne/modules/phpgwapi/trunk/js/tinymce/themes/advanced/jscripts/source_editor.js
    people/sigurdne/modules/phpgwapi/trunk/js/tinymce/themes/advanced/langs/
    people/sigurdne/modules/phpgwapi/trunk/js/tinymce/themes/advanced/langs/en.js
    people/sigurdne/modules/phpgwapi/trunk/js/tinymce/themes/advanced/link.htm
    people/sigurdne/modules/phpgwapi/trunk/js/tinymce/themes/advanced/source_editor.htm
    people/sigurdne/modules/phpgwapi/trunk/js/tinymce/themes/simple/
    people/sigurdne/modules/phpgwapi/trunk/js/tinymce/themes/simple/css/
    people/sigurdne/modules/phpgwapi/trunk/js/tinymce/themes/simple/css/editor_content.css
    people/sigurdne/modules/phpgwapi/trunk/js/tinymce/themes/simple/css/editor_popup.css
    people/sigurdne/modules/phpgwapi/trunk/js/tinymce/themes/simple/css/editor_ui.css
    people/sigurdne/modules/phpgwapi/trunk/js/tinymce/themes/simple/editor_template.js
    people/sigurdne/modules/phpgwapi/trunk/js/tinymce/themes/simple/editor_template_src.js
    people/sigurdne/modules/phpgwapi/trunk/js/tinymce/themes/simple/images/
    people/sigurdne/modules/phpgwapi/trunk/js/tinymce/themes/simple/images/bold.gif
    people/sigurdne/modules/phpgwapi/trunk/js/tinymce/themes/simple/images/bold_de_se.gif
    people/sigurdne/modules/phpgwapi/trunk/js/tinymce/themes/simple/images/bold_fr.gif
    people/sigurdne/modules/phpgwapi/trunk/js/tinymce/themes/simple/images/bold_ru.gif
    people/sigurdne/modules/phpgwapi/trunk/js/tinymce/themes/simple/images/bold_tw.gif
    people/sigurdne/modules/phpgwapi/trunk/js/tinymce/themes/simple/images/bullist.gif
    people/sigurdne/modules/phpgwapi/trunk/js/tinymce/themes/simple/images/buttons.gif
    people/sigurdne/modules/phpgwapi/trunk/js/tinymce/themes/simple/images/cleanup.gif
    people/sigurdne/modules/phpgwapi/trunk/js/tinymce/themes/simple/images/italic.gif
    people/sigurdne/modules/phpgwapi/trunk/js/tinymce/themes/simple/images/italic_de_se.gif
    people/sigurdne/modules/phpgwapi/trunk/js/tinymce/themes/simple/images/italic_ru.gif
    people/sigurdne/modules/phpgwapi/trunk/js/tinymce/themes/simple/images/italic_tw.gif
    people/sigurdne/modules/phpgwapi/trunk/js/tinymce/themes/simple/images/numlist.gif
    people/sigurdne/modules/phpgwapi/trunk/js/tinymce/themes/simple/images/redo.gif
    people/sigurdne/modules/phpgwapi/trunk/js/tinymce/themes/simple/images/separator.gif
    people/sigurdne/modules/phpgwapi/trunk/js/tinymce/themes/simple/images/spacer.gif
    people/sigurdne/modules/phpgwapi/trunk/js/tinymce/themes/simple/images/strikethrough.gif
    people/sigurdne/modules/phpgwapi/trunk/js/tinymce/themes/simple/images/underline.gif
    people/sigurdne/modules/phpgwapi/trunk/js/tinymce/themes/simple/images/underline_fr.gif
    people/sigurdne/modules/phpgwapi/trunk/js/tinymce/themes/simple/images/underline_ru.gif
    people/sigurdne/modules/phpgwapi/trunk/js/tinymce/themes/simple/images/underline_tw.gif
    people/sigurdne/modules/phpgwapi/trunk/js/tinymce/themes/simple/images/undo.gif
    people/sigurdne/modules/phpgwapi/trunk/js/tinymce/tiny_mce.js
    people/sigurdne/modules/phpgwapi/trunk/js/tinymce/tiny_mce_dev.js
    people/sigurdne/modules/phpgwapi/trunk/js/tinymce/tiny_mce_popup.js
    people/sigurdne/modules/phpgwapi/trunk/js/tinymce/tiny_mce_src.js
    people/sigurdne/modules/phpgwapi/trunk/js/tinymce/utils/
    people/sigurdne/modules/phpgwapi/trunk/js/tinymce/utils/form_utils.js
    people/sigurdne/modules/phpgwapi/trunk/js/tinymce/utils/mclayer.js
    people/sigurdne/modules/phpgwapi/trunk/js/tinymce/utils/mctabs.js
    people/sigurdne/modules/phpgwapi/trunk/js/tinymce/utils/validate.js
    people/sigurdne/modules/phpgwapi/trunk/templates/base/css/datatable.css
    people/sigurdne/modules/phpgwapi/trunk/templates/base/datatable.xsl
    people/sigurdne/modules/phpgwapi/trunk/templates/base/images/loading.gif
    people/sigurdne/modules/phpgwapi/trunk/templates/bkbooking/
    people/sigurdne/modules/phpgwapi/trunk/templates/bkbooking/css/
    people/sigurdne/modules/phpgwapi/trunk/templates/bkbooking/css/frontend.css
    people/sigurdne/modules/phpgwapi/trunk/templates/bkbooking/footer.tpl
    people/sigurdne/modules/phpgwapi/trunk/templates/bkbooking/head.inc.php
    people/sigurdne/modules/phpgwapi/trunk/templates/bkbooking/head.tpl
    people/sigurdne/modules/phpgwapi/trunk/templates/bkbooking/images/
    people/sigurdne/modules/phpgwapi/trunk/templates/bkbooking/images/bergen_logo.png
    people/sigurdne/modules/phpgwapi/trunk/templates/bkbooking/images/header_bg.png
    people/sigurdne/modules/phpgwapi/trunk/templates/bkbooking/images/header_fg.png
    people/sigurdne/modules/phpgwapi/trunk/templates/bkbooking/images/info.png
    people/sigurdne/modules/phpgwapi/trunk/templates/bkbooking/navbar.inc.php
    people/sigurdne/modules/phpgwapi/trunk/templates/bkbooking/navbar.tpl
    people/sigurdne/modules/phpgwapi/trunk/test/
    people/sigurdne/modules/phpgwapi/trunk/test/CodeSniffer/
    people/sigurdne/modules/phpgwapi/trunk/test/CodeSniffer/README.txt
    people/sigurdne/modules/phpgwapi/trunk/test/CodeSniffer/Standards/
    people/sigurdne/modules/phpgwapi/trunk/test/CodeSniffer/Standards/phpGroupWare/
    people/sigurdne/modules/phpgwapi/trunk/test/CodeSniffer/Standards/phpGroupWare/Sniffs/
    people/sigurdne/modules/phpgwapi/trunk/test/CodeSniffer/Standards/phpGroupWare/Sniffs/Classes/
    people/sigurdne/modules/phpgwapi/trunk/test/CodeSniffer/Standards/phpGroupWare/Sniffs/Classes/ClassDeclarationSniff.php
    people/sigurdne/modules/phpgwapi/trunk/test/CodeSniffer/Standards/phpGroupWare/Sniffs/Files/
    people/sigurdne/modules/phpgwapi/trunk/test/CodeSniffer/Standards/phpGroupWare/Sniffs/Files/LineLengthSniff.php
    people/sigurdne/modules/phpgwapi/trunk/test/CodeSniffer/Standards/phpGroupWare/Sniffs/Files/disallowTrailingWhitespaceSniff.php
    people/sigurdne/modules/phpgwapi/trunk/test/CodeSniffer/Standards/phpGroupWare/Sniffs/PHP/
    people/sigurdne/modules/phpgwapi/trunk/test/CodeSniffer/Standards/phpGroupWare/Sniffs/PHP/ForbiddenFunctionsSniff.php
    people/sigurdne/modules/phpgwapi/trunk/test/CodeSniffer/Standards/phpGroupWare/phpGroupWareCodingStandard.php
    people/sigurdne/modules/phpgwapi/trunk/test/phpunit/
    people/sigurdne/modules/phpgwapi/trunk/test/phpunit/TestCustomFields.php
    people/sigurdne/modules/phpgwapi/trunk/test/phpunit/TestCustomFunctions.php
    people/sigurdne/modules/phpgwapi/trunk/test/phpunit/phpGroupWareTestSuite.php

Modified: people/sigurdne/modules/phpgwapi/trunk/cron/asyncservices.php
===================================================================
--- people/sigurdne/modules/phpgwapi/trunk/cron/asyncservices.php	2009-11-20 10:27:41 UTC (rev 20844)
+++ people/sigurdne/modules/phpgwapi/trunk/cron/asyncservices.php	2009-11-20 10:28:10 UTC (rev 20845)
@@ -27,14 +27,30 @@
 
 	unset($GLOBALS['phpgw_info']['flags']['noapi']);
 
+	$GLOBALS['phpgw_info']['server']['sessions_type'] = 'db';
+
+	$_domain_info = isset($GLOBALS['phpgw_domain'][$_GET['domain']]) ? $GLOBALS['phpgw_domain'][$_GET['domain']] : '';
+	if(!$_domain_info)
+	{
+		echo "not a valid domain\n";
+		die();
+	}
+	else
+	{
+		$GLOBALS['phpgw_domain'] = array();
+		$GLOBALS['phpgw_domain'][$_GET['domain']] = $_domain_info;
+	}
+
 	$db_type = $GLOBALS['phpgw_domain'][$_GET['domain']]['db_type'];
+	if($db_type == 'postgres')
+	{
+		$db_type = 'pgsql';
+	}
 	if (!extension_loaded($db_type) && !dl($db_type.'.so'))
 	{
 		echo "Extension '$db_type' is not loaded and can't be loaded via dl('$db_type.so') !!!\n";
 	}
 	
-	$GLOBALS['phpgw_info']['server']['sessions_type'] = 'db';
-
 	/**
 	* Include API functions
 	*/

Modified: people/sigurdne/modules/phpgwapi/trunk/doc/coding_standard.txt
===================================================================
--- people/sigurdne/modules/phpgwapi/trunk/doc/coding_standard.txt	2009-11-20 10:27:41 UTC (rev 20844)
+++ people/sigurdne/modules/phpgwapi/trunk/doc/coding_standard.txt	2009-11-20 10:28:10 UTC (rev 20845)
@@ -1,32 +1,30 @@
-phpGroupWare coding Standards
-
-Please comply with the following standard when working on phpGroupWare if you 
-want your patches accepted and modules included in supported releases.
-
 1)	Format your code so that we can read it, please!
 
 2)	Use tabs for formatting, NOT SPACES.  Tabs create smaller files and editors allow
-	developers to view a tab as however many spaces as they prefer - we use 4 spaces.
-	Spaces do not allow this. There is one exception (see #11 below).
+	developers to view a tab as however many spaces as they prefer.  Spaces do not allow this.
+	There is one exception (see #11 below).
 
-3)	Use ' instead of " for strings, where substitutions aren't required.  This is a 
-	performance issue, and prevents	a lot of inconsistent coding styles.  When using 
-	substitutions, use curly braces around your variables - like so:
-	$var = "my_var: {$my_var}";
+3)	Use ' instead of " for strings.  This is a performance issue, and prevents
+	a lot of inconsistent coding styles.
 
-4)	Comments go on the line ABOVE the code, NOT to the right of the code, unless it 
-	is very short.
+4)	Comments go on the line ABOVE the code, NOT to the right of the code!
 
-5)	All functions and methods are to be documented using PhpDocumentor - http://phpdoc.org
+5)	For each section of code put a section divider with basic explanation of the following
+	code/functions.  It should look like this:
 
+	/****************************************************************************\
+	* These functions are used to pick my nose                                   *
+	\****************************************************************************/
+
 6)	Do not document every bit of code in comments.  PHP is an interpreted language and it will be
-	nasty on performance.  Provide enough information for someone else to understand your code.
+	nasty on performance.
 
-7)	Use switch statements where many else if's are going to be used.  Switch/case is faster
+7)	Use switch statements where many elseif's are going to be used.  Switch is faster and I (who?) like it
+	better!
 
 8)	'If' statements need to use the following format:
 
-	if ( $var == 'example' )
+	if ($var == 'example')
 	{
 		echo 'This is only an example';
 	}
@@ -39,32 +37,27 @@
 
 	if ($var == 'example'){ echo 'An example'; }
 
-	OR this
-
-	if($var = 'example')
-		echo "An {$var}";
-
 	All other styles are not to be used.  This is it. Use it or I will personally come and nag you to
 	death.
 
-9)	class/function format:
+9)	ALL 'if' statements MUST have matching { } (brackets).  Do NOT create 'if' statements like this:
 
-	/**
-	 * This class is for testing
-	 *
-	 * @package phpgroupware
-	 * @subpackage module
-	 * @category testing
-	 */
-	class module_testing 
+	if ($a == b)
+		dosomething();
+
+	or:
+
+	if ($a == b) dosomething();
+
+	They make the code more difficult to read and follow.
+
+10)	class/function format:
+
+	class testing 
 	{
-		/**
-		 * Output the value of $var the user
-		 */
-		public function print_to_screen()
+		function print_to_screen()
 		{
-			$var = phpgw::get_var('var', 'string', 'GET');
-			if ( $var == 'example' )
+			if ($var == 'example')
 			{
 				echo 'This is only an example';
 			}
@@ -75,7 +68,7 @@
 		}
 	}
 
-10)	Associative arrays must be written in the following manner:
+11)	Associative arrays must be written in the following manner:
 
 	$array = array
 	(
@@ -85,14 +78,11 @@
 
 	Note that tabs are preferred around the '=>'.
 
-11)	Use the long format for <?php.  Do NOT use <?.
+12)	Use the long format for <?php.  Do NOT use <?.
 
-12)	All code should start with 1 tab.  Example:
+13)	All code should start with 1 tab.  Example:
 
 <?php
-/**
- * PhpDoc page block here
- */
 	dosomething();
 	if ($a)
 	{
@@ -108,31 +98,6 @@
 	dosomemorestuff();
 }
 
-13)	Use lower case for variable and function names.  No stubbly/mixed/camel case code.
+14)	Use lower case for variable and function names.  No stubbly-case (mixed-case) code.
 
-14)	All classes are to use the PHP5 OOP methods so they pass E_STRICT error 
-	reporting.  All instance variables are to be declared protected, unless 
-	private is really justified, the same goes for non public methods.  This
-	makes it easier to extend them in the future.
-
-15)	Classes are to be named <module_name>_<class_name> to prevent clashes - and
-	this is what createObject will expect.
-
-16)	Always use symbol based comparison operators (&&, ||) instead of text based
-	operators (AND, OR) as they are evaluated in different orders and at different
-	speeds.  This is will prevent any confusion or strange results.
-
-17)	You code must run with E_ALL error reporting turned on, E_NOTICES are ERRORS!
-	Where possible your code should run with E_STRICT error reporting.
-
-18)	All variables, classes, methods, functions and comments must be in English.
-	Bad english is easier to work with than having to babelfish code to work out
-	how it works.
-
-19)	Files should not end with an ending php tag "?>".  Any whitespace after 
-	the closing tag is sent to the browser and cause errors, so don't include
-	them.
-
-20)	If you see code which doesn't comply with the above, please fix it :)
-
-Last Updated: $Id$
+15)	Thanks for following these rules :)

Modified: people/sigurdne/modules/phpgwapi/trunk/doc/generate-class-country.php
===================================================================
--- people/sigurdne/modules/phpgwapi/trunk/doc/generate-class-country.php	2009-11-20 10:27:41 UTC (rev 20844)
+++ people/sigurdne/modules/phpgwapi/trunk/doc/generate-class-country.php	2009-11-20 10:28:10 UTC (rev 20845)
@@ -14,51 +14,19 @@
 	* @copyright Portions Copyright (C) 2006 Free Software Foundation http://www.fsf.org/
 	* @license http://www.gnu.org/licenses/gpl.html GNU General Public License
 	*/
-
-	$year = date('Y');
-
-	// Do not change this, it ensures we are using utf-8 :)
-	setlocale(LC_ALL, 'en_US.UTF-8');
-
-	$raw_file = file_get_contents('http://www.iso.ch/iso/en/prods-services/iso3166ma/02iso-3166-code-lists/list-en1-semic.txt');
-	$cc_list = explode("\r\n", $raw_file);
-	if ( count($cc_list) < 3 )
-	{
-		echo "Invalid country code list, exiting\n";
-		exit;
-	}
-	unset($cc_list[0]);
-
-
-	echo <<<CODE
-<?php
+	echo"<?php\n";
+?>
 	/**
-	* phpGroupWare - ISO 3166 Countries and Continents
-	*
-	* @auhtor Dave Hall skwashd at phpGroupWare.org
+	* Countries
 	* @author Mark Peters <[email protected]>
+	* @auhtor Dave Hall skwashd at phpGroupWare.org
 	* @author Bettine Gille ceb at phpGroupWare.org
-	* @copyright Copyright (C) 2001 - {$year} Free Software Foundation http://www.fsf.org/
+	* @copyright Copyright (C) 2001 - 2006 Free Software Foundation http://www.fsf.org/
 	* @license http://www.gnu.org/licenses/gpl.html GNU General Public License
 	* @interal do not edit, edit and run phpgwapi/doc/generate-class-country.php to regenerate this class
 	* @package phpgwapi
 	* @subpackage contacts
-	* @version \$Id: \$
-	*/
-
-	/*
-	   This program is free software: you can redistribute it and/or modify
-	   it under the terms of the GNU General Public License as published by
-	   the Free Software Foundation, either version 3 of the License, or
-	   (at your option) any later version.
-
-	   This program is distributed in the hope that it will be useful,
-	   but WITHOUT ANY WARRANTY; without even the implied warranty of
-	   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-	   GNU General Public License for more details.
-
-	   You should have received a copy of the GNU General Public License
-	   along with this program.  If not, see <http://www.gnu.org/licenses/>.
+	* @version $Id$
 	 */
 
 	/**
@@ -67,32 +35,27 @@
 	* @package phpgwapi
 	* @subpackage contacts
 	*/
-	class phpgwapi_country
+	class country
 	{
 
 		/**
-		* @var array \$continent_array a list of continents
+		* @var array $continent_array a list of continents
 		*/
-		public static \$continent_array = array
-		(
-			'africa'		=> 'Africa',
-			'antarctica'	=> 'Antarctica',
-			'asia'			=> 'Asia',
-			'australia'		=> 'Australia',
-			'europe'		=> 'Europe',
-			'northamerica'	=> 'North America',
-			'southamerica'	=> 'South America'
-		);
+		var $continent_array = array();
+<?php
+	// Do not change this, it ensures we are using utf-8 :)
+	setlocale(LC_ALL, 'en_US.UTF-8');
 
+	$raw_file = file_get_contents('http://www.iso.ch/iso/en/prods-services/iso3166ma/02iso-3166-code-lists/list-en1-semic.txt');
+	$cc_list = explode("\r\n", $raw_file);
+	if ( count($cc_list) < 3 )
+	{
+		echo "Invalid country code list, exiting\n";
+		exit;
+	}
+	unset($cc_list[0]);
 
-		/**
-		* @var array $country_array list of ISO 3166 country codes
-		*/
-		public static \$country_array = array
-		(
-
-CODE;
-
+	echo "\n\t\t/**\n\t\t* @var array \$country_array list of ISO 3166 country codes\n\t\t*/\n\t\tvar \$country_array = array\n\t\t(\n\t\t\t'  '\t=> 'Select One',\n";
 	sort($cc_list, SORT_LOCALE_STRING);
 	foreach ( $cc_list as $entry )
 	{
@@ -104,35 +67,46 @@
 		$country = explode(';', iconv('ISO-8859-1', 'UTF-8', $entry));
 		echo "\t\t\t'" . trim($country[1]) . "'\t=> '" . addslashes(trim($country[0])) . "',\n";
 	}
-	echo <<<CODE
-		);
-
-CODE
+	echo "\t\t);\n\n";
 ?>
+		/**
+		* @constructor
+		*/
+		function country()
+		{
+			$this->continent_array = array
+			(
+				'africa'		=> lang('africa'),
+				'antarctica'	=> lang('antarctica'),
+				'asia'			=> lang('asia'),
+				'australia'		=> lang('australia'),
+				'europe'		=> lang('europe'),
+				'northamerica'	=> lang('northamerica'),
+				'southamerica'	=> lang('southamerica')
+			);
+		}
 
 		/**
-		* Translate the list of countries
+		* Create a select box filled with countries
 		*
-		* @return array list of translated country names iso_code => (translated) official name
+		* @param string $selected the currently selected country
+		* @param string $name the name of the select box element in the form, used for both the id and name attributes
+		* @return string the html for a select box form element
 		*/
-		public static function get_translated_list()
-		{
-			static $translated_list = null;
-			if ( is_null($translated_list) )
+		function form_select($selected,$name='')
 			{
-				 $translated_list = array();
-				 foreach ( self::$country_array as $code => $name )
+			if($name=='')
 				 {
-				 	$translated = lang($name);
-					if ( $translated == "{$name}*" )
-					{
-						$translated = $name;
-					}
-					$translated_list[$code] = $translated;
+				$name = 'country';
 				 }
-				 asort($translated_list);
+			$str = "<select name=\"$name\" id=\"$name\">\n";
+			reset($this->country_array);
+			while(list($key,$value) = each($this->country_array))
+			{
+				$str .= ' <option value="'.$key.'"'.($selected == $key?' selected="selected"':'').'>'.$value.'</option>'."\n";
 			}
-			return $translated_list;
+			$str .= '</select>'."\n";
+			return $str;
 		}
 
 		/**
@@ -141,11 +115,11 @@
 		* @param string $code the 2 letter iso 3166 code
 		* @return string the country name, empty string if invalid
 		*/
-		public static function get_full_name($selected)
+		function get_full_name($selected)
 		{
-			if ( isset(self::$country_array[$selected]) )
+			if ( isset($this->country_array[$selected]) )
 			{
-				return(self::$country_array[$selected]);
+				return($this->country_array[$selected]);
 			}
 			return '';
 		}
@@ -157,16 +131,16 @@
 		* @param string $select_name the name of the select box element in the form
 		* @return array list of continents
 		*/
-		public function xslt_continent_select($selected = '',$select_name='')
+		function xslt_continent_select($selected = '',$select_name='')
 		{
 			$GLOBALS['phpgw']->xslttpl->add_file('countries');
 
-			foreach(self::continent_array as $cname => $ctitle)
+			foreach($this->continent_array as $cname => $ctitle)
 			{
 				$carray[] = array
 				(
 					'continent_name' 	=> $cname,
-					'continent_title'	=> lang($ctitle),
+					'continent_title'	=> $ctitle,
 					'selected'			=> $cname == $selected ? 'selected' : ''
 				);
 			}
@@ -186,11 +160,11 @@
 		* @param string $select_name the name of the select box element in the form
 		* @return array list of countries
 		*/
-		public function xslt_country_select($selected = '', $select_name='')
+		function xslt_country_select($selected = '', $select_name='')
 		{
 			$GLOBALS['phpgw']->xslttpl->add_file('countries');
 
-			foreach(self::$country_array as $ccode => $cname)
+			foreach($this->country_array as $ccode => $cname)
 			{
 				$carray[] = array
 				(
@@ -208,3 +182,4 @@
 			);
 		}
 	}
+<?php echo '?>';?>

Modified: people/sigurdne/modules/phpgwapi/trunk/doc/ldap/README
===================================================================
--- people/sigurdne/modules/phpgwapi/trunk/doc/ldap/README	2009-11-20 10:27:41 UTC (rev 20844)
+++ people/sigurdne/modules/phpgwapi/trunk/doc/ldap/README	2009-11-20 10:28:10 UTC (rev 20845)
@@ -81,3 +81,20 @@
 include		/etc/openldap/phpgwcontact.oc.conf
 include		/etc/openldap/phpgwcontact.at.conf
 
+
+
+Some useful info:
+http://howtoforge.org/installing-and-configuring-openldap-on-ubuntu-intrepid-ibex
+http://www.debuntu.org/ldap-server-and-linux-ldap-clients
+
+Modify the slapd.conf file according to your needs and update the configuration of OpenLDAP:
+
+sudo /etc/init.d/slapd stop
+cd /etc/ldap
+sudo mv slapd.d slapd.d.bck
+sudo mkdir slapd.d
+sudo slaptest -f slapd.conf -F slapd.d
+sudo chown -R openldap:openldap slapd.d
+sudo /etc/init.d/slapd start
+
+

Modified: people/sigurdne/modules/phpgwapi/trunk/doc/ldap/phpgroupware.schema
===================================================================
--- people/sigurdne/modules/phpgwapi/trunk/doc/ldap/phpgroupware.schema	2009-11-20 10:27:41 UTC (rev 20844)
+++ people/sigurdne/modules/phpgwapi/trunk/doc/ldap/phpgroupware.schema	2009-11-20 10:28:10 UTC (rev 20845)
@@ -3,9 +3,8 @@
 # REQUIRED
 attributetype ( 1.3.6.1.4.1.9554.201
 	NAME 'phpgwContactID'
-	EQUALITY caseIgnoreMatch
-	SUBSTR caseIgnoreSubstringsMatch
-	SYNTAX 1.3.6.1.4.1.1466.115.121.1.15{16}
+	EQUALITY integerMatch
+        SYNTAX 1.3.6.1.4.1.1466.115.121.1.27
 	SINGLE-VALUE )
 
 # phpgwContact
@@ -27,14 +26,13 @@
        DESC 'Quota for this user in Filemanager'
        EQUALITY integerMatch
        SYNTAX 1.3.6.1.4.1.1466.115.121.1.27
-       SINGLE-VALUE)
+        SINGLE-VALUE )
 
 #REQUIRED
 attributetype (  1.3.6.1.4.1.9554.301
         NAME 'phpgwGroupID'
-        EQUALITY caseIgnoreMatch
-        SUBSTR caseIgnoreSubstringsMatch
-        SYNTAX 1.3.6.1.4.1.1466.115.121.1.15{16}
+        EQUALITY integerMatch
+        SYNTAX 1.3.6.1.4.1.1466.115.121.1.27
         SINGLE-VALUE )
 
 # phpgwGroup
@@ -48,6 +46,10 @@
         MUST phpgwGroupID
         )
 
+#attributetype ( 1.3.6.1.1.1.1.1 NAME 'gidNumber'
+#	DESC 'An integer uniquely identifying a group in an administrative domain'
+#	EQUALITY integerMatch
+#	SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 SINGLE-VALUE )
 
 #accountID
 attributetype ( 1.3.6.1.4.1.9554.101

Modified: people/sigurdne/modules/phpgwapi/trunk/doc/soap/README
===================================================================
--- people/sigurdne/modules/phpgwapi/trunk/doc/soap/README	2009-11-20 10:27:41 UTC (rev 20844)
+++ people/sigurdne/modules/phpgwapi/trunk/doc/soap/README	2009-11-20 10:28:10 UTC (rev 20845)
@@ -1,24 +1,7 @@
-Ok, You will find in this dir, the script used to generate the soap classes in phpgwapi from the nusoap library :
+Sigurd sept 2009:
 
-This will generate the following files :
+Converted to use native support for soap.
 
-class.nusoap_base.inc.php
-class.phpgw_soapval.inc.php *
-class.soap_client.inc.php
-class.soapclient.inc.php *
-class.soap_fault.inc.php
-class.soap_parser.inc.php
-class.soap_server.inc.php
-class.soap_transport_http.inc.php
-class.soapval.inc.php
-class.soap_XMLSchema.inc.php
-class.wsdl.inc.php
+Have a look on soap/test_client.php and phpgwapi/inc/class.soap_client.php to see how it works.
 
-using the following command line :
-
-$ php nusoap2phpgwapi nusoap.php
-
-where nusoap.php is the merged file of the nusoap library from the nusoap.sourceforge.net cvs repository.
-
-The two files with * are here for compatibility only, and should be avoided if possible (use directly soap_client and soapval !)
-
+The serverpart is found in soap.php (at the root)

Modified: people/sigurdne/modules/phpgwapi/trunk/doc/vfs/webdav.txt
===================================================================
--- people/sigurdne/modules/phpgwapi/trunk/doc/vfs/webdav.txt	2009-11-20 10:27:41 UTC (rev 20844)
+++ people/sigurdne/modules/phpgwapi/trunk/doc/vfs/webdav.txt	2009-11-20 10:28:10 UTC (rev 20845)
@@ -74,3 +74,26 @@
 
 	Note that using an Apache module for authentication is not strictly
 	required in order to use WebDAV within phpGroupWare.
+	
+	
+Note:
+For svn you need the "SVNAutoversioning on", example:
+ 
+  <Location /svn/myproject>
+     DAV svn
+     SVNPath /home/svn/myproject
+     AuthType Basic
+     AuthName "myproject subversion repository"
+     AuthUserFile /etc/subversion/passwd
+	 SVNAutoversioning on
+     <LimitExcept GET PROPFIND OPTIONS REPORT>
+        Require valid-user
+     </LimitExcept>
+  </Location>
+
+When using the svn-protocoll (neede for version information)- one still needs to spesify the http-url in setup.
+
+example:
+
+svn://localhost/svn/myproject (the same as for the http-version - even if the command line url is different)
+http://localhost/svn/myproject

Modified: people/sigurdne/modules/phpgwapi/trunk/inc/accounts/class.accounts_.inc.php
===================================================================
--- people/sigurdne/modules/phpgwapi/trunk/inc/accounts/class.accounts_.inc.php	2009-11-20 10:27:41 UTC (rev 20844)
+++ people/sigurdne/modules/phpgwapi/trunk/inc/accounts/class.accounts_.inc.php	2009-11-20 10:28:10 UTC (rev 20845)
@@ -7,7 +7,7 @@
 	* @author Philipp Kamps <[email protected]>
 	* @author Dave Hall <[email protected]>
 	* @copyright Copyright (C) 2000-2008 Free Software Foundation, Inc. http://www.fsf.org/
-	* @license http://www.gnu.org/licenses/lgpl.html GNU Lesser General Public License v3 or later
+	* @license http://www.gnu.org/licenses/lgpl.html GNU Lesser General Public License v2 or later
 	* @package phpgroupware
 	* @subpackage phpgwapi
 	* @version $Id$
@@ -16,7 +16,7 @@
 	/*
 	   This program is free software: you can redistribute it and/or modify
 	   it under the terms of the GNU Lesser General Public License as published by
-	   the Free Software Foundation, either version 3 of the License, or
+	   the Free Software Foundation, either version 2 of the License, or
 	   (at your option) any later version.
 
 	   This program is distributed in the hope that it will be useful,
@@ -89,10 +89,16 @@
 		{
 			$this->db =& $GLOBALS['phpgw']->db;
 			$this->like = $this->db->like;
+			$this->join = $this->db->join;
 
 			$this->set_account($account_id, $account_type);
 		}
 
+		public function get_id()
+		{
+			return $this->account_id;
+		}
+
 		/**
 		* Add an account to a group entry
 		*
@@ -308,11 +314,10 @@
 		 */
 		public function create($account, $group, $acls = array(), $modules = array())
 		{
-			$this->db->transaction_begin();
-
+		// FIXME: Conflicting transactions - there is a transaction in acl::save_repository()
+		//	$this->db->transaction_begin();
 			try
 			{
-
 				$class = get_class($account);
 				switch( $class )
 				{
@@ -336,23 +341,28 @@
 				$this->_cache_account($account);
 
 				$aclobj =& $GLOBALS['phpgw']->acl;
-				$aclobj->set_account_id($account->id);
+				$aclobj->set_account_id($account->id, true);
 				foreach ( $acls as $acl )
 				{
 					$aclobj->add($acl['appname'], $acl['location'], $acl['rights']);
 				}
+
+				// application permissions
+				foreach ( $modules as $module)
+				{
+					$aclobj->add($module, 'run', phpgwapi_acl::READ);
+				}
+
 				$aclobj->save_repository();
-				// application permissions
-				$this->grant_account_applications($modules, ($account->id));
 			}
 			catch (Exception $e)
 			{
-				$this->db->transaction_abort();
+		//		$this->db->transaction_abort();
 				// throw it again so it can be caught higher up
 				throw $e;
 			}
 
-			$this->db->transaction_commit();
+		//	$this->db->transaction_commit();
 			return $account->id;
 		}
 
@@ -570,17 +580,21 @@
 				{
 					$this->account_id = $account;
 					$user = $this->read_repository();
+
 					$principal = array
 					(
 						'per_prefix'		=> '',
 						'per_first_name'	=> $user->firstname,
 						'per_last_name'		=> $user->lastname,
 						'access'			=> 'public',
-						'owner'				=> $GLOBALS['phpgw_info']['server']['addressmaster']
+						'owner'				=> isset ($GLOBALS['phpgw_info']['server']['addressmaster']) ? $GLOBALS['phpgw_info']['server']['addressmaster'] : ''
 					);
+
 					$contact_type = $contacts->search_contact_type('Persons');
 					$user->person_id = $contacts->add_contact($contact_type, $principal);
-					$this->update_data($user_account);
+
+		//			$this->update_data($user);
+					$this->account = $user;
 					$this->save_repository();
 				}
 			}
@@ -598,6 +612,7 @@
 		public function update_group($group, $users, $modules = null)
 		{
 			$this->account = $group;
+			$this->account_id = $group->id;
 			$this->save_repository();
 
 			// handle group memberships
@@ -606,7 +621,7 @@
 			$drop_users = array_diff($old_users, $new_users);
 			if ( is_array($drop_users) && count($drop_users) )
 			{
-				foreach ( $drop_user as $user )
+				foreach ( $drop_users as $user )
 				{
 					$this->delete_account4group($user, $group->id);
 				}
@@ -619,7 +634,12 @@
 			}
 
 			// module permissions
-			$this->grant_account_applications($modules, $group->id);
+			if ( is_array($modules) )
+			{
+				$apps = createObject('phpgwapi.applications', $group->id);
+				$apps->update_data(array_keys($modules));
+				$apps->save_repository();
+			}
 
 			// FIXME This is broken and only supports localFS VFS
 			if ( $group->old_loginid != $group->lid )
@@ -641,7 +661,7 @@
 		 *
 		 * @return void
 		 */
-		public function update_user($user, $groups, $permissions = null, $modules = null)
+		public function update_user($user, $groups, $acls = array(), $modules = null)
 		{
 			$this->set_account($user->id);
 			$this->account = $user;
@@ -670,8 +690,25 @@
 
 			//FIXME need permissions here
 
+			$aclobj =& $GLOBALS['phpgw']->acl;
+			$aclobj->set_account_id($user->id, true);
+			$aclobj->delete_repository('preferences', 'changepassword', $user->id);
+			$aclobj->delete_repository('phpgwapi', 'anonymous', $user->id);
+			$aclobj->set_account_id($user->id, true); //reread the current repository
+			foreach ( $acls as $acl )
+			{
+				$aclobj->add($acl['appname'], $acl['location'], $acl['rights']);
+			}
+
+			$aclobj->save_repository();
+
 			// application permissions
-			$this->grant_account_applications($modules, $user->id);
+			if ( is_array($modules) )
+			{
+				$apps = createObject('phpgwapi.applications', $user->id);
+				$apps->update_data($modules);
+				$apps->save_repository();
+			}
 
 			return true;
 		}
@@ -687,7 +724,7 @@
 		 */
 		public function update_data($data)
 		{
-			if ( $data['account_type'] == 'g' )
+			if ( $this->get_type($data->id) == 'g' )
 			{
 				$account = new phpgwapi_group();
 			}
@@ -852,7 +889,7 @@
 			$contacts = createObject('phpgwapi.contacts');
 
 			// does the user already exist in the addressbook?
-			if ( $group->person_id && $group->exist_contact($group->person_id) )
+			if ( $group->person_id && $contacts->exist_contact($group->person_id) )
 			{
 				return !!$contacts->edit_org($group->person_id, $primary);
 			}
@@ -911,24 +948,4 @@
 			$user->person_id = $contacts->add_contact($type, $primary, $comms);
 			return !!$user->person_id;
 		}
-
-		/**
-		* Grant / remove the applications for current user
-		*
-		* @param array $modules list of applications to grant to the user
-		* @param int $id the user id to grant the use of applications
-		* 
-		* @return void
-		*/
-		private function grant_account_applications($modules, $id)
-		{
-			$data_app = array();
-			if ( is_array($modules) )
-			{
-				$data_app = $modules;
-			}
-			$apps = createObject('phpgwapi.applications', $id);
-			$apps->update_data($data_app);
-			$apps->save_repository();
-		}
 	}

Modified: people/sigurdne/modules/phpgwapi/trunk/inc/accounts/class.accounts_ldap.inc.php
===================================================================
--- people/sigurdne/modules/phpgwapi/trunk/inc/accounts/class.accounts_ldap.inc.php	2009-11-20 10:27:41 UTC (rev 20844)
+++ people/sigurdne/modules/phpgwapi/trunk/inc/accounts/class.accounts_ldap.inc.php	2009-11-20 10:28:10 UTC (rev 20845)
@@ -18,7 +18,7 @@
 	/*
 	   This program is free software: you can redistribute it and/or modify
 	   it under the terms of the GNU Lesser General Public License as published by
-	   the Free Software Foundation, either version 3 of the License, or
+	   the Free Software Foundation, either version 2 of the License, or
 	   (at your option) any later version.
 
 	   This program is distributed in the hope that it will be useful,
@@ -52,6 +52,10 @@
 		const FALLBACK_LOGINSHELL    = '/bin/false';
 
 		/**
+		* @var bool $connected ldap connection state
+		*/
+		public $connected = false;
+		/**
 		* @var resource $ds ldap connection resource
 		*/
 		protected $ds;
@@ -81,6 +85,10 @@
 		public function __construct($account_id = null, $account_type = null)
 		{
 			$this->ds = $GLOBALS['phpgw']->common->ldapConnect();
+			if($this->ds)
+			{
+				$this->connected = true;
+			}
 			$this->user_context  = $GLOBALS['phpgw_info']['server']['ldap_context'];
 			$this->group_context = $GLOBALS['phpgw_info']['server']['ldap_group_context'];
 			parent::__construct($account_id, $account_type);
@@ -93,17 +101,21 @@
 		* @param integer $groupID Group id
 		* @return boolean True on success otherwise false
 		*/
-		public function add_account2group($account_id, $group_id)
+	//	public function add_account2group($account_id, $group_id)
+		public function add_user2group($account_id, $group_id)
 		{
-			if ($account_id && $groupID)
+			if ($account_id && $group_id)
 			{
 				$groupEntry = $this->_group_exists($group_id);
 				$memberUID = $this->id2name($account_id);
+
 				if ($groupEntry && $memberUID)
 				{
-					if (!is_array($groupEntry['memberuid']) || !in_array($memberUID, $groupEntry['memberuid']))
+					if ( (!isset($groupEntry['memberuid']) || !is_array($groupEntry['memberuid']) ) || !in_array($memberUID, $groupEntry['memberuid']))
 					{
+						$entry = array();
 						$entry['memberuid'][] = $memberUID;
+						$this->_add_user2group_sql($account_id, $group_id); // to get easy access to membership
 						return ldap_mod_add($this->ds, $groupEntry['dn'], $entry);
 					}
 				}
@@ -111,7 +123,46 @@
 			return false;
 		}
 
+
 		/**
+		* Add an account to a group entry
+		*
+		* @param integer $account_id Account id
+		* @param integer $group_id   Group id
+		*
+		* @return boolean true on success otherwise false
+		*/
+		protected function _add_user2group_sql($account_id, $group_id)
+		{
+			$account_id = (int) $account_id;
+			$group_id = (int) $group_id;
+			$read = phpgwapi_acl::READ;
+
+			if ( !$account_id || !$group_id )
+			{
+				return false;
+			}
+
+			// Check if it already exists
+			$sql = 'SELECT group_id FROM phpgw_group_map'
+				. " WHERE	group_id = {$group_id}"
+					. " AND account_id = {$account_id}";
+
+			$this->db->query($sql, __LINE__, __FILE__);
+			if ( $this->db->next_record() )
+			{
+				return true;
+			}
+
+			$sql = 'INSERT INTO phpgw_group_map'
+				. " VALUES({$group_id}, {$account_id}, {$read})";
+
+			return !!$this->db->query($sql, __LINE__, __FILE__);
+		}
+
+
+
+		/**
 		 * Create a new user account  - this only creates the acccount
 		 *
 		 * For creating a fully working user, use self::create()
@@ -130,25 +181,45 @@
 		* @param integer $id Id of group/account to delete
 		* @return boolean True on success otherwise false
 		*/
-		public function delete($id = '')
+		public function delete($id)
 		{
 			$id = (int) get_account_id($id);
 			$type = $this->get_type($id);
 
 			if ($type == 'g')
 			{
-				$sri = ldap_search($this->ds, $this->group_context, "(&(objectclass=phpgwgroup)(gidnumber={$id}))");
+				$sri = ldap_search($this->ds, $this->group_context, "(&(objectclass=phpgwGroup)(gidnumber={$id}))");
 				$allValues = ldap_get_entries($this->ds, $sri);
 			}
 			else
 			{
-				$sri = ldap_search($this->ds, $this->user_context, "(&(objectclass=phpgwaccount)(uidnumber={$id}))");
+				$sri = ldap_search($this->ds, $this->user_context, "(&(objectclass=phpgwAccount)(uidnumber={$id}))");
 				$allValues = ldap_get_entries($this->ds, $sri);
 			}
 
-			if ($allValues[0]['dn'])
+			if (isset($allValues[0]['dn']) && $allValues[0]['dn'])
 			{
-				return ldap_delete($this->ds, $allValues[0]['dn']);
+				if( ldap_delete($this->ds, $allValues[0]['dn']))
+				{
+					phpgwapi_cache::system_clear('phpgwapi', "account_{$id}");
+					if ($type == 'g')
+			{
+						$sql = "DELETE FROM phpgw_group_map WHERE group_id = {$id}";
+					}
+					else
+					{
+						$sql = "DELETE FROM phpgw_group_map WHERE account_id = {$id}";
+					}
+					$sql_acl = "DELETE FROM phpgw_acl WHERE acl_account = {$id}";
+					$sql_acl_grant = "DELETE FROM phpgw_acl WHERE acl_grantor = {$id}";
+
+					$this->db->transaction_begin();
+					$this->db->query($sql, __LINE__, __FILE__, true);
+					$this->db->query($sql_acl, __LINE__, __FILE__, true);
+					$this->db->query($sql_acl_grant, __LINE__, __FILE__, true);
+					$this->db->transaction_commit();
+					return true;
+				}
 			}
 			else
 			{
@@ -165,6 +236,7 @@
 		*/
 		public function delete_account4group($account_id, $group_id)
 		{
+			$ok = false;
 			if ($account_id && $group_id)
 			{
 				$groupEntry = $this->_group_exists($group_id);
@@ -178,11 +250,17 @@
 							if ($groupEntry['memberuid'][$i] == $memberUID)
 							{
 								$entry = array('memberuid' => array($memberUID));
-								return ldap_mod_del($this->ds, $groupEntry['dn'], $entry);
+								$ok =  ldap_mod_del($this->ds, $groupEntry['dn'], $entry);
 							}
 						}
 					}
 				}
+				if($ok)
+				{
+					$sql = 'DELETE FROM phpgw_group_map'
+					. " WHERE group_id = {$group_id} AND account_id = {$account_id}";
+					return !!$this->db->query($sql, __LINE__, __FILE__);
+				}
 			}
 			return false;
 		}
@@ -199,7 +277,6 @@
 			{
 				$id = $this->name2id($id);
 			}
-
 			if ($id)
 			{
 				$return = 0;
@@ -267,31 +344,53 @@
 			$arrayFunctions = createObject('phpgwapi.arrayfunctions');
 			if(empty($order))
 			{
-				$order = 'account_lid';
+				$order = 'lid';
 			}
+			else
+			{
+				$order = str_replace('account_'  , '', $order);
+			}
+
 			$sortedlist = $arrayFunctions->arfsort($listentries,array($order),$sort);
 			$this->total = count($listentries); // this shouldn't be an obejct var for one account/group whatever
 			unset($listentries);
 
+			$accounts = array();
+
 			if ( is_array($sortedlist) )
 			{
 				if( $start > 0 && $offset > 0 )
 				{
 					//echo "defined limit - start: $start, offset: $offset<br>";
-					return array_slice($sortedlist, $start, $offset);
+					$result = array_slice($sortedlist, $start, $offset);
 				}
 				elseif($start != -1)
 				{
 					//echo "defined limit - start: $start, offset: user[max]<br>";
-					return array_slice($sortedlist, $start, $GLOBALS['phpgw_info']['user']['preferences']['common']['maxmatchs']);
+					$result =  array_slice($sortedlist, $start, $GLOBALS['phpgw_info']['user']['preferences']['common']['maxmatchs']);
 				}
 				else
 				{
-					//echo "return all<br>";
-					return $sortedlist;
+					$result =  $sortedlist;
 				}
+
+				foreach($result as $record)
+				{
+					$id = $record['id'];
+
+					if($record['type'] == 'u')
+					{
+						$accounts[$id] = new phpgwapi_user();
+				}
+				else
+				{
+						$accounts[$id] = new phpgwapi_group();					
+				}
+					$accounts[$id]->init($record);
 			}
-			return array();
+			}
+
+			return $accounts;
 		}
 
 		/**
@@ -352,7 +451,7 @@
 			elseif ($type == 'u')
 			{
 				$account = $this->_user_exists($id);
-				$name = $account['cn'][0];
+				$name = $account['uid'][0];
 			}
 			else
 			{
@@ -397,7 +496,7 @@
 
 			$allValues = array();
 			// Groups are person? are you sure?
-			$sri = ldap_search($this->ds, $this->group_context, "(&(phpgwContactID={$person_id})(phpgwGroupID=*))");
+			$sri = ldap_search($this->ds, $this->group_context, "(&(phpgwcontactid={$person_id})(phpgwgroupid=*))");
 			$allValues = ldap_get_entries($this->ds, $sri);
 
 			if (@$allValues[0]['gidnumber'][0])
@@ -407,7 +506,7 @@
 			}
 
 			$allValues = array();
-			$sri = ldap_search($this->ds, $this->user_context, "(&(phpgwContactID={$person_id})(phpgwAccountID=*))");
+			$sri = ldap_search($this->ds, $this->user_context, "(&(phpgwcontactid={$person_id})(phpgwaccountid=*))");
 			$allValues = ldap_get_entries($this->ds, $sri);
 
 			if (@$allValues[0]['uidnumber'][0])
@@ -483,11 +582,11 @@
 		*/
 		protected function _get_next_account_id()
 		{
-			$filter = '(|(objectclass=posixaccount)(objectclass=phpgwaccount))';
-			$result = ldap_search($this->ds, $this->user_context, $filter, array('uidnumber'));
+			$filter = '(|(objectclass=posixaccount)(objectclass=phpgwAccount))';
+			$result = ldap_search($this->ds, $this->user_context, $filter, array('uidNumber'));
 			$entries = ldap_get_entries($this->ds, $result);
 
-			if ( !is_array($entries) || !count($entries) )//this shouldn't happen
+			if ( !is_array($entries) || !count($entries)  || $entries['count'] == 0)//this shouldn't happen
 			{
 				return (int) $GLOBALS['phpgw_info']['server']['account_min_id'];
 			}
@@ -510,7 +609,7 @@
 		*/
 		protected function _get_next_group_id()
 		{
-			$filter = '(|(objectclass=posixgroup)(objectclass=phpgwgroup))';
+			$filter = '(|(objectclass=posixgroup)(objectclass=phpgwGroup))';
 			$result = ldap_search($this->ds, $this->group_context, $filter, array('gidnumber'));
 			$entries = ldap_get_entries($this->ds, $result);
 
@@ -543,11 +642,12 @@
 		{
 			if ($id)
 			{
-				$result = ldap_search($this->ds, $this->group_context, "(&(gidnumber={$id})(objectclass=posixgroup))");
+				$result = ldap_search($this->ds, $this->group_context, "(&(gidnumber={$id})(objectclass=posixGroup))");
 				$entries = ldap_get_entries($this->ds, $result);
-				if ( !is_array($entries) || !count($entries) )
+
+				if ( !is_array($entries) || !count($entries) || $entries['count'] == 0 )
 				{
-					return array();
+					return false;
 				}
 
 				if ( isset($entries[0]) && is_array($entries[0]) )
@@ -598,7 +698,7 @@
 		{
 			if ($id)
 			{
-				$result = ldap_search($this->ds, $this->user_context, "phpgwcontact={$id}");
+				$result = ldap_search($this->ds, $this->user_context, "phpgwContact={$id}");
 				$allValues = ldap_get_entries($this->ds, $result);
 				if ($allValues[0]['dn'])
 				{
@@ -643,21 +743,22 @@
 		* @param string $default_prefs Unused
 		* @return array|boolean Id of the newly created account or false
 		*/
-		function create($account_info, $default_prefs = true)
+		function create_old($account_info, $group, $acls = array(), $modules = array())
+	//	function create($account_info, $default_prefs = true)
 		{
 			//echo 'accounts_ldap::create called!';
-			if ( !isset($account_info['account_id']) || empty($account_info['account_id']) || !$account_info['account_id'] == 0 )
+			if ( !isset($account_info->id) || empty($account_info->id) || !$account_info->id == 0 )
 			{
 				//echo 'need new acct id for new entry';
-				$account_info['account_id'] = $this->get_nextid($account_info['account_type']);
-				//echo "- got given {$account_info['account_id']}<br>";
+				$account_info->id = $this->_get_nextid($account_info->type);
+				//echo "- got given {$account_info->id}<br>";
 			}
 
-			if ($account_info['account_type'] == 'u')
+			if ($account_info->type == 'u')
 			{
 				$this->create_account($account_info);
 			}
-			elseif($account_info['account_type'] == 'g')
+			elseif($account_info->type == 'g')
 			{
 				$this->create_group($account_info);
 			}
@@ -665,7 +766,7 @@
 			{
 				return false;
 			}
-			return parent::create($account_info, $default_prefs);
+			return parent::create($account_info, $group, $acls, $modules);
 		}
 
 		/**
@@ -674,11 +775,17 @@
 		* @param array $account_info Account information: account_id, account_expires, account_status, lastlogin, lastloginfrom, lastpasswd_change, account_firstname, account_lastname, account_passwd, homedirectory, ...
 		* @param string $default_prefs Unused
 		*/
-		function create_account($account_info)
+		function _create_user($account_info, $groups)
 		{
+			$this->_save_contact_for_user($account_info);
+			if ( !isset($account_info->id) || !$account_info->id )
+		{
+				$account_info->id = $this->_get_nextid($account_info->type);
+			}
+
 			$dn = $this->rdn_account .
 				  '=' .
-				  $this->_get_leaf_Name($account_info['account_firstname'], $account_info['account_lastname'], $account_info['account_lid']) .
+				  $this->_get_leaf_Name($account_info->firstname, $account_info->lastname, $account_info->lid) .
 				  ',' .
 				  $this->user_context;
 
@@ -687,95 +794,91 @@
 
 			// phpgw attributes
 			$entry['objectclass'][]       = 'phpgwAccount';
-			$entry['phpgwaccountid']      = $account_info['account_id'];
-			$entry['phpgwaccountexpires'] = isset($account_info['account_expires'])  ? $account_info['account_expires'] : $account_info['expires'];
-			if (isset($account_info['account_status']) || isset($account_info['status']))
+			$entry['phpgwaccountid']      = $account_info->id;
+			$entry['phpgwaccountexpires'] = isset($account_info->expires) && $account_info->expires ? $account_info->expires : -1;
+			
+			$entry['phpgwaccountstatus'] = isset($account_info->enabled) && $account_info->enabled ? 'A' : 'I';
+			
+			if (isset($account_info->last_login) && $account_info->last_login)
 			{
-				$entry['phpgwaccountstatus'] = isset($account_info['account_status']) ? $account_info['account_status'] : $account_info['status'];
+				$entry['phpgwlastlogin'] = $account_info->last_login;
 			}
-			else
+			if (isset($account_info->last_login_from) && $account_info->last_login_from)
 			{
-				$entry['phpgwaccountstatus'] = 'I'; // 'I' for inactiv
+				$entry['phpgwlastloginfrom'] = $account_info->last_login_from;
 			}
-			if (isset($account_info['lastlogin']))
+			if (isset($account_info->last_passwd_change) && $account_info->last_passwd_change)
 			{
-				$entry['phpgwlastlogin'] = $account_info['lastlogin'];
+				$entry['phpgwlastpasswordchange'] = $account_info->last_passwd_change;
 			}
-			if (isset($account_info['lastloginfrom']))
+			if (isset($account_info->quota) && $account_info->quota)
 			{
-				$entry['phpgwlastloginfrom'] = $account_info['lastloginfrom'];
+				$entry['phpgwquota'] = $account_info->quota;
 			}
-			if (isset($account_info['lastpasswd_change']))
-			{
-				$entry['phpgwlastpasswordchange'] = $account_info['lastpasswd_change'];
-			}
-			if (isset($account_info['quota']))
-			{
-				$entry['phpgwquota'] = $account_info['quota'];
-			}
 			else
 			{
-				$entry['phpgwquota'] = isset($this->quota) ? $this->quota : 0;
+				$entry['phpgwquota'] = isset($this->quota)  && $this->quota ? $this->quota : 0;
 			}
 			$structural_modification = false;
-			if(isset($account_info['person_id']) && (int) $account_info['person_id'])
+
+			if(isset($account_info->person_id) && (int) $account_info->person_id)
 			{
 				$entry['objectclass'][] = 'phpgwContact'; // shouldn't be structural
-				$entry['phpgwcontactid'] = (int)$account_info['person_id'];
+				$entry['phpgwcontactid'] = (int)$account_info->person_id;
 			}
-			else
-			{
 				$entry['objectclass'][]       = 'account';
-			}
-
 			// additional attributes from the phpgw for groups
 			$entry['objectclass'][]       = 'posixAccount';
-			$entry['cn']                  = $this->get_fullname($account_info['account_firstname'], $account_info['account_lastname']);
-			$entry['uidnumber']           = $account_info['account_id'];
-			$entry['uid']                 = $account_info['account_lid'];
+			$entry['cn']                  = $this->get_fullname($account_info->firstname, $account_info->lastname);
+			$entry['uidnumber']           = $account_info->id;
+			$entry['uid']                 = $account_info->lid;
 			$entry['description']         = str_replace('*','',lang('phpgw-created account'));
-			if ( isset($account_info['account_firstname']) )
+			if ( isset($account_info->firstname) )
 			{
-				$entry['givenname'] = $account_info['account_firstname'];
+				$entry['givenname'] = $account_info->firstname;
 			}
-			if ( isset($account_info['account_lastname']) )
+			if ( isset($account_info->lastname) )
 			{
-				$entry['sn'] = $account_info['account_lastname'];
+				$entry['sn'] = $account_info->lastname;
 			}
 			else
 			{
 				$entry['sn'] = ' ';
 			}
-			if ( isset($account_info['account_passwd']) )
+
+			if ( isset($account_info->passwd) && $account_info->passwd )
 			{
-				$entry['userpassword'] = $GLOBALS['phpgw']->auth->generate_hash($account_info['account_passwd']);
+				$entry['userpassword'] = $account_info->passwd;
 			}
 
 			// Fields are must for LDAP - so we write them in any case
-			$entry['homedirectory']       = $this->_get_homedirectory($account_info['homedirectory'], $account_info['account_lid']);
-			$entry['loginshell']          = $this->_get_loginshell($account_info['loginshell']);
+			// FIXME
+		//	$entry['homedirectory']       = $this->_get_homedirectory($account_info->homedirectory, $account_info->lid);
+		//	$entry['loginshell']          = $this->_get_loginshell($account_info->loginshell);
+			$entry['homedirectory']       = $this->_get_homedirectory('', $account_info->lid);
+			$entry['loginshell']          = $this->_get_loginshell('');
 
 
 			// special gidnumber handling
-			if ($GLOBALS['phpgw_info']['server']['ldap_group_id'])
+			if (isset($GLOBALS['phpgw_info']['server']['ldap_group_id']) && $GLOBALS['phpgw_info']['server']['ldap_group_id'])
 			{
-				$enty['gidnumber'] = $GLOBALS['phpgw_info']['server']['ldap_group_id'];
+				$entry['gidnumber'] = $GLOBALS['phpgw_info']['server']['ldap_group_id'];
 			}
 			else
 			{
-				$entry['gidnumber']           = $account_info['account_id'];
+				$entry['gidnumber']           = $account_info->id;
 			}
 
-			$oldEntry = $this->_user_exists($account_info['account_id'], $dn);
+			$oldEntry = $this->_user_exists($account_info->id, $dn);
 
 			if ($oldEntry) // found an existing entry in LDAP
 			{
-				if ($this->createMode == 'replace')
+				if (isset($this->createMode) && $this->createMode == 'replace')
 				{
 					ldap_delete($this->ds, $oldEntry['dn']);
 					$this->add_ldap_entry($dn, $entry);
 				}
-				elseif ($this->createMode == 'extend')
+				elseif (isset($this->createMode) && $this->createMode == 'extend')
 				{
 					/* not yet implemented */
 				}
@@ -876,54 +979,89 @@
 			}
 			else // entry not yet in LDAP
 			{
-				return $this->add_ldap_entry($dn, $entry);
+				$this->add_ldap_entry($dn, $entry);
+
+				foreach ( $groups as $group )
+				{
+					$this->add_user2Group($account_info->id, $group);
+				}
+
+				$GLOBALS['hook_values'] = array
+				(
+					'account_id'	=> $account_info->id,
+					'account_lid'	=> $account_info->lid,
+					'new_passwd'	=> $account_info->passwd
+				);
+				$GLOBALS['pref'] = CreateObject('phpgwapi.preferences', $account_info->id);
+				$GLOBALS['phpgw']->hooks->process('addaccount');
+				$GLOBALS['phpgw']->hooks->process('add_def_pref');
+				$GLOBALS['pref']->save_repository(false);
+				return $account_info->id;
 			}
 		}
 
+		function create_group_account($account_info)
+		{
+			return $this->create_group($account_info);
+		}
+
 		/**
 		* Create new group
 		*
 		* @param array $account_info Group information: account_id, account_lid, ...
 		* @param string $default_prefs Unused
 		*/
-		function create_group($account_info)
+		function _create_group($account_info, $members)
 		{
-			$dn = $this->rdn_group . '=' . $account_info['account_lid'] . ',' . $this->group_context;
+			$this->_save_contact_for_group($account_info);
+			if ( !isset($account_info->id) || !$account_info->id )
+			{
+				$account_info->id = $this->_get_nextid($account_info->type);
+			}
 
+			$ok = false;
+			$dn = $this->rdn_group . '=' . $account_info->lid . ',' . $this->group_context;
+
 			// phpgw needed attributes
 
 			$entry['objectclass'][]  = 'phpgwGroup';
-			$entry['phpgwgroupID']   = $account_info['account_id'];
-			$entry['gidnumber']      = $account_info['account_id'];
+			$entry['phpgwgroupid']   = $account_info->id;
+			$entry['gidnumber']      = $account_info->id;
 
 			// additional attributes from the phpgw for groups
 			$entry['objectclass'][]  = 'posixGroup';
-			$entry['cn']             = $account_info['account_lid'];
+			$entry['cn']             = $account_info->lid;
 			$entry['description']    = utf8_encode(str_replace('*', '', lang('phpgw-created group')));
-			$entry['memberuid']      = $this->_get_member_uids($account_info['account_id']);
+			$entry['memberuid']      = $this->_get_member_uids($account_info->id);
 			if (!$entry['memberuid'])
 			{
 				unset ($entry['memberuid']);
 			}
-			if (isset($account_info['quota']))
+			if (isset($account_info->quota) && $account_info->quota > 0)
 			{
-				$entry['phpgwquota'] = $account_info['quota'];
+				$entry['phpgwquota'] = $account_info->quota;
 			}
-			else
+			else if (isset($this->quota) && $this->quota > 0)
 			{
-				$entry['phpgwquota'] = isset($this->quota) ? $this->quota : 0;
+				$entry['phpgwquota'] = $this->quota;
 			}
 
-			$oldEntry = $this->_group_exists($account_info['account_id'], $dn);
+			if(isset($account_info->person_id) && (int) $account_info->person_id > 0)
+			{
+				$entry['objectclass'][] = 'phpgwContact'; // shouldn't be structural
+				$entry['phpgwcontactid'] = (int)$account_info->person_id;
+			}
 
+			$oldEntry = $this->_group_exists($account_info->id, $dn);
+
 			if ($oldEntry) // found an existing entry in LDAP
 			{
-				if ($this->createMode == 'replace')
+				if (isset($this->createMode) && $this->createMode == 'replace')
 				{
 					ldap_delete($this->ds, $oldEntry['dn']);
-					$this->add_ldap_entry($dn, $entry);
+					$ok = $this->add_ldap_entry($dn, $entry);
 				}
-				elseif ($this->createMode == 'extend')
+				else if (isset($this->createMode) && $this->createMode == 'extend')
 				{
 					/* not yet implemented */
 				}
@@ -958,29 +1096,38 @@
 									break;
 
 								case 'objectclass':
-									if( !in_array('phpgwGroup', $oldEntry[$key]) && !in_array('phpgwgroup', $oldEntry[$key]) )
+									if( !in_array('phpgwGroup', $oldEntry[$key]) && !in_array('phpgwGroup', $oldEntry[$key]) )
 									{
 										$entry[$key] = $oldEntry[$key];
 										array_push($entry[$key], 'phpgwGroup');
 									}
+									elseif((in_array('phpgwContact',$entry[$key]) && ! in_array('phpgwContact',$oldEntry[$key])))
+									{
+										$structural_modification = true;
+									}
 									else
 									{
 											$entry[$key] = $oldEntry[$key];
 									}
 									break;
-
 								default:
 									$entry[$key] = $oldEntry[$key];
 							}
 						}
 					}
-					$this->modify_LDAP_Entry($oldEntry['dn'], $entry);
+					$ok = $this->modify_LDAP_Entry($oldEntry['dn'], $entry);
 				}
 			}
 			else // entry not yet in LDAP
 			{
-				$this->add_ldap_entry($dn, $entry);
+				$ok = $this->add_ldap_entry($dn, $entry);
+				foreach ( $members as $member )
+				{
+					$this->add_user2Group($member, $account_info->id);
+				}
+				return $account_info->id;
 			}
+			return $ok;
 		}
 
 		/**
@@ -997,6 +1144,8 @@
 			if (!$success)
 			{
 				echo 'ldap_add FAILED: [' . ldap_errno($this->ds) . '] ' . ldap_error($this->ds).'<br><br>';
+				echo "Did you remember to include the phpgroupware ldap shema in slapd.conf?<br>";
+				echo "phpgwapi/doc/ldap/phpgroupware.schema<br>";
 				echo "<strong>Adds: {$dn}</strong><br>";
 				die("<pre>" . print_r($entry, true) . "</pre>\n<br>");
 			}
@@ -1139,6 +1288,7 @@
 
 		function get_account_with_contact()
 		{
+			$accounts = array();
 			$sri = ldap_search($this->ds, $this->user_context, "(&(phpgwaccounttype=u)(phpgwcontactid=*))", array('uidnumber', 'phpgwcontactid'));
 			$allValues = ldap_get_entries($this->ds, $sri);
 			if(is_array($allValues))
@@ -1154,23 +1304,45 @@
 			return $accounts;
 		}
 
-		function get_account_without_contact()
+		function get_account_without_contact($get_groups = true)
 		{
-			$sri = ldap_search($this->ds, $this->user_context, "(&(phpgwaccounttype=u)(!(phpgwcontactid=*)))", array('uidnumber'));
+	//		$sri = ldap_search($this->ds, $this->user_context, "(&(phpgwaccounttype=u)(!(phpgwcontactid=*)))", array('uidnumber'));
+			$sri = ldap_search($this->ds, $this->user_context, "(!(objectClass=phpgwcontact))", array('uidnumber'));
 			$allValues = ldap_get_entries($this->ds, $sri);
+
+			$accounts = array();
 			if(is_array($allValues))
 			{
 				$count = intval($allValues['count']);
 				for ( $i = 0; $i < $count; ++$i)//foreach(allValues as $value)
 				{
-					$value = &$allValue[$i];
-					$accounts[] = $value['uidnumber'][0];
+				//	$value = &$allValue[$i];
+					if(isset($allValues[$i]['uidnumber'][0]) && $allValues[$i]['uidnumber'][0])
+					$accounts[] = $allValues[$i]['uidnumber'][0];
 				}
 			}
+			unset ($allValues);
+
+			// get the groups as well
+			if($get_groups)
+		{
+				$sri = ldap_search($this->ds, $this->group_context, "(!(objectClass=phpgwcontact))", array('gidnumber'));
+			$allValues = ldap_get_entries($this->ds, $sri);
+
+			if(is_array($allValues))
+			{
+				$count = intval($allValues['count']);
+				for ( $i = 0; $i < $count; ++$i)//foreach(allValues as $value)
+				{
+					//	$value = &$allValue[$i];
+						if(isset($allValues[$i]['gidnumber'][0]) && $allValues[$i]['gidnumber'][0])
+						$accounts[] = $allValues[$i]['gidnumber'][0];
+					}
+				}
+			}
 			return $accounts;
 		}
 
-
 		/**
 		* Full name generation
 		*
@@ -1261,8 +1433,11 @@
 				return $this->members[$group_id];
 			}
 
+			$this->members[$group_id] = array();
+
 			$sri = ldap_search($this->ds, $this->group_context, "gidnumber={$group_id}");
 			$entries = ldap_get_entries($this->ds, $sri);
+
 			if ( !is_array($entries) )
 			{
 				$entries = array();
@@ -1270,12 +1445,24 @@
 
 			foreach ( $entries as $entry )
 			{
-				$this->members[$account_id][] = array
+				if (isset($entry['memberuid']))
+				{
+					unset ($entry['memberuid']['count']);
+					foreach ($entry['memberuid'] as $memberuid)
+					{
+						$id =  $this->name2id($memberuid);
+						$this->members[$group_id][$id] = array
 				(
-					'account_id'	=> $entry['uidnumber'],
-					'account_name'	=> $GLOBALS['phpgw']->common->display_fullname($entry[$this->rdn_account], $entry['givenname'], $entry['sn'])
+							'account_id'	=> $id
 				);
 			}
+				}
+			}
+
+			foreach ( $this->members[$group_id] as $id => &$acct )
+			{
+				$acct['account_name'] = (string) $this->get($id);
+			}
 			return $this->members[$group_id];
 		}
 
@@ -1290,27 +1477,31 @@
 		{
 			$account_id = get_account_id($account_id);
 
-			if ( isset($this->memberships[$account_id]) )
+			if ( isset($this->memberships[$account_id])
+				&& is_array($this->memberships[$account_id]) )
 			{
-				return $this->memeberships[$account_id];
+				return $this->memberships[$account_id];
 			}
 
 			$this->memberships[$account_id] = array();
 
-			$sql = 'SELECT phpgw_accounts.account_id, phpgw_accounts.account_firstname FROM phpgw_accounts, phpgw_group_map'
-				. ' WHERE phpgw_accounts.account_id = phpgw_group_map.group_id'
-					. " AND phpgw_group_map.account_id = {$account_id}";
-
+			$sql = 'SELECT group_id'
+				. ' FROM phpgw_group_map'
+				. " WHERE phpgw_group_map.account_id = {$account_id}";
 			$this->db->query($sql, __LINE__, __FILE__);
 
+			$ids = array();
 			while ( $this->db->next_record() )
 			{
-				$this->memberships[$account_id][] = array
-				(
-					'account_id'	=> $this->db->f('account_id'),
-					'account_name'	=> lang('%1 group', $this->db->f('account_firstname'))
-				);
+				$ids[] = $this->db->f('group_id');
 			}
+
+			$this->memberships[$account_id] = array();
+			foreach ( $ids as $id )
+			{
+				$this->memberships[$account_id][$id] = $this->get($id);
+			}
+
 			return $this->memberships[$account_id];
 		}
 
@@ -1325,8 +1516,21 @@
 			$id = (int) $id;
 			$account = null;
 
-			$acct_type = $this->get_type($this->account_id);
+			if(!$id)
+			{
+				return null;
+			}
+			if ( $use_cache )
+			{
+				$account = phpgwapi_cache::system_get('phpgwapi', "account_{$id}");
+				if ( is_object($account) )
+				{
+					return $account;
+				}
+			}
 
+			$acct_type = $this->get_type($id);
+
 			/* search the dn for the given uid */
 			if ( $acct_type == phpgwapi_account::TYPE_GROUP
 				&& $this->group_context )
@@ -1342,60 +1546,77 @@
 			{
 				throw new Exception('Invalid account requested');
 			}
+
 			$entries = ldap_get_entries($this->ds, $sri);
+
 			// first in best dressed - we can't tell which one is the correct one
 			$entry = $entries[0];
+
 			unset($entries);
+			$record = array();
+			/* Now dump it into the array; take first entry found */
+			if ( isset($entry['phpgwcontactid']) )
+			{
+				$record['person_id'] = $entry['phpgwcontactid'][0];
+			}
 
-			/* Now dump it into the array; take first entry found */
-			$this->data['account_dn']             = $entries[0]['dn'];
-			$this->data['fullname']               = $entries[0]['cn'][0];
+			$record['dn']					= $entry['dn'];
+			$record['fullname']				= $entry['cn'][0];
 			if($acct_type == 'g')
 			{
-				$this->account_id	= $this->data['account_id']			= $entries[0]['gidnumber'][0];
-				$this->lid			= $this->data['account_lid']		= $entries[0]['cn'][0];
-				$this->firstname	= $this->data['account_firstname']	= $entries[0]['cn'][0];
-				$this->lastname		= $this->data['account_lastname']	= lang('group');
-				$this->account_type	= $this->data['type']				= 'g';
+				$record['id']				= $entry['gidnumber'][0];
+				$record['lid']				= $entry['cn'][0];
+				$record['firstname']		= $entry['cn'][0];
+				$record['lastname']			= lang('group');
+				$record['type']				= 'g';
+
+				$account = new phpgwapi_group();
 			}
 			else
 			{
-				$this->account_id	= $this->data['account_id']			= $entries[0]['uidnumber'][0];
-				$this->lid			= $this->data['account_lid']		= $entries[0]['uid'][0];
-				$this->firstname	= $this->data['account_firstname']	= (isset($entries[0]['givenname']) && isset($entries[0]['givenname'][0])) ? $entries[0]['givenname'][0] : '';
-				$this->lastname		= $this->data['account_lastname']	= (isset($entries[0]['sn']) && isset($entries[0]['sn'][0])) ? $entries[0]['sn'][0] : '';
-				$this->expires 		= $this->data['expires'] = $this->data['account_expires'] = $entries[0]['phpgwaccountexpires'][0];
-				$this->data['homedirectory']          = isset($entries[0]['homedirectory']) ? $entries[0]['homedirectory'][0] : self::FALLBACK_HOMEDIRECTORY;
-				$this->data['loginshell']             = isset($entries[0]['loginshell']) ? $entries[0]['loginshell'][0] : self::FALLBACK_LOGINSHELL;
-				$this->status = $this->data['status'] = isset($entries[0]['phpgwaccountstatus']) && $entries[0]['phpgwaccountstatus'][0] == 'A' ? 'A' : '';
-				$this->account_type	= $this->data['type']				= 'u';
-			}
-			if ( isset($entries[0]['phpgwcontactid']) )
+				$record['id']				= $entry['uidnumber'][0];
+				$record['lid']				= $entry['uid'][0];
+				$record['firstname']		= (isset($entry['givenname']) && isset($entry['givenname'][0])) ? $entry['givenname'][0] : '';
+				$record['lastname']			= (isset($entry['sn']) && isset($entry['sn'][0])) ? $entry['sn'][0] : '';
+				$record['expires'] 			= $record['account_expires'] = $entry['phpgwaccountexpires'][0];
+		//		$record['homedirectory']    = isset($entry['homedirectory']) ? $entry['homedirectory'][0] : self::FALLBACK_HOMEDIRECTORY;
+		//		$record['loginshell']       = isset($entry['loginshell']) ? $entry['loginshell'][0] : self::FALLBACK_LOGINSHELL;
+				$record['enabled'] 			= isset($entry['phpgwaccountstatus']) && $entry['phpgwaccountstatus'][0] == 'A' ? true : false;
+				$record['type']				= 'u';
+				if ( !isset($entry['phpgwquota']) || $entry['phpgwquota'] === '')
 			{
-				$this->person_id	= $this->data['person_id'] = $entries[0]['phpgwcontactid'][0];
+					$record['quota'] = $this->quota; // set to 0 by default
 			}
-			if ( !isset($entries[0]['phpgwquota']) || $entries[0]['phpgwquota'] === '')
-			{
-				$this->data['quota'] = $this->quota; // set to 0 by default
-			}
 			else
 			{
-				$this->quota = $this->data['quota'] = $entries[0]['phpgwquota'];
+					$record['quota'] = $entry['phpgwquota'][0];
 			}
-			return $this->data;
+
+				$account = new phpgwapi_user();
+			}
+
+			$account->init($record);
+
+			phpgwapi_cache::system_set('phpgwapi', "account_{$id}", $account);
+
+			return $account;
 		}
 
 		public function save_repository()
 		{
+			if ( !$this->account->is_dirty() )
+			{
+				return true; // nothing to do here
+			}
+
 			$acct_type = $this->get_type($this->account_id);
-
 			if ($acct_type == 'g')
 			{
-				return $this->create_group($this->data, '');
+				return $this->_create_group($this->account, '');
 			}
 			else
 			{
-				return $this->create_account($this->data, '');
+				return $this->_create_user($this->account, '');
 			}
 		}
 
@@ -1431,16 +1652,15 @@
 				{
 					continue;
 				}
-
 				if ( !isset($GLOBALS['phpgw_info']['server']['global_denied_groups'][$test]) )
 				{
 					$groups[] = array
 					(
-						'account_id'        => $entry['gidnumber'][0],
-						'account_lid'       => $entry['cn'][0],
-						'account_firstname' => $entry['cn'][0],
-						'account_lastname'  => lang('group'),
-						'account_type'      => 'g',
+						'id'        => $entry['gidnumber'][0],
+						'lid'       => $entry['cn'][0],
+						'firstname' => $entry['cn'][0],
+						'lastname'  => lang('group'),
+						'type'      => 'g',
 					);
 				}
 			}
@@ -1511,10 +1731,12 @@
 			{
    			$members = $this->member($this->data['account_id']);
 			}
+
 			$return = array();
+			foreach( $members as $entry)
 			for ($i=0; $i<count($members); $i++)
 			{
-				$member = $this->id2name($members[$i]['account_id']);
+				$member = $this->id2name($entry['account_id']);
 				// function $this->member returns duplicated entries and empty entries :-(
 				if (!in_array($member, $return) && $member != '')
 				{
@@ -1569,12 +1791,12 @@
 				{
 					$accounts[] = array
 					(
-						'account_id'        => $entry['uidnumber'][0],
-						'account_lid'       => $entry['uid'][0],
-						'account_type'      => 'u',
-						'account_firstname' => $entry['givenname'][0],
-						'account_lastname'  => $entry['sn'][0],
-						'account_status'    => $entry['phpgwaccountstatus'][0] == 'A' ? 'A' : 'I'
+						'id'        => $entry['uidnumber'][0],
+						'lid'       => $entry['uid'][0],
+						'type'      => 'u',
+						'firstname' => $entry['givenname'][0],
+						'lastname'  => $entry['sn'][0],
+						'enabled'    => $entry['phpgwaccountstatus'][0] == 'A' ? true : false
 					);
 				}
 			}
@@ -1590,13 +1812,12 @@
 		*/
 		protected function _group_name2id($name)
 		{
-			$sri = ldap_search($this->ds, $this->group_context, "(&({$this->rdn_group}={$name})(objectclass=phpgwgroup))");
+			$sri = ldap_search($this->ds, $this->group_context, "(&({$this->rdn_group}={$name})(objectclass=phpgwGroup))");
 			$allValues = ldap_get_entries($this->ds, $sri);
-
 			//echo "searching for name {$name} <pre>" . print_r($allValues, true) . '</pre>';
-			if ( isset($allValues[0]['gidnumber'][0]) )
+			if ( isset($allValues['0']['gidnumber']['0']) )
 			{
-				return (int) $allValues[0]['gidnumber'][0];
+				return (int) $allValues['0']['gidnumber']['0'];
 			}
 			else
 			{
@@ -1612,7 +1833,7 @@
 		*/
 		protected function _user_name2id($name)
 		{
-			$sri = ldap_search($this->ds, $this->user_context, "(&({$this->rdn_account}={$name})(objectclass=phpgwaccount))");
+			$sri = ldap_search($this->ds, $this->user_context, "(&({$this->rdn_account}={$name})(objectclass=phpgwAccount))");
 			$allValues = ldap_get_entries($this->ds, $sri);
 
 			if ( isset($allValues[0]['uidnumber'][0]) )

Modified: people/sigurdne/modules/phpgwapi/trunk/inc/accounts/class.accounts_sql.inc.php
===================================================================
--- people/sigurdne/modules/phpgwapi/trunk/inc/accounts/class.accounts_sql.inc.php	2009-11-20 10:27:41 UTC (rev 20844)
+++ people/sigurdne/modules/phpgwapi/trunk/inc/accounts/class.accounts_sql.inc.php	2009-11-20 10:28:10 UTC (rev 20845)
@@ -7,7 +7,7 @@
 	* @author Dan Kuykendall <[email protected]>
 	* @author Bettina Gille <[email protected]>
 	* @copyright Copyright (C) 2000-2008 Free Software Foundation, Inc. http://www.fsf.org/
-	* @license http://www.gnu.org/licenses/lgpl.html GNU Lesser General Public License v3 or later
+	* @license http://www.gnu.org/licenses/lgpl.html GNU Lesser General Public License v2 or later
 	* @package phpgroupware
 	* @subpackage phpgwapi
 	* @version $Id$
@@ -16,7 +16,7 @@
 	/*
 	   This program is free software: you can redistribute it and/or modify
 	   it under the terms of the GNU Lesser General Public License as published by
-	   the Free Software Foundation, either version 3 of the License, or
+	   the Free Software Foundation, either version 2 of the License, or
 	   (at your option) any later version.
 
 	   This program is distributed in the hope that it will be useful,
@@ -37,6 +37,7 @@
 	*/
 	class phpgwapi_accounts_sql extends phpgwapi_accounts_
 	{
+		protected $global_lock = false;
 		/**
 		* Constructor
 		*
@@ -99,6 +100,15 @@
 		 */
 		public function create_group_account($account)
 		{
+			if ( $this->db->Transaction )
+			{
+				$this->global_lock = true;
+			}
+			else
+			{
+				$this->db->transaction_begin();
+			}
+
 			$id = (int) $account->id;
 			if ( !$id || $this->exists($id) )
 			{
@@ -114,12 +124,18 @@
 				'account_lastname'	=> "'" . $this->db->db_addslashes($account->lastname) . "'",
 				'account_expires'	=> -1,
 				'account_type'		=> "'" . phpgwapi_account::TYPE_GROUP . "'",
+				'account_status'	=> "'A'",
 				'person_id'			=> (int) $account->person_id
 			);
 
 			$this->db->query('INSERT INTO phpgw_accounts (' . implode(', ', array_keys($data)) . ') '.
 							'VALUES (' . implode(', ', $data) . ')', __LINE__, __FILE__);
 
+			if ( !$this->global_lock )
+			{
+				$this->db->transaction_commit();
+			}
+
 			$account->id = $id;
 			return $account->id;
 		}
@@ -138,48 +154,45 @@
 		 */
 		public function create_user_account($account)
 		{
-			$fields = array
-			(
-				'account_lid',
-				'account_type',
-				'account_firstname',
-				'account_lastname',
-				'account_pwd',
-				'account_status',
-				'account_expires',
-				'person_id',
-				'account_quota',
-				'account_id'
-			);
+			if ( $this->db->Transaction )
+			{
+				$this->global_lock = true;
+			}
+			else
+			{
+				$this->db->transaction_begin();
+			}
 
+			$id = (int) $account->id;
+			if ( !$id || $this->exists($id) )
+			{
+				$id = $this->_get_nextid('u');
+			}
+
 			$data = array
 			(
-				'lid'		=> "'" . $this->db->db_addslashes($account->lid) . "'",
-				'type'		=> "'" . phpgwapi_account::TYPE_USER . "'",
-				'firstname'	=> "'" . $this->db->db_addslashes($account->firstname) ."'",
-				'lastname'	=> "'" . $this->db->db_addslashes($account->lastname) . "'",
-				'password'	=> "'" . $this->db->db_addslashes($account->passwd_hash) . "'",
-				'status'	=> "'" . $account->enabled ? "'A'" : "'I'", // FIXME this really has to become a bool
-				'expires'	=> (int) $account->expires,
+				'account_id'=> $id,
+				'account_lid'		=> "'" . $this->db->db_addslashes($account->lid) . "'",
+				'account_type'		=> "'" . phpgwapi_account::TYPE_USER . "'",
+				'account_firstname'	=> "'" . $this->db->db_addslashes($account->firstname) ."'",
+				'account_lastname'	=> "'" . $this->db->db_addslashes($account->lastname) . "'",
+				'account_pwd'		=> "'" . $this->db->db_addslashes($account->passwd_hash) . "'",
+				'account_status'	=> $account->enabled ? "'A'" : "'I'", // FIXME this really has to become a bool
+				'account_expires'	=> (int) $account->expires,
 				'person_id'	=> (int) $account->person_id,
-				'quota'		=> (int) $account->quota,
+				'account_quota'		=> (int) $account->quota,
 			);
 
-			if ( (int) $account->id 
-				&& !$this->exists($account->id) )
+			$this->db->query('INSERT INTO phpgw_accounts (' . implode(', ', array_keys($data)) . ') '.
+							'VALUES (' . implode(', ', $data) . ')', __LINE__, __FILE__);
+
+			if ( !$this->global_lock )
 			{
-				$data['id'] = (int) $account->id;
+				$this->db->transaction_commit();
 			}
-			else
-			{
-				$data['id'] = $this->_get_nextid();
-			}
 
-			$this->db->query('INSERT INTO phpgw_accounts (' . implode(', ', $fields) . ') '.
-							'VALUES (' . implode(', ', $data) . ')', __LINE__, __FILE__);
+			$account->id = $id;
 
-			$account->id = $data['id'];
-
 			$this->account = $account;
 
 			return $account->id;
@@ -346,7 +359,8 @@
 					'enabled'			=> $this->db->f('account_status') == 'A',
 					'expires'			=> $this->db->f('account_expires'),
 					'person_id'			=> $this->db->f('person_id'),
-					'quota'				=> $this->db->f('account_quota')
+					'quota'				=> $this->db->f('account_quota'),
+					'type'				=> $this->db->f('account_type'),
 				);
 
 				if ( $this->db->f('account_type') == 'g' )
@@ -456,21 +470,30 @@
 
 			if ($query)
 			{
-				$query = $this->db->db_addslashes($query);
 				if ($whereclause)
 				{
-					$whereclause .= ' AND ( ';
+					$whereclause .= ' AND (';
 				}
 				else
 				{
-					$whereclause = ' WHERE ( ';
+					$whereclause = ' WHERE (';
 				}
 
-				$whereclause .= " account_firstname $this->like '%$query%' OR account_lastname $this->like "
-					. "'%$query%' OR account_lid $this->like '%$query%' OR person_id =" . (int)$query . ')';
+				if(ctype_digit($query))
+				{
+					$whereclause .= 'person_id =' . (int)$query . ')';
+				}
+				else
+				{
+					$query = $this->db->db_addslashes($query);
+
+					$whereclause .= "account_firstname $this->like '%$query%' OR account_lastname $this->like "
+						. "'%$query%' OR account_lid $this->like '%$query%')";
+				}
 			}
 
 			$sql = "SELECT * FROM phpgw_accounts $whereclause $orderclause";
+
 			if ($offset == -1 && $start == -1)
 			{
 				$this->db->query($sql, __LINE__, __FILE__);
@@ -531,10 +554,9 @@
 			}
 			$group_id = get_account_id($group_id);
 
-			$sql = 'SELECT phpgw_accounts.account_id'
-				. ' FROM phpgw_accounts, phpgw_group_map'
-				. ' WHERE phpgw_accounts.account_id = phpgw_group_map.group_id'
-					. " AND phpgw_group_map.group_id = {$this->account_id}";
+			$sql = 'SELECT phpgw_group_map.account_id'
+				. " FROM phpgw_accounts $this->join phpgw_group_map ON phpgw_accounts.account_id = phpgw_group_map.group_id"
+				. " WHERE phpgw_group_map.group_id = {$group_id}";
 
 			$this->db->query($sql, __LINE__, __FILE__);
 

Modified: people/sigurdne/modules/phpgwapi/trunk/inc/accounts/class.accounts_sqlldap.inc.php
===================================================================
--- people/sigurdne/modules/phpgwapi/trunk/inc/accounts/class.accounts_sqlldap.inc.php	2009-11-20 10:27:41 UTC (rev 20844)
+++ people/sigurdne/modules/phpgwapi/trunk/inc/accounts/class.accounts_sqlldap.inc.php	2009-11-20 10:28:10 UTC (rev 20845)
@@ -4,8 +4,8 @@
 	 *
 	 * @author Philipp Kamps <[email protected]>
 	 * @author Dave Hall <[email protected]>
-	 * @copyright Copyright (C) 2000-2008 Free Software Foundation, Inc. fsf.org
-	 * @license http://www.gnu.org/licenses/lgpl.html GNU Lesser General Public License v3 or later
+	 * @copyright Copyright (C) 2000-2009 Free Software Foundation, Inc. fsf.org
+	 * @license http://www.gnu.org/licenses/lgpl.html GNU Lesser General Public License v2 or later
 	 * @package phpgroupware
 	 * @subpackage phpgwapi
 	 * @version $Id$
@@ -14,7 +14,7 @@
 	/*
 	   This program is free software: you can redistribute it and/or modify
 	   it under the terms of the GNU Lesser General Public License as published by
-	   the Free Software Foundation, either version 3 of the License, or
+	   the Free Software Foundation, either version 2 of the License, or
 	   (at your option) any later version.
 
 	   This program is distributed in the hope that it will be useful,
@@ -46,7 +46,7 @@
 		 */
 		public function __construct($account_id = null, $account_type = null)
 		{
-			$this->ldap = new accounts_ldap($account_id, $account_type);
+			$this->ldap = new phpgwapi_accounts_ldap($account_id, $account_type);
 			parent::__construct($account_id, $account_type);
 		}
 
@@ -69,7 +69,7 @@
 		 * @param integer $account_id the account to delete
 		 * @return boolean was the account deleted?
 		 */
-		public function delete($accountid = 0)
+		public function delete($accountid)
 		{
 			if ( parent::delete($accountid) )
 			{
@@ -78,23 +78,52 @@
 			return false;
 		}
 
+
 		/**
-		 * Create a new account
+		 * Create a new group account  - this only creates the acccount
 		 *
-		 * @param object $account_info the new account to create
-		 * @param boolean $default_prefs apply the default preferences for the user
-		 * @return integer the new account id
+		 * For creating a fully working user, use self::create()
+		 *
+		 * @param object $account the phpgwapi_user object for the new account
+		 *
+		 * @return integer the new user id
+		 *
+		 * @see self::create
 		 */
-		public function create($account_info, $default_prefs = true)
+		public function create_group_account($account)
 		{
-			if ( parent::create($account_info, $default_prefs) )
+			if ( parent::create_group_account($account) )
 			{
-				return $this->ldap->create($account_info, $default_prefs);
+				$members = parent::member($account->id);
+				return $this->ldap->_create_group($account, $members);
 			}
 			return false;
 		}
 
+
 		/**
+		 * Create a new user account  - this only creates the acccount
+		 *
+		 * For creating a fully working user, use self::create()
+		 *
+		 * @param object $account the phpgwapi_user object for the new account
+		 *
+		 * @return integer the new user id
+		 *
+		 * @see self::create
+		 */
+		public function create_user_account($account)
+		{
+			if ( $account->id = parent::create_user_account($account) )
+			{
+				$groups = parent::membership($account->id);
+				return $this->ldap->_create_user($account, $groups);
+			}
+			return false;
+		}
+
+
+		/**
 		 * Add an account to a group entry
 		 *
 		 * @param integer $account_id Account id

Modified: people/sigurdne/modules/phpgwapi/trunk/inc/auth/class.auth_.inc.php
===================================================================
--- people/sigurdne/modules/phpgwapi/trunk/inc/auth/class.auth_.inc.php	2009-11-20 10:27:41 UTC (rev 20844)
+++ people/sigurdne/modules/phpgwapi/trunk/inc/auth/class.auth_.inc.php	2009-11-20 10:28:10 UTC (rev 20845)
@@ -14,7 +14,7 @@
 	/*
 	   This program is free software: you can redistribute it and/or modify
 	   it under the terms of the GNU Lesser General Public License as published by
-	   the Free Software Foundation, either version 3 of the License, or
+	   the Free Software Foundation, either version 2 of the License, or
 	   (at your option) any later version.
 
 	   This program is distributed in the hope that it will be useful,

Modified: people/sigurdne/modules/phpgwapi/trunk/inc/auth/class.auth_ads.inc.php
===================================================================
--- people/sigurdne/modules/phpgwapi/trunk/inc/auth/class.auth_ads.inc.php	2009-11-20 10:27:41 UTC (rev 20844)
+++ people/sigurdne/modules/phpgwapi/trunk/inc/auth/class.auth_ads.inc.php	2009-11-20 10:28:10 UTC (rev 20845)
@@ -12,7 +12,7 @@
 	/*
 	   This program is free software: you can redistribute it and/or modify
 	   it under the terms of the GNU Lesser General Public License as published by
-	   the Free Software Foundation, either version 3 of the License, or
+	   the Free Software Foundation, either version 2 of the License, or
 	   (at your option) any later version.
 
 	   This program is distributed in the hope that it will be useful,

Modified: people/sigurdne/modules/phpgwapi/trunk/inc/auth/class.auth_exchange.inc.php
===================================================================
--- people/sigurdne/modules/phpgwapi/trunk/inc/auth/class.auth_exchange.inc.php	2009-11-20 10:27:41 UTC (rev 20844)
+++ people/sigurdne/modules/phpgwapi/trunk/inc/auth/class.auth_exchange.inc.php	2009-11-20 10:28:10 UTC (rev 20845)
@@ -12,7 +12,7 @@
 	/*
 	   This program is free software: you can redistribute it and/or modify
 	   it under the terms of the GNU Lesser General Public License as published by
-	   the Free Software Foundation, either version 3 of the License, or
+	   the Free Software Foundation, either version 2 of the License, or
 	   (at your option) any later version.
 
 	   This program is distributed in the hope that it will be useful,

Modified: people/sigurdne/modules/phpgwapi/trunk/inc/auth/class.auth_http.inc.php
===================================================================
--- people/sigurdne/modules/phpgwapi/trunk/inc/auth/class.auth_http.inc.php	2009-11-20 10:27:41 UTC (rev 20844)
+++ people/sigurdne/modules/phpgwapi/trunk/inc/auth/class.auth_http.inc.php	2009-11-20 10:28:10 UTC (rev 20845)
@@ -13,7 +13,7 @@
 	/*
 	   This program is free software: you can redistribute it and/or modify
 	   it under the terms of the GNU Lesser General Public License as published by
-	   the Free Software Foundation, either version 3 of the License, or
+	   the Free Software Foundation, either version 2 of the License, or
 	   (at your option) any later version.
 
 	   This program is distributed in the hope that it will be useful,

Modified: people/sigurdne/modules/phpgwapi/trunk/inc/auth/class.auth_ldap.inc.php
===================================================================
--- people/sigurdne/modules/phpgwapi/trunk/inc/auth/class.auth_ldap.inc.php	2009-11-20 10:27:41 UTC (rev 20844)
+++ people/sigurdne/modules/phpgwapi/trunk/inc/auth/class.auth_ldap.inc.php	2009-11-20 10:28:10 UTC (rev 20845)
@@ -16,7 +16,7 @@
 	/*
 	   This program is free software: you can redistribute it and/or modify
 	   it under the terms of the GNU Lesser General Public License as published by
-	   the Free Software Foundation, either version 3 of the License, or
+	   the Free Software Foundation, either version 2 of the License, or
 	   (at your option) any later version.
 
 	   This program is distributed in the hope that it will be useful,
@@ -121,9 +121,8 @@
 				}
 
 				/* try to bind as the user with user suplied password */
-				$user_bind = @ldap_bind($ldap, $userDN, $passwd);
-				$ok = is_resource($user_bind);
-				@ldap_unbind($user_bind); // we don't need this connection anymore, so avoid a leak.
+				$ok = @ldap_bind($ldap, $userDN, $passwd);
+				@ldap_unbind($ldap); // we don't need this connection anymore, so avoid a leak.
 			}
 			@ldap_unbind($ldap);
 

Modified: people/sigurdne/modules/phpgwapi/trunk/inc/auth/class.auth_mail.inc.php
===================================================================
--- people/sigurdne/modules/phpgwapi/trunk/inc/auth/class.auth_mail.inc.php	2009-11-20 10:27:41 UTC (rev 20844)
+++ people/sigurdne/modules/phpgwapi/trunk/inc/auth/class.auth_mail.inc.php	2009-11-20 10:28:10 UTC (rev 20845)
@@ -12,7 +12,7 @@
 	/*
 	   This program is free software: you can redistribute it and/or modify
 	   it under the terms of the GNU Lesser General Public License as published by
-	   the Free Software Foundation, either version 3 of the License, or
+	   the Free Software Foundation, either version 2 of the License, or
 	   (at your option) any later version.
 
 	   This program is distributed in the hope that it will be useful,

Modified: people/sigurdne/modules/phpgwapi/trunk/inc/auth/class.auth_nis.inc.php
===================================================================
--- people/sigurdne/modules/phpgwapi/trunk/inc/auth/class.auth_nis.inc.php	2009-11-20 10:27:41 UTC (rev 20844)
+++ people/sigurdne/modules/phpgwapi/trunk/inc/auth/class.auth_nis.inc.php	2009-11-20 10:28:10 UTC (rev 20845)
@@ -13,7 +13,7 @@
 	/*
 	   This program is free software: you can redistribute it and/or modify
 	   it under the terms of the GNU Lesser General Public License as published by
-	   the Free Software Foundation, either version 3 of the License, or
+	   the Free Software Foundation, either version 2 of the License, or
 	   (at your option) any later version.
 
 	   This program is distributed in the hope that it will be useful,

Modified: people/sigurdne/modules/phpgwapi/trunk/inc/auth/class.auth_ntlm.inc.php
===================================================================
--- people/sigurdne/modules/phpgwapi/trunk/inc/auth/class.auth_ntlm.inc.php	2009-11-20 10:27:41 UTC (rev 20844)
+++ people/sigurdne/modules/phpgwapi/trunk/inc/auth/class.auth_ntlm.inc.php	2009-11-20 10:28:10 UTC (rev 20845)
@@ -12,7 +12,7 @@
 	/*
 	   This program is free software: you can redistribute it and/or modify
 	   it under the terms of the GNU Lesser General Public License as published by
-	   the Free Software Foundation, either version 3 of the License, or
+	   the Free Software Foundation, either version 2 of the License, or
 	   (at your option) any later version.
 
 	   This program is distributed in the hope that it will be useful,
@@ -31,7 +31,7 @@
 	* @subpackage accounts
 	* @ignore
 	*/
-	class phpgwapi_auth_ntlm extends phpgwapi_auth_remote_user
+	class phpgwapi_auth_ntlm extends phpgwapi_auth_
 	{
 
 		public function __construct()
@@ -39,10 +39,35 @@
 			parent::__construct();
 		}
 
-		function change_password($old_passwd, $new_passwd)
+		public function authenticate($username, $passwd)
 		{
+			return isset($_SERVER['REMOTE_USER']) && !!strlen($_SERVER['REMOTE_USER']);
+		}
+
+		public function change_password($old_passwd, $new_passwd, $account_id = 0)
+		{
 			// not yet supported - this script would change the windows domain password
 			return '';
 		}
 
+		/**
+		* Update when the user last logged in
+		*
+		* @param int $account_id the user's account id
+		* @param string $ip the source IP adddress for the request
+		*/
+		public function update_lastlogin($account_id, $ip)
+		{
+			$ip = $GLOBALS['phpgw']->db->db_addslashes($ip);
+			$account_id = (int) $account_id;
+			$now = time();
+
+			$sql = 'UPDATE phpgw_accounts'
+				. " SET account_lastloginfrom = '{$ip}',"
+					. " account_lastlogin = {$now}"
+				. " WHERE account_id = {$account_id}";
+
+			$GLOBALS['phpgw']->db->query($sql, __LINE__, __FILE__);
+		}
+
 	}

Modified: people/sigurdne/modules/phpgwapi/trunk/inc/auth/class.auth_remoteuser.inc.php
===================================================================
--- people/sigurdne/modules/phpgwapi/trunk/inc/auth/class.auth_remoteuser.inc.php	2009-11-20 10:27:41 UTC (rev 20844)
+++ people/sigurdne/modules/phpgwapi/trunk/inc/auth/class.auth_remoteuser.inc.php	2009-11-20 10:28:10 UTC (rev 20845)
@@ -12,7 +12,7 @@
 	/*
 	   This program is free software: you can redistribute it and/or modify
 	   it under the terms of the GNU Lesser General Public License as published by
-	   the Free Software Foundation, either version 3 of the License, or
+	   the Free Software Foundation, either version 2 of the License, or
 	   (at your option) any later version.
 
 	   This program is distributed in the hope that it will be useful,

Modified: people/sigurdne/modules/phpgwapi/trunk/inc/auth/class.auth_sql.inc.php
===================================================================
--- people/sigurdne/modules/phpgwapi/trunk/inc/auth/class.auth_sql.inc.php	2009-11-20 10:27:41 UTC (rev 20844)
+++ people/sigurdne/modules/phpgwapi/trunk/inc/auth/class.auth_sql.inc.php	2009-11-20 10:28:10 UTC (rev 20845)
@@ -13,7 +13,7 @@
 	/*
 	   This program is free software: you can redistribute it and/or modify
 	   it under the terms of the GNU Lesser General Public License as published by
-	   the Free Software Foundation, either version 3 of the License, or
+	   the Free Software Foundation, either version 2 of the License, or
 	   (at your option) any later version.
 
 	   This program is distributed in the hope that it will be useful,
@@ -92,7 +92,7 @@
 				}
 			}
 
-			$hash = $this->generate_hash($new_password);
+			$hash = $this->create_hash($new_passwd);
 			$hash_safe = $GLOBALS['phpgw']->db->db_addslashes($hash); // just to be safe :)
 			$now = time();
 

Modified: people/sigurdne/modules/phpgwapi/trunk/inc/auth/class.auth_sqlssl.inc.php
===================================================================
--- people/sigurdne/modules/phpgwapi/trunk/inc/auth/class.auth_sqlssl.inc.php	2009-11-20 10:27:41 UTC (rev 20844)
+++ people/sigurdne/modules/phpgwapi/trunk/inc/auth/class.auth_sqlssl.inc.php	2009-11-20 10:28:10 UTC (rev 20845)
@@ -13,7 +13,7 @@
 	/*
 	   This program is free software: you can redistribute it and/or modify
 	   it under the terms of the GNU Lesser General Public License as published by
-	   the Free Software Foundation, either version 3 of the License, or
+	   the Free Software Foundation, either version 2 of the License, or
 	   (at your option) any later version.
 
 	   This program is distributed in the hope that it will be useful,

Added: people/sigurdne/modules/phpgwapi/trunk/inc/class.Services_JSON.inc.php
===================================================================
--- people/sigurdne/modules/phpgwapi/trunk/inc/class.Services_JSON.inc.php	                        (rev 0)
+++ people/sigurdne/modules/phpgwapi/trunk/inc/class.Services_JSON.inc.php	2009-11-20 10:28:10 UTC (rev 20845)
@@ -0,0 +1,801 @@
+<?php
+/* vim: set expandtab tabstop=4 shiftwidth=4 softtabstop=4: */
+
+/** 
+ * Converts to and from JSON format.
+ * 
+ * JSON (JavaScript Object Notation) is a lightweight data-interchange
+ * format. It is easy for humans to read and write. It is easy for machines
+ * to parse and generate. It is based on a subset of the JavaScript
+ * Programming Language, Standard ECMA-262 3rd Edition - December 1999.
+ * This feature can also be found in  Python. JSON is a text format that is
+ * completely language independent but uses conventions that are familiar
+ * to programmers of the C-family of languages, including C, C++, C#, Java,
+ * JavaScript, Perl, TCL, and many others. These properties make JSON an
+ * ideal data-interchange language.
+ * 
+ * This package provides a simple encoder and decoder for JSON notation. It
+ * is intended for use with client-side Javascript applications that make
+ * use of HTTPRequest to perform server communication functions - data can
+ * be encoded into JSON notation for use in a client-side javascript, or
+ * decoded from incoming Javascript requests. JSON format is native to
+ * Javascript, and can be directly eval()'ed with no further parsing
+ * overhead
+ *
+ * All strings should be in ASCII or UTF-8 format!
+ *
+ * LICENSE: Redistribution and use in source and binary forms, with or
+ * without modification, are permitted provided that the following
+ * conditions are met: Redistributions of source code must retain the
+ * above copyright notice, this list of conditions and the following
+ * disclaimer. Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following disclaimer
+ * in the documentation and/or other materials provided with the
+ * distribution.
+ * 
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN
+ * NO EVENT SHALL CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
+ * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
+ * TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
+ * USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+ * DAMAGE.
+ * 
+ * @category
+ * @package     phpgwapi
+ * @subpackage  Services_JSON
+ * @author      Michal Migurski <[email protected]>
+ * @author      Matt Knapp <mdknapp[at]gmail[dot]com>
+ * @author      Brett Stimmerman <brettstimmerman[at]gmail[dot]com>
+ * @copyright   2005 Michal Migurski
+ * @license     http://www.opensource.org/licenses/bsd-license.php
+ * @link        http://pear.php.net/pepr/pepr-proposal-show.php?id=198
+ */
+
+/**
+ * Marker constant for Services_JSON::decode(), used to flag stack state
+ */
+define('SERVICES_JSON_SLICE',   1);
+
+/**
+ * Marker constant for Services_JSON::decode(), used to flag stack state
+ */
+define('SERVICES_JSON_IN_STR',  2);
+
+/**
+ * Marker constant for Services_JSON::decode(), used to flag stack state
+ */
+define('SERVICES_JSON_IN_ARR',  3);
+
+/**
+ * Marker constant for Services_JSON::decode(), used to flag stack state
+ */
+define('SERVICES_JSON_IN_OBJ',  4);
+
+/**
+ * Marker constant for Services_JSON::decode(), used to flag stack state
+ */
+define('SERVICES_JSON_IN_CMT', 5);
+
+/**
+ * Behavior switch for Services_JSON::decode()
+ */
+define('SERVICES_JSON_LOOSE_TYPE', 16);
+
+/**
+ * Behavior switch for Services_JSON::decode()
+ */
+define('SERVICES_JSON_SUPPRESS_ERRORS', 32);
+
+/** 
+ * Converts to and from JSON format.
+ *
+ * Brief example of use:
+ *
+ * <code>
+ * // create a new instance of Services_JSON
+ * $json = new Services_JSON();
+ * 
+ * // convert a complexe value to JSON notation, and send it to the browser
+ * $value = array('foo', 'bar', array(1, 2, 'baz'), array(3, array(4)));
+ * $output = $json->encode($value);
+ *
+ * print($output);
+ * // prints: ["foo","bar",[1,2,"baz"],[3,[4]]]
+ * 
+ * // accept incoming POST data, assumed to be in JSON notation
+ * $input = file_get_contents('php://input', 1000000);
+ * $value = $json->decode($input);
+ * </code>
+ * @package     phpgwapi
+ * @subpackage  Services_JSON
+ */
+class Services_JSON
+{
+   /**
+    * constructs a new JSON instance
+    *
+    * @param    int     $use    object behavior flags; combine with boolean-OR
+    *
+    *                           possible values:
+    *                           - SERVICES_JSON_LOOSE_TYPE:  loose typing.
+    *                                   "{...}" syntax creates associative arrays
+    *                                   instead of objects in decode().
+    *                           - SERVICES_JSON_SUPPRESS_ERRORS:  error suppression.
+    *                                   Values which can't be encoded (e.g. resources)
+    *                                   appear as NULL instead of throwing errors.
+    *                                   By default, a deeply-nested resource will
+    *                                   bubble up with an error, so all return values
+    *                                   from encode() should be checked with isError()
+    */
+    function Services_JSON($use = 0)
+    {
+        $this->use = $use;
+    }
+
+   /**
+    * convert a string from one UTF-16 char to one UTF-8 char
+    *
+    * Normally should be handled by mb_convert_encoding, but
+    * provides a slower PHP-only method for installations
+    * that lack the multibye string extension.
+    *
+    * @param    string  $utf16  UTF-16 character
+    * @return   string  UTF-8 character
+    * @access   private
+    */
+    function utf162utf8($utf16)
+    {
+        // oh please oh please oh please oh please oh please
+        if(function_exists('mb_convert_encoding'))
+            return mb_convert_encoding($utf16, 'UTF-8', 'UTF-16');
+        
+        $bytes = (ord($utf16{0}) << 8) | ord($utf16{1});
+
+        switch(true) {
+            case ((0x7F & $bytes) == $bytes):
+                // this case should never be reached, because we are in ASCII range
+                // see: http://www.cl.cam.ac.uk/~mgk25/unicode.html#utf-8
+                return chr(0x7F & $bytes);
+
+            case (0x07FF & $bytes) == $bytes:
+                // return a 2-byte UTF-8 character
+                // see: http://www.cl.cam.ac.uk/~mgk25/unicode.html#utf-8
+                return chr(0xC0 | (($bytes >> 6) & 0x1F))
+                     . chr(0x80 | ($bytes & 0x3F));
+
+            case (0xFFFF & $bytes) == $bytes:
+                // return a 3-byte UTF-8 character
+                // see: http://www.cl.cam.ac.uk/~mgk25/unicode.html#utf-8
+                return chr(0xE0 | (($bytes >> 12) & 0x0F))
+                     . chr(0x80 | (($bytes >> 6) & 0x3F))
+                     . chr(0x80 | ($bytes & 0x3F));
+        }
+
+        // ignoring UTF-32 for now, sorry
+        return '';
+    }        
+
+   /**
+    * convert a string from one UTF-8 char to one UTF-16 char
+    *
+    * Normally should be handled by mb_convert_encoding, but
+    * provides a slower PHP-only method for installations
+    * that lack the multibye string extension.
+    *
+    * @param    string  $utf8   UTF-8 character
+    * @return   string  UTF-16 character
+    * @access   private
+    */
+    function utf82utf16($utf8)
+    {
+        // oh please oh please oh please oh please oh please
+        if(function_exists('mb_convert_encoding'))
+            return mb_convert_encoding($utf8, 'UTF-16', 'UTF-8');
+        
+        switch(strlen($utf8)) {
+            case 1:
+                // this case should never be reached, because we are in ASCII range
+                // see: http://www.cl.cam.ac.uk/~mgk25/unicode.html#utf-8
+                return $ut8;
+
+            case 2:
+                // return a UTF-16 character from a 2-byte UTF-8 char
+                // see: http://www.cl.cam.ac.uk/~mgk25/unicode.html#utf-8
+                return chr(0x07 & (ord($utf8{0}) >> 2))
+                     . chr((0xC0 & (ord($utf8{0}) << 6))
+                         | (0x3F & ord($utf8{1})));
+                
+            case 3:
+                // return a UTF-16 character from a 3-byte UTF-8 char
+                // see: http://www.cl.cam.ac.uk/~mgk25/unicode.html#utf-8
+                return chr((0xF0 & (ord($utf8{0}) << 4))
+                         | (0x0F & (ord($utf8{1}) >> 2)))
+                     . chr((0xC0 & (ord($utf8{1}) << 6))
+                         | (0x7F & ord($utf8{2})));
+        }
+
+        // ignoring UTF-32 for now, sorry
+        return '';
+    }        
+
+   /**
+    * encodes an arbitrary variable into JSON format
+    *
+    * @param    mixed   $var    any number, boolean, string, array, or object to be encoded.
+    *                           see argument 1 to Services_JSON() above for array-parsing behavior.
+    *                           if var is a strng, note that encode() always expects it
+    *                           to be in ASCII or UTF-8 format!
+    *
+    * @return   mixed   JSON string representation of input var or an error if a problem occurs
+    * @access   public
+    */
+    function encode($var)
+    {
+        switch (gettype($var)) {
+            case 'boolean':
+                return $var ? 'true' : 'false';
+            
+            case 'NULL':
+                return 'null';
+            
+            case 'integer':
+                return (int) $var;
+                
+            case 'double':
+            case 'float':
+                return (float) $var;
+                
+            case 'string':
+                // STRINGS ARE EXPECTED TO BE IN ASCII OR UTF-8 FORMAT
+                $ascii = '';
+                $strlen_var = strlen($var);
+
+               /*
+                * Iterate over every character in the string,
+                * escaping with a slash or encoding to UTF-8 where necessary
+                */
+                for ($c = 0; $c < $strlen_var; ++$c) {
+                    
+                    $ord_var_c = ord($var{$c});
+                    
+                    switch (true) {
+                        case $ord_var_c == 0x08:
+                            $ascii .= '\b';
+                            break;
+                        case $ord_var_c == 0x09:
+                            $ascii .= '\t';
+                            break;
+                        case $ord_var_c == 0x0A:
+                            $ascii .= '\n';
+                            break;
+                        case $ord_var_c == 0x0C:
+                            $ascii .= '\f';
+                            break;
+                        case $ord_var_c == 0x0D:
+                            $ascii .= '\r';
+                            break;
+
+                        case $ord_var_c == 0x22:
+                        case $ord_var_c == 0x2F:
+                        case $ord_var_c == 0x5C:
+                            // double quote, slash, slosh
+                            $ascii .= '\\'.$var{$c};
+                            break;
+                            
+                        case (($ord_var_c >= 0x20) && ($ord_var_c <= 0x7F)):
+                            // characters U-00000000 - U-0000007F (same as ASCII)
+                            $ascii .= $var{$c};
+                            break;
+                        
+                        case (($ord_var_c & 0xE0) == 0xC0):
+                            // characters U-00000080 - U-000007FF, mask 110XXXXX
+                            // see http://www.cl.cam.ac.uk/~mgk25/unicode.html#utf-8
+                            $char = pack('C*', $ord_var_c, ord($var{$c + 1}));
+                            $c += 1;
+                            $utf16 = $this->utf82utf16($char);
+                            $ascii .= sprintf('\u%04s', bin2hex($utf16));
+                            break;
+    
+                        case (($ord_var_c & 0xF0) == 0xE0):
+                            // characters U-00000800 - U-0000FFFF, mask 1110XXXX
+                            // see http://www.cl.cam.ac.uk/~mgk25/unicode.html#utf-8
+                            $char = pack('C*', $ord_var_c,
+                                         ord($var{$c + 1}),
+                                         ord($var{$c + 2}));
+                            $c += 2;
+                            $utf16 = $this->utf82utf16($char);
+                            $ascii .= sprintf('\u%04s', bin2hex($utf16));
+                            break;
+    
+                        case (($ord_var_c & 0xF8) == 0xF0):
+                            // characters U-00010000 - U-001FFFFF, mask 11110XXX
+                            // see http://www.cl.cam.ac.uk/~mgk25/unicode.html#utf-8
+                            $char = pack('C*', $ord_var_c,
+                                         ord($var{$c + 1}),
+                                         ord($var{$c + 2}),
+                                         ord($var{$c + 3}));
+                            $c += 3;
+                            $utf16 = $this->utf82utf16($char);
+                            $ascii .= sprintf('\u%04s', bin2hex($utf16));
+                            break;
+    
+                        case (($ord_var_c & 0xFC) == 0xF8):
+                            // characters U-00200000 - U-03FFFFFF, mask 111110XX
+                            // see http://www.cl.cam.ac.uk/~mgk25/unicode.html#utf-8
+                            $char = pack('C*', $ord_var_c,
+                                         ord($var{$c + 1}),
+                                         ord($var{$c + 2}),
+                                         ord($var{$c + 3}),
+                                         ord($var{$c + 4}));
+                            $c += 4;
+                            $utf16 = $this->utf82utf16($char);
+                            $ascii .= sprintf('\u%04s', bin2hex($utf16));
+                            break;
+    
+                        case (($ord_var_c & 0xFE) == 0xFC):
+                            // characters U-04000000 - U-7FFFFFFF, mask 1111110X
+                            // see http://www.cl.cam.ac.uk/~mgk25/unicode.html#utf-8
+                            $char = pack('C*', $ord_var_c,
+                                         ord($var{$c + 1}),
+                                         ord($var{$c + 2}),
+                                         ord($var{$c + 3}),
+                                         ord($var{$c + 4}),
+                                         ord($var{$c + 5}));
+                            $c += 5;
+                            $utf16 = $this->utf82utf16($char);
+                            $ascii .= sprintf('\u%04s', bin2hex($utf16));
+                            break;
+                    }
+                }
+                
+                return '"'.$ascii.'"';
+                
+            case 'array':
+               /*
+                * As per JSON spec if any array key is not an integer
+                * we must treat the the whole array as an object. We
+                * also try to catch a sparsely populated associative
+                * array with numeric keys here because some JS engines
+                * will create an array with empty indexes up to
+                * max_index which can cause memory issues and because
+                * the keys, which may be relevant, will be remapped
+                * otherwise.
+                * 
+                * As per the ECMA and JSON specification an object may
+                * have any string as a property. Unfortunately due to
+                * a hole in the ECMA specification if the key is a
+                * ECMA reserved word or starts with a digit the
+                * parameter is only accessible using ECMAScript's
+                * bracket notation.
+                */
+                
+                // treat as a JSON object  
+                if (is_array($var) && count($var) && (array_keys($var) !== range(0, sizeof($var) - 1))) {
+                    $properties = array_map(array($this, 'name_value'),
+                                            array_keys($var),
+                                            array_values($var));
+                
+                    foreach($properties as $property)
+                        if(Services_JSON::isError($property))
+                            return $property;
+                    
+                    return '{' . join(',', $properties) . '}';
+                }
+
+                // treat it like a regular array
+                $elements = array_map(array($this, 'encode'), $var);
+                
+                foreach($elements as $element)
+                    if(Services_JSON::isError($element))
+                        return $element;
+                
+                return '[' . join(',', $elements) . ']';
+                
+            case 'object':
+                $vars = get_object_vars($var);
+
+                $properties = array_map(array($this, 'name_value'),
+                                        array_keys($vars),
+                                        array_values($vars));
+            
+                foreach($properties as $property)
+                    if(Services_JSON::isError($property))
+                        return $property;
+                
+                return '{' . join(',', $properties) . '}';
+
+            default:
+                return ($this->use & SERVICES_JSON_SUPPRESS_ERRORS)
+                    ? 'null'
+                    : new Services_JSON_Error(gettype($var)." can not be encoded as JSON string");
+        }
+    }
+    
+   /**
+    * array-walking function for use in generating JSON-formatted name-value pairs
+    *
+    * @param    string  $name   name of key to use
+    * @param    mixed   $value  reference to an array element to be encoded
+    *
+    * @return   string  JSON-formatted name-value pair, like '"name":value'
+    * @access   private
+    */
+    function name_value($name, $value)
+    {
+        $encoded_value = $this->encode($value);
+        
+        if(Services_JSON::isError($encoded_value))
+            return $encoded_value;
+    
+        return $this->encode(strval($name)) . ':' . $encoded_value;
+    }        
+
+   /**
+    * reduce a string by removing leading and trailing comments and whitespace
+    *
+    * @param    $str    string      string value to strip of comments and whitespace
+    *
+    * @return   string  string value stripped of comments and whitespace
+    * @access   private
+    */
+    function reduce_string($str)
+    {
+        $str = preg_replace(array(
+        
+                // eliminate single line comments in '// ...' form
+                '#^\s*//(.+)$#m',
+    
+                // eliminate multi-line comments in '/* ... */' form, at start of string
+                '#^\s*/\*(.+)\*/#Us',
+    
+                // eliminate multi-line comments in '/* ... */' form, at end of string
+                '#/\*(.+)\*/\s*$#Us'
+    
+            ), '', $str);
+        
+        // eliminate extraneous space
+        return trim($str);
+    }
+
+   /**
+    * decodes a JSON string into appropriate variable
+    *
+    * @param    string  $str    JSON-formatted string
+    *
+    * @return   mixed   number, boolean, string, array, or object
+    *                   corresponding to given JSON input string.
+    *                   See argument 1 to Services_JSON() above for object-output behavior.
+    *                   Note that decode() always returns strings
+    *                   in ASCII or UTF-8 format!
+    * @access   public
+    */
+    function decode($str)
+    {
+        $str = $this->reduce_string($str);
+    
+        switch (strtolower($str)) {
+            case 'true':
+                return true;
+
+            case 'false':
+                return false;
+            
+            case 'null':
+                return null;
+            
+            default:
+                if (is_numeric($str)) {
+                    // Lookie-loo, it's a number
+
+                    // This would work on its own, but I'm trying to be
+                    // good about returning integers where appropriate:
+                    // return (float)$str;
+
+                    // Return float or int, as appropriate
+                    return ((float)$str == (integer)$str)
+                        ? (integer)$str
+                        : (float)$str;
+                    
+                } elseif (preg_match('/^("|\').*(\1)$/s', $str, $m) && $m[1] == $m[2]) {
+                    // STRINGS RETURNED IN UTF-8 FORMAT
+                    $delim = substr($str, 0, 1);
+                    $chrs = substr($str, 1, -1);
+                    $utf8 = '';
+                    $strlen_chrs = strlen($chrs);
+                    
+                    for ($c = 0; $c < $strlen_chrs; ++$c) {
+                    
+                        $substr_chrs_c_2 = substr($chrs, $c, 2);
+                        $ord_chrs_c = ord($chrs{$c});
+                        
+                        switch (true) {
+                            case $substr_chrs_c_2 == '\b':
+                                $utf8 .= chr(0x08);
+                                ++$c;
+                                break;
+                            case $substr_chrs_c_2 == '\t':
+                                $utf8 .= chr(0x09);
+                                ++$c;
+                                break;
+                            case $substr_chrs_c_2 == '\n':
+                                $utf8 .= chr(0x0A);
+                                ++$c;
+                                break;
+                            case $substr_chrs_c_2 == '\f':
+                                $utf8 .= chr(0x0C);
+                                ++$c;
+                                break;
+                            case $substr_chrs_c_2 == '\r':
+                                $utf8 .= chr(0x0D);
+                                ++$c;
+                                break;
+
+                            case $substr_chrs_c_2 == '\\"':
+                            case $substr_chrs_c_2 == '\\\'':
+                            case $substr_chrs_c_2 == '\\\\':
+                            case $substr_chrs_c_2 == '\\/':
+                                if (($delim == '"' && $substr_chrs_c_2 != '\\\'') ||
+                                   ($delim == "'" && $substr_chrs_c_2 != '\\"')) {
+                                    $utf8 .= $chrs{++$c};
+                                }
+                                break;
+                                
+                            case preg_match('/\\\u[0-9A-F]{4}/i', substr($chrs, $c, 6)):
+                                // single, escaped unicode character
+                                $utf16 = chr(hexdec(substr($chrs, ($c + 2), 2)))
+                                       . chr(hexdec(substr($chrs, ($c + 4), 2)));
+                                $utf8 .= $this->utf162utf8($utf16);
+                                $c += 5;
+                                break;
+        
+                            case ($ord_chrs_c >= 0x20) && ($ord_chrs_c <= 0x7F):
+                                $utf8 .= $chrs{$c};
+                                break;
+        
+                            case ($ord_chrs_c & 0xE0) == 0xC0:
+                                // characters U-00000080 - U-000007FF, mask 110XXXXX
+                                //see http://www.cl.cam.ac.uk/~mgk25/unicode.html#utf-8
+                                $utf8 .= substr($chrs, $c, 2);
+                                ++$c;
+                                break;
+    
+                            case ($ord_chrs_c & 0xF0) == 0xE0:
+                                // characters U-00000800 - U-0000FFFF, mask 1110XXXX
+                                // see http://www.cl.cam.ac.uk/~mgk25/unicode.html#utf-8
+                                $utf8 .= substr($chrs, $c, 3);
+                                $c += 2;
+                                break;
+    
+                            case ($ord_chrs_c & 0xF8) == 0xF0:
+                                // characters U-00010000 - U-001FFFFF, mask 11110XXX
+                                // see http://www.cl.cam.ac.uk/~mgk25/unicode.html#utf-8
+                                $utf8 .= substr($chrs, $c, 4);
+                                $c += 3;
+                                break;
+    
+                            case ($ord_chrs_c & 0xFC) == 0xF8:
+                                // characters U-00200000 - U-03FFFFFF, mask 111110XX
+                                // see http://www.cl.cam.ac.uk/~mgk25/unicode.html#utf-8
+                                $utf8 .= substr($chrs, $c, 5);
+                                $c += 4;
+                                break;
+    
+                            case ($ord_chrs_c & 0xFE) == 0xFC:
+                                // characters U-04000000 - U-7FFFFFFF, mask 1111110X
+                                // see http://www.cl.cam.ac.uk/~mgk25/unicode.html#utf-8
+                                $utf8 .= substr($chrs, $c, 6);
+                                $c += 5;
+                                break;
+
+                        }
+
+                    }
+                    
+                    return $utf8;
+                
+                } elseif (preg_match('/^\[.*\]$/s', $str) || preg_match('/^\{.*\}$/s', $str)) {
+                    // array, or object notation
+
+                    if ($str{0} == '[') {
+                        $stk = array(SERVICES_JSON_IN_ARR);
+                        $arr = array();
+                    } else {
+                        if ($this->use & SERVICES_JSON_LOOSE_TYPE) {
+                            $stk = array(SERVICES_JSON_IN_OBJ);
+                            $obj = array();
+                        } else {
+                            $stk = array(SERVICES_JSON_IN_OBJ);
+                            $obj = new stdClass();
+                        }
+                    }
+                    
+                    array_push($stk, array('what'  => SERVICES_JSON_SLICE,
+                                           'where' => 0,
+                                           'delim' => false));
+
+                    $chrs = substr($str, 1, -1);
+                    $chrs = $this->reduce_string($chrs);
+                    
+                    if ($chrs == '') {
+                        if (reset($stk) == SERVICES_JSON_IN_ARR) {
+                            return $arr;
+
+                        } else {
+                            return $obj;
+
+                        }
+                    }
+
+                    //print("\nparsing {$chrs}\n");
+                    
+                    $strlen_chrs = strlen($chrs);
+                    
+                    for ($c = 0; $c <= $strlen_chrs; ++$c) {
+                    
+                        $top = end($stk);
+                        $substr_chrs_c_2 = substr($chrs, $c, 2);
+                    
+                        if (($c == $strlen_chrs) || (($chrs{$c} == ',') && ($top['what'] == SERVICES_JSON_SLICE))) {
+                            // found a comma that is not inside a string, array, etc.,
+                            // OR we've reached the end of the character list
+                            $slice = substr($chrs, $top['where'], ($c - $top['where']));
+                            array_push($stk, array('what' => SERVICES_JSON_SLICE, 'where' => ($c + 1), 'delim' => false));
+                            //print("Found split at {$c}: ".substr($chrs, $top['where'], (1 + $c - $top['where']))."\n");
+
+                            if (reset($stk) == SERVICES_JSON_IN_ARR) {
+                                // we are in an array, so just push an element onto the stack
+                                array_push($arr, $this->decode($slice));
+
+                            } elseif (reset($stk) == SERVICES_JSON_IN_OBJ) {
+                                // we are in an object, so figure
+                                // out the property name and set an
+                                // element in an associative array,
+                                // for now
+                                if (preg_match('/^\s*(["\'].*[^\\\]["\'])\s*:\s*(\S.*),?$/Uis', $slice, $parts)) {
+                                    // "name":value pair
+                                    $key = $this->decode($parts[1]);
+                                    $val = $this->decode($parts[2]);
+
+                                    if ($this->use & SERVICES_JSON_LOOSE_TYPE) {
+                                        $obj[$key] = $val;
+                                    } else {
+                                        $obj->$key = $val;
+                                    }
+                                } elseif (preg_match('/^\s*(\w+)\s*:\s*(\S.*),?$/Uis', $slice, $parts)) {
+                                    // name:value pair, where name is unquoted
+                                    $key = $parts[1];
+                                    $val = $this->decode($parts[2]);
+
+                                    if ($this->use & SERVICES_JSON_LOOSE_TYPE) {
+                                        $obj[$key] = $val;
+                                    } else {
+                                        $obj->$key = $val;
+                                    }
+                                }
+
+                            }
+
+                        } elseif ((($chrs{$c} == '"') || ($chrs{$c} == "'")) && ($top['what'] != SERVICES_JSON_IN_STR)) {
+                            // found a quote, and we are not inside a string
+                            array_push($stk, array('what' => SERVICES_JSON_IN_STR, 'where' => $c, 'delim' => $chrs{$c}));
+                            //print("Found start of string at {$c}\n");
+
+                        } elseif (($chrs{$c} == $top['delim']) &&
+                                 ($top['what'] == SERVICES_JSON_IN_STR) &&
+                                 (($chrs{$c - 1} != '\\') ||
+                                 ($chrs{$c - 1} == '\\' && $chrs{$c - 2} == '\\'))) {
+                            // found a quote, we're in a string, and it's not escaped
+                            array_pop($stk);
+                            //print("Found end of string at {$c}: ".substr($chrs, $top['where'], (1 + 1 + $c - $top['where']))."\n");
+
+                        } elseif (($chrs{$c} == '[') &&
+                                 in_array($top['what'], array(SERVICES_JSON_SLICE, SERVICES_JSON_IN_ARR, SERVICES_JSON_IN_OBJ))) {
+                            // found a left-bracket, and we are in an array, object, or slice
+                            array_push($stk, array('what' => SERVICES_JSON_IN_ARR, 'where' => $c, 'delim' => false));
+                            //print("Found start of array at {$c}\n");
+
+                        } elseif (($chrs{$c} == ']') && ($top['what'] == SERVICES_JSON_IN_ARR)) {
+                            // found a right-bracket, and we're in an array
+                            array_pop($stk);
+                            //print("Found end of array at {$c}: ".substr($chrs, $top['where'], (1 + $c - $top['where']))."\n");
+
+                        } elseif (($chrs{$c} == '{') &&
+                                 in_array($top['what'], array(SERVICES_JSON_SLICE, SERVICES_JSON_IN_ARR, SERVICES_JSON_IN_OBJ))) {
+                            // found a left-brace, and we are in an array, object, or slice
+                            array_push($stk, array('what' => SERVICES_JSON_IN_OBJ, 'where' => $c, 'delim' => false));
+                            //print("Found start of object at {$c}\n");
+
+                        } elseif (($chrs{$c} == '}') && ($top['what'] == SERVICES_JSON_IN_OBJ)) {
+                            // found a right-brace, and we're in an object
+                            array_pop($stk);
+                            //print("Found end of object at {$c}: ".substr($chrs, $top['where'], (1 + $c - $top['where']))."\n");
+
+                        } elseif (($substr_chrs_c_2 == '/*') &&
+                                 in_array($top['what'], array(SERVICES_JSON_SLICE, SERVICES_JSON_IN_ARR, SERVICES_JSON_IN_OBJ))) {
+                            // found a comment start, and we are in an array, object, or slice
+                            array_push($stk, array('what' => SERVICES_JSON_IN_CMT, 'where' => $c, 'delim' => false));
+                            $c++;
+                            //print("Found start of comment at {$c}\n");
+
+                        } elseif (($substr_chrs_c_2 == '*/') && ($top['what'] == SERVICES_JSON_IN_CMT)) {
+                            // found a comment end, and we're in one now
+                            array_pop($stk);
+                            $c++;
+                            
+                            for ($i = $top['where']; $i <= $c; ++$i)
+                                $chrs = substr_replace($chrs, ' ', $i, 1);
+                            
+                            //print("Found end of comment at {$c}: ".substr($chrs, $top['where'], (1 + $c - $top['where']))."\n");
+
+                        }
+                    
+                    }
+                    
+                    if (reset($stk) == SERVICES_JSON_IN_ARR) {
+                        return $arr;
+
+                    } elseif (reset($stk) == SERVICES_JSON_IN_OBJ) {
+                        return $obj;
+
+                    }
+                
+                }
+        }
+    }
+    
+    /**
+     * @todo Ultimately, this should just call PEAR::isError()
+     */
+    function isError($data, $code = null)
+    {
+        if (class_exists('pear')) {
+            return PEAR::isError($data, $code);
+        } elseif (is_object($data) && (get_class($data) == 'services_json_error' ||
+                                 is_subclass_of($data, 'services_json_error'))) {
+            return true;
+        }
+
+        return false;
+    }
+}
+
+if (class_exists('pear_error')) {
+
+    /**
+    * Error Handler for Services_JSON
+    *
+    * @package phpgwapi
+    * @subpackage Services_JSON
+    */
+    class Services_JSON_Error extends PEAR_Error
+    {
+        function Services_JSON_Error($message = 'unknown error', $code = null,
+                                     $mode = null, $options = null, $userinfo = null)
+        {
+            parent::PEAR_Error($message, $code, $mode, $options, $userinfo);
+        }
+    }
+
+} else {
+
+    /**
+     * @todo Ultimately, this class shall be descended from PEAR_Error
+     * @ignore
+     */
+    class Services_JSON_Error
+    {
+        function Services_JSON_Error($message = 'unknown error', $code = null,
+                                     $mode = null, $options = null, $userinfo = null)
+        {
+        
+        }
+    }
+
+}
+    
+?>


Property changes on: people/sigurdne/modules/phpgwapi/trunk/inc/class.Services_JSON.inc.php
___________________________________________________________________
Added: svn:keywords
   + Id Revision
Added: svn:eol-style
   + native

Modified: people/sigurdne/modules/phpgwapi/trunk/inc/class.Template.inc.php
===================================================================
--- people/sigurdne/modules/phpgwapi/trunk/inc/class.Template.inc.php	2009-11-20 10:27:41 UTC (rev 20844)
+++ people/sigurdne/modules/phpgwapi/trunk/inc/class.Template.inc.php	2009-11-20 10:28:10 UTC (rev 20845)
@@ -13,21 +13,6 @@
  *
  */
 
-	/*
-	   This program is free software: you can redistribute it and/or modify
-	   it under the terms of the GNU Lesser General Public License as published by
-	   the Free Software Foundation, either version 3 of the License, or
-	   (at your option) any later version.
-
-	   This program is distributed in the hope that it will be useful,
-	   but WITHOUT ANY WARRANTY; without even the implied warranty of
-	   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-	   GNU General Public License for more details.
-
-	   You should have received a copy of the GNU Lesser General Public License
-	   along with this program.  If not, see <http://www.gnu.org/licenses/>.
-	 */
-
 /**
  * The template class allows you to keep your HTML code in some external files
  * which are completely free of PHP code, but contain replacement fields.
@@ -521,10 +506,8 @@
 		reset($this->varvals);
 		while (list($k, $v) = each($this->varvals)) {
 			$varvals_quoted[$k] = preg_replace(array('/\\\\/', '/\$/'), array('\\\\\\\\', '\\\\$'), $v);
-			//XXX Caeies 02/09 Ouch how is this possible ?
 			if(is_array($varvals_quoted[$k]))
 			{
-				//_debug_array($k);
 				$varvals_quoted[$k] = implode($varvals_quoted[$k]);
 			}
 		}

Modified: people/sigurdne/modules/phpgwapi/trunk/inc/class.Template_experimental.inc.php
===================================================================
--- people/sigurdne/modules/phpgwapi/trunk/inc/class.Template_experimental.inc.php	2009-11-20 10:27:41 UTC (rev 20844)
+++ people/sigurdne/modules/phpgwapi/trunk/inc/class.Template_experimental.inc.php	2009-11-20 10:28:10 UTC (rev 20845)
@@ -8,21 +8,6 @@
 	* @package phpgwapi
 	* @subpackage gui
 	* @version $Id$
-	*/
-
-	/*
-	   This program is free software: you can redistribute it and/or modify
-	   it under the terms of the GNU Lesser General Public License as published by
-	   the Free Software Foundation, either version 3 of the License, or
-	   (at your option) any later version.
-
-	   This program is distributed in the hope that it will be useful,
-	   but WITHOUT ANY WARRANTY; without even the implied warranty of
-	   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-	   GNU General Public License for more details.
-
-	   You should have received a copy of the GNU Lesser General Public License
-	   along with this program.  If not, see <http://www.gnu.org/licenses/>.
 	 */
 
 	/**

Modified: people/sigurdne/modules/phpgwapi/trunk/inc/class.account.inc.php
===================================================================
--- people/sigurdne/modules/phpgwapi/trunk/inc/class.account.inc.php	2009-11-20 10:27:41 UTC (rev 20844)
+++ people/sigurdne/modules/phpgwapi/trunk/inc/class.account.inc.php	2009-11-20 10:28:10 UTC (rev 20845)
@@ -5,16 +5,16 @@
 	 *
 	 * @author Dave Hall <[email protected]>
 	 * @copyright Copyright (C) 2008 Free Software Foundation, Inc. http://www.fsf.org/
-	 * @license http://www.gnu.org/licenses/lgpl.html GNU Lesser General Public License v3 or later
+	 * @license http://www.gnu.org/licenses/lgpl.html GNU Lesser General Public License v2 or later
 	 * @package phpgroupware
 	 * @subpackage phpgwapi
-	 * @version $Id: class.accounts_.inc.php 779 2008-02-26 09:53:55Z dave $
+	 * @version $Id: class.account.inc.php 2588 2009-04-14 11:00:02Z sigurd $
 	 */
 
 	/*
 	   This program is free software: you can redistribute it and/or modify
 	   it under the terms of the GNU Lesser General Public License as published by
-	   the Free Software Foundation, either version 3 of the License, or
+	   the Free Software Foundation, either version 2 of the License, or
 	   (at your option) any later version.
 
 	   This program is distributed in the hope that it will be useful,
@@ -88,7 +88,8 @@
 			'expires'			=> 0,
 			'person_id'			=> 0,
 			'quota'				=> 0,
-			'old_loginid'		=> ''
+			'old_loginid'		=> '',
+			'type' 				=> ''
 		);
 
 		/**
@@ -227,7 +228,26 @@
 	 */
 	class phpgwapi_group extends phpgwapi_account
 	{
+
 		/**
+		 * @var array $_data the group data
+		 */
+
+		protected $_data = array
+		(
+			'id'				=> 0,
+			'lid'				=> '',
+			'firstname'			=> '',
+			'lastname'			=> 'Group',
+			'passwd_hash'		=> '',
+			'enabled'			=> false,
+			'expires'			=> 0,
+			'person_id'			=> 0,
+			'old_loginid'		=> '',
+			'type' 				=> 'g'
+		);
+
+		/**
 		 * Initialise the values of the object - this should only be called from phpgwapi_accounts
 		 *
 		 * @param array $arr the values to initialise the values of the object with
@@ -255,7 +275,8 @@
 					// we ignore the rest
 				}
 			}
-			$this->_data['lastname'] = 'Group';
+		//	$this->_data['lastname'] = 'Group';
+		//	$this->_data['type'] = 'g';
 			$this->_hash = $this->_generate_hash();
 		}
 
@@ -267,6 +288,7 @@
 		public function __construct()
 		{
 			$this->_data['lastname'] = 'Group';
+			$this->_data['type'] 		= parent::TYPE_GROUP;
 		}
 
 		/**
@@ -292,7 +314,9 @@
 				case 'person_id':
 				case 'quota':
 				case 'old_loginid':
+				case 'type':
 					return $this->_data[$name];
+
 				default:
 					throw new Exception(lang('Unknown value: %1', $name));
 			}
@@ -355,11 +379,21 @@
 				throw new Exception('Group name is too short');
 			}
 
-			if ( $lookup && 
-				$this->_data['id'] != $GLOBALS['phpgw']->accounts->name2id($group) )
+			if ( $lookup )
 			{
+				if ($this->_data['id'])
+				{
+					if($this->_data['id'] != $GLOBALS['phpgw']->accounts->name2id($group)
+						&& $GLOBALS['phpgw']->accounts->name2id($group) )
+					{
+						throw new Exception('Group name already in use');
+					}
+				}
+				else if($GLOBALS['phpgw']->accounts->name2id($group))
+			{
 				throw new Exception('Group name already in use');
 			}
+			}
 
 			phpgw::import_class('phpgwapi.globally_denied');
 			if ( phpgwapi_globally_denied::user($group) )
@@ -380,6 +414,12 @@
 	 */
 	class phpgwapi_user extends phpgwapi_account
 	{
+
+		public function __construct()
+		{
+			$this->_data['type'] 		= parent::TYPE_USER;
+		}
+
 		/**
 		 * Initialise the values of the object - this should only be called from phpgwapi_accounts
 		 *
@@ -411,6 +451,7 @@
 					case 'enabled':
 					case 'person_id':
 					case 'quota':
+					case 'type':
 						$this->_data[$key] = $val;
 				}
 			}
@@ -424,7 +465,7 @@
 		 */
 		public function is_expired()
 		{
-			$expires = $this->data['expires'];
+			$expires = $this->_data['expires'];
 			return $expires <> -1 && $expires < time();
 		}
 
@@ -469,6 +510,7 @@
 				case 'person_id':
 				case 'quota':
 				case 'old_loginid':
+				case 'type':
 					return $this->_data[$name];
 				default:
 					throw new Exception(lang('Unknown value: %1', $name));
@@ -504,7 +546,7 @@
 					break;
 
 				case 'passwd':
-					$this->_validate_password($value);
+					$this->validate_password($value);
 					$this->_data['passwd_hash'] = ExecMethod('phpgwapi.auth.create_hash', $value);
 					$this->_data['last_passwd_change'] = time();
 					break;
@@ -534,6 +576,10 @@
 					$this->_validate_quota($value);
 					break;
 
+				case 'type':
+					$this->_data['type'] = 'u';
+					break;
+
 				case 'dn':
 				case 'homedirectory':
 				case 'loginshell':
@@ -649,7 +695,7 @@
 		 *
 		 * @throws Exception when password is invalid/insecure
 		 */
-		protected function _validate_password($passwd)
+		public function validate_password($passwd)
 		{
 			$dict_loc = ini_get('crack.default_dictionary');
 
@@ -664,37 +710,103 @@
 			}
 			else
 			{
+				switch ( $GLOBALS['phpgw_info']['server']['password_level'] )
+				{
+					default:
+					case 'NONALPHA':
+						self::_validate_password_level_nonalpha($passwd);
+						// fall through
+					case '1NUM':
+						self::_validate_password_level_1num($passwd);
+						// fall through
+					case '2LOW':
+						self::_validate_password_level_2low($passwd);
+						// fall through
+					case '2UPPER':
+						self::_validate_password_level_2upper($passwd);
+						// fall through
+					case '8CHAR':
+						self::_validate_password_level_8char($passwd);
+				}
+			}
+		}
+
+		/**
+		 * Check that a password is at least 8 characters long
+		 *
+		 * @param string $passwd the password to check
+		 *
+		 * @throws Exception when password is shorter than 8 characters long
+		 */
+		protected static function _validate_password_level_8char($passwd)
+		{
 				$len = strlen($passwd); 
 				if ( $len < 8 )
 				{
 					throw new Exception(lang('Password must be at least 8 characters long, not %1', $len));
 				}
-
-				$m = array();
-				if ( preg_match_all('/[a-z]/', $passwd, $m) < 2 )
-				{
-					throw new Exception(lang('Password must contain at least 2 lower case characters'));
 				}
 
+		/**
+		 * Check that a password contain at least 2 upper case characters
+		 *
+		 * @param string $passwd the password to check
+		 *
+		 * @throws Exception when password do not contain at least 2 upper case characters
+		 */
+		protected static function _validate_password_level_2upper($passwd)
+		{
 				$m = array();
 				if ( preg_match_all('/[A-Z]/', $passwd, $m) < 2 )
 				{
 					throw new Exception(lang('Password must contain at least 2 upper case characters'));
 				}
-
+		}
+		/**
+		 * Check that a password contain at least 2 lower case characters
+		 *
+		 * @param string $passwd the password to check
+		 *
+		 * @throws Exception when password do not contain at least 2 lower case characters
+		 */
+		protected static function _validate_password_level_2low($passwd)
+		{
+			$m = array();
+			if ( preg_match_all('/[a-z]/', $passwd, $m) < 2 )
+			{
+				throw new Exception(lang('Password must contain at least 2 lower case characters'));
+			}
+		}
+		/**
+		 * Check that a password contain at least 1 number
+		 *
+		 * @param string $passwd the password to check
+		 *
+		 * @throws Exception when password is invalid/insecure do not contain at least 1 number
+		 */
+		protected static function _validate_password_level_1num($passwd)
+		{
 				$m = array();
 				if ( !preg_match_all('/[0-9]/', $passwd, $m) )
 				{
 					throw new Exception(lang('Password must contain at least 1 number'));
 				}
-
+		}
+		/**
+		 * Check that a password contain at least 1 non alphanumeric character
+		 *
+		 * @param string $passwd the password to check
+		 *
+		 * @throws Exception when password do not contain at least 1 non alphanumeric character
+		 */
+		protected static function _validate_password_level_nonalpha($passwd)
+		{
 				$m = array();
 				if ( !preg_match_all('/\W/', $passwd, $m)  )
 				{
 					throw new Exception(lang('Password must contain at least 1 non alphanumeric character'));
 				}
 			}
-		}
 
 		/**
 		 * Check if the specified quota is a valid value
@@ -713,7 +825,7 @@
 			}
 
 			//FIXME this should be stored in the API - not filemanager - it is a global value!
-			$config = createObject('phpgwapi.config', 'filemanager')->read();
+			$config = createObject('phpgwapi.config', 'filemanager')->read_repository();
 			if ( !isset($config['set_quota']) )
 			{
 				return true; // misocnfigured, but lets just accept it - for now

Added: people/sigurdne/modules/phpgwapi/trunk/inc/class.accounts_popup.inc.php
===================================================================
--- people/sigurdne/modules/phpgwapi/trunk/inc/class.accounts_popup.inc.php	                        (rev 0)
+++ people/sigurdne/modules/phpgwapi/trunk/inc/class.accounts_popup.inc.php	2009-11-20 10:28:10 UTC (rev 20845)
@@ -0,0 +1,343 @@
+<?php
+	/**
+	* Shared functions for other account repository managers and loader
+	* @author Bettina Gille <[email protected]>
+	* @author Philipp Kamps <[email protected]>
+	* @author Dave Hall <[email protected]>
+	* @copyright Copyright (C) 2000-2008 Free Software Foundation, Inc. http://www.fsf.org/
+	* @license http://www.gnu.org/licenses/lgpl.html GNU Lesser General Public License v2 or later
+	* @package phpgwapi
+	* @subpackage ui
+	* @version $Id$
+	*/
+
+	/*
+	   This program is free software: you can redistribute it and/or modify
+	   it under the terms of the GNU Lesser General Public License as published by
+	   the Free Software Foundation, either version 2 of the License, or
+	   (at your option) any later version.
+
+	   This program is distributed in the hope that it will be useful,
+	   but WITHOUT ANY WARRANTY; without even the implied warranty of
+	   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+	   GNU General Public License for more details.
+
+	   You should have received a copy of the GNU Lesser General Public License
+	   along with this program.  If not, see <http://www.gnu.org/licenses/>.
+	 */
+
+
+	class phpgwapi_accounts_popup
+	{
+		/**
+		 * @var object $t reference to global template object
+		 */
+		private $t;
+
+		public function __construct()
+		{
+			$this->t =& $GLOBALS['phpgw']->template;
+		}
+
+		public function render($app)
+		{
+			$group_id = phpgw::get_var('group_id', 'int');
+
+			$query = phpgw::get_var('query', 'string', 'POST');
+			$start = phpgw::get_var('start', 'int', 'GET');
+			$order = phpgw::get_var('order', 'string', 'GET', 'account_lid');
+			$sort = phpgw::get_var('sort', 'string', 'GET', 'ASC');
+
+			$nextmatches = createObject('phpgwapi.nextmatchs');
+
+			$this->t->set_root(PHPGW_TEMPLATE_DIR);
+
+			$this->t->set_file(array('accounts_list_t' => 'accounts_popup.tpl'));
+			$this->t->set_block('accounts_list_t','group_select','select');
+			$this->t->set_block('accounts_list_t','group_other','other');
+			$this->t->set_block('accounts_list_t','group_all','all');
+
+			$this->t->set_block('accounts_list_t','withperm_intro','withperm');
+			//$this->t->set_block('accounts_list_t','other_intro','iother');
+			$this->t->set_block('accounts_list_t','withoutperm_intro','withoutperm');
+
+
+			$this->t->set_block('accounts_list_t','accounts_list','list');
+
+
+			$this->t->set_var('title', isset($GLOBALS['phpgw_info']['site_title']) ? $GLOBALS['phpgw_info']['site_title'] : '');
+			$this->t->set_var('charset', 'urf-8');
+			$this->t->set_var('lang_search',lang('search'));
+			$this->t->set_var('lang_groups',lang('user groups'));
+			$this->t->set_var('lang_accounts',lang('user accounts'));
+
+			$this->t->set_var('img',$GLOBALS['phpgw']->common->image('phpgwapi','select'));
+			$this->t->set_var('lang_select_user',lang('Select user'));
+			$this->t->set_var('lang_select_group',lang('Select group'));
+			$this->t->set_var('css_file', "{$GLOBALS['phpgw_info']['server']['webserver_url']}/phpgwapi/templates/idots/css/idots.css");
+
+			switch($app)
+			{
+				case 'admin':
+					$action = 'admin.uiaccounts.accounts_popup';
+					$this->t->set_var('select_name',"account_user[]']");
+					$this->t->set_var('js_function','ExchangeAccountSelect');
+					$this->t->set_var('lang_perm',lang('group name'));
+					$this->t->fp('withperm','withperm_intro',true);
+					break;
+				case 'admin_acl':
+					$action = 'admin.uiaclmanager.accounts_popup';
+					$app = 'addressbook';
+					$this->t->set_var('select_name',"account_addressmaster[]']");
+					$this->t->set_var('js_function','ExchangeAccountSelect');
+					$this->t->fp('withperm','withperm_intro',true);
+					$this->t->fp('withoutperm','withoutperm_intro',true);
+					break;
+				case 'projects':
+					$action = 'projects.uiprojects.accounts_popup';
+					$this->t->set_var('select_name',"values[coordinator]']");
+					$this->t->set_var('js_function','ExchangeAccountText');
+					$this->t->fp('withperm','withperm_intro',true);
+					$this->t->fp('withoutperm','withoutperm_intro',true);
+					break;
+				case 'e_projects':
+					$action = 'projects.uiprojects.e_accounts_popup';
+					$app = 'projects';
+					$this->t->set_var('select_name',"employees[]']");
+					$this->t->set_var('js_function','ExchangeAccountSelect');
+					$this->t->fp('withperm','withperm_intro',true);
+					$this->t->fp('withoutperm','withoutperm_intro',true);
+					break;
+			}
+
+			$this->t->set_var('lang_perm',lang('Groups with permission for %1',lang($app)));
+			$this->t->set_var('lang_nonperm',lang('Groups without permission for %1',lang($app)));
+
+			$link_data = array
+			(
+				'menuaction'	=> $action,
+				'group_id'		=> $group_id
+			);
+
+			$app_groups = array();
+
+			if ($app != 'admin')
+			{
+				$user_groups = $GLOBALS['phpgw']->accounts->membership($this->account_id);
+				$aclusers = $GLOBALS['phpgw']->acl->get_ids_for_location('run', 1, $app);
+				$acl_users = $GLOBALS['phpgw']->accounts->return_members($aclusers);
+				$app_user	= $acl_users['users'];
+				$app_groups	= $acl_users['groups'];
+				/*
+				$app_groups	= $this->get_list('groups');
+				$app_user	= $this->get_list('accounts');
+				*/
+
+			}
+			else
+			{
+				$all_groups	= $GLOBALS['phpgw']->accounts->get_list('groups');
+				$all_user	= $GLOBALS['phpgw']->accounts->get_list('accounts');
+
+				while(is_array($all_groups) && (list(,$agroup) = each($all_groups)))
+				{
+					$user_groups[] = array
+					(
+						'account_id'	=> $agroup->id,
+						'account_name'	=> $agroup->firstname
+					);
+				}
+
+			//	$i = 0;
+			//	for($j=0;$j<count($user_groups); ++$j)
+				$app_groups = array();
+				foreach ($all_user as $group)
+				{
+					$app_groups[] = $group->id;
+				//	++$i;
+				}
+
+				$app_user = array();
+				foreach ($all_user as $user)
+				//for($j=0;$j<count($all_user);$j++)
+				{
+					$app_user[] = $user->id;
+				//	++$i;
+				}
+
+//_debug_array($user_groups);
+			}
+
+			while ( isset($user_groups) && is_array($user_groups) && (list(,$group) = each($user_groups)) )
+			{
+				$i = 0;
+				if (in_array($group->id, $app_groups))
+				{
+					$this->t->set_var('tr_class', $nextmatches->alternate_row_class(++$i%2));
+					//$link_data['group_id'] = $group['account_id'];
+					$this->t->set_var('link_user_group', $GLOBALS['phpgw']->link('/index.php', array('menuaction' => $action, 'group_id' => (int)$group->id) ) );
+					$this->t->set_var('name_user_group', $group->lid);
+					$this->t->set_var('account_display', $GLOBALS['phpgw']->common->grab_owner_name($group->id));
+					$this->t->set_var('accountid', $group->id);
+					switch($app)
+					{
+						case 'addressbook':
+						default:
+							$this->t->fp('other','group_other',true);
+					}
+				}
+				else
+				{
+//_debug_array($group['account_id']);
+					if ($app != 'admin')
+					{
+						$this->t->set_var('link_all_group', $GLOBALS['phpgw']->link('/index.php', array('menuaction' => $action, 'group_id' => (int)$group->id) ) );
+						$this->t->set_var('name_all_group', $group->lid);
+						$this->t->set_var('accountid', $group->id);
+						$this->t->fp('all', 'group_all', true);
+					}
+				}
+			}
+
+			if ( !$query )
+			{
+				$val_users = array();
+				if (isset($group_id) && !empty($group_id))
+				{
+					//echo 'GROUP_ID: ' . $group_id;
+					$users =  $GLOBALS['phpgw']->accounts->get_members($group_id);
+
+					for ($i=0;$i<count($users); ++$i)
+					{
+						if (in_array($users[$i],$app_user))
+						{
+							$account = $GLOBALS['phpgw']->accounts->get($users[$i]);
+
+							switch ($order)
+							{
+								case 'account_firstname':
+									$id = $account->firstname;
+									break;
+								case 'account_lastname':
+									$id = $account->lastname;
+									break;
+								case 'account_lid':
+								default:
+									$id = $account->lid;
+									break;
+							}
+
+							$id .= $account->lastname;	// default sort-order
+							$id .= $account->firstname;
+							$id .= $account->id;	// make our index unique
+
+							$val_users[$id] = array
+							(
+								'account_id'		=> $account->id,
+								'account_firstname'	=> $account->firstname,
+								'account_lastname'	=> $account->lastname
+							);
+						}
+					}
+
+					if (is_array($val_users))
+					{
+						if ($sort == 'ASC')
+						{
+							ksort($val_users);
+						}
+						else
+						{
+							krsort($val_users);
+						}
+					}
+					$val_users = array_values($val_users);	// get a numeric index
+				}
+				$total = count($val_users);
+			}
+			else
+			{
+				switch($app)
+				{
+					case 'calendar':	$select = 'both'; break;
+					default:			$select = 'accounts'; break;
+				}
+				$entries	=$GLOBALS['phpgw']->accounts->get_list($select, $start, $sort, $order, $query);
+				$total		= $this->total;
+				foreach ( $entries as $entry)
+				{
+					if (in_array($entry->id,$app_user))
+					{
+						$val_users[] = array
+						(
+							'account_id'		=> $entry->id,
+							'account_firstname'	=> $entry->firstname,
+							'account_lastname'	=> $entry->lastname
+						);
+					}
+				}
+			}
+
+	// --------------------------------- nextmatch ---------------------------
+
+			$left = $nextmatches->left('/index.php',$start,$total,$link_data);
+			$right = $nextmatches->right('/index.php',$start,$total,$link_data);
+			$this->t->set_var('left',$left);
+			$this->t->set_var('right',$right);
+
+			$this->t->set_var('lang_showing',$nextmatches->show_hits($total,$start));
+
+	// -------------------------- end nextmatch ------------------------------------
+
+			$this->t->set_var('search_action',$GLOBALS['phpgw']->link('/index.php',$link_data));
+			$this->t->set_var('search_list',$nextmatches->search(array('query' => $query, 'search_obj' => 1)));
+
+	// ---------------- list header variable template-declarations --------------------------
+
+	// -------------- list header variable template-declaration ------------------------
+			$this->t->set_var('sort_lid',$nextmatches->show_sort_order($sort,'account_lid',$order,'/index.php',lang('LoginID'),$link_data));
+			$this->t->set_var('sort_firstname',$nextmatches->show_sort_order($sort,'account_firstname',$order,'/index.php',lang('Firstname'),$link_data));
+			$this->t->set_var('sort_lastname',$nextmatches->show_sort_order($sort,'account_lastname',$order,'/index.php',lang('Lastname'),$link_data));
+
+	// ------------------------- end header declaration --------------------------------
+			$stop = $start + $nextmatches->maxmatches;
+			for ($i=$start;$i<count($val_users)&&$i<$stop;$i++)
+			{
+				$this->t->set_var('tr_class', $nextmatches->alternate_row_class($i%2));
+				
+				$firstname = $val_users[$i]['account_firstname'];
+				if (!$firstname)
+				{
+					$firstname = '&nbsp;';
+				}
+				
+				$lastname = $val_users[$i]['account_lastname'];
+				if (!$lastname)
+				{
+					$lastname = '&nbsp;';
+				}
+
+	// ---------------- template declaration for list records -------------------------- 
+
+				$this->t->set_var(array
+				(
+					'firstname'			=> $firstname,
+					'lastname'			=> $lastname,
+					'accountid'			=> $val_users[$i]['account_id'],
+					'account_display'	=> $GLOBALS['phpgw']->common->grab_owner_name($val_users[$i]['account_id'])
+				));
+
+				$this->t->fp('list','accounts_list',true);
+			}
+
+			$this->t->set_var('start', $start);
+			$this->t->set_var('sort', $sort);
+			$this->t->set_var('order', $order);
+			$this->t->set_var('query', $query);
+			$this->t->set_var('group_id', $group_id);
+
+			$this->t->set_var('lang_done',lang('done'));
+			$this->t->pfp('out','accounts_list_t',true);
+			$GLOBALS['phpgw']->common->phpgw_exit();
+		}
+	}


Property changes on: people/sigurdne/modules/phpgwapi/trunk/inc/class.accounts_popup.inc.php
___________________________________________________________________
Added: svn:keywords
   + Id Revision
Added: svn:eol-style
   + native

Modified: people/sigurdne/modules/phpgwapi/trunk/inc/class.acl.inc.php
===================================================================
--- people/sigurdne/modules/phpgwapi/trunk/inc/class.acl.inc.php	2009-11-20 10:27:41 UTC (rev 20844)
+++ people/sigurdne/modules/phpgwapi/trunk/inc/class.acl.inc.php	2009-11-20 10:28:10 UTC (rev 20845)
@@ -3,8 +3,9 @@
 	* Access Control List - Security scheme based on ACL design
 	* @author Dan Kuykendall <[email protected]>
 	* @author Dave Hall <[email protected]>
+	* @author Sigurd Nes <[email protected]>
 	* @copyright Copyright (C) 2000-2008 Free Software Foundation, Inc. http://www.fsf.org/
-	* @license http://www.gnu.org/licenses/lgpl.html GNU Lesser General Public License v3 or later
+	* @license http://www.gnu.org/licenses/lgpl.html GNU Lesser General Public License v2 or later
 	* @package phpgwapi
 	* @subpackage accounts
 	* @version $Id$
@@ -13,7 +14,7 @@
 	/*
 		This program is free software: you can redistribute it and/or modify
 		it under the terms of the GNU Lesser General Public License as published by
-		the Free Software Foundation, either version 3 of the License, or
+		the Free Software Foundation, either version 2 of the License, or
 		(at your option) any later version.
 
 		This program is distributed in the hope that it will be useful,
@@ -47,20 +48,19 @@
 
 		/**
 		* Account type
-		* @var string $_account_type Account type
+		* @var string $account_type Account type
 		*/
-		protected $account_type;
+		public $account_type;
 
 		/**
-		 * Data cache
-		 * @var object $_cache data cache object
+		* @var array $_data Array with ACL records
 		 */
-		protected $cache;
+		protected $_data = array();
 
 		/**
-		* @var array $_data Array with ACL records
+		* @var array $_clear_cache Array with locations to clear from cache
 		*/
-		protected $_data = array();
+		protected $_clear_cache = array();
 
 		/**
 		* @var object $_db Database connection
@@ -78,6 +78,11 @@
 		protected $_join = 'JOIN';
 
 		/**
+		* @var bool $enable_inheritance determines whether rights are inherited down the hierarchy when saving permissions
+		*/
+		public $enable_inheritance = false;
+
+		/**
 		* Read rights
 		*/
         const READ = 1;
@@ -133,6 +138,8 @@
 		*/
 		const CUSTOM_3 = 256;
 
+		protected $global_lock = false;
+
 		/**
 		* ACL constructor for setting account id
 		*
@@ -147,10 +154,13 @@
 
 			$this->_like =& $this->_db->like;
 			$this->_join =& $this->_db->join;
-			$this->cache =& $GLOBALS['phpgw']->cache;
+			$this->_left_join	=& $this->_db->left_join;		
 
+			if($account_id)
+			{
 			$this->set_account_id($account_id);
 		}
+		}
 
 		/**
 		 * Set the account id used for lookups
@@ -161,7 +171,7 @@
 		 *
 		 * @return null
 		 */
-		public function set_account_id($account_id = 0, $read_repo = true)
+		public function set_account_id($account_id = 0, $read_repo = false, $appname = '', $location = '', $account_type = 'accounts')
 		{
 			$this->_account_id = (int) $account_id;
 
@@ -172,7 +182,15 @@
 
 			if ( $read_repo )
 			{
-				$this->_read_repository();
+				$app_id		 = 0;
+				$location_id = 0;
+				if($location)
+				{
+					$app_id			= $GLOBALS['phpgw']->applications->name2id($appname);
+					$location_id	= $GLOBALS['phpgw']->locations->get_id($appname, $location);
+				}
+
+				$this->_read_repository($account_type, $app_id, $location_id);
 			}
 		}
 
@@ -226,45 +244,13 @@
 		 */
 
 		/**
-		 * Reads ACL records from database and return array along with storing it
-		 *
-		 * @param string $account_type the type of accounts sought accounts|groups
-		 *
-		 * @return array Array with ACL records
-		 */
-		protected function _read_repository($account_type = 'both')
-		{
-			if ( !$this->_account_id )
-			{
-				$this->set_account_id($this->_account_id, false);
-			}
-
-			$data = $this->cache->system_get('phpgwapi', "acl_data_{$this->_account_id}");
-			if ( !is_null($data) )
-			{
-				$this->_data[$this->_account_id] = $data;
-				return; // nothing more to do
-			}
-
-			switch( $GLOBALS['phpgw_info']['server']['account_repository'] )
-			{
-				case 'ldap':
-					$this->_read_repository_ldap($account_type);
-					break;
-
-				default:
-					$this->_read_repository_sql($account_type);
-			}
-		}
-
-		/**
 		* Get acl records
 		*
 		* @return array Array with ACL records
 		*/
 		public function read()
 		{
-			if (count($this->_data[$this->_account_id]) == 0)
+			if ( count($this->_data[$this->_account_id]) == 0 )
 			{
 				$this->_read_repository();
 			}
@@ -277,26 +263,34 @@
 		* @param string  $appname  Application name.
 		* @param string  $location Application location
 		* @param integer $rights   Access rights in bitmask form
-		* @param boolean $grantor  NFI ask sigurd he added this wihtout documenting it
-		* @param boolean $type     NFI ask sigurd he added this wihtout documenting it
+		* @param boolean $grantor  ID of user that grants right to others
+		*						   -1 means that this is a ordinary ACL - record
+		* @param boolean $mask     Mask (1) or Right (0): Mask revoke rights
 		*
 		* @return array Array with ACL records
 		*/
-		public function add($appname, $location, $rights, $grantor = false, $type = false)
+		public function add($appname, $location, $rights, $grantor = -1, $mask = 0)
 		{
-			if ( !is_array($this->_data[$this->_account_id]) )
+			$app_id = $GLOBALS['phpgw']->applications->name2id($appname);
+			$location_id	= $GLOBALS['phpgw']->locations->get_id($appname, $location);
+			
+			if( !$location_id > 0)
 			{
+				return $this->_data;
+			}
+			$this->_clear_cache[$location_id] = true;
+
+			if ( !isset($this->_data[$this->_account_id]) || !is_array($this->_data[$this->_account_id]) )
+			{
 				$this->_data[$this->_account_id] = array();
 			}
 
-			$this->_data[$this->_account_id][] = array
+			$this->_data[$this->_account_id][$app_id][$location_id][] = array
 			(
-				'appname'	=> $appname,
-				'location'	=> $location,
 				'account'	=> $this->_account_id,
 				'rights'	=> $rights,
 				'grantor'	=> $grantor,
-				'type'		=> $type
+				'type'		=> $mask
 			);
 			return $this->_data;
 		}
@@ -307,53 +301,127 @@
 		* @param string  $appname  Application name
 		* @param string  $location Application location
 		* @param integer $grantor  account_id of the user that has granted access to their records.
-		*						0 means that this is a ordinary ACL - record
-		* @param integer $type     mask or right (1 means mask , 0 means right)
+		*						   -1 means that this is a ordinary ACL - record
+		* @param integer $mask     mask or right (1 means mask , 0 means right)
 		*
 		* @return array Array with ACL records
 		*/
-		public function delete($appname, $location, $grantor = 0, $type = 0)
+		public function delete($appname, $location, $grantor = -1, $mask = 0)
 		{
 			if ($appname == '')
 			{
 				$appname = $GLOBALS['phpgw_info']['flags']['currentapp'];
 			}
 
-			if(isset($this->_data[$this->_account_id]) && is_array($this->_data[$this->_account_id]))
+			$app_id = $GLOBALS['phpgw']->applications->name2id($appname);
+
+			$locations = array();
+			$locations[] = $GLOBALS['phpgw']->locations->get_id($appname, $location);
+
+			if( $this->enable_inheritance )
 			{
-				foreach ( $this->_data[$this->_account_id] as $idx => $value )
+				$subs = $GLOBALS['phpgw']->locations->get_subs($appname, $location);
+				$locations = array_merge($locations, array_keys($subs));
+			}
+
+			foreach ($locations as $location_id )
+			{
+				$this->_clear_cache[$location_id] = true;
+				if(isset($this->_data[$this->_account_id][$app_id][$location_id]) && is_array($this->_data[$this->_account_id][$app_id][$location_id]))
+			{
+					foreach ( $this->_data[$this->_account_id][$app_id][$location_id] as $idx => $value )
 				{
-					if ( (isset($value['appname']) && $value['appname'] == $appname )
-						&& strpos($value['location'], $location) === 0
-						&& $value['account'] == $this->_account_id
+						if ( $value['account'] == $this->_account_id
 						&& $value['grantor'] == $grantor
-						&& $value['type'] == $type )
+							&& $value['type'] == $mask )
+						{
+							unset($this->_data[$this->_account_id][$app_id][$location_id][$idx]);
+							if(!count($this->_data[$this->_account_id][$app_id][$location_id]))
 					{
-						unset($this->_data[$this->_account_id][$idx]);
+						//		unset($this->_data[$this->_account_id][$app_id][$location_id]);
+								$this->_data[$this->_account_id][$app_id][$location_id] = array();
+							}
 					}
 				}
-				reset($this->_data[$this->_account_id]);
 			}
+			}
+			reset($this->_data[$this->_account_id]);
 			return $this->_data;
 		}
 
 		/**
 		* Save repository in database
 		*
-		* @param string $unused  This parameter is unused it is only for backwards compatibility
-		* @param string $ignored This parameter is also ignored it is only for backwards compatibility
+		* @param string $appname  used for a spesific location
+		* @param string $location used for a spesific location
 		*
 		* @return array Array with ACL records
 		*/
-		public function save_repository($unused = null, $ignored = null)
+		public function save_repository($appname = '', $location = '')
 		{
+			$app_id = $GLOBALS['phpgw']->applications->name2id($appname);
+			$location_id	= $GLOBALS['phpgw']->locations->get_id($appname, $location);
+
+			$_locations = array();
+			if($appname)
+			{
+				$_locations[] = $location_id;
+			}
+			else
+			{
+				foreach ($this->_data[$this->_account_id] as $_app => $_location)
+				{
+					foreach ($_location as $location_id => $dummy)
+					{
+						$_locations[] = $location_id;
+					}
+				}
+			}
+
+			if( !$_locations )
+			{
+				return; //nothing more to do here.
+			}
 			$acct_id = (int) $this->_account_id;
 			$locations =& $GLOBALS['phpgw']->locations;
+			$subs = array();
+			$sub_delete = '';
 
+			if( $this->enable_inheritance )
+			{
+				foreach ($_locations as $location_id)
+				{
+					$location_info = $locations->get_name($location_id);
+					$_subs = $locations->get_subs($location_info['appname'], $location_info['location']);
+					if($_subs)
+					{
+						$subs = array_merge($subs, array_keys($_subs));
+					}
+				}
+			}
+
+			if($subs)
+			{
+				$_locations = array_merge($_locations, $subs);
+				$_locations = array_unique($_locations);
+			}
+			$sql_delete_location = ' AND location_id IN (' . implode(',', $_locations) . ')';
+			unset($subs);
+			unset($_locations);
+
+			if ( $this->_db->Transaction )
+			{
+				$this->global_lock = true;
+			}
+			else
+			{
 			$this->_db->transaction_begin();
+			}
 
+
 			$sql = 'DELETE FROM phpgw_acl'
-					. " WHERE acl_account = {$acct_id}";
+					. " WHERE acl_account = {$acct_id} {$sql_delete_location}";
+
 			$this->_db->query($sql, __LINE__, __FILE__);
 
 			if ( !isset($this->_data[$acct_id])
@@ -361,7 +429,11 @@
 				|| !count($this->_data[$acct_id])
 				)
 			{
+
+				if ( !$this->global_lock )
+				{
 				$this->_db->transaction_commit();
+				}
 
 				$this->_data[$acct_id] = array();
 
@@ -369,27 +441,30 @@
 			}
 
 			$new_data = array();
-			foreach ( $this->_data[$acct_id] as $entry )
+			foreach ( $this->_data[$acct_id] as $app => $loc )
 			{
-				$loc = $locations->get_id($entry['appname'], $entry['location']);
-
-				if ( $entry['grantor'] == '' )
+				foreach ( $loc as $location_id => $at_location )
 				{
-					$entry['grantor'] = 'NULL';
-				}
+					$location_info = $locations->get_name($location_id);
+					foreach ($at_location as $entry)
+					{
+						$entry['grantor']	= $entry['grantor'] ? $entry['grantor'] : -1; 
+						$entry['type']		= $entry['type'] ? $entry['type'] : 0; 
 
-				if ( !isset($new_data[$loc][$entry['grantor']][$entry['type']]) )
+						if ( !isset($new_data[$location_id][$entry['grantor']][$entry['type']]) )
 				{
-					$new_data[$loc][$entry['grantor']][$entry['type']] = 0;
+							$new_data[$location_id][$entry['grantor']][$entry['type']] = 0;
 				}
+						$new_data[$location_id][$entry['grantor']][$entry['type']] |= $entry['rights'];
 
-				$new_data[$loc][$entry['grantor']][$entry['type']] |= $entry['rights'];
-
 				/*
-					FIXME The inheritence model is broken
-					this shouldn't be done here, it should be handled in the check
+							FIXME The inheritence model should be handled in the check
 				*/
-				$subs = $locations->get_subs($entry['appname'], $entry['location']);
+
+						if( $this->enable_inheritance )
+						{
+							$subs = $locations->get_subs($location_info['appname'], $location_info['location']);
+
 				foreach ( array_keys($subs) as $sub )
 				{
 					if ( !isset($new_data[$sub][$entry['grantor']][$entry['type']]) )
@@ -400,38 +475,242 @@
 					$new_data[$sub][$entry['grantor']][$entry['type']] |= $entry['rights'];
 				}
 			}
+					}
+				}
+			}
 
-			foreach ( $new_data as $loc => $grants )
+			// using stored prosedures
+			$sql = 'INSERT INTO phpgw_acl (acl_account, acl_rights, acl_grantor, acl_type, location_id)'
+							. ' VALUES(?, ?, ?, ?, ?)';
+			$valueset=array();
+
+			foreach ( $new_data as $loc_id => $grants )
 			{
 				foreach ( $grants as $grantor => $right_types )
 				{
-					foreach ( $right_types as $type => $rights )
+					foreach ( $right_types as $mask => $rights )
 					{
-						$sql = 'INSERT INTO phpgw_acl'
-							. " VALUES({$acct_id}, {$rights}, {$grantor}, {$type}, {$loc})";
-
-						$this->_db->query($sql, __LINE__, __FILE__);
+						$valueset[] = array
+						(
+							1	=> array
+							(
+								'value'	=> $acct_id,
+								'type'	=> PDO::PARAM_INT
+							),
+							2	=> array
+							(
+								'value'	=> $rights,
+								'type'	=>	PDO::PARAM_INT
+							),
+							3	=> array
+							(
+								'value'	=> $grantor,
+								'type'	=> PDO::PARAM_INT
+							),
+							4	=> array
+							(
+								'value'	=> $mask,
+								'type'	=>	PDO::PARAM_INT
+							),
+							5	=> array
+							(
+								'value'	=> $loc_id,
+								'type'	=> PDO::PARAM_INT
+							),								
+						);
 					}
 				}
+					}
+
+			$this->_db->insert($sql, $valueset, __LINE__, __FILE__);
+			unset($sql);
+			unset($valueset);
+
+
+			/*remove duplicates*/
+
+			$sql = "SELECT * FROM phpgw_acl WHERE acl_account = {$acct_id}"
+			. ' GROUP BY acl_account, acl_rights, acl_grantor, acl_type, location_id';
+			$this->_db->query($sql,__LINE__,__FILE__);
+
+			$test = array();
+
+			while($this->_db->next_record())
+			{
+				$_acl_account	= $this->_db->f('acl_account');
+				$_acl_rights	= $this->_db->f('acl_rights');
+				$_acl_grantor	= $this->_db->f('acl_grantor');
+				$_acl_type		= $this->_db->f('acl_type');
+				$_location_id	= $this->_db->f('location_id');
+
+				//avoid doubled set of rights
+		//		if(!$test[$_acl_account][$_acl_grantor][$_acl_type][$_location_id])
+				{
+					$unique_data[]= array
+					(
+						1	=> array
+						(
+							'value'	=> $_acl_account,
+							'type'	=> PDO::PARAM_INT
+						),
+						2	=> array
+						(
+							'value'	=> $_acl_rights,
+							'type'	=>	PDO::PARAM_INT
+						),
+						3	=> array
+						(
+							'value'	=> $_acl_grantor,
+							'type'	=> PDO::PARAM_INT
+						),
+						4	=> array
+						(
+							'value'	=> $_acl_type,
+							'type'	=>	PDO::PARAM_INT
+						),
+						5	=> array
+						(
+							'value'	=> $_location_id,
+							'type'	=> PDO::PARAM_INT
+						),								
+					);
+				}
+		//		$test[$_acl_account][$_acl_grantor][$_acl_type][$_location_id] = true;
 			}
 
+			$sql = 'DELETE FROM phpgw_acl'
+					. " WHERE acl_account = {$acct_id}";
+			$this->_db->query($sql, __LINE__, __FILE__);
+
+			$sql = 'INSERT INTO phpgw_acl (acl_account, acl_rights, acl_grantor, acl_type, location_id)'
+							. ' VALUES(?, ?, ?, ?, ?)';
+
+			$this->_db->insert($sql, $unique_data, __LINE__, __FILE__);
+			unset($unique_data);
+/*
+			//FIXME: this one is temporary to avoid problems with the old acl_grantor being NULL
+			$this->_db->query('UPDATE phpgw_acl SET acl_grantor = -1 WHERE acl_grantor is NULL',__LINE__,__FILE__,true);
+*/
+			if ( !$this->global_lock )
+			{
 			$this->_db->transaction_commit();
+			}
 
-			$this->delete_cache($this->_account_id);
+			$clear_cache = array_keys($this->_clear_cache);
+			foreach($clear_cache as $location_id)
+			{
+				$this->_delete_cache($this->_account_id, $location_id);
+			}
 
+	//		$this->remove_duplicates($acct_id);
+	//		$this->remove_duplicates();
 			return $this->_data[$this->_account_id];
 		}
 
-		// These are the non-standard $account_id specific functions
 
+
 		/**
+		* experimental clean up in case of duplicates or references to deleted accounts
+		*
+		* @$param integer $acct_id  account to clean - all accounts if not given
+		*
+		* @return void
+		*/
+		public function remove_duplicates($acct_id = 0)
+		{
+			$this->_db->transaction_begin();
+
+			$acconts_to_delete = array();
+			$sql = "SELECT acl_account FROM phpgw_acl $this->_left_join phpgw_accounts ON phpgw_acl.acl_account = phpgw_accounts.account_id WHERE phpgw_accounts.account_id IS NULL GROUP BY acl_account";
+			$this->_db->query($sql,__LINE__,__FILE__);
+			while($this->_db->next_record())
+			{
+				$acconts_to_delete[] = $this->_db->f('acl_account');
+			}
+
+			if($acconts_to_delete)
+			{
+				$sql = 'DELETE FROM phpgw_acl WHERE acl_account IN (' . implode(',', $acconts_to_delete) . ')';
+				$this->_db->query($sql,__LINE__,__FILE__);
+			}
+
+			//This one is temporary to avoid problems with the old acl_grantor being NULL
+			$this->_db->query('UPDATE phpgw_acl SET acl_grantor = -1 WHERE acl_grantor is NULL',__LINE__,__FILE__,true);
+			$this->_db->query('DELETE FROM phpgw_acl WHERE location_id = 0',__LINE__,__FILE__,true);
+
+			$condition = '';
+			if($acct_id > 0)
+			{
+				$condition = "WHERE acl_account = {$acct_id}";
+			}
+			$sql = "SELECT * FROM phpgw_acl {$condition}"
+			. ' GROUP BY acl_account, acl_rights, acl_grantor, acl_type, location_id';
+			$this->_db->query($sql,__LINE__,__FILE__);
+
+			$cache_info = array();
+			while($this->_db->next_record())
+			{
+				$cache_info[$this->_db->f('acl_account')][$this->_db->f('location_id')] = $this->_db->f('location_id');
+
+				$unique_data[]= array
+				(
+					1	=> array
+					(
+						'value'	=> $this->_db->f('acl_account'),
+						'type'	=> PDO::PARAM_INT
+					),
+					2	=> array
+					(
+						'value'	=> $this->_db->f('acl_rights'),
+						'type'	=>	PDO::PARAM_INT
+					),
+					3	=> array
+					(
+						'value'	=> $this->_db->f('acl_grantor'),
+						'type'	=> PDO::PARAM_INT
+					),
+					4	=> array
+					(
+						'value'	=> (int) $this->_db->f('acl_type'),
+						'type'	=>	PDO::PARAM_INT
+					),
+					5	=> array
+					(
+						'value'	=> $this->_db->f('location_id'),
+						'type'	=> PDO::PARAM_INT
+					),								
+				);
+			}
+
+			$sql = "DELETE FROM phpgw_acl {$condition}";
+			$this->_db->query($sql, __LINE__, __FILE__);
+
+			$sql = 'INSERT INTO phpgw_acl (acl_account, acl_rights, acl_grantor, acl_type, location_id)'
+							. ' VALUES(?, ?, ?, ?, ?)';
+
+			$this->_db->insert($sql, $unique_data, __LINE__, __FILE__);
+			unset($unique_data);
+
+			$this->_db->transaction_commit();
+
+			foreach($cache_info as $account_id => $location)
+			{
+				foreach($location as $location_id)
+				{
+					$this->_delete_cache($account_id, $location_id);
+				}
+			}
+		}
+
+
+		/**
 		* Get rights from the repository not specific to this object
 		*
 		* @param string  $location     location within application
 		* @param string  $appname      Application name
 		* @param integer $grantor      account_id of the user that has granted access to their records
-		*					No value means that this is a ordinary ACL - record
-		* @param integer $type         mask or right (1 means mask , 0 means right)
+		*							  -1 means that this is a ordinary ACL - record
+		* @param integer $mask         mask or right (1 means mask , 0 means right)
 		* @param string  $account_type used to disiguish between checkpattern
 		*						"accounts","groups" and "both" - the normal behaviour is ("both")
 		*						to first check for rights given to groups -
@@ -439,7 +718,7 @@
 		*
 		* @return integer Access rights in bitmask form
 		*/
-		public function get_rights($location, $appname = '', $grantor = null, $type = false, $account_type = 'both')
+		public function get_rights($location, $appname = '', $grantor = -1, $mask = 0, $account_type = 'both', $required = '')
 		{
 			// For XML-RPC, change this once its working correctly for passing parameters (jengo)
 			if (is_array($location))
@@ -448,59 +727,47 @@
 				$location	= $a['location'];
 				$appname	= $a['appname'];
 				$grantor	= $a['grantor'];
-				$type		= $a['type'];
+				$mask		= $a['type'];
 			}
 
-			if ( !isset($this->_data[$this->_account_id])
-				|| count($this->_data[$this->_account_id]) == 0)
-			{
-				$this->_data[$this->_account_id] = array();
-				$cached = $GLOBALS['phpgw']->cache->system_get('phpgwapi',
-																"acl_data_{$this->_account_id}");
-				if ( is_array($cached) && count($cached) )
+			if ( !$appname )
 				{
-					$this->_data[$this->_account_id] = $cached;
+				trigger_error('phpgwapi_acl::get_rights() called with empty appname argument'
+						. ' - check your calls to phpgwapi_acl::check()', E_USER_NOTICE);
+				$appname = $GLOBALS['phpgw_info']['flags']['currentapp'];
 				}
-				else
+
+			$app_id = $GLOBALS['phpgw']->applications->name2id($appname);
+			
+			if( !$location_id = $GLOBALS['phpgw']->locations->get_id($appname, $location))
 				{
-					$this->_read_repository($account_type);
-					$GLOBALS['phpgw']->cache->system_set('phpgwapi',
-														"acl_data_{$this->_account_id}",
-														$this->_data[$this->_account_id]);
-				}
+				//not a valid location
+				return 0;
 			}
 
-			if ( !$appname )
+			if ( !isset($this->_data[$this->_account_id][$app_id][$location_id])
+				|| count($this->_data[$this->_account_id][$app_id][$location_id]) == 0)
 			{
-				trigger_error('phpgwapi_acl::get_rights() called with empty appname argument'
-						. ' - check your calls to phpgwapi_acl::check()', E_USER_NOTICE);
-				$appname = $GLOBALS['phpgw_info']['flags']['currentapp'];
+				$this->_data[$this->_account_id][$app_id][$location_id] = array();
+				$this->_read_repository($account_type, $app_id, $location_id);
 			}
 
 
-			$count = (isset($this->_data[$this->_account_id])?count($this->_data[$this->_account_id]):0);
+
+		//	$count = (isset($this->_data[$this->_account_id])?count($this->_data[$this->_account_id]):0);
 			$rights = 0;
 
-			if(isset($this->_data[$this->_account_id]) && is_array($this->_data[$this->_account_id]))
-			{
-				foreach ( $this->_data[$this->_account_id] as $values )
+			if(isset($this->_data[$this->_account_id][$app_id][$location_id]) && is_array($this->_data[$this->_account_id][$app_id][$location_id]))
 				{
-					if ( $values['appname'] == $appname
-						&& ( $values['location'] == $location
-							// FIXME this should probably be . not everywhere - skwashd jan08
-							|| $values['location'] == 'everywhere')
-						&& $values['type'] == $type
-						&& (!$grantor || ( $grantor && $values['grantor'] ) ) )
+				foreach ( $this->_data[$this->_account_id][$app_id][$location_id] as $values )
 					{
-						if ( $values['grantor'] == $grantor)
+					if ( $values['type'] == $mask && $values['rights'] > 0 && $values['grantor'] ==$grantor)
 						{
-							if ( $values['rights'] == 0 )
-							{
-								return false;
-							}
+						$this->account_type = $values['account_type'];
 							$rights |= $values['rights'];
-							$this->_account_type = $values['account_type'];
-						}
+						//stop looking when found
+						if ($rights & $required)
+						return $rights;
 					}
 				}
 			}
@@ -519,8 +786,8 @@
 		*/
 		public function check($location, $required, $appname = '')
 		{
-			$rights = $this->check_rights($location, $required, $appname, false, 0);
-			$mask = $this->check_rights($location, $required, $appname, false, 1);
+			$rights = $this->check_rights($location, $required, $appname, -1, 0);
+			$mask = $this->check_rights($location, $required, $appname, -1, 1);
 
 			if ( $mask > 0 && $rights > 0 )
 			{
@@ -536,13 +803,13 @@
 		* @param integer $required     Required right (bitmask) to check against
 		* @param string  $appname      Application name - default $GLOBALS['phpgw_info']['flags']['currentapp']
 		* @param integer $grantor      useraccount to check against
-		* @param integer $type         mask or right (1 means mask , 0 means right) to check against
+		* @param integer $mask         mask or right (1 means mask , 0 means right) to check against
 		* @param string  $account_type to check for righst given by groups and accounts separately
 		*
 		* @return boolean true when $required bitmap matched otherwise false
 		*/
 		public function check_rights($location, $required, $appname = '',
-									$grantor=false, $type=false, $account_type='')
+									$grantor = -1, $mask = 0, $account_type = '')
 		{
 			//This is only for setting new rights / grants
 			if ( is_array($account_type) )
@@ -550,8 +817,7 @@
 				foreach ( $account_type as $entry )
 				{
 					$this->_data[$this->_account_id] = array();
-					$rights = $this->get_rights($location, $appname, $grantor, $type, $entry);
-
+					$rights = $this->get_rights($location, $appname, $grantor, $mask, $entry, $required);
 					if ( !!($rights & $required) )
 					{
 						break;
@@ -560,13 +826,13 @@
 			}
 			else
 			{
-				$rights = $this->get_rights($location, $appname, $grantor, $type, 'both');
+				$rights = $this->get_rights($location, $appname, $grantor, $mask, 'both', $required);
 			}
 			return !!($rights & $required);
 		}
 
 		/**
-		* Get specific rights - yes really who woulda thunk it
+		* Get specific rights
 		*
 		* @param string $location location within application
 		* @param string $appname  Application name
@@ -588,14 +854,14 @@
 			}
 			$rights = 0;
 
-			if ( is_array($this->_data[$this->_account_id]) && count($this->_data[$this->_account_id]) )
+			$app_id = $GLOBALS['phpgw']->applications->name2id($appname);
+			$location_id	= $GLOBALS['phpgw']->locations->get_id($appname, $location);
+
+			if(isset($this->_data[$this->_account_id][$app_id][$location_id]) && count($this->_data[$this->_account_id][$app_id][$location_id]))
 			{
-				foreach ( $this->_data[$this->_account_id] as $value )
+				foreach ( $this->_data[$this->_account_id][$app_id][$location_id] as $value )
 				{
-					if ($value['appname'] == $appname
-						&& ($value['location'] == $location
-							|| $value['location'] == 'everywhere')
-						&& $value['account'] == $this->_account_id)
+					if ($value['account'] == $this->_account_id)
 					{
 						if ($value['rights'] == 0)
 						{
@@ -642,7 +908,7 @@
 			{
 				foreach ( $equalto as $group )
 				{
-					$acct_ids[] = $group['account_id'];
+					$acct_ids[] = $group->id;
 				}
 			}
 
@@ -652,23 +918,22 @@
 				. ' FROM phpgw_locations'
 				. " {$this->_join} phpgw_acl ON phpgw_locations.location_id = phpgw_acl.location_id"
 				. " {$this->_join} phpgw_applications ON phpgw_locations.app_id = phpgw_applications.app_id"
-				. " WHERE applications.name = '{$app}' AND acl_account IN($ids)";
+				. " WHERE phpgw_applications.app_name = '{$app}' AND acl_account IN($ids)";
 			$this->_db->query($sql, __LINE__, __FILE__);
 
-			$rights = 0;
 			while ($this->_db->next_record())
 			{
 				if ($this->_db->f('acl_rights') == 0)
 				{
 					return false;
 				}
-				$rights |= $this->_db->f('acl_rights');
+				$rights = $this->_db->f('acl_rights');
 				if (!!($rights & $required) == true)
 				{
-					$locations[] = $this->_db->f('acl_location');
+					$locations[] = $this->_db->f('name');
 				}
 			}
-			return $locations;
+			return array_unique($locations);
 		}
 
 
@@ -688,7 +953,6 @@
 		{
 			$this->delete_repository($app, $location, $account_id);
 
-			// FIXME another example of the broken inherentence model
 			$inherit_location = array();
 
 			$sql = 'SELECT phpgw_locations.location_id'
@@ -706,11 +970,12 @@
 			foreach ( $inherit_location as $acl_location )
 			{
 				$sql = 'INSERT INTO phpgw_acl (location_id, acl_account, acl_rights, acl_grantor, acl_type)'
-					. " VALUES ('{$acl_location}', {$account_id}, {$rights}, NULL , 0)";
+					. " VALUES ('{$acl_location}', {$account_id}, {$rights}, -1 , 0)";
 				$this->_db->query($sql, __LINE__, __FILE__);
 			}
 
-			$this->delete_cache($account_id);
+			$location_id	= $GLOBALS['phpgw']->locations->get_id($app, $location);
+			$this->_delete_cache($account_id, $location_id);
 
 			return true;
 		}
@@ -731,6 +996,7 @@
 			$account_sel = '';
 
 			$accountid = (int) $accountid;
+			$account_id = 0;
 			if ($accountid )
 			{
 				if ( isset($cache_accountid[$accountid])
@@ -749,22 +1015,43 @@
 			$app = $this->_db->db_addslashes($app);
 
 			// this slows things down but makes the code easier to read & this isn't a common operation
-			$sub = 'SELECT location_id FROM phpgw_locations'
+			$sql = 'SELECT location_id FROM phpgw_locations'
 				. " {$this->_join} phpgw_applications ON phpgw_locations.app_id = phpgw_applications.app_id"
 				. " WHERE phpgw_applications.app_name {$this->_like} '{$app}'"
 					. " AND phpgw_locations.name {$this->_like} '{$location}'";
 
-			$sql = 'DELETE FROM phpgw_acl '
-				. " WHERE location_id IN ({$sub}) $account_sel";
 			$this->_db->query($sql, __LINE__, __FILE__);
 
+			$locations = array();
+			while ($this->_db->next_record())
+			{
+				$locations[] = $this->_db->f('location_id');
+			}
+
+			$location_filter = implode(',', $locations);
+
+			$sql = 'DELETE FROM phpgw_acl'
+				. " WHERE location_id IN ({$location_filter}) $account_sel";
+			$this->_db->query($sql, __LINE__, __FILE__);
+
 			$ret = !!$this->_db->num_rows();
 
 			if ( $ret )
 			{
-				$this->delete_cache($account_id);
+				$location_id	= $GLOBALS['phpgw']->locations->get_id($app, $location);
+				if($account_id)
+				{
+					$this->_delete_cache($account_id, $location_id);
+				}
+				else
+				{
+					$account_objects = $GLOBALS['phpgw']->accounts->get_list('both', -1, 'ASC', '', '', -1);
+					foreach($account_objects as $account)
+					{
+						$this->_delete_cache($account->id, $location_id);
+					}
+				}
 			}
-
 			return $ret;
 		}
 
@@ -986,15 +1273,20 @@
 		* @param string  $app      Application name
 		*				if emptry string, value of $GLOBALS['phpgw_info']['flags']['currentapp'] is used
 		* @param string  $location location within application
-		* @param integer $type     mask or right (1 means mask , 0 means right) to check against
+		* @param integer $mask     mask or right (1 means mask , 0 means right) to check against
 		*
 		* @return array Associative array with granted access rights for accounts
 		*
 		* @internal FIXME this should be simplified - if it is actually used
 		*/
-		public function get_grants_type($app = '', $location = '', $type = 0)
+		public function get_grants_type($app = '', $location = '', $mask = 0)
 		{
 			$grants = array();
+			$accounts = array();
+			if(!$this->_account_id)
+			{
+				return $accounts;
+			}
 
 			if ( !$app )
 			{
@@ -1013,7 +1305,6 @@
 			$acct_ids[] = $this->_account_id;
 
 			$rights = 0;
-			$accounts = array();
 
 			$ids = implode(',', $acct_ids);
 			$sql = 'SELECT acl_account, acl_grantor, acl_rights'
@@ -1021,11 +1312,11 @@
 				. " {$this->_join} phpgw_locations ON phpgw_acl.location_id = phpgw_locations.location_id"
 				. " {$this->_join} phpgw_applications ON phpgw_applications.app_id = phpgw_locations.app_id"
 				. " WHERE phpgw_applications.app_name = '$app' $at_location"
-					. " AND acl_grantor IS NOT NULL AND acl_type = $type"
+					. " AND acl_grantor > 0 AND acl_type = $mask"
 					. " AND acl_account IN ($ids)";
 
 			$this->_db->query($sql, __LINE__, __FILE__);
-			if ( $this->_db->num_rows() == 0 && $type == 0 )
+			if ( $this->_db->num_rows() == 0 && $mask == 0  && isset($GLOBALS['phpgw_info']['user']['account_id']))
 			{
 				return array($GLOBALS['phpgw_info']['user']['account_id'] => 31);
 			}
@@ -1041,14 +1332,15 @@
 				);
 			}
 
-			// we do this so we don't have to use multiple db objects and other hacks
 			foreach ($records as $record )
 			{
 				$grantor = $record['grantor'];
 				$rights = $record['rights'];
 
-				if ( !isset($accounts[$grantor]) )
+				if( $grantor > 0 )
 				{
+					if (!isset($accounts[$grantor]))
+				{
 					$is_group[$grantor] = $accts->get_type($grantor) == phpgwapi_account::TYPE_GROUP;
 					if ( !$is_group[$grantor] )
 					{
@@ -1085,14 +1377,15 @@
 					$grants[$grantors] |= $rights;
 				}
 			}
+			}
 
-			if ( $type == 0 )
+			if ( $mask == 0 && isset($GLOBALS['phpgw_info']['user']['account_id']))
 			{
 				$grants[$GLOBALS['phpgw_info']['user']['account_id']] = 31;
 			}
 			else
 			{
-				if ( isset($grants[$GLOBALS['phpgw_info']['user']['account_id']]) )
+				if ( isset($GLOBALS['phpgw_info']['user']['account_id']) && isset($grants[$GLOBALS['phpgw_info']['user']['account_id']]) )
 				{
 					unset ($grants[$GLOBALS['phpgw_info']['user']['account_id']]);
 				}
@@ -1129,76 +1422,228 @@
 		}
 
 		/**
-		* Reads ACL records from database for LDAP accounts
+		* Reads ACL accounts from database and return array with accounts that have rights
 		*
+		* @param string  $appname  Application name
+		*		if empty string the value of $GLOBALS['phpgw_info']['flags']['currentapp'] is used
+		* @param string  $location location within Application name
+		* @param integer $grantor  check if this is grants or ordinary rights/mask
+		*						   -1 means that this is a ordinary ACL - record
+		* @param integer $mask     mask or right (1 means mask , 0 means right) to check against
+		*
+		* @return array Array with accounts
+		*/
+		public function get_accounts_at_location($appname = '', $location = '',
+												$grantor = -1 ,$mask = 0)
+		{
+			$acl_accounts = array();
+			if ( !$appname )
+			{
+				$appname = $GLOBALS['phpgw_info']['flags']['currentapp'];
+			}
+
+			$filter_grants = ' AND acl_grantor = -1';
+			if($grantor > 0)
+			{
+				$filter_grants = ' AND acl_grantor > 0';
+			}
+
+			$sql = 'SELECT acl_account FROM phpgw_acl'
+					. " $this->_join phpgw_locations ON phpgw_acl.location_id = phpgw_locations.location_id"
+					. " $this->_join phpgw_applications ON phpgw_locations.app_id = phpgw_applications.app_id"
+				. " WHERE app_name = '{$appname}'"
+					. " AND phpgw_locations.name {$this->_like} '{$location}%' {$filter_grants}"
+					. " AND acl_type = '{$mask}'"
+				. ' GROUP BY acl_account';
+			$this->_db->query($sql, __LINE__, __FILE__);
+
+			while ($this->_db->next_record())
+			{
+				$acl_accounts[$this->_db->f('acl_account')] = true;
+			}
+
+			return $acl_accounts;
+		}
+
+		/**
+		* Delete ACL information from cache
+		*
+		* @param integer $account_id the account to delete data from the cache for
+		*
+		* @return null
+		*/
+		protected function _delete_cache($account_id, $location_id)
+		{
+			$accounts = array();
+			if($GLOBALS['phpgw']->accounts->get_type($account_id) == phpgwapi_account::TYPE_GROUP)
+			{
+				$accounts = $GLOBALS['phpgw']->accounts->get_members($account_id);
+			}
+			$accounts[] = $account_id;
+
+			$sql = "SELECT app_id FROM phpgw_locations WHERE location_id = {$location_id}";
+			$this->_db->query($sql, __LINE__, __FILE__);
+			$this->_db->next_record();
+			$app_id	= $this->_db->f('app_id');
+
+			foreach($accounts as $id)
+			{
+				phpgwapi_cache::user_clear('phpgwapi', "acl_data_{$app_id}_{$location_id}", $id);
+			}
+		}
+
+		/**
+		 * Reads ACL records from database and return array along with storing it
+		*
 		* @param string $account_type the type of accounts sought accounts|groups
 		*
 		* @return array Array with ACL records
-		*
-		* @internal data is cached for future look ups
 		*/
-		protected function _read_repository_ldap($account_type)
+		protected function _read_repository($account_type = 'both',  $app_id = '', $location_id= '')
 		{
-			$this->_data[$this->_account_id] = array();
+			if ( !$this->_account_id )
+			{
+				$this->set_account_id($this->_account_id, false);
+			}
 
-			if(!$account_type || $account_type == 'accounts' || $account_type == 'both')
+			if(!$app_id && $account_type != 'accounts')
 			{
-				$account_list[] = $this->_account_id;
-				$account_list[] = 0;
+				$data = phpgwapi_cache::user_get('phpgwapi', 'acl_data', $this->_account_id);
+				if ( !is_null($data) )
+				{
+					$this->_data[$this->_account_id] = $data;
+					return; // nothing more to do
+				}
 			}
+			elseif($account_type != 'accounts')
+			{
+				$data = phpgwapi_cache::user_get('phpgwapi', "acl_data_{$app_id}_{$location_id}", $this->_account_id);
+				if ( !is_null($data) )
+				{
+					$this->_data[$this->_account_id][$app_id][$location_id] = $data;
+					return; // nothing more to do
+				}
+			}
 
-			if($account_type == 'groups' || $account_type == 'both')
+			switch( $GLOBALS['phpgw_info']['server']['account_repository'] )
 			{
-				$groups = $this->get_location_list_for_id('phpgw_group', 1, $this->_account_id);
-				if ( is_array($groups) && count($groups) )
+				case 'ldap':
+					$this->_read_repository_ldap($account_type, $app_id, $location_id);
+					break;
+
+				default:
+					$this->_read_repository_sql($account_type, $app_id, $location_id);
+			}
+			if($account_type != 'accounts')
 				{
-					foreach ( $groups as $key => $value )
+				if(!$app_id && $this->_data[$this->_account_id])
 					{
-						if ( !$value )
+					phpgwapi_cache::user_set('phpgwapi', 'acl_data', $this->_data[$this->_account_id], $this->_account_id);
+				}
+				else
 						{
-							continue;
+					if(isset($this->_data[$this->_account_id][$app_id][$location_id]) && is_array($this->_data[$this->_account_id][$app_id][$location_id]))
+					{
+//						throw new Exception("user_set ({$app_id}, {$location_id}) not set");
+						phpgwapi_cache::user_set('phpgwapi', "acl_data_{$app_id}_{$location_id}", $this->_data[$this->_account_id][$app_id][$location_id], $this->_account_id);			
 						}
-						$account_list[] = $value;
 					}
 				}
 			}
 
+		/**
+		* Reads ACL records from database for LDAP accounts
+		*
+		* @param string $account_type the type of accounts sought accounts|groups
+		*
+		* @return array Array with ACL records
+		*
+		* @internal data is cached for future look ups
+		*/
+		protected function _read_repository_ldap($account_type, $app_id = '', $location_id= '')
+		{
+			if(!$account_type || $account_type == 'accounts' || $account_type == 'both')
+			{
+				$account_list[] = $this->_account_id;
+				$account_list[] = 0;
+			}
+
+			if($account_type == 'groups' || $account_type == 'both')
+			{
+				$groups = createObject('phpgwapi.accounts')->membership($this->_account_id);
+				$account_list = array_merge($account_list, array_keys($groups));
+				unset($groups);
+			}
+
 			if(!is_array($account_list))
 			{
 				return array();
 			}
 
-			$sql = 'SELECT * FROM phpgw_acl WHERE acl_account in (' . implode(',', $account_list) . ')';
+			$at_location = '';
+			if($location_id)
+			{
+				$location_id = (int) $location_id;
+				$at_location = " AND phpgw_acl.location_id = {$location_id}";
+				$this->_data[$this->_account_id][$app_id][$location_id] = array();
+			}
+			else
+			{
+				$this->_data[$this->_account_id] = array();
+			}
 
+			$sql = 'SELECT phpgw_applications.app_id, phpgw_locations.location_id,'
+					. ' phpgw_acl.acl_account, phpgw_acl.acl_grantor,'
+					. ' phpgw_acl.acl_rights, phpgw_acl.acl_type'
+					. ' FROM phpgw_acl'
+					. " {$this->_join} phpgw_locations ON phpgw_acl.location_id = phpgw_locations.location_id"
+					. " {$this->_join} phpgw_applications ON phpgw_applications.app_id = phpgw_locations.app_id"
+					. ' WHERE acl_account in (' . implode(',', $account_list) . "){$at_location}";
+
 			$this->_db->query($sql, __LINE__, __FILE__);
 
 			while ( $this->_db->next_record() )
 			{
-				$this->_data[$this->_account_id][] = array
+				$this->_data[$this->_account_id][$this->_db->f('app_id')][$this->_db->f('location_id')][] = array
 				(
-					'appname'		=> $this->_db->f('acl_appname'),
-					'location'		=> $this->_db->f('acl_location'),
 					'account'		=> $this->_db->f('acl_account'),
 					'rights'		=> $this->_db->f('acl_rights'),
 					'grantor'		=> $this->_db->f('acl_grantor'),
 					'type'			=> $this->_db->f('acl_type'),
-					'account_type'	=> $GLOBALS['phpgw']->accounts->get_type($this->_db->f('account_type'))
+					'account_type'	=> $this->_get_type_ldap($this->_db->f('acl_account'))
 				);
 			}
 			return $this->_data;
 		}
 
 		/**
+		* Get account_type for LDAP user and cache the result for performance
+		*
+		* @param integer $account_id Account id
+		*
+		* @return string account_type for ldap-user 'g' (group) or 'u' (user)
+		*/
+		protected function _get_type_ldap($account_id)
+		{
+			static $ldap_user = array();
+
+			if( !isset($ldap_user[$account_id]) )
+			{
+				$ldap_user[$account_id] = $GLOBALS['phpgw']->accounts->get_type($account_id);
+			}
+
+			return $ldap_user[$account_id];
+		}
+
+		/**
 		* Reads ACL records from database for SQL accounts and return array and caches the data for future look ups
 		*
 		* @param string $account_type the type of accounts sought accounts|groups
 		*
 		* @return array Array with ACL records
 		*/
-		protected function _read_repository_sql($account_type)
+		protected function _read_repository_sql($account_type, $app_id = '', $location_id= '')
 		{
-			$this->_data[$this->_account_id] = array();
-
 			$account_list = array();
 			if ( $account_type == 'accounts' || $account_type == 'both' )
 			{
@@ -1212,29 +1657,38 @@
 				unset($groups);
 			}
 
-			if(!isset($account_list) || !is_array($account_list))
+			if(!count($account_list))
 			{
 				return array();
 			}
 
+			$at_location = '';
+			if($location_id)
+			{
+				$location_id = (int) $location_id;
+				$at_location = " AND phpgw_acl.location_id = {$location_id}";
+				$this->_data[$this->_account_id][$app_id][$location_id] = array();
+			}
+			else
+			{
+				$this->_data[$this->_account_id] = array();
+			}
 			$ids = implode(',', $account_list);
-			$sql = 'SELECT phpgw_applications.app_name, phpgw_locations.name,'
+			$sql = 'SELECT phpgw_applications.app_id, phpgw_locations.location_id,'
 					. ' phpgw_acl.acl_account, phpgw_acl.acl_grantor,'
 					. ' phpgw_acl.acl_rights, phpgw_acl.acl_type, phpgw_accounts.account_type'
 				. ' FROM phpgw_acl'
 				. " {$this->_join} phpgw_locations ON phpgw_acl.location_id = phpgw_locations.location_id"
 				. " {$this->_join} phpgw_applications ON phpgw_applications.app_id = phpgw_locations.app_id"
-				. "{$this->_join} phpgw_accounts ON phpgw_acl.acl_account = phpgw_accounts.account_id "
-				. " WHERE acl_account IN ($ids)";
+					. " {$this->_join} phpgw_accounts ON phpgw_acl.acl_account = phpgw_accounts.account_id "
+				. " WHERE acl_account IN ($ids){$at_location}";
 
 			$this->_db->query($sql, __LINE__, __FILE__);
 
 			while ( $this->_db->next_record() )
 			{
-				$this->_data[$this->_account_id][] = array
+				$this->_data[$this->_account_id][$this->_db->f('app_id')][$this->_db->f('location_id')][] = array
 				(
-					'appname'		=> $this->_db->f('app_name'),
-					'location'		=> $this->_db->f('name'),
 					'account'		=> $this->_db->f('acl_account'),
 					'rights'		=> $this->_db->f('acl_rights'),
 					'grantor'		=> $this->_db->f('acl_grantor'),
@@ -1246,60 +1700,134 @@
 		}
 
 		/**
-		* Reads ACL accounts from database and return array with accounts that have rights
+		* Reads ACL accounts from database and return array with accounts that have certain rights for a given location
 		*
+		* @param integer $required  Required access rights in bitmap form
+		* @param string  $location location within Application name
 		* @param string  $appname  Application name
 		*		if empty string the value of $GLOBALS['phpgw_info']['flags']['currentapp'] is used
-		* @param string  $location location within Application name
-		* @param integer $grantor  check if this is grants or ordinary rights/mask
-		* @param integer $type     mask or right (1 means mask , 0 means right) to check against
 		*
 		* @return array Array with accounts
 		*/
-		public function get_accounts_at_location($appname = '', $location = '',
-												$grantor = 0 ,$type = '')
+		public function get_user_list_right($required, $location, $appname = '')
 		{
-			$acl_accounts = array();
+			$myaccounts			= & $GLOBALS['phpgw']->accounts;
+			$active_accounts	= array();
+			$accounts			= array();
+			$users				= array();
+
 			if ( !$appname )
 			{
 				$appname = $GLOBALS['phpgw_info']['flags']['currentapp'];
 			}
-			$app_id = $GLOBALS['phpgw']->applications->name2id($appname);
 
-			if($grantor > 0)
+			$appname = $this->_db->db_addslashes($appname);
+			$location = $this->_db->db_addslashes($location);
+
+			if( $GLOBALS['phpgw_info']['server']['account_repository'] == 'ldap' )
 			{
-				$filter_grants = ' AND acl_grantor IS NOT NULL';
+				$account_objects = $GLOBALS['phpgw']->accounts->get_list('both', -1, 'ASC', 'account_lastname', $query = '', -1); // maybe $query could be used for filtering on active accounts?
+				$active_accounts = array();
+
+				foreach ($account_objects as $account_object)
+			{
+					$active_accounts[] = array
+					(
+						'account_id'	=> $account_object->id,
+						'account_type'	=> $account_object->type
+					);
+				}
 			}
 			else
 			{
-				$filter_grants = ' AND acl_grantor IS NULL';
+				$sql = "SELECT account_id, account_type FROM phpgw_accounts"
+					. " $this->_join phpgw_acl on phpgw_accounts.account_id = phpgw_acl.acl_account"
+					. " $this->_join phpgw_locations on phpgw_acl.location_id = phpgw_locations.location_id"
+					. " WHERE account_status = 'A' AND phpgw_locations.name = '{$location}'"
+					. " ORDER BY account_lastname ASC";
+
+				$this->_db->query($sql,__LINE__,__FILE__);
+
+				while ($this->_db->next_record())
+				{
+					$active_accounts[] = array
+					(
+						'account_id'	=> $this->_db->f('account_id'),
+						'account_type'	=> $this->_db->f('account_type')
+					);
 			}
-			//XXX Caeies : Not sure that the IN (SELECT location_id from phpgw_locations WHERE app_id = '{$app_id}' AND name {$this->_like} '{$location}%') is portable for all supported db
-			//Replacing it by a join is perhaps better ?
-			$sql = 'SELECT acl_account FROM phpgw_acl'
-				. " WHERE location_id IN (SELECT location_id from phpgw_locations WHERE app_id = '{$app_id}' AND name {$this->_like} '{$location}%')"
-					. " {$filter_grants}"
-					. " AND acl_type = '{$type}'"
-				. ' GROUP BY acl_account';
-			$this->_db->query($sql, __LINE__, __FILE__);
+			}
 
+			foreach ($active_accounts as $entry)
+			{
+				$this->_account_id = $entry['account_id'];
+
+				if($this->check($location, $required, $appname))
+				{
+					if($entry['account_type']=='g')
+					{
+						// Would be nice if inactive members could be filtered out from the result
+						$members = $myaccounts->member($entry['account_id']);
+
+						if (isset($members) AND is_array($members))
+						{
+							foreach($members as $user)
+							{
+								$accounts[$user['account_id']] = $user['account_id'];
+							}
+							unset($members);
+						}
+					}
+					else
+					{
+						$accounts[$entry['account_id']] = $entry['account_id'];
+					}
+				}
+			}
+
+			unset($active_accounts);
+			unset($myaccounts);
+
+			$sql = "SELECT account_id FROM phpgw_accounts WHERE account_status = 'I'";
+			$this->_db->query($sql,__LINE__,__FILE__);
 			while ($this->_db->next_record())
 			{
-				$acl_accounts[$this->_db->f('acl_account')] = true;
+				unset($accounts[$this->_db->f('account_id')]);
 			}
 
-			return $acl_accounts;
+			if (isset($accounts) AND is_array($accounts))
+			{
+				foreach($accounts as $account_id)
+				{
+					$this->_account_id = $account_id;
+
+					if(!$this->check($location,$required, $appname))
+					{
+						unset($accounts[$account_id]);
+					}
+				}
 		}
 
-		/**
-		* Delete ACL information from cache
-		*
-		* @param integer $account_id the account to delete data from the cache for
-		*
-		* @return null
-		*/
-		private function delete_cache($account_id)
+			$accounts = array_keys($accounts);
+
+			if(isset($accounts) && count($accounts) > 0)
+			{
+				$sql = 'SELECT * FROM phpgw_accounts where account_id in ('. implode(',',$accounts) . ') ORDER BY account_lastname';
+				$this->_db->query($sql,__LINE__,__FILE__);
+				while ($this->_db->next_record())
 		{
-			$this->cache->system_clear('phpgwapi', "acl_data_{$account_id}");
+					$users[] = array
+					(
+						'account_id'        => $this->_db->f('account_id'),
+						'account_lid'       => $this->_db->f('account_lid'),
+						'account_type'      => $this->_db->f('account_type'),
+						'account_firstname' => $this->_db->f('account_firstname'),
+						'account_lastname'  => $this->_db->f('account_lastname'),
+						'account_status'    => $this->_db->f('account_status'),
+						'account_expires'   => $this->_db->f('account_expires')
+					);
+				}
+			}
+			return $users;
 		}
 	}

Modified: people/sigurdne/modules/phpgwapi/trunk/inc/class.applications.inc.php
===================================================================
--- people/sigurdne/modules/phpgwapi/trunk/inc/class.applications.inc.php	2009-11-20 10:27:41 UTC (rev 20844)
+++ people/sigurdne/modules/phpgwapi/trunk/inc/class.applications.inc.php	2009-11-20 10:28:10 UTC (rev 20845)
@@ -2,8 +2,9 @@
 	/**
 	* Applications manager functions
 	* @author Mark Peters <[email protected]>
+	* @author Dave Hall <[email protected]>
 	* @copyright Copyright (C) 2001,2002 Mark Peters
-	* @copyright Portions Copyright (C) 2003,2004 Free Software Foundation, Inc. http://www.fsf.org/
+	* @copyright Copyright (C) 2003 - 2008 Free Software Foundation, Inc. http://www.fsf.org/
 	* @license http://www.gnu.org/licenses/lgpl.html GNU Lesser General Public License
 	* @package phpgwapi
 	* @subpackage application
@@ -13,13 +14,13 @@
 	/*
 	   This program is free software: you can redistribute it and/or modify
 	   it under the terms of the GNU Lesser General Public License as published by
-	   the Free Software Foundation, either version 3 of the License, or
+		the Free Software Foundation, either version 2 of the License, or
 	   (at your option) any later version.
 
 	   This program is distributed in the hope that it will be useful,
 	   but WITHOUT ANY WARRANTY; without even the implied warranty of
 	   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-	   GNU General Public License for more details.
+		GNU Lesser General Public License for more details.
 
 	   You should have received a copy of the GNU Lesser General Public License
 	   along with this program.  If not, see <http://www.gnu.org/licenses/>.
@@ -33,9 +34,24 @@
 	*/
 	class phpgwapi_applications
 	{
+		/**
+		* @var int $account_id the current users' account id
+		*/
 		private $account_id;
+
+		/**
+		* @var array data about the applications installed
+		*/
 		private $data = array();
+
+		/**
+		* @var object $db Local reference to the global database object
+		*/
 		private $db;
+
+		/**
+		* @var array $public_function the methods of the class available via menuaction calls
+		*/
 		public $public_functions = array
 		(
 			'list_methods' => True,
@@ -65,7 +81,7 @@
 		* Get available xmlrpc or soap methods
 		*
 		* @param string|array $_type Type of methods to list: 'xmlrpc' or 'soap'
-		* @return array Array touple (might be empty) with the following fields in the keys value array: function, signature, docstring
+		* @return array array touple (might be empty) with the following fields in the keys value array: function, signature, docstring
 		* This handles introspection or discovery by the logged in client,
 		* in which case the input might be an array.  The server always calls
 		* this function to fill the server dispatch map using a string.
@@ -111,16 +127,17 @@
 		/**
 		* Read application repository from ACLs
 		*
-		* @return array|boolean Array with list of available applications or false
+		* @return array|boolean array with list of available applications or false
+		* @access private
 		*/
-		protected function read_repository()
+		public function read_repository()
 		{
 			if (!isset($GLOBALS['phpgw_info']['apps']) ||
 				!is_array($GLOBALS['phpgw_info']['apps']))
 			{
 				$this->read_installed_apps();
 			}
-			$this->data = Array();
+			$this->data = array();
 			if ( $this->account_id == False )
 			{
 				return array();
@@ -133,7 +150,7 @@
 				{
 					$this->data[$app['name']] = array
 					(
-						'title'   => lang($app['name']),
+						'title'   => $GLOBALS['phpgw']->translation->translate($app['name'], array(),false, $app['name']),
 						'name'    => $app['name'],
 						'enabled' => True,
 						'status'  => $GLOBALS['phpgw_info']['apps'][$app['name']]['status'],
@@ -161,8 +178,7 @@
 		/**
 		* Add an application to a user profile
 		*
-		* @param string|array $apps Array or string containing application names to add for a user
-		*
+		* @param string|array $apps array or string containing application names to add for a user
 		* @return array List with applications for the user
 		*/	
 		public function add($apps)
@@ -199,7 +215,6 @@
 		* Delete an application from a user profile
 		*
 		* @param string $appname Application name
-		*
 		* @return array List with applications for the user
 		*/
 		public function delete($appname)
@@ -215,7 +230,6 @@
 		* Update list of applications for a user
 		*
 		* @param array $data Update the list of applications
-		*
 		* @return array List with applications for the user
 		*/
 		public function update_data($data)
@@ -306,18 +320,20 @@
 
 		/**
 		* Populate array with a list of installed apps
-		*
-		* @return void
 		*/
 		public function read_installed_apps()
 		{
-			$apps = (array) $this->db->adodb->GetAssoc('SELECT * FROM phpgw_applications WHERE app_enabled != 0 ORDER BY app_order ASC');
+			$this->db->fetchmode = 'ASSOC';
+			$sql = 'SELECT * FROM phpgw_applications WHERE app_enabled != 0 ORDER BY app_order ASC';
+			$this->db->query($sql,__LINE__,__FILE__);
+			$apps = $this->db->resultSet;
+			$this->db->fetchmode = 'BOTH';
 			foreach($apps as $key => $value)
 			{
 				$GLOBALS['phpgw_info']['apps'][$value['app_name']] = array
 				(
 					'name'    => $value['app_name'],
-					'title'   => lang($value['app_name']),
+					'title'   => $GLOBALS['phpgw']->translation->translate($value['app_name'], array(),false, $value['app_name']),
 					'enabled' => true,
 					'status'  => $value['app_enabled'],
 					'id'      => (int) $value['app_id'],
@@ -330,14 +346,12 @@
 		* Test if an application is enabled
 		*
 		* @param array $appname Names of the applications to test for. When the type is different read_installed_apps() will be used.
-		*
 		* @return boolean True when the application is available otherwise false
-		*
 		* @see read_installed_apps()
 		*/
 		public function is_system_enabled($appname)
 		{
-			if(!isset($GLOBALS['phpgw_info']['apps']) || !is_array($GLOBALS['phpgw_info']['apps']))
+			if( !isset($GLOBALS['phpgw_info']['apps']) || !is_array($GLOBALS['phpgw_info']['apps']))
 			{
 				$this->read_installed_apps();
 			}
@@ -348,7 +362,6 @@
 		* Get the application name associated with the application id
 		*
 		* @param int $id the application id to look up
-		*
 		* @return string the application name - empty string if invalid
 		*/
 		public function id2name($id)
@@ -374,7 +387,6 @@
 		* Convert an application name to an id
 		*
 		* @param string $appname the application to lookup
-		*
 		* @return int the application id - 0 if invalid
 		*/
 		public function name2id($appname)

Modified: people/sigurdne/modules/phpgwapi/trunk/inc/class.arrayfunctions.inc.php
===================================================================
--- people/sigurdne/modules/phpgwapi/trunk/inc/class.arrayfunctions.inc.php	2009-11-20 10:27:41 UTC (rev 20844)
+++ people/sigurdne/modules/phpgwapi/trunk/inc/class.arrayfunctions.inc.php	2009-11-20 10:28:10 UTC (rev 20845)
@@ -8,21 +8,6 @@
 	* @package phpgwapi
 	* @subpackage utilities
 	* @version $Id$
-	*/
-
-	/*
-	   This program is free software: you can redistribute it and/or modify
-	   it under the terms of the GNU General Public License as published by
-	   the Free Software Foundation, either version 3 of the License, or
-	   (at your option) any later version.
-
-	   This program is distributed in the hope that it will be useful,
-	   but WITHOUT ANY WARRANTY; without even the implied warranty of
-	   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-	   GNU General Public License for more details.
-
-	   You should have received a copy of the GNU General Public License
-	   along with this program.  If not, see <http://www.gnu.org/licenses/>.
 	 */
 
 	/**

Modified: people/sigurdne/modules/phpgwapi/trunk/inc/class.asyncservice.inc.php
===================================================================
--- people/sigurdne/modules/phpgwapi/trunk/inc/class.asyncservice.inc.php	2009-11-20 10:27:41 UTC (rev 20844)
+++ people/sigurdne/modules/phpgwapi/trunk/inc/class.asyncservice.inc.php	2009-11-20 10:28:10 UTC (rev 20845)
@@ -7,21 +7,6 @@
 	* @package phpgwapi
 	* @subpackage application
 	* @version $Id$
-	*/
-
-	/*
-	   This program is free software: you can redistribute it and/or modify
-	   it under the terms of the GNU General Public License as published by
-	   the Free Software Foundation, either version 3 of the License, or
-	   (at your option) any later version.
-
-	   This program is distributed in the hope that it will be useful,
-	   but WITHOUT ANY WARRANTY; without even the implied warranty of
-	   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-	   GNU General Public License for more details.
-
-	   You should have received a copy of the GNU General Public License
-	   along with this program.  If not, see <http://www.gnu.org/licenses/>.
 	 */
 
 	/**
@@ -48,7 +33,7 @@
 		var $crontab = '';
 		var $db;
 		var $db_table = 'phpgw_async';
-		var $debug = true;
+		var $debug = false;
 
 		/**
 		* Constructor
@@ -94,7 +79,7 @@
 			);
 			$this->write($job);
 			
-			return True;
+			return true;
 		}
 
 		/**
@@ -415,9 +400,10 @@
 						$lang   = $GLOBALS['phpgw_info']['user']['preferences']['common']['lang'];
 						unset($GLOBALS['phpgw_info']['user']);
 
-						if ($GLOBALS['phpgw']->session->account_id = $job['account_id'])
+						if ($job['account_id'])
 						{
-							$GLOBALS['phpgw']->session->account_lid = $GLOBALS['phpgw']->accounts->id2name($job['account_id']);
+							$GLOBALS['phpgw']->session->set_account_id($job['account_id']);
+							$GLOBALS['phpgw']->session->account_lid = $GLOBALS['phpgw']->accounts->id2lid($job['account_id']);
 							$GLOBALS['phpgw']->session->account_domain = $domain;
 							$GLOBALS['phpgw']->session->read_repositories(False,False);
 							$GLOBALS['phpgw_info']['user']  = $GLOBALS['phpgw']->session->user;
@@ -447,6 +433,9 @@
 						{ // update async data field, it could be changed during ExecMethod()
 							$job['data'] = $updated_jobs[$id]['data'];
 						}
+						// TK 20.11.06 write job to get 'next' and alarm updated
+						$job['data']['time'] = $job['next'];
+						$this->write($job);
 					}
 					else	// no further runs
 					{
@@ -564,7 +553,7 @@
 			{
 				$binarys = array(
 					'php'  => '/usr/bin/php',
-					'php4' => '/usr/bin/php4',		// this is for debian
+					'php5' => '/usr/bin/php5',		// this is for debian
 					'crontab' => '/usr/bin/crontab'
 				);
 				foreach ($binarys as $name => $path)
@@ -588,9 +577,9 @@
 					}
 					//echo "<p>$name = '".$this->$name."'</p>\n";
 				}
-				if ($this->php4[0] == '/')	// we found a php4 binary
+				if ($this->php5[0] == '/')	// we found a php5 binary
 				{
-					$this->php = $this->php4;
+					$this->php = $this->php5;
 				}
 			}
 		
@@ -683,4 +672,35 @@
 			}
 			return $this->installed();
 		}
+
+		/**
+		* UnInstalls asyncservices as cron-job
+		*
+		* @return integer|array|boolean The times asyncservices are run or False if they are not installed or 0 if crontab not found
+		* @internal Not implemented for Windows, always returns 0
+		*/
+		function uninstall()
+		{
+			if ($this->only_fallback) {
+				return 0;
+			}
+			$this->installed();	// find other installed cronlines
+
+			if(isset($this->other_cronlines) && $this->other_cronlines)
+			{
+				if (($crontab = popen('/bin/sh -c "'.$this->crontab.' -" 2>&1','w')) !== False)
+				{
+					foreach ($this->other_cronlines as $cronline)
+					{
+						fwrite($crontab,$cronline);		// preserv the other lines
+					}
+					@pclose($crontab);
+				}
+			}
+			else
+			{
+				system('crontab -r');
+			}
+			return $this->installed();
+		}
 	}

Modified: people/sigurdne/modules/phpgwapi/trunk/inc/class.bojsaddressbook.inc.php
===================================================================
--- people/sigurdne/modules/phpgwapi/trunk/inc/class.bojsaddressbook.inc.php	2009-11-20 10:27:41 UTC (rev 20844)
+++ people/sigurdne/modules/phpgwapi/trunk/inc/class.bojsaddressbook.inc.php	2009-11-20 10:28:10 UTC (rev 20845)
@@ -8,21 +8,6 @@
 	* @subpackage gui
 	*/
 
-	/*
-	   This program is free software: you can redistribute it and/or modify
-	   it under the terms of the GNU General Public License as published by
-	   the Free Software Foundation, either version 3 of the License, or
-	   (at your option) any later version.
-
-	   This program is distributed in the hope that it will be useful,
-	   but WITHOUT ANY WARRANTY; without even the implied warranty of
-	   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-	   GNU General Public License for more details.
-
-	   You should have received a copy of the GNU General Public License
-	   along with this program.  If not, see <http://www.gnu.org/licenses/>.
-	 */ 
-
 	/**
 	* Logic for the javascript addressbook
 	*
@@ -586,7 +571,7 @@
 			if(intval($list))
 			{
 				$criteria = $this->contactsobject->criteria_for_index($GLOBALS['phpgw_info']['user']['account_id'], PHPGW_CONTACTS_ALL, $list);
-				$new = phpgwapi_sql_criteria::token_and($criteria, pgpgwapi_sql_criteria::_equal('comm_descr', $this->contactsobject->search_comm_descr('work email')));
+				$new = phpgwapi_sql_criteria::token_and($criteria, phpgwapi_sql_criteria::_equal('comm_descr', $this->contactsobject->search_comm_descr('work email')));
 				$persons = $this->contactsobject->get_persons(array('per_full_name', 'comm_data'), '', '', '', '', '', $new);
 				if(!is_array($persons))
 				{
@@ -602,4 +587,3 @@
 			return $persons_list;
 		}
 	}
-?>

Modified: people/sigurdne/modules/phpgwapi/trunk/inc/class.browser.inc.php
===================================================================
--- people/sigurdne/modules/phpgwapi/trunk/inc/class.browser.inc.php	2009-11-20 10:27:41 UTC (rev 20844)
+++ people/sigurdne/modules/phpgwapi/trunk/inc/class.browser.inc.php	2009-11-20 10:28:10 UTC (rev 20845)
@@ -11,21 +11,6 @@
 	* @internal Majority of code borrowed from Sourceforge 2.5
 	*/
 
-	/*
-	   This program is free software: you can redistribute it and/or modify
-	   it under the terms of the GNU Lesser General Public License as published by
-	   the Free Software Foundation, either version 3 of the License, or
-	   (at your option) any later version.
-
-	   This program is distributed in the hope that it will be useful,
-	   but WITHOUT ANY WARRANTY; without even the implied warranty of
-	   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-	   GNU General Public License for more details.
-
-	   You should have received a copy of the GNU Lesser General Public License
-	   along with this program.  If not, see <http://www.gnu.org/licenses/>.
-	 */
-
 	/**
 	* Browser detect functions
 	*
@@ -273,11 +258,11 @@
 			}
 			if($fn)
 			{
-				if($this->get_agent() == 'IE') // && browser_get_version() == "5.5")
+				if($this->get_agent() == 'IE' && $this->BROWSER_VER == '5.5')
 				{
 					$attachment = '';
 				}
-				elseif( ($this->get_agent() != 'IE') && ($mime != 'text/plain') )
+				else if( $mime != 'text/plain' )
 				{
 					$attachment = ' attachment;';
 				}

Modified: people/sigurdne/modules/phpgwapi/trunk/inc/class.cache.inc.php
===================================================================
--- people/sigurdne/modules/phpgwapi/trunk/inc/class.cache.inc.php	2009-11-20 10:27:41 UTC (rev 20844)
+++ people/sigurdne/modules/phpgwapi/trunk/inc/class.cache.inc.php	2009-11-20 10:28:10 UTC (rev 20845)
@@ -4,16 +4,16 @@
 	*
 	* @author Dave Hall <[email protected]>
 	* @copyright Copyright (C) 2008 Free Software Foundation, Inc. http://www.fsf.org/
-	* @license http://www.gnu.org/licenses/lgpl.html GNU Lesser General Public License Version 3 or later
+	* @license http://www.gnu.org/licenses/lgpl.html GNU Lesser General Public License Version 2 or later
 	* @package phpgroupware
 	* @subpackage phpgwapi
-	* @version $Id: class.acl.inc.php 775 2008-02-24 23:18:32Z dave $
+	* @version $Id: class.cache.inc.php 3061 2009-06-14 18:18:21Z sigurd $
 	*/
 
 	/*
 		This program is free software: you can redistribute it and/or modify
 		it under the terms of the GNU Lesser General Public License as published by
-		the Free Software Foundation, either version 3 of the License, or
+		the Free Software Foundation, either version 2 of the License, or
 		(at your option) any later version.
 
 		This program is distributed in the hope that it will be useful,
@@ -145,9 +145,10 @@
 		 * @param mixed the value to store
 		 * @return value to store as a string
 		 */
-		protected static function _value_prepare($value)
+		protected static function _value_prepare($value, $bypass = false)
 		{
-			return $GLOBALS['phpgw']->crypto->encrypt(serialize($value));
+		//	return $GLOBALS['phpgw']->crypto->encrypt(serialize($value));
+			return $GLOBALS['phpgw']->crypto->encrypt($value, $bypass);
 		}
 
 		/**
@@ -156,7 +157,7 @@
 		 * @param string $str the string to process
 		 * @return mixed the unserialized string
 		 */
-		protected static function _value_return($str)
+		protected static function _value_return($str, $bypass = false)
 		{
 			if ( is_null($str) )
 			{
@@ -164,7 +165,7 @@
 			}
 
 			// crypto class unserializes the data for us
-			return $GLOBALS['phpgw']->crypto->decrypt($str);
+			return $GLOBALS['phpgw']->crypto->decrypt($str, $bypass);
 		}
 
 		/**
@@ -196,7 +197,7 @@
 			$key = self::_gen_key($module, $id);
 			if ( isset($_SESSION['phpgw_cache'][$key]) )
 			{
-				return self::_value_return($_SESSION['phpgw_cache'][$key]);
+				return self::_value_return($_SESSION['phpgw_cache'][$key], true);
 			}
 			return null;
 		}
@@ -212,7 +213,12 @@
 		public static function session_set($module, $id, $data)
 		{
 			$key = self::_gen_key($module, $id);
-			$_SESSION['phpgw_cache'][$key] = self::_value_prepare($data);
+
+			if($data)
+			{
+				$data = self::_value_prepare($data, true); // suhoshin is already encrypting the data
+			}
+			$_SESSION['phpgw_cache'][$key] = $data;
 			return true;
 		}
 
@@ -241,7 +247,7 @@
 		 * @param string $id the internal module id for the data
 		 * @return mixed the data from system wide cache
 		 */
-		public static function system_get($module, $id)
+		public static function system_get($module, $id, $bypass = false, $compress = false)
 		{
 			$key = self::_gen_key($module, $id);
 
@@ -253,7 +259,21 @@
 			{
 				$value = self::_file_get($key);
 			}
-			return self::_value_return($value);
+
+			if(!$value)
+			{
+				return null;
+			}
+
+			if(function_exists('gzcompress') && $compress)
+			{
+				$value =  self::_value_return(gzuncompress(base64_decode($value)));
+				return $value;
+			}
+			else
+			{
+				return self::_value_return($value, $bypass);
+			}
 		}
 
 		/**
@@ -264,11 +284,16 @@
 		 * @param mixed $data the data to store
 		 * @return bool was the data stored in the system wide cache?
 		 */
-		public static function system_set($module, $id, $value)
+		public static function system_set($module, $id, $value, $bypass = false, $compress = false)
 		{
 			$key = self::_gen_key($module, $id);
-			$value = self::_value_prepare($value);
+			$value = self::_value_prepare($value, $bypass);
 
+			if(function_exists('gzcompress') && $compress)
+			{
+				$value =  base64_encode(gzcompress($value, 9));
+			}
+
 			if ( $GLOBALS['phpgw']->shm->is_enabled() )
 			{
 				return self::_shm_set($key, $value);
@@ -286,10 +311,74 @@
 		 */
 		public static function user_clear($module, $id, $uid)
 		{
+			$db = true;
+			if($db)
+			{
+				return self::_user_clear_db($module, $id, $uid);
+			}
+			else
+			{
+				return self::_user_clear($module, $id, $uid);			
+			}
+		}
+
+		/**
+		 * Retreive data from the user cache
+		 *
+		 * @param string $module the module name the data belongs to
+		 * @param string $id the internal module id for the data
+		 * @param int $uid the user id to the data is stored for
+		 * @return mixed the data from user cache
+		 */
+		public static function user_get($module, $id, $uid, $bypass = true, $compress = false)
+		{
+			$db = true;
+			if($db)
+			{
+				return self::_user_get_db($module, $id, $uid, $bypass, $compress);
+			}
+			else
+			{
+				return self::_user_get($module, $id, $uid, $bypass, $compress);
+			}
+		}
+
+		/**
+		 * Store data in the user cache
+		 *
+		 * @param string $module the module name the data belongs to
+		 * @param string $id the internal module id for the data
+		 * @param mixed $data the data to store in user cache
+		 * @param int $uid the user id to store the data for
+		 * @return bool was the data stored in the user cache?
+		 */
+		public static function user_set($module, $id, $value, $uid, $bypass = true, $compress = false)
+		{
+			$db = true;
+			if($db)
+			{
+				return self::_user_set_db($module, $id, $value, $uid, $bypass, $compress);
+			}
+			else
+			{
+				return self::_user_set($module, $id, $value, $uid, $bypass, $compress);
+			}
+		}
+
+		/**
+		 * Clear the data from the user cache
+		 *
+		 * @param string $module the module name the data belongs to
+		 * @param string $id the internal module id for the data
+		 * @param int $uid the user id the data is stored for
+		 * @return bool was the data deleted?
+		 */
+		protected static function _user_clear_db($module, $id, $uid)
+		{
 			$key = $GLOBALS['phpgw']->db->db_addslashes(self::_gen_key($module, $id));
 			$uid = (int) $uid;
 
-			$sql = "DELETE FROM phpgw_cache WHERE item_key = '{$key}'";
+			$sql = "DELETE FROM phpgw_cache_user WHERE item_key = '{$key}'";
 
 			// this is a bit of a hack, but we need some way of clearing cache values of all users - i am open to suggestions
 			if ( $uid <> -1 )
@@ -307,7 +396,7 @@
 		 * @param int $uid the user id to the data is stored for
 		 * @return mixed the data from user cache
 		 */
-		public static function user_get($module, $id, $uid)
+		protected static function _user_get_db($module, $id, $uid, $bypass = true, $compress = true)
 		{
 			$key = $GLOBALS['phpgw']->db->db_addslashes(self::_gen_key($module, $id));
 			$uid = (int) $uid;
@@ -318,7 +407,16 @@
 			$GLOBALS['phpgw']->db->query($sql, __LINE__, __FILE__);
 			if ( $GLOBALS['phpgw']->db->next_record() )
 			{
-				$ret = self::_value_return($GLOBALS['phpgw']->db-f('cache_data', true));
+				$ret = $GLOBALS['phpgw']->db->f('cache_data');
+				if($compress && function_exists('gzcompress'))
+				{
+					$ret =  gzuncompress(base64_decode($ret));
+				}
+				else
+				{
+					$ret = stripslashes($ret);
+				}
+				$ret = self::_value_return($ret, $bypass);
 			}
 			return $ret;
 		}
@@ -332,14 +430,135 @@
 		 * @param int $uid the user id to store the data for
 		 * @return bool was the data stored in the user cache?
 		 */
-		public static function user_set($module, $id, $value, $uid)
+		protected static function _user_set_db($module, $id, $value, $uid, $bypass = true, $compress = true)
 		{
+			$uid = (int) $uid;
+
+			if ($uid == 0)
+			{
+				return false;
+			}
+
 			$key = $GLOBALS['phpgw']->db->db_addslashes(self::_gen_key($module, $id));
-			$uid = (int) $uid;
-			$value = $GLOBALS['phpgw']->db->db_addslashes(self::_value_prepare($value));
+			$value = self::_value_prepare($value, $bypass);
+			if($compress && function_exists('gzcompress'))
+			{
+				$value =  base64_encode(gzcompress($value, 9));
+			}
+			else
+			{
+				$value = $GLOBALS['phpgw']->db->db_addslashes($value);
+			}
+
 			$now = time();
 
-			$sql = "INSERT INTO phpgw_cache_user VALUES('{$key}', {$uid}, '{$value}', $now)";
+			$GLOBALS['phpgw']->db->query("SELECT user_id FROM phpgw_cache_user WHERE item_key = '{$key}' AND user_id = {$uid}", __LINE__, __FILE__);
+			if ( $GLOBALS['phpgw']->db->next_record() )
+			{
+				$sql = 'UPDATE phpgw_cache_user'
+					. " SET cache_data = '{$value}', lastmodts = {$now}"
+					. " WHERE item_key = '{$key}' AND user_id = {$uid}";
+			}
+			else
+			{
+				$sql = "INSERT INTO phpgw_cache_user (item_key, user_id, cache_data, lastmodts) VALUES('{$key}', {$uid}, '{$value}', $now)";
+			}
+
 			return !!$GLOBALS['phpgw']->db->query($sql, __LINE__, __FILE__);
 		}
+
+		/**
+		 * Clear the data from the user cache
+		 *
+		 * @param string $module the module name the data belongs to
+		 * @param string $id the internal module id for the data
+		 * @param int $uid the user id the data is stored for
+		 * @return bool was the data deleted?
+		 */
+		protected static function _user_clear($module, $id, $uid)
+		{
+			$uid = (int) $uid;
+			$module = $module . '_' . $uid;
+
+			$key = self::_gen_key($module, $id);
+
+			if ( $GLOBALS['phpgw']->shm->is_enabled() )
+			{
+				return self::_shm_clear($key);
+			}
+			return self::_file_clear($key);
+		}
+
+		/**
+		 * Retreive data from the user cache
+		 *
+		 * @param string $module the module name the data belongs to
+		 * @param string $id the internal module id for the data
+		 * @param int $uid the user id to the data is stored for
+		 * @return mixed the data from user cache
+		 */
+		protected static function _user_get($module, $id, $uid, $bypass = true, $compress = false)
+		{
+			$uid = (int) $uid;
+			$module = $module . '_' . $uid;
+			$key = self::_gen_key($module, $id);
+
+			if ( $GLOBALS['phpgw']->shm->is_enabled() )
+			{
+				$value = self::_shm_get($key);
+			}
+			else
+			{
+				$value = self::_file_get($key);
+			}
+
+			if(!$value)
+			{
+				return null;
+			}
+
+			if(function_exists('gzcompress') && $compress)
+			{
+				$value =  self::_value_return(gzuncompress(base64_decode($value)));
+				return $value;
+			}
+			else
+			{
+				return self::_value_return($value, $bypass);
+			}
+		}
+
+		/**
+		 * Store data in the user cache
+		 *
+		 * @param string $module the module name the data belongs to
+		 * @param string $id the internal module id for the data
+		 * @param mixed $data the data to store in user cache
+		 * @param int $uid the user id to store the data for
+		 * @return bool was the data stored in the user cache?
+		 */
+		protected static function _user_set($module, $id, $value, $uid, $bypass = true, $compress = false)
+		{
+			$uid = (int) $uid;
+
+			if ($uid == 0)
+			{
+				return false;
+			}
+
+			$module = $module . '_' . $uid;
+			$key = self::_gen_key($module, $id);
+			$value = self::_value_prepare($value, $bypass);
+
+			if(function_exists('gzcompress') && $compress)
+			{
+				$value =  base64_encode(gzcompress($value, 9));
+			}
+
+			if ( $GLOBALS['phpgw']->shm->is_enabled() )
+			{
+				return self::_shm_set($key, $value);
+			}
+			return self::_file_set($key, $value);
+		}
 	}

Modified: people/sigurdne/modules/phpgwapi/trunk/inc/class.calendar_holidays.inc.php
===================================================================
--- people/sigurdne/modules/phpgwapi/trunk/inc/class.calendar_holidays.inc.php	2009-11-20 10:27:41 UTC (rev 20844)
+++ people/sigurdne/modules/phpgwapi/trunk/inc/class.calendar_holidays.inc.php	2009-11-20 10:28:10 UTC (rev 20845)
@@ -1,5 +1,5 @@
 <?php
-	/**
+/**
 	 * Calendar holidays calculation
 	 * @author Kai Hofmann <[email protected]>
 	 * @copyright Copyright (C) 2004 Free Software Foundation, Inc. http://www.fsf.org/
@@ -11,22 +11,7 @@
 	 * @internal For more about calendar calculations see http://www.datelib.de/
 	 */
 
-		/*
-		   This program is free software: you can redistribute it and/or modify
-		   it under the terms of the GNU Lesser General Public License as published by
-		   the Free Software Foundation, either version 3 of the License, or
-		   (at your option) any later version.
-
-		   This program is distributed in the hope that it will be useful,
-		   but WITHOUT ANY WARRANTY; without even the implied warranty of
-		   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-		   GNU General Public License for more details.
-
-		   You should have received a copy of the GNU Lesser General Public License
-		   along with this program.  If not, see <http://www.gnu.org/licenses/>.
-		 */
-
-	/**
+/**
 	 * Calendar holidays calculation
 	 *
 	 * @package phpgwapi
@@ -51,6 +36,16 @@
 	   var $federal_states = array('Germany' => array('Baden-Wuerttemberg','Bavaria','Berlin','Brandenburg','Hansestadt Bremen','Hansestadt Hamburg','Hesse','Mecklenburg-Western Pomerania','Lower Saxony','North Rhine-Westphalia','Rhineland-Palatinate','Saarland','Saxony','Saxony-Anhalt','Schleswig-Holstein','Thuringia'));
 
 		/**
+	 * Constructor
+	 *
+	 * @static
+	 */
+   function calendar_holidays()
+   {
+   }
+   
+
+	/**
 		* Count the number of occurences for a fixed date within a given start/end date range
 		*
 		* The start/end date range is not allowed to be larger than 1 year (i.e. 365/366 days)
@@ -572,3 +567,4 @@
 	 $cal_workdays->add_number_of_workdays(31,5,2004,3,'Germany','Lower Saxony','Evangelic',$day,$month,$year);
 	 echo $year . '-' . $month . '-' . $day . "\n";
 	 */
+?>
\ No newline at end of file

Modified: people/sigurdne/modules/phpgwapi/trunk/inc/class.categories.inc.php
===================================================================
--- people/sigurdne/modules/phpgwapi/trunk/inc/class.categories.inc.php	2009-11-20 10:27:41 UTC (rev 20844)
+++ people/sigurdne/modules/phpgwapi/trunk/inc/class.categories.inc.php	2009-11-20 10:28:10 UTC (rev 20845)
@@ -8,21 +8,6 @@
 	* @package phpgwapi
 	* @subpackage utilities
 	* @version $Id$
-	*/
-
-	/*
-	   This program is free software: you can redistribute it and/or modify
-	   it under the terms of the GNU Lesser General Public License as published by
-	   the Free Software Foundation, either version 3 of the License, or
-	   (at your option) any later version.
-
-	   This program is distributed in the hope that it will be useful,
-	   but WITHOUT ANY WARRANTY; without even the implied warranty of
-	   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-	   GNU General Public License for more details.
-
-	   You should have received a copy of the GNU Lesser General Public License
-	   along with this program.  If not, see <http://www.gnu.org/licenses/>.
 	 */
 
 	/**
@@ -42,6 +27,11 @@
 		var $grants;
 
 		/**
+		* @var bool $supress_info supress the [' . lang('Global') . '&nbsp;' . lang($this->app_name) . ']'
+		*/
+		var $supress_info = false;
+
+		/**
 		* Constructor
 		*
 		* @param integer $accountid Account id
@@ -513,7 +503,7 @@
 					{
 						$s .= '&nbsp;[' . lang('Global') . ']';
 					}
-					if ($cat['owner'] == '-1')
+					if ($cat['owner'] == '-1' && !$this->supress_info)
 					{
 						$s .= '&nbsp;[' . lang('Global') . '&nbsp;' . lang($this->app_name) . ']';
 					}
@@ -625,7 +615,7 @@
 				{
 					$name .= ' [' . lang('Global') . ']';
 				}
-				if ($cat['owner'] == '-1')
+				if ($cat['owner'] == '-1' && !$this->supress_info)
 				{
 					$name .= ' [' . lang('Global') . ' ' . lang($this->app_name) . ']';
 				}
@@ -783,12 +773,15 @@
 			$values['id']		= intval($values['cat_id']);
 			$values['parent']	= intval($values['parent']);
 
-			if (isset($values['old_parent']) && intval($values['old_parent']) != $values['parent'])
+			//Sigurd feb 09: Seems like an error to me - will break relations to existing records
+/*			if (isset($values['old_parent']) && intval($values['old_parent']) != $values['parent'])
 			{
 				$this->delete($values['id'],False,True);
 				return $this->add($values);
 			}
 			else
+
+*/
 			{
 				if ($values['parent'] > 0)
 				{
@@ -946,4 +939,3 @@
 			$this->grants		= $GLOBALS['phpgw']->acl->get_grants($appname);
 		}
 	}
-?>

Modified: people/sigurdne/modules/phpgwapi/trunk/inc/class.clientsniffer.inc.php
===================================================================
--- people/sigurdne/modules/phpgwapi/trunk/inc/class.clientsniffer.inc.php	2009-11-20 10:27:41 UTC (rev 20844)
+++ people/sigurdne/modules/phpgwapi/trunk/inc/class.clientsniffer.inc.php	2009-11-20 10:28:10 UTC (rev 20845)
@@ -16,21 +16,6 @@
 	* @link http://developer.netscape.com/docs/examples/javascript/NAME_type.html
 	*/
 
-	/*
-	   This program is free software: you can redistribute it and/or modify
-	   it under the terms of the GNU Lesser General Public License as published by
-	   the Free Software Foundation, either version 3 of the License, or
-	   (at your option) any later version.
-
-	   This program is distributed in the hope that it will be useful,
-	   but WITHOUT ANY WARRANTY; without even the implied warranty of
-	   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-	   GNU General Public License for more details.
-
-	   You should have received a copy of the GNU Lesser General Public License
-	   along with this program.  If not, see <http://www.gnu.org/licenses/>.
-	 */
-
 	/**
 	* Returns client information based on HTTP_USER_AGENT
 	*

Modified: people/sigurdne/modules/phpgwapi/trunk/inc/class.common.inc.php
===================================================================
--- people/sigurdne/modules/phpgwapi/trunk/inc/class.common.inc.php	2009-11-20 10:27:41 UTC (rev 20844)
+++ people/sigurdne/modules/phpgwapi/trunk/inc/class.common.inc.php	2009-11-20 10:28:10 UTC (rev 20845)
@@ -4,26 +4,11 @@
 	* @author Dan Kuykendall <[email protected]>
 	* @author Joseph Engo <[email protected]>
 	* @author Mark Peters <[email protected]>
-	* @copyright Copyright (C) 2000-2005 Free Software Foundation, Inc http://www.fsf.org/
+	* @copyright Copyright (C) 2000-2008 Free Software Foundation, Inc http://www.fsf.org/
 	* @license http://www.gnu.org/licenses/lgpl.html GNU Lesser General Public License
 	* @package phpgwapi
 	* @subpackage utilities
 	* @version $Id$
-	*/
-
-	/*
-	   This program is free software: you can redistribute it and/or modify
-	   it under the terms of the GNU Lesser General Public License as published by
-	   the Free Software Foundation, either version 3 of the License, or
-	   (at your option) any later version.
-
-	   This program is distributed in the hope that it will be useful,
-	   but WITHOUT ANY WARRANTY; without even the implied warranty of
-	   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-	   GNU General Public License for more details.
-
-	   You should have received a copy of the GNU Lesser General Public License
-	   along with this program.  If not, see <http://www.gnu.org/licenses/>.
 	 */
 
 	/**
@@ -98,6 +83,11 @@
 
 			for($i=1;$i<6;++$i)
 			{
+				if(!isset($regs2[$i]) && !isset($regs[$i]))
+				{
+					continue;
+				}
+
 				if($debug) { echo "<br />$i: $regs[$i] - $regs2[$i]"; }
 
 				if($regs2[$i] == $regs[$i])
@@ -301,11 +291,14 @@
 			if ( is_null($final_called) )
 			{
 				// call the asyncservice check_run function if it is not explicitly set to cron-only
-				if (!isset($GLOBALS['phpgw_info']['server']['asyncservice']) || !$GLOBALS['phpgw_info']['server']['asyncservice'] )
+				if ( !isset($GLOBALS['phpgw_info']['server']['asyncservice'])
+					|| !$GLOBALS['phpgw_info']['server']['asyncservice'] 
+					|| $GLOBALS['phpgw_info']['server']['asyncservice'] == 'fallback')
 				{
 					ExecMethod('phpgwapi.asyncservice.check_run', 'fallback');
 				}
 				$GLOBALS['phpgw']->db->disconnect();
+				$GLOBALS['phpgw']->session->commit_session();
 				$final_called = true;
 			}
 		}
@@ -484,15 +477,14 @@
 			}
 		}
 
-
-
 		/**
 		* Grab the owner name
 		*
 		* @param integer $accountid Account id
+		*
 		* @return string Users fullname
 		*/
-		public function grab_owner_name($accountid = '')
+		public function grab_owner_name($accountid = null)
 		{
 			return (string) $GLOBALS['phpgw']->accounts->get($accountid);
 		}
@@ -502,32 +494,29 @@
 		*
 		* @param array $tabs With ($id,$tab) pairs
 		* @param integer $selection array key of selected tab
-		* @param boolean $lang When true use translation otherwise use given label
-		* @return string HTML output string
+		* @param boolean $lang      Translate label?
+		*
+		* @return string html snippet for creating tabs in a modern browser
 		*/
 		public function create_tabs($tabs, $selection, $lang = false)
 		{
-			$output = <<<HTML
-			<div class="yui-navset">
-				<ul class="yui-nav">
-
-HTML;
-				foreach($tabs as $id => $tab)
+			phpgw::import_class('phpgwapi.yui');
+			if ( $lang )
 				{
-				$selected = $id == $selection ? ' class="selected"' : '';
-				$label = $lang ? lang($tab['label']) : $tab['label'];
-				$output .= <<<HTML
-					<li{$selected}><a href="{$tab['link']}"><em>{$label}</em></a></li>
-
-HTML;
+				foreach ( $tabs as &$tab )
+				{
+					$tab = lang($tab);
 			}
-			$output .= <<<HTML
-				</ul>
+			}
+
+			$html = phpgwapi_yui::tabview_generate($tabs, $selection);
+			$output = <<<HTML
+			<div class="yui-navset">
+				{$html}
 			</div>
 
 HTML;
 			return $output;
-
 		}
 
 		/**
@@ -601,7 +590,7 @@
 		/**
 		* List themes available
 		*
-		* Themes can either be css files like in HEAD (if the template has a css-directory) or ordinary .14 themes-files
+		* Themes are CSS files stored under the template directory
 		* @return array List with available themes
 		*/
 		public static function list_themes()
@@ -642,26 +631,24 @@
 
 			$list = array();
 
-			$d = dir(PHPGW_SERVER_ROOT . '/phpgwapi/templates');
-			while ($entry=$d->read())
-			{
-				if ( !in_array($entry, $ignore_list)
-					&& is_dir(PHPGW_SERVER_ROOT . "/phpgwapi/templates/{$entry}"))
-				{
-					$list[$entry]['name'] = $entry;
-					$f = PHPGW_SERVER_ROOT . "/phpgwapi/templates/{$entry}/details.inc.php";
-					if (file_exists ($f))
+			$dirname = PHPGW_SERVER_ROOT . '/phpgwapi/templates';
+
+			$dir = new DirectoryIterator($dirname);
+			foreach ( $dir as $file )
 					{
-						include($f);
-						$list[$entry]['title'] = "Use {$GLOBALS['phpgw_info']['template'][$entry]['title']}interface";
-					}
-					else
+				$entry = (string) $file;
+				if ( !in_array($entry, $ignore_list) && $file->isDir() )
 					{
 						$list[$entry]['title'] = $entry;
+
+					$f = "{$dirname}/{$entry}/details.inc.php";
+					if ( file_exists($f) )
+					{
+						require_once $f;
+						$list[$entry]['title'] = lang ('Use %s interface', $GLOBALS['phpgw_info']['template'][$entry]['title']);
 					}
 				}
 			}
-			$d->close();
 			ksort($list);
 			return $list;
 		}
@@ -882,7 +869,7 @@
 		/**
 		* Find an individual image
 		*
-		* @param string $module the module the image is for
+		* @param string $module the module the image is from
 		* @param string $image the image to search for
 		* @param string $ext the filename extension of the image - should usually be an empty string
 		* @param bool $use_lang use a translated verison of the image
@@ -952,7 +939,7 @@
 		{
 			if (file_exists(PHPGW_APP_INC . '/header.inc.php'))
 			{
-				include(PHPGW_APP_INC . '/header.inc.php');
+				require_once PHPGW_APP_INC . '/header.inc.php';
 			}
 		}
 
@@ -976,8 +963,8 @@
 				$tpl_name = 'simple';
 			}
 
-			include_once(PHPGW_INCLUDE_ROOT . "/phpgwapi/templates/{$tpl_name}/head.inc.php");
-			include_once(PHPGW_INCLUDE_ROOT . "/phpgwapi/templates/{$tpl_name}/navbar.inc.php");
+			require_once PHPGW_INCLUDE_ROOT . "/phpgwapi/templates/{$tpl_name}/head.inc.php";
+			require_once PHPGW_INCLUDE_ROOT . "/phpgwapi/templates/{$tpl_name}/navbar.inc.php";
 			if ($navbar)
 			{
 				echo parse_navbar();
@@ -1009,7 +996,7 @@
 				if ( !isset($GLOBALS['phpgw_info']['flags']['nofooter'])
 					|| !$GLOBALS['phpgw_info']['flags']['nofooter'] )
 				{
-					include(PHPGW_API_INC . '/footer.inc.php');
+					require_once PHPGW_API_INC . '/footer.inc.php';
 				}
 			}
 		}
@@ -1085,6 +1072,18 @@
 			{
 				$js .= $GLOBALS['phpgw']->js->get_script_links();
 			}
+			if( isset($GLOBALS['phpgw']->yuical) && is_object($GLOBALS['phpgw']->yuical))
+			{
+				if($cal_script = $GLOBALS['phpgw']->yuical->get_script())
+				{
+					$GLOBALS['phpgw_info']['flags']['java_script'] .= "\n"
+						. '<script type="text/javascript">' ."\n"
+						. '//<[CDATA[' ."\n"
+						. $cal_script ."\n"
+						. '//]]' ."\n"
+						. "</script>\n";
+				}
+			}
 
 			if ( isset($GLOBALS['phpgw_info']['menuaction']) )
 			{
@@ -1127,7 +1126,6 @@
 		* Convert hexadecimal data into binary
 		*
 		* @param string $data hexidecimal data as a string
-		*
 		* @return string binary value of $data;
 		*/
 		public static function hex2bin($data)
@@ -1158,58 +1156,6 @@
 		}
 
 		/**
-		* DES encrypt a password
-		*
-		* @param string $userpass User password
-		* @param string $random Random seed
-		* @return string DES encrypted password
-		*/
-		public function des_cryptpasswd($userpass, $random)
-		{
-			$lcrypt = '{crypt}';
-			$password = crypt($userpass, $random);
-			$ldappassword = sprintf('%s%s', $lcrypt, $password);
-			return $ldappassword;
-		}
-
-		/**
-		* MD5 encrypt password
-		*
-		* @author fechner at ponton dot de (source http://au3.php.net/manual/en/function.ldap-modify.php)
-		* @internal as there is really only 1 way to do this, it isn't copyrightable :)
-		* @param string $userpass User password
-		* @param string $random Random seed
-		* @return string MD5 encrypted password
-		*/
-		public function md5_cryptpasswd($userpass)
-		{
-			return '{md5}' . base64_encode(pack('H*', md5($userpass)));
-		}
-
-		/**
-		* Encrypt password based on encryption type set in setup
-		*
-		* @param string $password Password to encrypt
-		* @return Encrypted password or false
-		*/
-		public function encrypt_password($password)
-		{
-			if (strtolower($GLOBALS['phpgw_info']['server']['ldap_encryption_type']) == 'des')
-			{
-				$salt       = $this->randomstring(2);
-				$e_password = $this->des_cryptpasswd($password, $salt);
-
-				return $e_password;
-			}
-			elseif (strtolower($GLOBALS['phpgw_info']['server']['ldap_encryption_type']) == 'md5')
-			{
-				return $this->md5_cryptpasswd($password);
-			}
-
-			return false;
-		}
-
-		/**
 		* Find the current position of the application in the users portal_order preference
 		*
 		* @param integer $app Application id to find current position
@@ -1260,7 +1206,8 @@
 		{
 			if (!$t || (substr(php_uname(), 0, 7) == "Windows" && intval($t) <= 0))
 			{
-				$t = phpgwapi_datetime::gmtnow();
+				return ''; // return nothing if not valid input
+//				$t = phpgwapi_datetime::gmtnow();
 			}
 
 			//  + (date('I') == 1?3600:0)
@@ -1636,19 +1583,22 @@
 					{
 						$img	= $this->image('phpgwapi','msgbox_good');
 						$alt	= lang('OK');
+						$class  = 'msg_good';
 					}
 					else
 					{
 						$img	= $this->image('phpgwapi','msgbox_bad');
 						$alt	= lang('ERROR');
+						$class  = 'error';
 					}
 
 					$data[] = array
 					(
-						'msgbox_text'				=> lang($key),
+						'msgbox_text'				=> $key,
 						'msgbox_img'				=> $img,
 						'msgbox_img_alt'			=> $alt,
-						'lang_msgbox_statustext'	=> $alt
+						'lang_msgbox_statustext'	=> $alt,
+						'msgbox_class'				=> $class
 					);
 				}
 			}
@@ -1696,26 +1646,33 @@
 
 		public function msgbox_data($receipt)
 		{
-			$msgbox_data_error=array();
-			if (isSet($receipt['error']) AND is_array($receipt['error']))
+			$msgbox_data_error	 = array();
+			$msgbox_data_message = array();
+			if (isset($receipt['error']) && is_array($receipt['error']))
 			{
-				foreach($receipt['error'] as $errors)
+				foreach($receipt['error'] as $dummy => $error)
 				{
-					$msgbox_data_error += array($errors['msg']=> False);
+					$msgbox_data_error[$error['msg']] = false;
 				}
 			}
+			else if(isset($receipt['error']))
+			{
+				$msgbox_data_error[$receipt['error']] = false;			
+			}
 
-			$msgbox_data_message=array();
-
-			if (isSet($receipt['message']) AND is_array($receipt['message']))
+			if (isset($receipt['message']) && is_array($receipt['message']))
 			{
-				foreach($receipt['message'] as $messages)
+				foreach($receipt['message'] as $dummy => $message)
 				{
-					$msgbox_data_message += array($messages['msg']=> True);
+					$msgbox_data_message[$message['msg']] = true;
 				}
 			}
+			else if(isset($receipt['message']))
+			{
+				$msgbox_data_message[$receipt['message']] = true;			
+			}
 
-			$msgbox_data = $msgbox_data_error + $msgbox_data_message;
+			$msgbox_data = array_merge($msgbox_data_error, $msgbox_data_message);
 
 			return $msgbox_data;
 		}

Modified: people/sigurdne/modules/phpgwapi/trunk/inc/class.config.inc.php
===================================================================
--- people/sigurdne/modules/phpgwapi/trunk/inc/class.config.inc.php	2009-11-20 10:27:41 UTC (rev 20844)
+++ people/sigurdne/modules/phpgwapi/trunk/inc/class.config.inc.php	2009-11-20 10:28:10 UTC (rev 20845)
@@ -1,9 +1,11 @@
 <?php
+
 	/**
 	* Application configuration in a centralized location
 	* @author Joseph Engo <[email protected]>
-	* @copyright Copyright (C) 2000-2004 Free Software Foundation, Inc. http://www.fsf.org/
-	* @license http://www.gnu.org/licenses/lgpl.html GNU Lesser General Public License
+	* @author Dave Hall <[email protected]>
+	* @copyright Copyright (C) 2000-2008 Free Software Foundation, Inc. http://www.fsf.org/
+	* @license http://www.gnu.org/licenses/lgpl.html GNU Lesser General Public License v2 or later
 	* @package phpgwapi
 	* @subpackage application
 	* @version $Id$
@@ -12,7 +14,7 @@
 	/*
 	   This program is free software: you can redistribute it and/or modify
 	   it under the terms of the GNU Lesser General Public License as published by
-	   the Free Software Foundation, either version 3 of the License, or
+	   the Free Software Foundation, either version 2 of the License, or
 	   (at your option) any later version.
 
 	   This program is distributed in the hope that it will be useful,
@@ -33,42 +35,62 @@
 	class phpgwapi_config
 	{
 		/**
-		 * @var phpgwapi_db $db reference to global database object
+		 * @var object $db reference to global phpgwapi_db object
 		 */
-		protected $db;
+		private $db;
 
 		/**
-		 * @var string $appname the module accessing class
+		 * @var string $module the module the data belongs to
 		 */
-		public $appname;
 		
+		protected $module;
 		/**
-		 * @var array $config_data configuration data
-		 *
-		 * @todo make me protected and use __get|set to catch accessors
+		 * @var array $config_data the configuration data - this is likely to become protected
 		 */
-		public $config_data;
+		public $config_data = array();
 
 		/**
 		 * Constructor
 		 *
-		 * @return void
+		 * @param string $module the module to store the data for
 		 */
-		public function __construct($appname = '')
+		public function __construct($module = '')
 		{
-			if (! $appname)
+			if ( !$module )
 			{
-				$appname = $GLOBALS['phpgw_info']['flags']['currentapp'];
+				$module = $GLOBALS['phpgw_info']['flags']['currentapp'];
 			}
 			$this->db      =& $GLOBALS['phpgw']->db;
-			$this->appname = $this->db->db_addslashes($appname);
+			$this->module = $this->db->db_addslashes($module);
 		}
 
-		protected function read_repository()
+
+		/**
+		 * Load the config values for the current module
+		 *
+		 * @return array the config values
+		 */
+
+		public function read()
+ 		{
+			if(!count($this->config_data))
+			{
+				$this->read_repository();
+			}
+			return $this->config_data;
+		}
+
+		/**
+		 * Load the config values for the current module
+		 * @todo change to protected
+		 *
+		 * @return array the config values
+		 */
+		public function read_repository()
 		{
 			$this->config_data = array();
 			
-			$this->db->query("SELECT * FROM phpgw_config WHERE config_app='{$this->appname}'",__LINE__,__FILE__);
+			$this->db->query("SELECT * FROM phpgw_config WHERE config_app='{$this->module}'",__LINE__,__FILE__);
 			while ($this->db->next_record())
 			{
 				$test = @unserialize($this->db->f('config_value', true));
@@ -81,29 +103,19 @@
 					$this->config_data[$this->db->f('config_name')] = $this->db->f('config_value', true);
 				}
 			}
+			return $this->config_data;
 		}
 
-		//XXX Caeies nov08 -> possible bugs here if the config_data is updated. Should not occurs if using the value method ?
 		/**
-		* @todo to deprecate ! (use the __get|set instead)
-		* @return array the whole config 
+		 * Store the current configuration
 		*/
-		public function read()
-		{
-			if(!count($this->config_data))
-			{
-				$this->read_repository();
-			}
-			return $this->config_data;
-		}
-
 		public function save_repository()
 		{
 			$config_data = $this->config_data;
 
 			if ( is_array($config_data) && count($config_data) )
 			{
-				$this->db->lock(array('phpgw_config'));
+				$this->db->transaction_begin();
 				$this->delete_repository();
 				foreach ( $config_data as $name => $value )
 				{
@@ -114,20 +126,31 @@
 					$name  = $this->db->db_addslashes($name);
 					$value = $this->db->db_addslashes($value);
 					$query = "INSERT INTO phpgw_config (config_app,config_name,config_value) "
-						. "VALUES ('{$this->appname}', '{$name}', '{$value}')";
+						. "VALUES ('{$this->module}', '{$name}', '{$value}')";
 					$this->db->query($query, __LINE__, __FILE__);
 				}
-				$this->db->unlock();
+				$this->db->transaction_commit();
 			}
 		}
 
+		/**
+		 * Delete all configuration data for the selected module
+		 */
 		public function delete_repository()
 		{
-			$this->db->query("DELETE FROM phpgw_config WHERE config_app='{$this->appname}'",__LINE__,__FILE__);
+			$this->db->query("DELETE FROM phpgw_config WHERE config_app='{$this->module}'",__LINE__,__FILE__);
 		}
 
-		public function value($variable_name,$variable_data)
+		/**
+		 * Add/update configuration data
+		 *
+		 * Should call save_repository() to store the new configuration data
+		 *
+		 * @var string $name the key for the configuration data data
+		 * @var mixed $data the data to store
+		 */
+		public function value($name, $data)
 		{
-			$this->config_data[$variable_name] = $variable_data;
+			$this->config_data[$name] = $data;
 		}
 	}

Modified: people/sigurdne/modules/phpgwapi/trunk/inc/class.contact_accounts.inc.php
===================================================================
--- people/sigurdne/modules/phpgwapi/trunk/inc/class.contact_accounts.inc.php	2009-11-20 10:27:41 UTC (rev 20844)
+++ people/sigurdne/modules/phpgwapi/trunk/inc/class.contact_accounts.inc.php	2009-11-20 10:28:10 UTC (rev 20845)
@@ -7,27 +7,13 @@
 	* @package phpgwapi
 	* @subpackage contacts
 	* @version $Id$
-	*/
-
-	/*
-	   This program is free software: you can redistribute it and/or modify
-	   it under the terms of the GNU Lesser General Public License as published by
-	   the Free Software Foundation, either version 3 of the License, or
-	   (at your option) any later version.
-
-	   This program is distributed in the hope that it will be useful,
-	   but WITHOUT ANY WARRANTY; without even the implied warranty of
-	   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-	   GNU General Public License for more details.
-
-	   You should have received a copy of the GNU Lesser General Public License
-	   along with this program.  If not, see <http://www.gnu.org/licenses/>.
 	 */
 
 	/**
 	* Use SQL criteria
 	*/
 	phpgw::import_class('phpgwapi.sql_criteria');
+
 	/**
 	* Use SQL entity
 	*/
@@ -95,4 +81,3 @@
 			$this->add_field('is_user', 'count('.$this->real_field('account_id').')');
 		}
 	}
-?>

Modified: people/sigurdne/modules/phpgwapi/trunk/inc/class.contact_addr.inc.php
===================================================================
--- people/sigurdne/modules/phpgwapi/trunk/inc/class.contact_addr.inc.php	2009-11-20 10:27:41 UTC (rev 20844)
+++ people/sigurdne/modules/phpgwapi/trunk/inc/class.contact_addr.inc.php	2009-11-20 10:28:10 UTC (rev 20845)
@@ -7,27 +7,13 @@
 	* @package phpgwapi
 	* @subpackage contacts
 	* @version $Id$
-	*/
-
-	/*
-	   This program is free software: you can redistribute it and/or modify
-	   it under the terms of the GNU Lesser General Public License as published by
-	   the Free Software Foundation, either version 3 of the License, or
-	   (at your option) any later version.
-
-	   This program is distributed in the hope that it will be useful,
-	   but WITHOUT ANY WARRANTY; without even the implied warranty of
-	   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-	   GNU General Public License for more details.
-
-	   You should have received a copy of the GNU Lesser General Public License
-	   along with this program.  If not, see <http://www.gnu.org/licenses/>.
 	 */
 
 	/**
 	* Use SQL criteria
 	*/
 	phpgw::import_class('phpgwapi.sql_criteria');
+
 	/**
 	* Use SQL entity
 	*/
@@ -292,7 +278,7 @@
 		function select_adr_one_street($element)
 		{
 			$this->set_primary_address($element);
-			$this->field_list['adr_one_street']=phpgwapi_sql::concat_null(array($this->put_alias('add1'), $this->put_alias('add2'), $this->put_alias('add3')));
+			$this->field_list['adr_one_street'] = phpgwapi_sql::concat_null(array($this->put_alias('add1'), $this->put_alias('add2'), $this->put_alias('add3')));
 
 		}
 
@@ -317,7 +303,7 @@
 		function select_adr_two_street($element)
 		{
 			$this->set_secondary_address($element);
-			$this->field_list['adr_one_street']=phpgwapi_sql_criteria::concat_null(array($this->put_alias('add1'), $this->put_alias('add2'), $this->put_alias('add3')));
+			$this->field_list['adr_one_street'] = phpgwapi_sql_criteria::concat_null(array($this->put_alias('add1'), $this->put_alias('add2'), $this->put_alias('add3')));
 		}
 
 		/**
@@ -342,7 +328,7 @@
 		function criteria_adr_one_street($element)
 		{
 			$this->set_primary_address($element);
-			$criteria=phpgwapi_sql_criteria::or_(phpgwapi_sql_criteria::has($this->put_alias('add1'),$element['value']),
+			$criteria = phpgwapi_sql_criteria::or_(phpgwapi_sql_criteria::has($this->put_alias('add1'),$element['value']),
 							phpgwapi_sql_criteria::has($this->put_alias('add2'),$element['value']));
 			$this->_add_criteria($criteria);
 		}
@@ -356,7 +342,7 @@
 		function criteria_primary($element)
 		{
 			$this->set_primary_address($element);
-			$criteria=phpgwapi_sql_criteria::has($this->put_alias($element['real_field']),phpgwapi_sql::string($element['value']));
+			$criteria = phpgwapi_sql_criteria::has($this->put_alias($element['real_field']), phpgwapi_sql::string($element['value']));
 			$this->add_criteria($criteria);
 		}
 
@@ -369,8 +355,8 @@
 		function criteria_adr_two_street($element)
 		{
 			$this->set_secondary_address($element);
-			$criteria=phpgwapi_sql_criteria::or_(phpgwapi_sql_criteria::has($this->put_alias('add1'),phpgwapi_sql::string($element['value'])),
-							phpgwapi_sql_criteria::has($this->put_alias('add2'),phpgwapi_sql::string($element['value'])));
+			$criteria = phpgwapi_sql_criteria::or_(phpgwapi_sql_criteria::has($this->put_alias('add1'), phpgwapi_sql::string($element['value'])),
+							phpgwapi_sql_criteria::has($this->put_alias('add2'), phpgwapi_sql::string($element['value'])));
 			$this->_add_criteria($criteria);
 
 		}
@@ -378,7 +364,7 @@
 		function criteria_secondary($element)
 		{
 			$this->set_secondary_address($element);
-			$criteria=phpgwapi_sql_criteria::has($this->put_alias($element['real_field']),phpgwapi_sql::string($element['value']));
+			$criteria = phpgwapi_sql_criteria::has($this->put_alias($element['real_field']), phpgwapi_sql::string($element['value']));
 			$this->_add_criteria($criteria);
 		}
 
@@ -386,7 +372,7 @@
 		{
 			if($this->primary_set != 'primary')
 			{
-				$criteria=phpgwapi_sql_criteria::equal($this->put_alias('precedence'),'1');
+				$criteria = phpgwapi_sql_criteria::equal($this->put_alias('precedence'),'1');
 				$this->_add_criteria($criteria);
 				$this->primary_set='primary';
 			}
@@ -397,7 +383,7 @@
 		{
 			if($this->secondary_set != 'secondary')
 			{
-				$criteria=phpgwapi_sql_criteria::equal($this->put_alias('precedence'),'2');
+				$criteria = phpgwapi_sql_criteria::equal($this->put_alias('precedence'),'2');
 				$this->_add_criteria($criteria);
 				$this->secondary_set='secondary';
 			}
@@ -426,4 +412,3 @@
 			}
 		}
 	}
-?>

Modified: people/sigurdne/modules/phpgwapi/trunk/inc/class.contact_addr_type.inc.php
===================================================================
--- people/sigurdne/modules/phpgwapi/trunk/inc/class.contact_addr_type.inc.php	2009-11-20 10:27:41 UTC (rev 20844)
+++ people/sigurdne/modules/phpgwapi/trunk/inc/class.contact_addr_type.inc.php	2009-11-20 10:28:10 UTC (rev 20845)
@@ -7,21 +7,6 @@
 	* @package phpgwapi
 	* @subpackage contacts
 	* @version $Id$
-	*/
-
-	/*
-	   This program is free software: you can redistribute it and/or modify
-	   it under the terms of the GNU Lesser General Public License as published by
-	   the Free Software Foundation, either version 3 of the License, or
-	   (at your option) any later version.
-
-	   This program is distributed in the hope that it will be useful,
-	   but WITHOUT ANY WARRANTY; without even the implied warranty of
-	   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-	   GNU General Public License for more details.
-
-	   You should have received a copy of the GNU Lesser General Public License
-	   along with this program.  If not, see <http://www.gnu.org/licenses/>.
 	 */
 
 	/**

Modified: people/sigurdne/modules/phpgwapi/trunk/inc/class.contact_categories.inc.php
===================================================================
--- people/sigurdne/modules/phpgwapi/trunk/inc/class.contact_categories.inc.php	2009-11-20 10:27:41 UTC (rev 20844)
+++ people/sigurdne/modules/phpgwapi/trunk/inc/class.contact_categories.inc.php	2009-11-20 10:28:10 UTC (rev 20845)
@@ -7,27 +7,13 @@
 	* @package phpgwapi
 	* @subpackage contacts
 	* @version $Id$
-	*/
-
-	/*
-	   This program is free software: you can redistribute it and/or modify
-	   it under the terms of the GNU Lesser General Public License as published by
-	   the Free Software Foundation, either version 3 of the License, or
-	   (at your option) any later version.
-
-	   This program is distributed in the hope that it will be useful,
-	   but WITHOUT ANY WARRANTY; without even the implied warranty of
-	   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-	   GNU General Public License for more details.
-
-	   You should have received a copy of the GNU Lesser General Public License
-	   along with this program.  If not, see <http://www.gnu.org/licenses/>.
 	 */
 
 	/**
 	* Use SQL criteria
 	*/
 	phpgw::import_class('phpgwapi.sql_criteria');
+
 	/**
 	* Use SQL entity
 	*/
@@ -80,4 +66,3 @@
 			$this->set_elinks('key_cat_id', 'phpgwapi.contact_categories','parent_id');
 		}
 	}
-?>

Modified: people/sigurdne/modules/phpgwapi/trunk/inc/class.contact_central.inc.php
===================================================================
--- people/sigurdne/modules/phpgwapi/trunk/inc/class.contact_central.inc.php	2009-11-20 10:27:41 UTC (rev 20844)
+++ people/sigurdne/modules/phpgwapi/trunk/inc/class.contact_central.inc.php	2009-11-20 10:28:10 UTC (rev 20845)
@@ -7,21 +7,6 @@
 	* @package phpgwapi
 	* @subpackage contacts
 	* @version $Id$
-	*/
-
-	/*
-	   This program is free software: you can redistribute it and/or modify
-	   it under the terms of the GNU Lesser General Public License as published by
-	   the Free Software Foundation, either version 3 of the License, or
-	   (at your option) any later version.
-
-	   This program is distributed in the hope that it will be useful,
-	   but WITHOUT ANY WARRANTY; without even the implied warranty of
-	   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-	   GNU General Public License for more details.
-
-	   You should have received a copy of the GNU Lesser General Public License
-	   along with this program.  If not, see <http://www.gnu.org/licenses/>.
 	 */
 
 	/**
@@ -180,7 +165,7 @@
 			{
 				foreach($element['value'] as $value)
 				{
-					$data[] = phpgwapi_sql_criteria::or_(phpgwapi_sql_criteria::equal($field, phpgwapi_sql::string($value)),
+					$data[] = phpgwapi_sql_criteria::or_(phpgwapi_sql_criteria::equal($field, sql::string($value)),
 									phpgwapi_sql_criteria::has($field, ',' . $value . ','));
 				}
 				
@@ -193,4 +178,3 @@
 			}
 		}
 	}
-?>

Modified: people/sigurdne/modules/phpgwapi/trunk/inc/class.contact_comm.inc.php
===================================================================
--- people/sigurdne/modules/phpgwapi/trunk/inc/class.contact_comm.inc.php	2009-11-20 10:27:41 UTC (rev 20844)
+++ people/sigurdne/modules/phpgwapi/trunk/inc/class.contact_comm.inc.php	2009-11-20 10:28:10 UTC (rev 20845)
@@ -7,21 +7,6 @@
 	* @package phpgwapi
 	* @subpackage contacts
 	* @version $Id$
-	*/
-
-	/*
-	   This program is free software: you can redistribute it and/or modify
-	   it under the terms of the GNU Lesser General Public License as published by
-	   the Free Software Foundation, either version 3 of the License, or
-	   (at your option) any later version.
-
-	   This program is distributed in the hope that it will be useful,
-	   but WITHOUT ANY WARRANTY; without even the implied warranty of
-	   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-	   GNU General Public License for more details.
-
-	   You should have received a copy of the GNU Lesser General Public License
-	   along with this program.  If not, see <http://www.gnu.org/licenses/>.
 	 */
 
 	/**
@@ -281,4 +266,3 @@
 			$this->_add_criteria($this->index_criteria($element));
 		}
 	}
-?>

Modified: people/sigurdne/modules/phpgwapi/trunk/inc/class.contact_comm_descr.inc.php
===================================================================
--- people/sigurdne/modules/phpgwapi/trunk/inc/class.contact_comm_descr.inc.php	2009-11-20 10:27:41 UTC (rev 20844)
+++ people/sigurdne/modules/phpgwapi/trunk/inc/class.contact_comm_descr.inc.php	2009-11-20 10:28:10 UTC (rev 20845)
@@ -7,27 +7,13 @@
 	* @package phpgwapi
 	* @subpackage contacts
 	* @version $Id$
-	*/
-
-	/*
-	   This program is free software: you can redistribute it and/or modify
-	   it under the terms of the GNU Lesser General Public License as published by
-	   the Free Software Foundation, either version 3 of the License, or
-	   (at your option) any later version.
-
-	   This program is distributed in the hope that it will be useful,
-	   but WITHOUT ANY WARRANTY; without even the implied warranty of
-	   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-	   GNU General Public License for more details.
-
-	   You should have received a copy of the GNU Lesser General Public License
-	   along with this program.  If not, see <http://www.gnu.org/licenses/>.
 	 */
 
 	/**
 	* Use SQL criteria
 	*/
 	phpgw::import_class('phpgwapi.sql_criteria');
+
 	/**
 	* Use SQL entity
 	*/
@@ -106,4 +92,3 @@
 			$this->_add_criteria($criteria);
 		}
 	}
-?>

Modified: people/sigurdne/modules/phpgwapi/trunk/inc/class.contact_comm_type.inc.php
===================================================================
--- people/sigurdne/modules/phpgwapi/trunk/inc/class.contact_comm_type.inc.php	2009-11-20 10:27:41 UTC (rev 20844)
+++ people/sigurdne/modules/phpgwapi/trunk/inc/class.contact_comm_type.inc.php	2009-11-20 10:28:10 UTC (rev 20845)
@@ -7,27 +7,13 @@
 	* @package phpgwapi
 	* @subpackage contacts
 	* @version $Id$
-	*/
-
-	/*
-	   This program is free software: you can redistribute it and/or modify
-	   it under the terms of the GNU Lesser General Public License as published by
-	   the Free Software Foundation, either version 3 of the License, or
-	   (at your option) any later version.
-
-	   This program is distributed in the hope that it will be useful,
-	   but WITHOUT ANY WARRANTY; without even the implied warranty of
-	   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-	   GNU General Public License for more details.
-
-	   You should have received a copy of the GNU Lesser General Public License
-	   along with this program.  If not, see <http://www.gnu.org/licenses/>.
 	 */
 
 	/**
 	* Use SQL criteria
 	*/
 	phpgw::import_class('phpgwapi.sql_criteria');
+
 	/**
 	* Use SQL entity
 	*/
@@ -90,4 +76,3 @@
 			$this->set_ilinks('comm_type_id', 'phpgwapi.contact_comm_descr','comm_type');
 		}
 	}
-?>

Modified: people/sigurdne/modules/phpgwapi/trunk/inc/class.contact_note.inc.php
===================================================================
--- people/sigurdne/modules/phpgwapi/trunk/inc/class.contact_note.inc.php	2009-11-20 10:27:41 UTC (rev 20844)
+++ people/sigurdne/modules/phpgwapi/trunk/inc/class.contact_note.inc.php	2009-11-20 10:28:10 UTC (rev 20845)
@@ -7,21 +7,6 @@
 	* @package phpgwapi
 	* @subpackage contacts
 	* @version $Id$
-	*/
-
-	/*
-	   This program is free software: you can redistribute it and/or modify
-	   it under the terms of the GNU Lesser General Public License as published by
-	   the Free Software Foundation, either version 3 of the License, or
-	   (at your option) any later version.
-
-	   This program is distributed in the hope that it will be useful,
-	   but WITHOUT ANY WARRANTY; without even the implied warranty of
-	   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-	   GNU General Public License for more details.
-
-	   You should have received a copy of the GNU Lesser General Public License
-	   along with this program.  If not, see <http://www.gnu.org/licenses/>.
 	 */
 
 	/**

Modified: people/sigurdne/modules/phpgwapi/trunk/inc/class.contact_note_type.inc.php
===================================================================
--- people/sigurdne/modules/phpgwapi/trunk/inc/class.contact_note_type.inc.php	2009-11-20 10:27:41 UTC (rev 20844)
+++ people/sigurdne/modules/phpgwapi/trunk/inc/class.contact_note_type.inc.php	2009-11-20 10:28:10 UTC (rev 20845)
@@ -7,27 +7,13 @@
 	* @package phpgwapi
 	* @subpackage contacts
 	* @version $Id$
-	*/
-
-	/*
-	   This program is free software: you can redistribute it and/or modify
-	   it under the terms of the GNU Lesser General Public License as published by
-	   the Free Software Foundation, either version 3 of the License, or
-	   (at your option) any later version.
-
-	   This program is distributed in the hope that it will be useful,
-	   but WITHOUT ANY WARRANTY; without even the implied warranty of
-	   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-	   GNU General Public License for more details.
-
-	   You should have received a copy of the GNU Lesser General Public License
-	   along with this program.  If not, see <http://www.gnu.org/licenses/>.
 	 */
 
 	/**
 	* Use SQL criteria
 	*/
 	phpgw::import_class('phpgwapi.sql_criteria');
+
 	/**
 	* Use SQL entity
 	*/
@@ -73,4 +59,3 @@
 		}		
 
 	}
-?>

Modified: people/sigurdne/modules/phpgwapi/trunk/inc/class.contact_org.inc.php
===================================================================
--- people/sigurdne/modules/phpgwapi/trunk/inc/class.contact_org.inc.php	2009-11-20 10:27:41 UTC (rev 20844)
+++ people/sigurdne/modules/phpgwapi/trunk/inc/class.contact_org.inc.php	2009-11-20 10:28:10 UTC (rev 20845)
@@ -7,27 +7,13 @@
 	* @package phpgwapi
 	* @subpackage contacts
 	* @version $Id$
-	*/
-
-	/*
-	   This program is free software: you can redistribute it and/or modify
-	   it under the terms of the GNU Lesser General Public License as published by
-	   the Free Software Foundation, either version 3 of the License, or
-	   (at your option) any later version.
-
-	   This program is distributed in the hope that it will be useful,
-	   but WITHOUT ANY WARRANTY; without even the implied warranty of
-	   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-	   GNU General Public License for more details.
-
-	   You should have received a copy of the GNU Lesser General Public License
-	   along with this program.  If not, see <http://www.gnu.org/licenses/>.
 	 */
 
 	/**
 	* Use SQL criteria
 	*/
 	phpgw::import_class('phpgwapi.sql_criteria');
+
 	/**
 	* Use SQL entity
 	*/
@@ -166,6 +152,4 @@
 		{
 			$this->add_field('count_orgs', 'count(org_id)');
 		}
-
 	}
-?>

Modified: people/sigurdne/modules/phpgwapi/trunk/inc/class.contact_org_person.inc.php
===================================================================
--- people/sigurdne/modules/phpgwapi/trunk/inc/class.contact_org_person.inc.php	2009-11-20 10:27:41 UTC (rev 20844)
+++ people/sigurdne/modules/phpgwapi/trunk/inc/class.contact_org_person.inc.php	2009-11-20 10:28:10 UTC (rev 20845)
@@ -7,27 +7,13 @@
 	* @package phpgwapi
 	* @subpackage contacts
 	* @version $Id$
-	*/
-
-	/*
-	   This program is free software: you can redistribute it and/or modify
-	   it under the terms of the GNU Lesser General Public License as published by
-	   the Free Software Foundation, either version 3 of the License, or
-	   (at your option) any later version.
-
-	   This program is distributed in the hope that it will be useful,
-	   but WITHOUT ANY WARRANTY; without even the implied warranty of
-	   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-	   GNU General Public License for more details.
-
-	   You should have received a copy of the GNU Lesser General Public License
-	   along with this program.  If not, see <http://www.gnu.org/licenses/>.
 	 */
 
 	/**
 	* Use SQL criteria
 	*/
 	phpgw::import_class('phpgwapi.sql_criteria');
+
 	/**
 	* Use SQL entity
 	*/
@@ -154,4 +140,3 @@
 			return $criteria;
 		}
 	}
-?>

Modified: people/sigurdne/modules/phpgwapi/trunk/inc/class.contact_others.inc.php
===================================================================
--- people/sigurdne/modules/phpgwapi/trunk/inc/class.contact_others.inc.php	2009-11-20 10:27:41 UTC (rev 20844)
+++ people/sigurdne/modules/phpgwapi/trunk/inc/class.contact_others.inc.php	2009-11-20 10:28:10 UTC (rev 20845)
@@ -7,21 +7,6 @@
 	* @package phpgwapi
 	* @subpackage contacts
 	* @version $Id$
-	*/
-
-	/*
-	   This program is free software: you can redistribute it and/or modify
-	   it under the terms of the GNU Lesser General Public License as published by
-	   the Free Software Foundation, either version 3 of the License, or
-	   (at your option) any later version.
-
-	   This program is distributed in the hope that it will be useful,
-	   but WITHOUT ANY WARRANTY; without even the implied warranty of
-	   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-	   GNU General Public License for more details.
-
-	   You should have received a copy of the GNU Lesser General Public License
-	   along with this program.  If not, see <http://www.gnu.org/licenses/>.
 	 */
 
 	/**

Modified: people/sigurdne/modules/phpgwapi/trunk/inc/class.contact_person.inc.php
===================================================================
--- people/sigurdne/modules/phpgwapi/trunk/inc/class.contact_person.inc.php	2009-11-20 10:27:41 UTC (rev 20844)
+++ people/sigurdne/modules/phpgwapi/trunk/inc/class.contact_person.inc.php	2009-11-20 10:28:10 UTC (rev 20845)
@@ -7,27 +7,13 @@
 	* @package phpgwapi
 	* @subpackage contacts
 	* @version $Id$
-	*/
-
-	/*
-	   This program is free software: you can redistribute it and/or modify
-	   it under the terms of the GNU Lesser General Public License as published by
-	   the Free Software Foundation, either version 3 of the License, or
-	   (at your option) any later version.
-
-	   This program is distributed in the hope that it will be useful,
-	   but WITHOUT ANY WARRANTY; without even the implied warranty of
-	   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-	   GNU General Public License for more details.
-
-	   You should have received a copy of the GNU Lesser General Public License
-	   along with this program.  If not, see <http://www.gnu.org/licenses/>.
 	 */
 
 	/**
 	* Use SQL criteria
 	*/
 	phpgw::import_class('phpgwapi.sql_criteria');
+
 	/**
 	* Use SQL entity
 	*/
@@ -296,7 +282,7 @@
 				 'people'		=> array('select'	=> 'relink_org_person'),
 				 'people_local'		=> array('select'	=> 'relink_org_person'));
 
-		public	function contact_person ($ali = '', $field = '', $criteria = 	'')
+		function contact_person ($ali = '', $field = '', $criteria = 	'')
 		{
 			$this->_constructor('phpgw_contact_person', 'contact_person');
 			if($field)
@@ -335,13 +321,10 @@
 
 		function full_name()
 		{
-
 			$this->add_field('per_full_name', phpgwapi_sql::concat_null(array($this->real_field('per_prefix'), phpgwapi_sql::string(' '),
 										 $this->real_field('per_first_name'), phpgwapi_sql::string(' '),
 										 $this->real_field('per_middle_name'), phpgwapi_sql::string(' '),
 										 $this->real_field('per_last_name'), phpgwapi_sql::string(' '),
 										 $this->real_field('per_suffix'))));
 		}
-
 	}
-?>

Modified: people/sigurdne/modules/phpgwapi/trunk/inc/class.contact_types.inc.php
===================================================================
--- people/sigurdne/modules/phpgwapi/trunk/inc/class.contact_types.inc.php	2009-11-20 10:27:41 UTC (rev 20844)
+++ people/sigurdne/modules/phpgwapi/trunk/inc/class.contact_types.inc.php	2009-11-20 10:28:10 UTC (rev 20845)
@@ -7,21 +7,6 @@
 	* @package phpgwapi
 	* @subpackage contacts
 	* @version $Id$
-	*/
-
-	/*
-	   This program is free software: you can redistribute it and/or modify
-	   it under the terms of the GNU Lesser General Public License as published by
-	   the Free Software Foundation, either version 3 of the License, or
-	   (at your option) any later version.
-
-	   This program is distributed in the hope that it will be useful,
-	   but WITHOUT ANY WARRANTY; without even the implied warranty of
-	   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-	   GNU General Public License for more details.
-
-	   You should have received a copy of the GNU Lesser General Public License
-	   along with this program.  If not, see <http://www.gnu.org/licenses/>.
 	 */
 
 	/**

Modified: people/sigurdne/modules/phpgwapi/trunk/inc/class.contacts.inc.php
===================================================================
--- people/sigurdne/modules/phpgwapi/trunk/inc/class.contacts.inc.php	2009-11-20 10:27:41 UTC (rev 20844)
+++ people/sigurdne/modules/phpgwapi/trunk/inc/class.contacts.inc.php	2009-11-20 10:28:10 UTC (rev 20845)
@@ -7,27 +7,13 @@
 	* @subpackage contacts
 	*/
 
-	/*
-	   This program is free software: you can redistribute it and/or modify
-	   it under the terms of the GNU Lesser General Public License as published by
-	   the Free Software Foundation, either version 3 of the License, or
-	   (at your option) any later version.
-
-	   This program is distributed in the hope that it will be useful,
-	   but WITHOUT ANY WARRANTY; without even the implied warranty of
-	   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-	   GNU General Public License for more details.
-
-	   You should have received a copy of the GNU Lesser General Public License
-	   along with this program.  If not, see <http://www.gnu.org/licenses/>.
-	 */
-
 	//print_debug('Contact Repository:',"'".$GLOBALS['phpgw_info']['server']['contact_repository']."'",'api'); 
 	/**
 	* Include SQL handler
 	*/
-	include(PHPGW_API_INC . '/class.contacts_sql.inc.php');
+	phpgw::import_class('phpgwapi.contacts_sql');
+
 	/**
 	* Include shared methods
 	*/
-	include(PHPGW_API_INC . '/class.contacts_shared.inc.php');
+	phpgw::import_class('phpgwapi.contacts_shared');

Modified: people/sigurdne/modules/phpgwapi/trunk/inc/class.contacts_shared.inc.php
===================================================================
--- people/sigurdne/modules/phpgwapi/trunk/inc/class.contacts_shared.inc.php	2009-11-20 10:27:41 UTC (rev 20844)
+++ people/sigurdne/modules/phpgwapi/trunk/inc/class.contacts_shared.inc.php	2009-11-20 10:28:10 UTC (rev 20845)
@@ -10,21 +10,6 @@
 	* @package phpgwapi
 	* @subpackage contacts
 	* @version $Id$
-	*/
-
-	/*
-	   This program is free software: you can redistribute it and/or modify
-	   it under the terms of the GNU Lesser General Public License as published by
-	   the Free Software Foundation, either version 3 of the License, or
-	   (at your option) any later version.
-
-	   This program is distributed in the hope that it will be useful,
-	   but WITHOUT ANY WARRANTY; without even the implied warranty of
-	   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-	   GNU General Public License for more details.
-
-	   You should have received a copy of the GNU Lesser General Public License
-	   along with this program.  If not, see <http://www.gnu.org/licenses/>.
 	 */
 
 	/**

Modified: people/sigurdne/modules/phpgwapi/trunk/inc/class.contacts_sql.inc.php
===================================================================
--- people/sigurdne/modules/phpgwapi/trunk/inc/class.contacts_sql.inc.php	2009-11-20 10:27:41 UTC (rev 20844)
+++ people/sigurdne/modules/phpgwapi/trunk/inc/class.contacts_sql.inc.php	2009-11-20 10:28:10 UTC (rev 20845)
@@ -10,39 +10,24 @@
 	* @internal Development of this application was funded by http://www.sogrp.com
 	*/
 
-	/*
-	   This program is free software: you can redistribute it and/or modify
-	   it under the terms of the GNU Lesser General Public License as published by
-	   the Free Software Foundation, either version 3 of the License, or
-	   (at your option) any later version.
-
-	   This program is distributed in the hope that it will be useful,
-	   but WITHOUT ANY WARRANTY; without even the implied warranty of
-	   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-	   GNU General Public License for more details.
-
-	   You should have received a copy of the GNU Lesser General Public License
-	   along with this program.  If not, see <http://www.gnu.org/licenses/>.
-	 */
-
 	/**
 	* Include SQL Builder
 	* @see sql_builder
 	*/
-	include_once(PHPGW_API_INC . '/class.sql_builder.inc.php');
+	phpgw::import_class('phpgwapi.sql_builder');
 	
 	/**
 	* Include SQL criteria
-	* @see sql_criteria
+	* @see phpgwapi_sql_criteria
 	*/
 	phpgw::import_class('phpgwapi.sql_criteria');
 	
 	/**
-	* Use SQL entity
+	* Include SQL entity
+	* @see sql_entity
 	*/
 	phpgw::import_class('phpgwapi.sql_entity');
 	
-
 	/**
 	* All categories
 	*/
@@ -80,6 +65,7 @@
 		var $account_id = 0;
 		var $total_records = 0;
 		var $grants;
+		protected $global_lock = false;
 		/**
 		* All exporteds fields
 		*
@@ -811,45 +797,46 @@
 				'n_family'			=> $person_data['last_name'],
 				'n_suffix'			=> $person_data['suffix'],
 				'label'				=> '',
-				'adr_one_street'	=> $person_data['locations'][1]['add1'],
-				'adr_one_locality'	=> $person_data['locations'][1]['city'],
-				'adr_one_region'	=> $person_data['locations'][1]['state'],
-				'adr_one_postalcode'=> $person_data['locations'][1]['postal_code'],
-				'adr_one_countryname'=> $person_data['locations'][1]['country'],
-				'adr_one_type'		=> $person_data['locations'][1]['type'],
-				'adr_two_street'	=> $person_data['locations'][2]['add1'],
-				'adr_two_locality'	=> $person_data['locations'][2]['city'],
-				'adr_two_region'	=> $person_data['locations'][2]['state'],
-				'adr_two_postalcode'=> $person_data['locations'][2]['postal_code'],
-				'adr_two_countryname'=> $person_data['locations'][2]['country'],
-				'adr_two_type'		=> $person_data['locations'][2]['type'],
-				'tz'				=> $person_data['locations'][1]['tz'],
+				'adr_one_street'	=> isset($person_data['locations'][1]['add1']) ? $person_data['locations'][1]['add1'] : '',
+				'adr_one_locality'	=> isset($person_data['locations'][1]['city']) ? $person_data['locations'][1]['city'] : '',
+				'adr_one_region'	=> isset($person_data['locations'][1]['state']) ? $person_data['locations'][1]['state'] : '',
+				'adr_one_postalcode'=> isset($person_data['locations'][1]['postal_code']) ? $person_data['locations'][1]['postal_code'] : '',
+				'adr_one_countryname'=> isset($person_data['locations'][1]['country']) ? $person_data['locations'][1]['country'] : '',
+				'adr_one_type'		=> isset($person_data['locations'][1]['type']) ? $person_data['locations'][1]['type'] : '',
+				'adr_two_street'	=> isset($person_data['locations'][2]['add1']) ? $person_data['locations'][2]['add1'] : '',
+				'adr_two_locality'	=> isset($person_data['locations'][2]['city']) ? $person_data['locations'][2]['city'] : '',
+				'adr_two_region'	=> isset($person_data['locations'][2]['state']) ? $person_data['locations'][2]['state'] : '',
+				'adr_two_postalcode'=> isset($person_data['locations'][2]['postal_code']) ? $person_data['locations'][2]['postal_code'] : '',
+				'adr_two_countryname'=> isset($person_data['locations'][2]['country']) ? $person_data['locations'][2]['country'] : '',
+				'adr_two_type'		=> isset($person_data['locations'][2]['type']) ? $person_data['locations'][2]['type'] : '',
+				'tz'				=> isset($person_data['locations'][1]['tz']) ? $person_data['locations'][1]['tz'] : '',
 				'geo'				=> '',
-				'tel_work'			=> $person_data['work phone'],
-				'tel_home'			=> $person_data['home phone'],
-				'tel_voice'			=> $person_data['voice phone'],
-				'tel_msg'			=> $person_data['msg phone'],
-				'tel_fax'			=> $person_data['work fax'],
-				'tel_pager'			=> $person_data['pager'],
-				'tel_cell'			=> $person_data['mobile (cell) phone'],
-				'tel_bbs'			=> $person_data['bbs'],
-				'tel_modem'			=> $person_data['modem'],
-				'tel_isdn'			=> $person_data['isdn'],
-				'tel_car'			=> $person_data['car phone'],
-				'tel_video'			=> $person_data['video'],
+				'tel_work'			=> isset($person_data['comm_media']['work phone'])? $person_data['comm_media']['work phone'] : '',
+				'tel_home'			=> isset($person_data['comm_media']['home phone'])? $person_data['comm_media']['home phone'] : '',
+				'tel_voice'			=> isset($person_data['comm_media']['voice phone']) ? $person_data['comm_media']['voice phone'] : '',
+				'tel_msg'			=> isset($person_data['comm_media']['msg phone']) ? $person_data['comm_media']['msg phone'] : '',
+				'tel_fax'			=> isset($person_data['comm_media']['work fax']) ? $person_data['comm_media']['work fax'] : '',
+				'tel_pager'			=> isset($person_data['comm_media']['pager']) ? $person_data['comm_media']['pager'] : '',
+				'tel_cell'			=> isset($person_data['comm_media']['mobile (cell) phone']) ? $person_data['comm_media']['mobile (cell) phone'] : '',
+				'tel_bbs'			=> isset($person_data['comm_media']['bbs']) ? $person_data['comm_media']['bbs'] : '',
+				'tel_modem'			=> isset($person_data['comm_media']['modem']) ? $person_data['comm_media']['modem'] : '',
+				'tel_isdn'			=> isset($person_data['comm_media']['isdn']) ? $person_data['comm_media']['isdn'] : '',
+				'tel_car'			=> isset($person_data['comm_media']['car phone']) ? $person_data['comm_media']['car phone'] : '',
+				'tel_video'			=> isset($person_data['comm_media']['video']) ? $person_data['comm_media']['video'] : '',
 				'tel_prefer'		=> '',
-				'email'				=> $person_data['work email'],
-				'email_type'		=> $person_data['comm_type']['work email'],
-				'email_home'		=> $person_data['home email'],
-				'email_home_type'	=> $person_data['comm_type']['home email'],
-				'address2'			=> $person_data['locations'][1]['add2'],
-				'address3'			=> $person_data['locations'][1]['add3'],
+				'email'				=> isset($person_data['comm_media']['work email'])? $person_data['comm_media']['work email'] : '',
+				'email_type'		=> isset($person_data['comm_type']['work email']) ? $person_data['comm_type']['work email'] : '',
+				'email_home'		=> isset($person_data['comm_media']['home email']) ? $person_data['comm_media']['home email'] : '',
+				'email_home_type'	=> isset($person_data['comm_type']['home email']) ? $person_data['comm_type']['home email'] : '',
+				'address2'			=> isset($person_data['locations'][1]['add2']) ? $person_data['locations'][1]['add2'] : '',
+				'address3'			=> isset($person_data['locations'][1]['add3']) ? $person_data['locations'][1]['add3'] : '',
 				'ophone'			=> '',
-				'bday'				=> $person_data['birthday'],
-				'url'				=> $person_data['website'],
-				'pubkey'			=> $person_data['per_pubkey'],
-				'note'				=> $person_data['notes'][1]['text']
+				'bday'				=> isset($person_data['birthday']) ? $person_data['birthday'] : '',
+				'url'				=> isset($person_data['comm_media']['website']) ?  $person_data['comm_media']['website'] : '',
+				'pubkey'			=> isset($person_data['pubkey']) ? $person_data['pubkey'] : '',
+				'note'				=> isset($person_data['notes'][1]['text']) ? $person_data['notes'][1]['text'] : ''
 			);
+
 			if(is_array($fields))
 			{
 				foreach($fields as $field)
@@ -1046,7 +1033,8 @@
 		* @deprecated
 		* @access private
 		*/
-		function update($id,$owner,$fields,$access='',$cat_id='',$tid='n')
+		//FIXME Sigurd: This function used to be named "update" - but that conflicts with the parent class - is it used?
+		function update_contact($id,$owner,$fields,$access='',$cat_id='',$tid='n')
 		{
 			$this->update($fields);
 			$this->criteria('contact_id', $id);
@@ -1118,7 +1106,7 @@
 		* @param mixed $criteria_token same like $criteria but builded<br>with phpgwapi_sql_criteria class, more powerfull
 		* @return array Array person with records
 		*/
-		function get_persons($fields, $limit='', $ofset='', $orderby='', $sort='', $criteria='', $criteria_token='')
+		function get_persons($fields, $start='', $limit='', $orderby='', $sort='', $criteria='', $criteria_token='')
 		{
 			$this->request($fields);
 			if(in_array('org_name', $fields))
@@ -1151,7 +1139,7 @@
 			$sql = $this->get_sql();
 			if ($limit)
 			{
-				$this->db->limit_query($sql, $ofset, __LINE__, __FILE__, $limit);
+				$this->db->limit_query($sql, $start, __LINE__, __FILE__, $limit);
 			}
 			else
 			{
@@ -1159,19 +1147,12 @@
 			}
 
 			$this->total_records = $this->db->num_rows();
-			$persons = false;
+			$persons = array();
 
-		/*	while ($this->db->next_record())
+			while ($this->db->next_record())
 			{
-				$persons[] = $this->db->resultSet->fetchRow();
+				$persons[] = $this->db->Record;
 			}
-		*/
-
-			while (!$this->db->resultSet->EOF)
-			{
-				$persons[] = $this->db->resultSet->fetchRow();
-			}
-
 			return $persons;
 		}
 
@@ -1206,7 +1187,7 @@
 			$this->criteria(array('contact_id' => $contact_id));
 			if($get_org==True)
 			{
-				$this->request(array('org_name', 'org_id', 'people'));
+				$this->request(array('org_name', 'people', 'org_id'));
 				$this->criteria(array('my_preferred' => 'Y'));
 			}
 			return $this->get_query($action, __LINE__, __FILE__);
@@ -1296,7 +1277,7 @@
 			$this->total_records = $this->db->num_rows();
 			while ($this->db->next_record())
 			{
-				$orgs[] = $this->db->resultSet->fetchRow();
+				$orgs[] = $this->db->Record;
 			}
 			
 			return $orgs;
@@ -1658,9 +1639,9 @@
 			$accounts = $GLOBALS['phpgw']->accounts->get_list();
 			foreach($accounts as $account_data)
 			{
-				if($account_data['person_id'])
+				if($account_data->person_id)
 				{
-					$people[] = $account_data['person_id'];
+					$people[] = $account_data->person_id;
 				}
 			}
 
@@ -1732,7 +1713,7 @@
 		{
 			$sql = 'SELECT cat2.cat_id FROM phpgw_categories as cat '
 				.'INNER JOIN phpgw_categories as cat2 ON cat.cat_id=cat2.cat_parent '
-				.'WHERE '.phpgwapi_sql::in('cat.cat_id', $cat_id);
+				.'WHERE ' . phpgwapi_sql::in('cat.cat_id', $cat_id);
 
 			$this->db->query($sql, __LINE__, __FILE__);
 			while ($this->db->next_record())
@@ -1929,7 +1910,7 @@
 
 			while ($this->db->next_record())
 			{
-				$record = $this->db->resultSet->fetchRow();
+				$record = $this->db->Record;
 				$contact['contact_id']		= $record['contact_id'];
 				$contact['access']		= $record['access'];
 				$contact['owner']		= $record['owner'];
@@ -1946,11 +1927,11 @@
 				$contact['initials']		= $record['per_initials'];
 				$contact['sound']		= $record['per_sound'];
 				$contact['active']		= $record['per_active'];
-				$contact['createon']		= $record['per_createon'];
-				$contact['createby']		= $record['per_createby'];
+				$contact['createon']		= isset($record['per_createon']) ? $record['per_createon'] : ''; //Sigurd sept 08: not included in sql - but who knows - it might?
+				$contact['createby']		= isset($record['per_createby']) ? $record['per_createby'] : ''; // not in sql
 				$contact['modby']		= $record['per_modby'];
 				$contact['modon']		= $record['per_modon'];
-				$contact['account_id']		= $record['account_id'];
+				$contact['account_id']		= isset($record['account_id']) ? $record['account_id'] : ''; // not in sql
 				$contact['org_name']		= $record['org_name'];
 				// Locations info
 				$loc_id				= $record['key_addr_id'];
@@ -2123,7 +2104,7 @@
 			{
 				$principal['owner'] = $GLOBALS['phpgw_info']['user']['account_id'];
 			}
-			return $contact->update($principal, phpgwapi_sql_criteria::_equal('contact_id',phpgwapi_sql::integer($cid)), $action);
+			return $contact->update($principal, phpgwapi_sql_criteria::_equal('contact_id', phpgwapi_sql::integer($cid)), $action);
 		}
 
 		/**
@@ -2145,7 +2126,7 @@
 			{
 				$data['per_modby'] = $this->get_user_id();
 			}
-			return $person->update($data, phpgwapi_sql_criteria::_equal('person_id',phpgwapi_sql::integer($id)), $action);
+			return $person->update($data, phpgwapi_sql_criteria::_equal('person_id', phpgwapi_sql::integer($id)), $action);
 		}
 
 		/**
@@ -2167,7 +2148,7 @@
 			{
 				$data['org_modby'] = $this->get_user_id();
 			}
-			return $org->update($data, phpgwapi_sql_criteria::_equal('org_id',phpgwapi_sql::integer($id)), $action);
+			return $org->update($data, phpgwapi_sql_criteria::_equal('org_id', phpgwapi_sql::integer($id)), $action);
 		}
 
 
@@ -2190,7 +2171,7 @@
 			{
 				$data['addr_modby'] = $this->get_user_id();
 			}
-			return $loc->update($data, phpgwapi_sql_criteria::_equal('contact_addr_id',phpgwapi_sql::integer($id)), $action);
+			return $loc->update($data, phpgwapi_sql_criteria::_equal('contact_addr_id', phpgwapi_sql::integer($id)), $action);
 		}
 
 		/**
@@ -2212,7 +2193,7 @@
 			{
 				$data['addr_modby'] = $this->get_user_id();
 			}
-			return $loc->update($data, phpgwapi_sql_criteria::_equal('contact_id',phpgwapi_sql::integer($contact_id)), $action);
+			return $loc->update($data, phpgwapi_sql_criteria::_equal('contact_id', phpgwapi_sql::integer($contact_id)), $action);
 		}
 
 		/**
@@ -2234,7 +2215,7 @@
 			{
 				$data['comm_modby'] = $this->get_user_id();
 			}
-			return $comm->update($data, phpgwapi_sql_criteria::_equal('comm_id',phpgwapi_sql::integer($id)), $action);
+			return $comm->update($data, phpgwapi_sql_criteria::_equal('comm_id', phpgwapi_sql::integer($id)), $action);
 		}
 
 		/**
@@ -2248,7 +2229,7 @@
 		function edit_other($id, $data, $action=PHPGW_SQL_RETURN_SQL)
 		{
 			$comm = createObject('phpgwapi.contact_others');
-			return $comm->update($data, phpgwapi_sql_criteria::_equal('other_id',phpgwapi_sql::integer($id)), $action);
+			return $comm->update($data, phpgwapi_sql_criteria::_equal('other_id', phpgwapi_sql::integer($id)), $action);
 		}
 
 		/**
@@ -2262,7 +2243,7 @@
 		function edit_comms_by_contact($id, $data, $action=PHPGW_SQL_RETURN_SQL)
 		{
 			$comm = createObject('phpgwapi.contact_comm');
-			return $comm->update($data, phpgwapi_sql_criteria::_equal('contact_id',phpgwapi_sql::integer($id)), $action);
+			return $comm->update($data, phpgwapi_sql_criteria::_equal('contact_id', phpgwapi_sql::integer($id)), $action);
 		}
 
 		/**
@@ -2280,16 +2261,16 @@
 			$relation = createObject('phpgwapi.contact_org_person');
 			if($org_id && $person_id)
 			{
-				$criteria = phpgwapi_sql_criteria::and_(phpgwapi_sql_criteria::equal('org_id',phpgwapi_sql::integer($org_id)),
-								 phpgwapi_sql_criteria::equal('person_id',phpgwapi_sql::integer($person_id)));
+				$criteria = phpgwapi_sql_criteria::and_(phpgwapi_sql_criteria::equal('org_id', phpgwapi_sql::integer($org_id)),
+								 phpgwapi_sql_criteria::equal('person_id', phpgwapi_sql::integer($person_id)));
 			}
 			elseif($org_id)
 			{
-				$criteria = phpgwapi_sql_criteria::equal('org_id',phpgwapi_sql::integer($org_id));
+				$criteria = phpgwapi_sql_criteria::equal('org_id', phpgwapi_sql::integer($org_id));
 			}
 			elseif($person_id)
 			{
-				$criteria = phpgwapi_sql_criteria::equal('person_id',phpgwapi_sql::integer($person_id));
+				$criteria = phpgwapi_sql_criteria::equal('person_id', phpgwapi_sql::integer($person_id));
 			}
 
 			return $relation->update($data, $criteria, $action);
@@ -2310,7 +2291,7 @@
 			}
 			$contact = createObject('phpgwapi.contact_central');
 			return $contact->update(array('owner' => $new_owner),
-						phpgwapi_sql_criteria::_equal('owner',phpgwapi_sql::integer($old_owner)),
+						phpgwapi_sql_criteria::_equal('owner', phpgwapi_sql::integer($old_owner)),
 						PHPGW_SQL_RUN_SQL);
 		}
 
@@ -2329,7 +2310,7 @@
 			}
 			$contact = createObject('phpgwapi.contact_others');
 			return $contact->update(array('contact_owner' => $new_owner),
-						phpgwapi_sql_criteria::_equal('contact_owner',phpgwapi_sql::integer($old_owner)),
+						phpgwapi_sql_criteria::_equal('contact_owner', phpgwapi_sql::integer($old_owner)),
 						PHPGW_SQL_RUN_SQL);
 		}
 
@@ -2363,7 +2344,7 @@
 		{
 			$contact = createObject('phpgwapi.contact_central');
 			$principal['cat_id'] = $this->get_categories($categories);
-			return $contact->update($principal, phpgwapi_sql_criteria::_equal('contact_id',phpgwapi_sql::integer($cid)), $action);
+			return $contact->update($principal, phpgwapi_sql_criteria::_equal('contact_id', phpgwapi_sql::integer($cid)), $action);
 		}
 
 
@@ -2384,27 +2365,46 @@
 		function add_contact($type, $principal=array(), $comms=array(), $locations=array(), $categories=array(), $others=array(), $contact_relations=array(), $notes=array())
 		{
 			$this->contact = createObject('phpgwapi.contact_central');
-			$owner = isset($principal['owner']) && $principal['owner'] ? $principal['owner'] : $GLOBALS['phpgw_info']['user']['account_id'];
-			$this->lock_table($this->contact->table);
 
-			$this->contact->insert(array
-			(
-				'owner' => $owner,
-				'access' => $principal['access'],
-				'cat_id' => $this->get_categories($categories),
-				'contact_type' => $type
-			), PHPGW_SQL_RUN_SQL);
+			// addressmaster is a sane default
+			$owner = -3;
+			if ( isset($principal['owner']) 
+					&& $principal['owner'] )
+			{
+				$owner = (int) $principal['owner'];
+			}
+			else if ( isset($GLOBALS['phpgw_info']['user']['account_id']) )
+			{
+				$owner = (int) $GLOBALS['phpgw_info']['user']['account_id'];
+			}
 			
 			if ( !isset($principal['preferred_org']) )
 			{
-				$principal['preferred_org'] = null;
+				$principal['preferred_org'] = '';
 			}
 
 			if ( !isset($principal['preferred_address']) )
 			{
-				$principal['preferred_address'] = null;
+				$principal['preferred_address'] = '';
 			}
 			
+			if ( $this->db->Transaction )
+			{
+				$this->global_lock = true;
+			}
+			else
+			{
+				$this->lock_table($this->contact->table);
+			}
+
+			$this->contact->insert(array
+			(
+				'owner' => $owner,
+				'access' => $principal['access'],
+				'cat_id' => $this->get_categories($categories),
+				'contact_type' => $type
+			), PHPGW_SQL_RUN_SQL);
+
 			$cid = $this->last_id('contact', 'contact_id');
 			$this->unlock_table();
 			$add_type = $this->search_contact_type_id($type);
@@ -2420,7 +2420,7 @@
 					break;
 			}
 
-			if(is_array($comms))
+			if ( is_array($comms) && count($comms) )
 			{
 				foreach($comms as $comm)
 				{
@@ -2428,7 +2428,7 @@
 					$this->unlock_table();
 				}
 			}
-			if(is_array($locations))
+			if ( is_array($locations) && count($locations) )
 			{
 				foreach($locations as $location)
 				{
@@ -2437,7 +2437,7 @@
 				}
 			}
 
-			if(is_array($others))
+			if ( is_array($others) && count($others) )
 			{
 				foreach($others as $other)
 				{
@@ -2445,7 +2445,7 @@
 					$this->unlock_table();
 				}
 			}
-			if(is_array($notes))
+			if ( is_array($notes) && count($notes) )
 			{
 				foreach($notes as $note)
 				{
@@ -2474,9 +2474,16 @@
 			$this->org = createObject('phpgwapi.contact_org');
 			if ($action == PHPGW_SQL_RUN_SQL)
 			{
-				$this->lock_table($this->org->table);
+				if ( $this->db->Transaction )
+				{
+					$this->global_lock = true;
 			}
+				else
+				{
 			$this->lock_table($this->org->table);
+				}
+			}
+
 			$principal['org_creaton'] = $this->get_mkdate();
 			$principal['org_creatby'] = $this->get_user_id();
 			$principal['org_modon'] = $this->get_mkdate();
@@ -2500,9 +2507,16 @@
 			$this->person = createObject('phpgwapi.contact_person');
 			if ($action == PHPGW_SQL_RUN_SQL)
 			{
-				$this->lock_table($this->person->table);
+				if ( $this->db->Transaction )
+				{
+					$this->global_lock = true;
 			}
+				else
+				{
 			$this->lock_table($this->person->table);
+				}
+			}
+
 			$principal['per_creaton'] = $this->get_mkdate();
 			$principal['per_creatby'] = $this->get_user_id();
 			$principal['per_modon'] = $this->get_mkdate();
@@ -2551,8 +2565,15 @@
 
 				if ($action == PHPGW_SQL_RUN_SQL)
 				{
+					if ( $this->db->Transaction )
+					{
+						$this->global_lock = true;
+					}
+					else
+					{
 					$this->lock_table($this->relations->table);
 				}
+				}
 				$sql[] = $this->_add($data,'relations', 'my_org_id', $cid, $action);
 				$this->unlock_table();
 			}
@@ -2591,8 +2612,15 @@
 					$data['my_creatby'] = $this->get_user_id();
 					if ($action == PHPGW_SQL_RUN_SQL)
 					{
+						if ( $this->db->Transaction )
+						{
+							$this->global_lock = true;
+						}
+						else
+						{
 						$this->lock_table($this->relations->table);
 					}
+					}
 					$sql[] = $this->_add($data,'relations', 'my_person_id', $cid, $action);
 					$this->unlock_table();
 				}
@@ -2614,8 +2642,15 @@
 			$this->location = createObject('phpgwapi.contact_addr');
 			if ($action == PHPGW_SQL_RUN_SQL)
 			{
+				if ( $this->db->Transaction )
+				{
+					$this->global_lock = true;
+				}
+				else
+				{
 				$this->lock_table($this->location->table);
 			}
+			}
 			if(count($addr[0]) == 0)
 			{
 				$location['addr_preferred'] = 'Y';
@@ -2647,8 +2682,15 @@
 			$this->comm = createObject('phpgwapi.contact_comm');
 			if ($action == PHPGW_SQL_RUN_SQL)
 			{
+				if ( $this->db->Transaction )
+				{
+					$this->global_lock = true;
+				}
+				else
+				{
 				$this->lock_table($this->comm->table);
 			}
+			}
 
 			$comm['comm_creatby'] = $this->get_user_id();
 			$comm['comm_modby'] = $this->get_user_id();
@@ -2673,8 +2715,15 @@
 			$this->note = createObject('phpgwapi.contact_note');
 			if ($action == PHPGW_SQL_RUN_SQL)
 			{
+				if ( $this->db->Transaction )
+				{
+					$this->global_lock = true;
+				}
+				else
+				{
 				$this->lock_table($this->note->table);
 			}
+			}
 
 			$note['note_creatby'] = $this->get_user_id();
 			$note['note_modby'] = $this->get_user_id();
@@ -2699,8 +2748,15 @@
 			$this->others = createObject('phpgwapi.contact_others');
 			if ($action == PHPGW_SQL_RUN_SQL)
 			{
+				if ( $this->db->Transaction )
+				{
+					$this->global_lock = true;
+				}
+				else
+				{
 				$this->lock_table($this->others->table);
 			}
+			}
 
 			unset($others['key_other_id']);
 
@@ -2867,7 +2923,15 @@
 		function delete_org_person_relation($org_id, $person_id, $action=PHPGW_SQL_RUN_SQL)
 		{
 			$relations = createObject('phpgwapi.contact_org_person');
+			if ( $this->db->Transaction )
+			{
+				$this->global_lock = true;
+			}
+			else
+			{
 			$this->lock_table($relations->table);
+			}
+
 			$criteria = $relations->entity_criteria(phpgwapi_sql_criteria::token_and(phpgwapi_sql_criteria::_equal('my_org_id', $org_id),
 											phpgwapi_sql_criteria::_equal('my_person_id', $person_id)));
 			$sql = $relations->delete($criteria, $action);
@@ -3115,7 +3179,7 @@
 			$this->db->query($sql, __LINE__, __FILE__);
 			while ($this->db->next_record())
 			{
-				$orgs = &$this->db->resultSet->fetchRow();
+				$orgs = $this->db->Record;
 			}
 			return $orgs;
 		}
@@ -3160,7 +3224,7 @@
 			$this->db->query($this->get_sql(), __LINE__, __FILE__);
 			while ($this->db->next_record())
 			{
-				$cats[] = $this->db->resultSet->fetchRow();
+				$cats[] = $this->db->Record;
 			}
 
 			return $cats;
@@ -3357,9 +3421,9 @@
 			$accounts = $GLOBALS['phpgw']->accounts->get_list();
 			foreach($accounts as $account_data)
 			{
-				if($account_data['person_id'] == $contact_id)
+				if($account_data->id == $contact_id)
 				{
-					$account_id = $account_data['account_id'];
+					$account_id = $account_data->id;
 					break;
 				}
 			}
@@ -3460,7 +3524,7 @@
 			$this->db->query($query,__LINE__, __FILE__);
 			while($this->db->next_record())
 			{
-				$contact = $this->db->resultSet->fetchRow();
+				$contact = $this->db->Record;
 				$contact['account_id'] = $GLOBALS['phpgw']->accounts->search_person($contact['contact_id']);
 				$contacts[] = $contact;
 			}
@@ -3865,7 +3929,15 @@
 				foreach($records as $data)
 				{
 					$this->relations = createObject('phpgwapi.contact_org_person');
+					if ( $this->db->Transaction )
+					{
+						$this->global_lock = true;
+					}
+					else
+					{
 					$this->lock_table($this->relations->table);
+					}
+
 					$data['my_creaton'] = $this->get_mkdate();
 					$data['my_creatby'] = $this->get_user_id();
 					$sql[] = $this->_add($data, 'relations', 'my_person_id', $new_person_id, PHPGW_SQL_RUN_SQL);
@@ -3891,7 +3963,15 @@
 					if(!$this->exist_org_person_relation($new_organization_id, $data['my_person_id']))
 					{
 						$this->relations = createObject('phpgwapi.contact_org_person');
+						if ( $this->db->Transaction )
+						{
+							$this->global_lock = true;
+						}
+						else
+						{
 						$this->lock_table($this->relations->table);
+						}
+
 						$data['my_creaton'] = $this->get_mkdate();
 						$data['my_creatby'] = $this->get_user_id();
 						$sql[] = $this->_add($data,'relations', 'my_org_id', $new_organization_id, PHPGW_SQL_RUN_SQL);
@@ -4016,7 +4096,10 @@
 			if(count($this->locked))
 			{
 				$this->ldebug('unlock_table', array('count' => count($this->locked)));
+				if ( !$this->global_lock )
+				{
 				$this->db->unlock();
+				}
 				$this->locked = NULL;
 			}
 		}
@@ -4076,9 +4159,9 @@
 		function is_contact($account_id)
 		{
 			$account = $GLOBALS['phpgw']->accounts->get($account_id);
-			if(intval($account->person_id) == 0)
+			if ( !is_object($account) )
 			{
-				return False;
+				return 0;
 			}
 			return $account->person_id;
 		}
@@ -4120,8 +4203,6 @@
 
 		function get_mkdate()
 		{
-			// TODO use again mktime with timezone properly defined
-			// $date=mktime();
 			$date = time();
 			return $date;
 		}
@@ -4631,4 +4712,3 @@
 			}
 		}
 	}
-?>

Modified: people/sigurdne/modules/phpgwapi/trunk/inc/class.country.inc.php
===================================================================
--- people/sigurdne/modules/phpgwapi/trunk/inc/class.country.inc.php	2009-11-20 10:27:41 UTC (rev 20844)
+++ people/sigurdne/modules/phpgwapi/trunk/inc/class.country.inc.php	2009-11-20 10:28:10 UTC (rev 20845)
@@ -1,31 +1,15 @@
 <?php
 	/**
-	* phpGroupWare - ISO 3166 Countries and Continents
-	*
-	* @auhtor Dave Hall skwashd at phpGroupWare.org
+	* Countries
 	* @author Mark Peters <[email protected]>
+	* @auhtor Dave Hall skwashd at phpGroupWare.org
 	* @author Bettine Gille ceb at phpGroupWare.org
-	* @copyright Copyright (C) 2001 - 2008 Free Software Foundation http://www.fsf.org/
+	* @copyright Copyright (C) 2001 - 2006 Free Software Foundation http://www.fsf.org/
 	* @license http://www.gnu.org/licenses/gpl.html GNU General Public License
 	* @interal do not edit, edit and run phpgwapi/doc/generate-class-country.php to regenerate this class
 	* @package phpgwapi
 	* @subpackage contacts
 	* @version $Id$
-	*/
-
-	/*
-	   This program is free software: you can redistribute it and/or modify
-	   it under the terms of the GNU General Public License as published by
-	   the Free Software Foundation, either version 3 of the License, or
-	   (at your option) any later version.
-
-	   This program is distributed in the hope that it will be useful,
-	   but WITHOUT ANY WARRANTY; without even the implied warranty of
-	   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-	   GNU General Public License for more details.
-
-	   You should have received a copy of the GNU General Public License
-	   along with this program.  If not, see <http://www.gnu.org/licenses/>.
 	 */
 
 	/**
@@ -51,9 +35,8 @@
 			'southamerica'	=> 'South America'
 		);
 
-
 		/**
-		* @var array  list of ISO 3166 country codes
+		* @var array $country_array list of ISO 3166 country codes
 		*/
 		public static $country_array = array
 		(
@@ -109,8 +92,8 @@
 			'CD'	=> 'CONGO, THE DEMOCRATIC REPUBLIC OF THE',
 			'CK'	=> 'COOK ISLANDS',
 			'CR'	=> 'COSTA RICA',
+			'CI'	=> 'COTE D\'IVOIRE',
 			'HR'	=> 'CROATIA',
-			'CI'	=> 'CÔTE D\'IVOIRE',
 			'CU'	=> 'CUBA',
 			'CY'	=> 'CYPRUS',
 			'CZ'	=> 'CZECH REPUBLIC',
@@ -175,7 +158,7 @@
 			'KR'	=> 'KOREA, REPUBLIC OF',
 			'KW'	=> 'KUWAIT',
 			'KG'	=> 'KYRGYZSTAN',
-			'AX'	=> 'ÅLAND ISLANDS',
+			'AX'	=> 'ALAND ISLANDS',
 			'LA'	=> 'LAO PEOPLE\'S DEMOCRATIC REPUBLIC',
 			'LV'	=> 'LATVIA',
 			'LB'	=> 'LEBANON',
@@ -240,11 +223,9 @@
 			'RO'	=> 'ROMANIA',
 			'RU'	=> 'RUSSIAN FEDERATION',
 			'RW'	=> 'RWANDA',
-			'BL'	=> 'SAINT BARTHÉLEMY',
 			'SH'	=> 'SAINT HELENA',
 			'KN'	=> 'SAINT KITTS AND NEVIS',
 			'LC'	=> 'SAINT LUCIA',
-			'MF'	=> 'SAINT MARTIN',
 			'PM'	=> 'SAINT PIERRE AND MIQUELON',
 			'VC'	=> 'SAINT VINCENT AND THE GRENADINES',
 			'WS'	=> 'SAMOA',
@@ -316,7 +297,7 @@
 			if ( is_null($translated_list) )
 			{
 				 $translated_list = array();
-				 foreach ( self::$country_array as $code => $name )
+				 foreach ( phpgwapi_country::$country_array as $code => $name )
 				 {
 				 	$translated = lang($name);
 					if ( $translated == "{$name}*" )
@@ -336,7 +317,7 @@
 		* @param string $code the 2 letter iso 3166 code
 		* @return string the country name, empty string if invalid
 		*/
-		public static function get_full_name($selected)
+		function get_full_name($selected)
 		{
 			if ( isset(self::$country_array[$selected]) )
 			{
@@ -352,7 +333,7 @@
 		* @param string $select_name the name of the select box element in the form
 		* @return array list of continents
 		*/
-		public function xslt_continent_select($selected = '',$select_name='')
+		function xslt_continent_select($selected = '',$select_name='')
 		{
 			$GLOBALS['phpgw']->xslttpl->add_file('countries');
 
@@ -381,7 +362,7 @@
 		* @param string $select_name the name of the select box element in the form
 		* @return array list of countries
 		*/
-		public function xslt_country_select($selected = '', $select_name='')
+		function xslt_country_select($selected = '', $select_name='')
 		{
 			$GLOBALS['phpgw']->xslttpl->add_file('countries');
 
@@ -403,3 +384,4 @@
 			);
 		}
 	}
+?>

Modified: people/sigurdne/modules/phpgwapi/trunk/inc/class.crypto.inc.php
===================================================================
--- people/sigurdne/modules/phpgwapi/trunk/inc/class.crypto.inc.php	2009-11-20 10:27:41 UTC (rev 20844)
+++ people/sigurdne/modules/phpgwapi/trunk/inc/class.crypto.inc.php	2009-11-20 10:28:10 UTC (rev 20845)
@@ -7,21 +7,6 @@
 	* @package phpgwapi
 	* @subpackage network
 	* @version $Id$
-	*/
-
-	/*
-	   This program is free software: you can redistribute it and/or modify
-	   it under the terms of the GNU Lesser General Public License as published by
-	   the Free Software Foundation, either version 3 of the License, or
-	   (at your option) any later version.
-
-	   This program is distributed in the hope that it will be useful,
-	   but WITHOUT ANY WARRANTY; without even the implied warranty of
-	   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-	   GNU General Public License for more details.
-
-	   You should have received a copy of the GNU Lesser General Public License
-	   along with this program.  If not, see <http://www.gnu.org/licenses/>.
 	 */
 
 	/**
@@ -105,9 +90,9 @@
 
 		function cleanup()
 		{
-			if ($this->enabled)
+			if ($this->enabled && $this->td)
 			{
-				mcrypt_generic_deinit($this->td);
+				@mcrypt_generic_deinit($this->td);
 			}
 		}
 
@@ -117,7 +102,7 @@
 			return pack('H'.$len, $data);
 		}
 
-		function encrypt($data)
+		function encrypt($data, $bypass = false)
 		{
 			$_obj = false;
 			if($this->debug)
@@ -146,10 +131,13 @@
 				{
 					echo '<br>' . time() . ' crypto->encrypt() found "' . gettype($data) . '". No serialization...' . "\n";
 				}
+				//FIXME - Strings are not decrypted correctly
+				$data = serialize($data);
+				$_obj = true;
 			}
 
 			/* Disable all encryption if the admin didn't set it up */
-			if ($this->enabled)
+			if ($this->enabled && !$bypass)
 			{
 				if($_obj)
 				{
@@ -187,7 +175,7 @@
 			}
 		}
 
-		function decrypt($encrypteddata)
+		function decrypt($encrypteddata, $bypass = false)
 		{
 			if($this->debug)
 			{
@@ -201,7 +189,7 @@
 			}
 
 			/* Disable all encryption if the admin didn't set it up */
-			if ($this->enabled)
+			if ($this->enabled && !$bypass)
 			{
 				$data = $this->hex2bin($encrypteddata);
 				mcrypt_generic_init ($this->td, $this->key, $this->iv);
@@ -212,7 +200,7 @@
 					echo '<br>' . time() . ' crypto->decrypt() decrypted data: ---->>>>' . $data;
 				}
 				$test = stripslashes($data);
-				if(@unserialize($test))
+				if( $test )
 				{
 					if($this->debug)
 					{
@@ -234,7 +222,7 @@
 			}
 
 			$newdata = @unserialize($data);
-			if($newdata)
+			if($newdata || is_array($newdata)) // Check for empty array
 			{
 				if($this->debug)
 				{
@@ -254,4 +242,3 @@
 			}
 		}
 	} // class crypto
-?>

Modified: people/sigurdne/modules/phpgwapi/trunk/inc/class.css.inc.php
===================================================================
--- people/sigurdne/modules/phpgwapi/trunk/inc/class.css.inc.php	2009-11-20 10:27:41 UTC (rev 20844)
+++ people/sigurdne/modules/phpgwapi/trunk/inc/class.css.inc.php	2009-11-20 10:28:10 UTC (rev 20845)
@@ -8,21 +8,6 @@
 	* @version $Id:
 	*/
 
-	/*
-	   This program is free software: you can redistribute it and/or modify
-	   it under the terms of the GNU General Public License as published by
-	   the Free Software Foundation, either version 3 of the License, or
-	   (at your option) any later version.
-
-	   This program is distributed in the hope that it will be useful,
-	   but WITHOUT ANY WARRANTY; without even the implied warranty of
-	   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-	   GNU General Public License for more details.
-
-	   You should have received a copy of the GNU General Public License
-	   along with this program.  If not, see <http://www.gnu.org/licenses/>.
-	 */
-
 	/**
  	* phpGroupWare css support class
 	*

Modified: people/sigurdne/modules/phpgwapi/trunk/inc/class.csstooltip.inc.php
===================================================================
--- people/sigurdne/modules/phpgwapi/trunk/inc/class.csstooltip.inc.php	2009-11-20 10:27:41 UTC (rev 20844)
+++ people/sigurdne/modules/phpgwapi/trunk/inc/class.csstooltip.inc.php	2009-11-20 10:28:10 UTC (rev 20845)
@@ -15,21 +15,6 @@
 	* @package phpgwapi
 	* @subpackage gui
 	* @version $Id$
-	*/
-
-	/*
-	   This program is free software: you can redistribute it and/or modify
-	   it under the terms of the GNU General Public License as published by
-	   the Free Software Foundation, either version 3 of the License, or
-	   (at your option) any later version.
-
-	   This program is distributed in the hope that it will be useful,
-	   but WITHOUT ANY WARRANTY; without even the implied warranty of
-	   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-	   GNU General Public License for more details.
-
-	   You should have received a copy of the GNU General Public License
-	   along with this program.  If not, see <http://www.gnu.org/licenses/>.
 	 */
 	
 	/**

Modified: people/sigurdne/modules/phpgwapi/trunk/inc/class.custom_fields.inc.php
===================================================================
--- people/sigurdne/modules/phpgwapi/trunk/inc/class.custom_fields.inc.php	2009-11-20 10:27:41 UTC (rev 20844)
+++ people/sigurdne/modules/phpgwapi/trunk/inc/class.custom_fields.inc.php	2009-11-20 10:28:10 UTC (rev 20845)
@@ -5,116 +5,99 @@
 	* @author Sigurd Nes <[email protected]>
 	* @author Dave Hall dave.hall at skwashd.com
 	* @copyright Copyright (C) 2003-2006 Free Software Foundation http://www.fsf.org/
-	* @license http://www.gnu.org/licenses/gpl.html GNU General Public License
+	 * @license http://www.gnu.org/licenses/gpl.html GNU General Public License v2 or later
 	* @internal Development of this application was funded by http://www.bergen.kommune.no/bbb_/ekstern/
-	* @package phpgwapi
-	* @version $Id$
+	 * @package phpgroupware
+	 * @subpackage phpgwapi
+	 * @version $Id$
 	*/
 
 	/*
 	   This program is free software: you can redistribute it and/or modify
 	   it under the terms of the GNU General Public License as published by
-	   the Free Software Foundation, either version 3 of the License, or
+	   the Free Software Foundation, either version 2 of the License, or
 	   (at your option) any later version.
 
 	   This program is distributed in the hope that it will be useful,
 	   but WITHOUT ANY WARRANTY; without even the implied warranty of
 	   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-	   GNU General Public License for more details.
+	   GNU Lesser General Public License for more details.
 
 	   You should have received a copy of the GNU General Public License
 	   along with this program.  If not, see <http://www.gnu.org/licenses/>.
 	 */
 
+	/*
+	 * Import the datetime class for date processing
+	 */
+	phpgw::import_class('phpgwapi.datetime');
+
 	/**
 	 * Custom Fields
-	 * @package phpgwapi
+	 *
+	 * @package phpgroupware
+	 * @subpackage phpgwapi
 	 */
-	class custom_fields
+	class phpgwapi_custom_fields
 	{
+		
 		/**
-		 * @var string $appname the name of the current application
+		* @var array $receipt messages from the prosessing of functions
 		 */
-		var $appname;
+		public $receipt = array();
 		
 		/**
-		 * @var array $grants the various rights for this current location
+		* @var array $datatype_text the translated end user field types
 		 */
-		var $grants;
+		public $datatype_text = array();
 		
 		/**
-		 * @var string $location the name of the current location
+		 * @var string $_appname the name of the current application
 		 */
-		var $location;
+		protected $_appname;
 
-
 		/**
-		 * @var array $public_functions the publicly available methods of this class
-		 * @internal TODO remove most of these as it is an api bo+so class 
+		 * @var object $_db reference to the global database object
 		 */
-		var $public_functions = array
-		(
-			'check_perms'		=> true,
-			'delete'			=> true,
-			'read'				=> true,
-			'read_single'		=> true,
-			'save'				=> true
-		);
+		protected $_db;
 
 		/**
-		* @var int $total_records total number of records found
+		 * @var string $_join SQL JOIN statement
 		*/
-		var $total_records = 0;
+		protected $_join;
 
-		var $soap_functions = array(
-			'list' => array(
-				'in'  => array('int','int','struct','string','int'),
-				'out' => array('array')
-			),
-			'read' => array(
-				'in'  => array('int','struct'),
-				'out' => array('array')
-			),
-			'save' => array(
-				'in'  => array('int','struct'),
-				'out' => array()
-			),
-			'delete' => array(
-				'in'  => array('int','struct'),
-				'out' => array()
-			)
-		);
+		/**
+		 * @var string $_like SQL LIKE statement
+		 */
+		protected $_like;
 
 		/**
-		* @var array $datatype_text the translated end user field types
+		* @var int $_total_records total number of records found
 		*/
-		var $datatype_text = array();
+		protected $_total_records = 0;
 
 		/**
 		 * Constructor
+		 *
+		 * @param string $appname the name of the module using the custom fields
+		 *
+		 * @return void
 		 */
-		function custom_fields($appname='', $location='')
+		public function __construct($appname = null)
 		{
-			$this->appname = $appname;
-			if ( strlen($this->appname) == 0 )
+			$this->_appname = $appname;
+			if ( is_null($this->_appname) )
 			{
-				$this->appname =& $GLOBALS['phpgw_info']['flags']['currentapp'];
+				$this->_appname =& $GLOBALS['phpgw_info']['flags']['currentapp'];
 			}
 			
-			$this->location = $location;
-		
-			$this->account		= $GLOBALS['phpgw_info']['user']['account_id'];
-			$this->db           =& $GLOBALS['phpgw']->db; // clone to avoid conflict the db in lang-function
-			$this->join			= $this->db->join;
-			$this->like			= $this->db->like;
-			$this->dateformat 		= phpgwapi_db::date_format();
-			$this->datetimeformat 	= phpgwapi_db::datetime_format();
+			$this->_db           	=& $GLOBALS['phpgw']->db;
+			$this->_join			=& $this->_db->join;
+			$this->_like			=& $this->_db->like;
+			$this->_dateformat 		= phpgwapi_db::date_format();
+			$this->_datetimeformat 	= phpgwapi_db::datetime_format();
+			$this->_db->Halt_On_Error = 'yes';
 
-			if($this->appname && $this->location)
-			{
-				$this->category_name	= $this->read_category_name($this->appname, $this->location);
-			}
-
 			$this->datatype_text = array
 			(
 				'V'		=> lang('Varchar'),
@@ -129,263 +112,542 @@
 				'AB'	=> lang('Contact'),
 				'VENDOR'=> lang('Vendor'),
 				'email'	=> lang('Email'),
-				'link'	=> lang('Link')
+				'link'	=> lang('Link'),
+				'pwd' 	=> lang('password'),
+				'user' 	=> 'phpgw_user',
+				'event'	=> lang('event')
 			);
+
+			$this->_oProc			= createObject('phpgwapi.schema_proc', $GLOBALS['phpgw_info']['server']['db_type']);
+			$this->_oProc->m_odb	=& $this->_db;
 		}
 
 		/**
-		 * Add a custom field/attribute
+		 * Magic get method
+		 *
+		 * @param string $varname the variable to fetch
+		 *
+		 * @return mixed the value of the variable sought - null if not found
+		 */
+		public function __get($varname)
+		{
+			if ( $varname == 'total_records' )
+			{
+				return $this->_total_records;
+			}
+
+			return null;
+		}
+
+		/**
+		 * Add a group for custom fields/attributes
 		 * 
 		 * @param array $attrib the field data
-		 * @param string $attrib_table where to append the attrib
-		 * @param bool $doubled sometimes the attribute fits into a history-table as a double
+		 *
 		 * @return int the the new custom field db pk
 		 */
-		function add_attrib($attrib, $attrib_table = '', $doubled = false)
+		public function add_group($group)
 		{
 			$receipt = array();
-			// Checkboxes are only present if ticked, so we declare them here to stop errors
-			$attrib['search'] = isset($attrib['search']) ? !!$attrib['search'] : false;
-			$attrib['list'] = isset($attrib['list']) ? !!$attrib['list'] : false;
-			$attrib['history'] = isset($attrib['history']) ? !!$attrib['history'] : false;
 
-			$attrib['column_name'] = $this->db->db_addslashes(strtolower($attrib['column_name']));
-			$attrib['input_text'] = $this->db->db_addslashes($attrib['input_text']);
-			$attrib['statustext'] = $this->db->db_addslashes($attrib['statustext']);
-			$attrib['default'] =  isset($arrib['default']) ? $this->db->db_addslashes($attrib['default']) : '';
-			$attrib['helpmsg'] = $this->db->db_addslashes($attrib['helpmsg']);
+			$appname	= $group['appname'];
+			$location	= $group['location'];
 
-			$sql = "SELECT * FROM phpgw_cust_attribute where appname='{$attrib['appname']}' AND location='{$attrib['location']}' AND column_name = '{$attrib['column_name']}'";
-			$this->db->query($sql,__LINE__,__FILE__);
-			if ( $this->db->next_record() && !$doubled)
+			// don't continue if the location is invalid
+			$location_id = $GLOBALS['phpgw']->locations->get_id($appname, $location);
+			if ( !$location_id )
 			{
-				$receipt['id'] = 0;
-				$receipt['error'] = array();
-				$receipt['error'][] = array('msg' => lang('field already exists, please choose another name'));
-				$receipt['error'][] = array('msg'	=> lang('Attribute has NOT been saved'));
-				return $receipt; //no point continuing
+				return 0;
 			}
 
+			$values = array
+			(
+				'location_id'	=> $location_id,
+				'id'			=> 0,
+				'name'	=> $this->_db->db_addslashes(strtolower($group['group_name'])),
+				'descr'	=> $this->_db->db_addslashes($group['descr']),
+				'remark'	=> $this->_db->db_addslashes($group['remark']),
+				'group_sort'	=> 0,
+			);
 
 
-			$sql = 'SELECT MAX(attrib_sort) AS max_sort, MAX(id) AS current_id FROM phpgw_cust_attribute'
-					. " WHERE appname='{$attrib['appname']}' AND location='{$attrib['location']}'";
-			$this->db->query($sql,__LINE__,__FILE__);
-			$this->db->next_record();
-			$attrib_sort	= $this->db->f('max_sort')+1;
-			$attrib['id']	= $this->db->f('current_id')+1;		
+			unset($group);
+
+			$this->_db->transaction_begin();
 			
-			if($attrib['column_info']['type']=='R' || $attrib['column_info']['type']== 'CH' || $attrib['column_info']['type'] =='LB' || $attrib['column_info']['type'] =='AB' || $attrib['column_info']['type'] =='VENDOR')
+			$sql = "SELECT id FROM phpgw_cust_attribute_group"
+				. " WHERE location_id = {$values['location_id']}"
+					. " AND name = '{$values['name']}'";
+			$this->_db->query($sql, __LINE__, __FILE__);
+			if ( $this->_db->next_record() )
 			{
-				if ( $attrib['history'] )
+				return -1;
+			}
+
+			$sql = 'SELECT MAX(group_sort) AS max_sort, MAX(id) AS current_id'
+				. ' FROM phpgw_cust_attribute_group '
+				. " WHERE location_id ='{$values['location_id']}'";
+			$this->_db->query($sql, __LINE__, __FILE__);
+			$this->_db->next_record();
+			$values['group_sort']	= $this->_db->f('max_sort') + 1;
+			$values['id']	= $this->_db->f('current_id') + 1;		
+			
+			$cols = implode(', ', array_keys($values));
+			$vals = $this->_db->validate_insert($values);
+
+			$sql = "INSERT INTO phpgw_cust_attribute_group({$cols}) VALUES({$vals})";
+			$this->_db->query($sql, __LINE__, __FILE__);
+
+			unset($cols, $vals);
+
+			$receipt['id'] = $values['id'];
+
+			if ( $this->_db->transaction_commit() )
 				{
-					$receipt['error'][] = array('msg'	=> lang('History not allowed for this datatype'));
+				return $values['id'];
 				}
 
-				$attrib['history'] = false;
+			return 0;
+		}
+		/**
+		 * Add a custom field/attribute
+		 * 
+		 * @param array $attrib the field data
+		 * @param string $attrib_table where to append the attrib
+		 * @param bool $doubled sometimes the attribute fits into a history-table as a double
+		 *
+		 * @return int the the new custom field db pk
+		 */
+		public function add($attrib, $attrib_table = null, $doubled = false)
+		{
+			$receipt = array();
+
+			$appname	= $attrib['appname'];
+			$location	= $attrib['location'];
+
+			// don't continue if the location is invalid
+			$location_id = $GLOBALS['phpgw']->locations->get_id($appname, $location);
+			if ( !$location_id )
+			{
+				return 0;
 			}
 
-			$values= array
+			if ( is_null($attrib_table) )
+			{
+				$attrib_table = $GLOBALS['phpgw']->locations->get_attrib_table($appname, $location);
+			}
+
+			// Need a table to operate on
+			if ( !$attrib_table )
+			{
+				return -1;
+			}
+
+			$values = array
 			(
-				$attrib['appname'],
-				$attrib['location'],
-				$attrib['id'],
-				$attrib['column_name'],
-				$attrib['input_text'],
-				$attrib['statustext'],
-				$attrib['search'],
-				$attrib['list'],
-				$attrib['history'],
-				$attrib['disabled'],
-				$attrib['helpmsg'],
-				$attrib_sort,
-				$attrib['column_info']['type'],
-				$attrib['column_info']['precision'],
-				$attrib['column_info']['scale'],
-				$attrib['column_info']['default'],
-				$attrib['column_info']['nullable']
+				'location_id'	=> $location_id,
+				'id'			=> 0,
+				'column_name'	=> $this->_db->db_addslashes(strtolower($attrib['column_name'])),
+				'input_text'	=> $this->_db->db_addslashes($attrib['input_text']),
+				'statustext'	=> $this->_db->db_addslashes($attrib['statustext']),
+				'search'		=> false,
+				'list'			=> false,
+				'history'		=> false,
+				'lookup_form'	=> false,
+				'disabled'		=> false,
+				'helpmsg'		=> $this->_db->db_addslashes($attrib['helpmsg']),
+				'group_id'		=> (int) $attrib['group_id'],
+				'attrib_sort'	=> 0,
+				'datatype'		=> $this->_db->db_addslashes($attrib['column_info']['type']),
+				'precision_'	=> (int) $attrib['column_info']['precision'],
+				'scale'			=> (int) $attrib['column_info']['scale'],
+				'default_value'	=> '',
+				'nullable'		=> $attrib['column_info']['nullable']
 			);
 
-			$values	= $this->db->validate_insert($values);
+			if ( isset($attrib['search']) )
+			{
+				$values['search'] = !!$attrib['search'];
+			}
 
-			$this->_init_process();
+			if ( isset($attrib['list']) )
+			{
+				$values['list'] = !!$attrib['list'];
+			}
 
-			$this->db->transaction_begin();
+			if ( isset($attrib['history']) )
+			{
+				$values['history'] = !!$attrib['history'];
+			}
 
-			if(!$doubled)
+			if ( isset($attrib['lookup_form']) )
 			{
-				$this->db->query("INSERT INTO phpgw_cust_attribute (appname,location,id,column_name, input_text, statustext,search,list,history,disabled,helpmsg,attrib_sort, datatype,precision_,scale,default_value,nullable) "
-					. "VALUES ($values)",__LINE__,__FILE__);
+				$values['lookup_form'] = !!$attrib['lookup_form'];
 			}
 
-			$receipt['id']= $attrib['id'];
+			if ( isset($attrib['disabled']) )
+			{
+				$values['disabled'] = !!$attrib['disabled'];
+			}
 
-			if(!$attrib['column_info']['precision'])
+			if ( isset($attrib['column_info']['default']) )
 			{
-				if($precision = $this->translate_datatype_precision($attrib['column_info']['type']))
+				$values['default_value'] = $this->_db->db_addslashes($attrib['column_info']['default']);
+			}
+
+			switch ( $values['datatype'] )
+			{
+				case 'R':
+				case 'CH':
+				case 'LB':
+				case 'AB':
+				case 'VENDOR':
+				case 'event':
+					if ( $attrib['history'] )
 				{
-					$attrib['column_info']['precision']=$precision;
+						$receipt['error'][] = array('msg' => lang('History not allowed for this datatype'));
 				}
+					$values['history'] = false;
+					break;
+
+				default: // all is good
 			}
 
-			$attrib['column_info']['type']  = $this->translate_datatype_insert($attrib['column_info']['type']);
+			unset($attrib);
 
-			if(!$attrib['column_info']['default'])
+			$this->_db->transaction_begin();
+
+			$sql = "SELECT id FROM phpgw_cust_attribute"
+				. " WHERE location_id = {$values['location_id']}"
+					. " AND column_name = '{$values['column_name']}'";
+			$this->_db->query($sql, __LINE__, __FILE__);
+			if ( $this->_db->next_record() && !$doubled)
 			{
-				unset($attrib['column_info']['default']);
+				return -2;
 			}
 
-			if(!$attrib_table)
+
+			if ( !$doubled )
 			{
-			$attrib_table = $this->get_attrib_table($attrib['appname'],$attrib['location']);
+				$sql = 'SELECT MAX(id) AS current_id'
+					. ' FROM phpgw_cust_attribute '
+					. " WHERE location_id ='{$values['location_id']}'";
+				$this->_db->query($sql, __LINE__, __FILE__);
+				$this->_db->next_record();
+				$values['id']	= $this->_db->f('current_id') + 1;		
+
+				$sql = 'SELECT MAX(attrib_sort) AS max_sort'
+					. ' FROM phpgw_cust_attribute '
+					. " WHERE location_id ='{$values['location_id']}' AND group_id = {$values['group_id']}";
+				$this->_db->query($sql, __LINE__, __FILE__);
+				$this->_db->next_record();
+				$values['attrib_sort']	= $this->_db->f('max_sort') + 1;
+			
+				$cols = implode(', ', array_keys($values));
+				$vals = $this->_db->validate_insert($values);
+
+				$sql = "INSERT INTO phpgw_cust_attribute({$cols}) VALUES({$vals})";
+				$this->_db->query($sql, __LINE__, __FILE__);
 			}
 
-			$this->oProc->m_odb->transaction_begin();
+			unset($cols, $vals);
 
-			$this->oProc->AddColumn($attrib_table,$attrib['column_name'], $attrib['column_info']);
+			$receipt['id'] = $values['id'];
 			
-			if($this->oProc->m_odb->transaction_commit())
+			if ( !$values['precision_'] > 0)
 			{
-				$receipt['message'][] = array('msg'	=> lang('Attribute has been saved')	);
-				$this->db->transaction_commit();
+				$precision = $this->_translate_datatype_precision($values['datatype']);
+				if ( $precision )
+			{
+					$values['precision_'] = $precision;
 			}
-			else
+			}
+
+			$col_info = array
+			(
+				'type'		=> $this->_translate_datatype_insert($values['datatype']),
+				'precision'	=> (int) $values['precision_'],
+				'scale'		=> (int) $values['scale'],
+				'default'	=> $values['default_value'],
+				'nullable'	=> $values['nullable']
+			);
+
+			if ( !$col_info['default'] )
 			{
-				$receipt['error'][] = array('msg'	=> lang('column could not be added')	);
-				if($this->db->Transaction)
+				if(!is_numeric($col_info['default']) )
 				{
-					$this->db->transaction_abort();
+					unset($col_info['default']);
 				}
-				else
-				{
-					$this->db->query("DELETE FROM phpgw_cust_attribute WHERE appname='" . $attrib['appname']. "' AND location='" . $attrib['id']. "' AND id='" . $receipt['id'] . "'",__LINE__,__FILE__);
-					unset($receipt['id']);
+				}
 
-				}
+			$this->_oProc->AddColumn($attrib_table, $values['column_name'], $col_info);
+
+			if ( $this->_db->transaction_commit() )
+			{
+				return $values['id'];
 			}
 
-			return $receipt;
+			return 0;
 		}
 
 		/**
-		 * Add a custom function
+		 * Prepare an attribute value so it can be saved in the database
 		 * 
-		 * @internal get more info from sigud so this can be documented - skwashd Apr2006
+		 * @param array $values_attribute an attribute structure
+		 *
+		 * @return array the structure with the value prepared
+		 *
+		 * @internal the name of this method is misleading
 		 */
-		function add_custom_function($custom_function)
+		public function convert_attribute_save($values_attribute = null)
 		{
-			if(!$custom_function['location'] || !$custom_function['appname'])
+			if ( !is_array($values_attribute) )
 			{
-				return 	$receipt['error'][] = array('msg' => lang('location or appname is missing'));
+				return '';
 			}
-			else
+
+			foreach ( $values_attribute as &$attrib )
 			{
-				$location = $custom_function['location'];
-				$appname = $custom_function['appname'];
+				if ( !$attrib['value'] )
+				{
+					continue;
 			}
 
-			$custom_function['descr'] = $this->db->db_addslashes($custom_function['descr']);
+				switch ( $attrib['datatype'] )
+				{
+					case 'CH':
+						$attrib['value'] = serialize($attrib['value']);
+						break;
 
-			$this->db->transaction_begin();
-			$this->db->query("SELECT max(id) as maximum FROM phpgw_cust_function WHERE appname='$appname' AND location='$location'",__LINE__,__FILE__);
-			$this->db->next_record();
-			$custom_function['id'] = $this->db->f('maximum')+1;
+					case 'R':
+						$attrib['value'] = $attrib['value'][0];
+						break;
 
-			$sql = "SELECT max(custom_sort) as max_sort FROM phpgw_cust_function where appname='$appname' AND location='$location'";
-			$this->db->query($sql,__LINE__,__FILE__);
-			$this->db->next_record();
-			$custom_sort	= $this->db->f('max_sort')+1;
+					case 'N':
+						$attrib['value'] = str_replace(',', '.', $attrib['value']);
+						break;
 
-			$values= array
-			(
-				$appname,
-				$location,
-				$custom_function['id'],
-				$custom_function['custom_function_file'],
-				$custom_function['descr'],
-				$custom_function['active'],
-				$custom_sort
-			);
+					case 'D':
+						$ts = phpgwapi_datetime::date_to_timestamp($attrib['value']);
+						$attrib['value'] = date($this->_dateformat, $ts);
+						break;
+				}
+			}
+			return $values_attribute;
+		}
 
-			$values	= $this->db->validate_insert($values);
+		/**
+		 * Delete a custom field/attribute group
+		 * 
+		 * @param string $location within an application
+		 * @param string $appname where to delete the attrib
+		 * @param integer $group_id id of attrib to delete
+		 *
+		 * @return boolean was the record deleted?
+		 */
+		public function delete_group($appname, $location, $group_id)
+		{
+			$loc_id		= $GLOBALS['phpgw']->locations->get_id($appname, $location);
+			$group_id	= (int) $group_id;
 
-			$this->db->query("INSERT INTO phpgw_cust_function (appname,location, id, file_name, descr, active, custom_sort) "
-				. "VALUES ($values)",__LINE__,__FILE__);
+			$this->_db->transaction_begin();
 
-			$receipt['id']= $custom_function['id'];
+			$sql = "SELECT name FROM phpgw_cust_attribute_group"
+				. " WHERE location_id = {$loc_id} AND id = {$group_id}";
+			$this->_db->query($sql, __LINE__, __FILE__);
+			if ( !$this->_db->next_record() )
+			{
+				$this->_db->transaction_abort();
+				return false;
+			}
 
-			$this->db->transaction_commit();
+			$sql = "SELECT MAX(attrib_sort) AS max_sort"
+				. " FROM phpgw_cust_attribute WHERE location_id = {$loc_id} AND group_id = 0";
+			$this->_db->query($sql, __LINE__, __FILE__);
+			$this->_db->next_record();
+			$max_sort	= (int) $this->_db->f('max_sort');
 
-			return $receipt;
+			$sql = "UPDATE phpgw_cust_attribute SET attrib_sort = attrib_sort + {$max_sort}, group_id = 0"
+					. " WHERE location_id = {$loc_id} AND group_id = {$group_id}";
+			$this->_db->query($sql, __LINE__, __FILE__);
+
+			$sql = "DELETE FROM phpgw_cust_attribute_group"
+					. " WHERE location_id = {$loc_id} AND id = {$group_id}";
+			$this->_db->query($sql, __LINE__,__FILE__);
+
+			return $this->_db->transaction_commit();
 		}
-
 		/**
-		 * Delete a custom attribute or custom function
+		 * Delete a custom field/attribute
 		 * 
-		 * @param string $location the location
-		 * @param string $appname the application name
-		 * @param int $attrib_id the db pk for the attribute to delete
-		 * @param int $function_id the db pk of the function to delete
+		 * @param string $location within an application
+		 * @param string $appname where to delete the attrib
+		 * @param integer $attrib_id id of attrib to delete
+		 * @param bool $doubled sometimes the attribute fits into a history-table as a double
+		 * 
+		 * @return boolean was the record deleted?
 		 */
-		function delete($location, $appname, $attrib_id=0,$function_id=0)
+		public function delete($appname, $location, $attrib_id, $table = '',$doubled = false )
 		{
-			if($attrib_id && $location && $appname && !$function_id):
+			$loc_id		= $GLOBALS['phpgw']->locations->get_id($appname, $location);
+			$attrib_id	= (int) $attrib_id;
+
+			if(!$table)
+		{
+				$table	= $GLOBALS['phpgw']->locations->get_attrib_table($appname, $location);
+			}
+
+			$this->_db->transaction_begin();
+
+			$sql = "SELECT column_name FROM phpgw_cust_attribute"
+				. " WHERE location_id = {$loc_id} AND id = {$attrib_id}";
+			$this->_db->query($sql, __LINE__, __FILE__);
+			if ( !$this->_db->next_record() )
 			{
-				$this->_delete_attrib($location,$appname,$attrib_id);
+				$this->_db->transaction_abort();
+				return false;
 			}
-			elseif($function_id && $appname && $location):
+
+			$column_name = $this->_db->f('column_name');
+
+			$this->_oProc->DropColumn($table, false, $column_name);
+
+			if(!$doubled) // else: wait for it - another one is coming
 			{
-				$this->_delete_custom_function($appname,$location,$function_id);
+				$sql = "SELECT group_id FROM phpgw_cust_attribute " 
+					. " WHERE location_id = {$loc_id} AND id = {$attrib_id}";
+				$this->_db->query($sql, __LINE__, __FILE__);
+				$this->_db->next_record();
+				$group_id	= (int) $this->_db->f('group_id');
+
+				$sql = "SELECT attrib_sort FROM phpgw_cust_attribute"
+					. " WHERE location_id = {$loc_id} AND id = {$attrib_id} AND group_id = {$group_id}";
+				$this->_db->query($sql,__LINE__,__FILE__);
+				$this->_db->next_record();
+				$attrib_sort	= $this->_db->f('attrib_sort');
+
+				$sql = "SELECT MAX(attrib_sort) AS max_sort"
+					. " FROM phpgw_cust_attribute WHERE location_id = {$loc_id} AND group_id = {$group_id}";
+				$this->_db->query($sql, __LINE__, __FILE__);
+				$this->_db->next_record();
+				$max_sort	= $this->_db->f('max_sort');
+			
+				if ( $max_sort > $attrib_sort )
+			{
+					$sql = "UPDATE phpgw_cust_attribute SET attrib_sort = attrib_sort - 1"
+						. " WHERE location_id = {$loc_id} AND attrib_sort > {$attrib_sort} AND group_id = {$group_id}";
+					$this->_db->query($sql, __LINE__, __FILE__);
+				}
+				$sql = "DELETE FROM phpgw_cust_attribute"
+						. " WHERE location_id = {$loc_id} AND id = {$attrib_id}";
+				$this->_db->query($sql, __LINE__,__FILE__);
 			}
-			endif;
+			return $this->_db->transaction_commit();
 		}
+
+		/**
+		 * Edit a group for custom fields
+		 * 
+		 * @param array  $group  the field data
+		 *
+		 * @return integer the database id of the group
+		 */
+		function edit_group($group)
+		{
+
+			$location_id	= $GLOBALS['phpgw']->locations->get_id($group['appname'], $group['location']);
+			$group_id		= (int) $group['id'];
+
+			$this->_db->transaction_begin();
+
+			$value_set = array
+			(
+				'name'		=> $this->_db->db_addslashes($group['group_name']),
+				'descr'		=> $this->_db->db_addslashes($group['descr']),
+				'remark'	=> $this->_db->db_addslashes($group['remark'])
+			);
+
+			$value_set	= $this->_db->validate_update($value_set);
+
+			$this->_db->query("UPDATE phpgw_cust_attribute_group SET $value_set WHERE location_id = {$location_id} AND id=" . $group_id,__LINE__,__FILE__);
+
+			if ( $this->_db->transaction_commit() )
+			{
+				return $group_id;
+		}
 		
+			return false;
+		}
 		/**
 		 * Edit a custom field
 		 * 
 		 * @param array $attrib the field data
-		 * @param string $attrib_table where to edit the attrib
-		 * @return int the field db pk
+		 * @param string $attrib_table which table the attribute is part of
+		 * @param bool $doubled sometimes the attribute fits into a history-table as a double
+		 *
+		 * @return integer the database id of the attribute
 		 */
-		function edit_attrib($attrib, $attrib_table = '')
+		function edit($attrib, $attrib_table = '', $doubled = false)
 		{
 			// Checkboxes are only present if ticked, so we declare them here to stop errors
 			$attrib['search'] = isset($attrib['search']) ? !!$attrib['search'] : false;
 			$attrib['list'] = isset($attrib['list']) ? !!$attrib['list'] : false;
 			$attrib['history'] = isset($attrib['history']) ? !!$attrib['history'] : false;
+			$attrib['lookup_form'] = isset($attrib['lookup_form']) ? !!$attrib['lookup_form'] : false;
+			$attrib['group_id']		= (int) $attrib['group_id'];
 			
 			if(!$attrib_table)
 			{
-			$attrib_table = $this->get_attrib_table($attrib['appname'],$attrib['location']);
+				$attrib_table = $GLOBALS['phpgw']->locations->get_attrib_table($attrib['appname'],$attrib['location']);
 			}
-			$choice_table = 'phpgw_cust_choice';
 
-			$attrib['column_name'] = $this->db->db_addslashes($attrib['column_name']);
-			$attrib['input_text'] = $this->db->db_addslashes($attrib['input_text']);
-			$attrib['statustext'] = $this->db->db_addslashes($attrib['statustext']);
-			$attrib['helpmsg'] = $this->db->db_addslashes($attrib['helpmsg']);
-			$attrib['column_info']['default'] = $this->db->db_addslashes($attrib['column_info']['default']);
+			$location_id	= $GLOBALS['phpgw']->locations->get_id($attrib['appname'], $attrib['location']);
+			$attrib_id		= (int) $attrib['id'];
 
-			if($attrib['column_info']['type']=='R' || $attrib['column_info']['type']== 'CH' || $attrib['column_info']['type'] =='LB' || $attrib['column_info']['type'] =='AB' || $attrib['column_info']['type'] =='VENDOR')
+			$attrib['column_name'] = $this->_db->db_addslashes(strtolower($attrib['column_name']));
+			$attrib['input_text'] = $this->_db->db_addslashes($attrib['input_text']);
+			$attrib['statustext'] = $this->_db->db_addslashes($attrib['statustext']);
+			$attrib['helpmsg'] = $this->_db->db_addslashes($attrib['helpmsg']);
+			$attrib['column_info']['default'] = $this->_db->db_addslashes($attrib['column_info']['default']);
+
+			switch ($attrib['column_info']['type'] )
 			{
-				if ($attrib['history'])
+				case 'R':
+				case 'CH':
+				case 'LB':
+				case 'AB':
+				case 'VENDOR':
+				case 'event':
+					if ( $attrib['history'] )
 				{
-					$receipt['error'][] = array('msg'	=> lang('History not allowed for this datatype'));
+						$this->receipt['error'][] = array('msg'	=> lang('History not allowed for this datatype'));
 				}
-				
 				$attrib['history'] = false;
+					break;
+
+				default: // all is good
 			}
 
-			$this->db->query("SELECT column_name, datatype,precision_ FROM phpgw_cust_attribute WHERE appname='" . $attrib['appname']. "' AND location='" . $attrib['location']. "' AND id='" . $attrib['id']. "'",__LINE__,__FILE__);
-			$this->db->next_record();
-			$OldColumnName		= $this->db->f('column_name');
-			$OldDataType		= $this->db->f('datatype');
-			$OldPrecision		= $this->db->f('precision_');			
+			$sql = "SELECT column_name, datatype, precision_, group_id FROM phpgw_cust_attribute " 
+				. " WHERE location_id  = {$location_id} AND id = {$attrib_id}";
+			$this->_db->query($sql, __LINE__, __FILE__);
+			if ( !$this->_db->next_record() )
+			{
+				// doesn't exist so we can't edit it
+				return false;
+			}
+
+			$OldColumnName		= $this->_db->f('column_name');
+			$OldDataType		= $this->_db->f('datatype');
+			$OldPrecision		= $this->_db->f('precision_');
+			$OldGroup			= (int) $this->_db->f('group_id');			
 			
 			$table_def = $this->get_table_def($attrib_table);	
 
-			$this->db->transaction_begin();
+			$this->_db->transaction_begin();
 
+			if( !$doubled )
+			{
 			$value_set = array
 			(
 				'input_text'	=> $attrib['input_text'],
@@ -396,37 +658,85 @@
 				'nullable'		=> $attrib['column_info']['nullable'] == 'False' ? 'False' : 'True',
 				'disabled'		=> isset($attrib['disabled']) ? $attrib['disabled'] : '',
 				'helpmsg'		=> $attrib['helpmsg'],
+					'lookup_form'	=> isset($attrib['lookup_form']) ? $attrib['lookup_form'] : '',
+					'group_id'		=> $attrib['group_id']
 			);
 
-			$value_set	= $this->db->validate_update($value_set);
+				if($OldGroup != $attrib['group_id'])
+				{
+					$sql = "SELECT MAX(attrib_sort) AS max_sort FROM phpgw_cust_attribute " 
+						. " WHERE location_id = {$location_id} AND group_id = {$attrib['group_id']}";
+					$this->_db->query($sql,__LINE__,__FILE__);
+					$this->_db->next_record();
+					$max_sort	= $this->_db->f('max_sort');
+					
+					$value_set['attrib_sort'] = $max_sort + 1;
 
-			$this->db->query("UPDATE phpgw_cust_attribute set $value_set WHERE appname='" . $attrib['appname']. "' AND location='" . $attrib['location']. "' AND id=" . $attrib['id'],__LINE__,__FILE__);
 
-			$this->oProc->m_odb->transaction_begin();
+					$sql = "SELECT attrib_sort FROM phpgw_cust_attribute"
+						. " WHERE location_id = {$location_id} AND id = {$attrib_id} AND group_id = {$OldGroup}";
+					$this->_db->query($sql,__LINE__,__FILE__);
+					$this->_db->next_record();
+					$attrib_sort	= $this->_db->f('attrib_sort');
 
-			$this->oProc->m_aTables = $table_def;
+					$sql = "SELECT MAX(attrib_sort) AS max_sort"
+						. " FROM phpgw_cust_attribute WHERE location_id = {$location_id} AND group_id = {$OldGroup}";
+					$this->_db->query($sql, __LINE__, __FILE__);
+					$this->_db->next_record();
+					$max_sort	= $this->_db->f('max_sort');
 
+					if ( $max_sort > $attrib_sort )
+					{
+						$sql = "UPDATE phpgw_cust_attribute SET attrib_sort = attrib_sort - 1"
+							. " WHERE location_id = {$location_id} AND attrib_sort > {$attrib_sort} AND group_id = {$OldGroup}";
+						$this->_db->query($sql, __LINE__, __FILE__);
+					}
+				}
+
+				$value_set	= $this->_db->validate_update($value_set);
+
+				$this->_db->query("UPDATE phpgw_cust_attribute set $value_set WHERE location_id = {$location_id} AND id=" . $attrib_id,__LINE__,__FILE__);
+
+			}
+
+			$this->_oProc->m_aTables = $table_def;
+
 			if($OldColumnName !=$attrib['column_name'])
 			{
 				$value_set=array('column_name'	=> $attrib['column_name']);
 
-				$value_set	= $this->db->validate_update($value_set);
+				if( !$doubled )
+				{
+					$value_set	= $this->_db->validate_update($value_set);
+					$this->_db->query("UPDATE phpgw_cust_attribute set $value_set WHERE location_id = {$location_id} AND id=" . $attrib_id,__LINE__,__FILE__);
+				}
 
-				$this->db->query("UPDATE phpgw_cust_attribute set $value_set WHERE appname='" . $attrib['appname']. "' AND location='" . $attrib['location']. "' AND id=" . $attrib['id'],__LINE__,__FILE__);
-
-				$this->oProc->RenameColumn($attrib_table, $OldColumnName, $attrib['column_name']);
+				$this->_oProc->RenameColumn($attrib_table, $OldColumnName, $attrib['column_name']);
 			}
 
-			if (($OldDataType != $attrib['column_info']['type']) || ($OldPrecision != $attrib['column_info']['precision']) )
+			if (($OldDataType != $attrib['column_info']['type'])
+				|| ($OldPrecision != $attrib['column_info']['precision']) )
 			{
-				if($attrib['column_info']['type']!='R' && $attrib['column_info']['type']!='CH' && $attrib['column_info']['type']!='LB')
+				if( !$doubled )
 				{
-					$this->db->query("DELETE FROM $choice_table WHERE appname='" . $attrib['appname']. "' AND location='" . $attrib['location']. "' AND attrib_id=" . $attrib['id'],__LINE__,__FILE__);
+					switch ( $attrib['column_info']['type'] )
+					{
+						default:
+							$sql = "DELETE FROM phpgw_cust_choice"
+							. " WHERE location_id = {$location_id}"
+							. " AND attrib_id = {$attrib_id}";
+							$this->_db->query($sql, __LINE__, __FILE__);
+							break;
+						case 'R':
+						case 'CH':
+						case 'LB':
+							//do nothing
+					}
 				}
 
 				if(!$attrib['column_info']['precision'])
 				{
-					if($precision = $this->translate_datatype_precision($attrib['column_info']['type']))
+					if($precision = $this->_translate_datatype_precision($attrib['column_info']['type']))
 					{
 						$attrib['column_info']['precision']=$precision;
 					}
@@ -446,612 +756,439 @@
 					'nullable'		=> $attrib['column_info']['nullable']
 					);
 
-				$value_set	= $this->db->validate_update($value_set);
+				if( !$doubled )
+				{
+					$value_set	= $this->_db->validate_update($value_set);
 
-				$this->db->query("UPDATE phpgw_cust_attribute set $value_set WHERE appname='" . $attrib['appname']. "' AND location='" . $attrib['location']. "' AND id=" . $attrib['id'],__LINE__,__FILE__);
+					$sql = 'UPDATE phpgw_cust_attribute'
+							. " SET {$value_set}"
+							. " WHERE  location_id = {$location_id}"
+								. " AND id = {$attrib_id}";
+					$this->_db->query($sql ,__LINE__,__FILE__);
+				}
 
-				$attrib['column_info']['type']  = $this->translate_datatype_insert($attrib['column_info']['type']);
-				$this->oProc->AlterColumn($attrib_table,$attrib['column_name'],$attrib['column_info']);			
+				$attrib['column_info']['type']  = $this->_translate_datatype_insert($attrib['column_info']['type']);
+				$this->_oProc->AlterColumn($attrib_table,$attrib['column_name'],$attrib['column_info']);			
 			}
 			
-			if(isset($attrib['new_choice']) && $attrib['new_choice'])
+			if(isset($attrib['new_choice']) && $attrib['new_choice'] && !$doubled )
 			{
-				$choice_id = $this->next_id($choice_table ,array('appname'=>$attrib['appname'],'location'=>$attrib['location'],'attrib_id'=>$attrib['id']));
+				$choice_id = $this->_next_id('phpgw_cust_choice' ,array('location_id'=> $location_id, 'attrib_id'=>$attrib_id));
 
 				$values= array(
-					$attrib['appname'],
-					$attrib['location'],
-					$attrib['id'],
+					$location_id,
+					$attrib_id,
 					$choice_id,
 					$attrib['new_choice']
 					);
 
-				$values	= $this->db->validate_insert($values);
+				$values	= $this->_db->validate_insert($values);
 
-				$this->db->query("INSERT INTO $choice_table (appname,location,attrib_id,id,value) "
+				$this->_db->query("INSERT INTO phpgw_cust_choice (location_id, attrib_id, id, value) "
 				. "VALUES ($values)",__LINE__,__FILE__);
 			}
 
-			if(isset($attrib['delete_choice']) && is_array($attrib['delete_choice']))
+			if ( count($attrib['delete_choice'])  && !$doubled )
 			{
-				for ($i=0;$i<count($attrib['delete_choice']);$i++)
+				foreach ($attrib['delete_choice'] as $choice_id)
 				{
-					$this->db->query("DELETE FROM $choice_table WHERE appname='" . $attrib['appname']. "' AND location='" . $attrib['location']. "' AND attrib_id=" . $attrib['id']  ." AND id=" . $attrib['delete_choice'][$i],__LINE__,__FILE__);
+					$choice_id = (int) $choice_id;
+					$sql = "DELETE FROM phpgw_cust_choice"
+						. " WHERE location_id = {$location_id}"
+							. " AND attrib_id = {$attrib_id}"
+							. " AND id = {$choice_id}";
+					$this->_db->query($sql, __LINE__, __FILE__);
 				}
 			}
 
-			$this->db->transaction_commit();
-			$this->oProc->m_odb->transaction_commit();
-			$receipt['message'][] = array('msg'	=> lang('Attribute has been edited'));
-
-			return $receipt;
-		}
-
-
-		/**
-		* @internal TODO document me :)
-		*/
-		function edit_custom_function($custom_function)
-		{
-			if(!$custom_function['location'] || !$custom_function['appname'])
+			if ( $this->_db->transaction_commit() )
 			{
-				return 	$receipt['error'][] = array('msg' => lang('location or appname is missing'));
+				return true;
 			}
-			else
-			{
-				$location = $custom_function['location'];
-				$appname = $custom_function['appname'];
-			}
 
-			$custom_function['descr'] = $this->db->db_addslashes($custom_function['descr']);
+			return false;
+		}
 
-			$this->db->transaction_begin();
 
-				$value_set=array(
-					'descr'		=> $custom_function['descr'],
-					'file_name'	=> $custom_function['custom_function_file'],
-					'active'	=> isset($custom_function['active'])?$custom_function['active']:''
-					);
-
-				$value_set	= $this->db->validate_update($value_set);
-
-				$this->db->query("UPDATE phpgw_cust_function set $value_set WHERE appname='$appname' AND location='$location' AND id=" . $custom_function['id'],__LINE__,__FILE__);
-
-			$this->db->transaction_commit();
-
-			$receipt['message'][] = array('msg'	=> lang('Custom function has been edited'));
-
-			return $receipt;
-		}
-
 		/**
 		 * Get a list of attributes
 		 * 
 		 * @param string $appname the name of the application
 		 * @param string $location the name of the location
+		 * @param integer $start
+		 * @param string query         
+		 * @param string $sort         
+		 * @param string $order        
+		 * @param bool   $allrows      
+		 * @param bool   $inc_choices  
+		 * @param array $filtermethod
+		 *
+		 * @return array attributes at location
 		 */
-		function get_attribs($appname, $location, $start = 0, $query = '', $sort = 'ASC', $order = 'attrib_sort', $allrows = false, $inc_choices = false,$filtermethod='')
+		public function find($appname, $location, $start = 0, $query = '', $sort = 'ASC', 
+				$order = 'attrib_sort', $allrows = false, $inc_choices = false, $filter = array())
 		{
+			$location_id	= $GLOBALS['phpgw']->locations->get_id($appname, $location);
 			$start		= (int) $start;
-			$query		= $this->db->db_addslashes($query);
-			$sort		= $sort == 'ASC' ? 'ASC' : 'DESC';
-			$order		= $this->db->db_addslashes($order);
+			$query			= $this->_db->db_addslashes($query);
+			$order			= $this->_db->db_addslashes($order);
 			$allrows	= !!$allrows;
-			$appname	= $this->db->db_addslashes($appname);
-			$location	= $this->db->db_addslashes($location);
 
-			if ( $allrows )
+			
+			$filtermethod	= '';
+			if ($filter && is_array($filter))
 			{
-				$this->allrows = $allrows;
+				$condition = array();
+				foreach ($filter as $column => $value)
+			{
+					if($value)
+					{
+						$condition[] = "$column = '{$value}'";
+					}
+					else
+					{
+						$condition[] = "$column IS NULL";					
+					}
 			}
 
-			if ( $order != '')
+				if( $condition )
 			{
-				$ordermethod = " ORDER BY $order $sort";
+					$filtermethod = 'AND ' . implode(" AND ", $condition);
+				}
 
 			}
-			else
+			
+			$ordermethod = 'ORDER BY group_id ASC, attrib_sort ASC';
+			if ( $order )
 			{
-				$ordermethod = ' ORDER BY attrib_sort ASC';
+				if ( $sort == 'DESC')
+			{
+					$sort = 'DESC';
+				}
+
+				$ordermethod = "ORDER BY group_id ASC, {$order} {$sort}";
 			}
 
 			$querymethod = '';
 			if ( $query )
 			{
-				$querymethod = " AND (phpgw_cust_attribute.column_name $this->like '%$query%' or phpgw_cust_attribute.input_text $this->like '%$query%')";
+				$querymethod = "AND (phpgw_cust_attribute.column_name {$this->_like} '%{$query}%'"
+					. " OR phpgw_cust_attribute.input_text {$this->_like} '%{$query}%')";
 			}
 
-			$sql = "FROM phpgw_cust_attribute WHERE appname='$appname' AND location = '$location' AND custom = 1 $querymethod $filtermethod";
+			$sql = "FROM phpgw_cust_attribute "
+				. " WHERE location_id = {$location_id}"
+					. " AND custom = 1 $querymethod $filtermethod";
 
-			$this->total_records = 0;
-			$this->db->query("SELECT COUNT(id) AS cnt_rec $sql",__LINE__,__FILE__);
-			if ( $this->db->next_record() )
+			$this->_total_records = 0;
+			$this->_db->query("SELECT COUNT(*) AS cnt_rec {$sql}",__LINE__,__FILE__);
+			if ( !$this->_db->next_record() )
 			{
-				$this->total_records = $this->db->f('cnt_rec');;
+				return array();
 			}
 
+			$this->_total_records = $this->_db->f('cnt_rec');
+
+			$sql = "SELECT * {$sql} {$ordermethod}";
+
 			if ( $allrows )
 			{
-				$this->db->query("SELECT * $sql" . $ordermethod, __LINE__, __FILE__);
+				$this->_db->query($sql, __LINE__, __FILE__);
 			}
 			else
 			{
-				$this->db->limit_query("SELECT * $sql" . $ordermethod,$start, __LINE__, __FILE__);
+				$this->_db->limit_query($sql, $start, __LINE__, __FILE__);
 			}
 
 			$attribs = array();
-			while ($this->db->next_record())
+			while ( $this->_db->next_record() )
 			{
-				$attribs[] = array
+				$id = $this->_db->f('id');
+				$attribs[$id] = array
 				(
-					'id'				=> $this->db->f('id'),
-					'attrib_id'			=> $this->db->f('id'), // FIXME: for now...
-					'entity_type'		=> $this->db->f('type_id'),
-					'attrib_sort'		=> (int) $this->db->f('attrib_sort'),
-					'list'				=> $this->db->f('list'),
-					'lookup_form'		=> $this->db->f('lookup_form'),
-					'entity_form'		=> $this->db->f('entity_form'),
-					'column_name'		=> $this->db->f('column_name'),
-					'name'				=> $this->db->f('column_name'),
-					'size'				=> $this->db->f('size'),
-					'statustext'		=> $this->db->f('statustext', true),
-					'input_text'		=> $this->db->f('input_text', true),
-					'type_name'			=> $this->db->f('type'),
-					'datatype'			=> $this->db->f('datatype'),
-					'search'			=> $this->db->f('search'),
-					'trans_datatype'	=> $this->translate_datatype($this->db->f('datatype')),
-					'nullable'			=> ($this->db->f('nullable') == 'True'),
-					'allow_null'		=> ($this->db->f('nullable') == 'True'), // FIXME: for now...
-					'history'			=> $this->db->f('history'),
-					'disabled'			=> $this->db->f('disabled'),
-					'helpmsg'			=> !!$this->db->f('helpmsg')
+					'id'				=> $id,
+					//'attrib_id'			=> $this->_db->f('id'), // FIXME
+					'entity_type'		=> $this->_db->f('type_id'),
+					'group_id'			=> (int) $this->_db->f('group_id'),					
+					'attrib_sort'		=> (int) $this->_db->f('attrib_sort'),
+					'list'				=> $this->_db->f('list'),
+					'lookup_form'		=> $this->_db->f('lookup_form'),
+					'entity_form'		=> $this->_db->f('entity_form'),
+					'column_name'		=> $this->_db->f('column_name'),
+					'name'				=> $this->_db->f('column_name'),
+					'size'				=> $this->_db->f('size'),
+					'statustext'		=> $this->_db->f('statustext', true),
+					'input_text'		=> $this->_db->f('input_text', true),
+					'type_name'			=> $this->_db->f('type'),
+					'datatype'			=> $this->_db->f('datatype'),
+					'search'			=> $this->_db->f('search'),
+					'trans_datatype'	=> $this->translate_datatype($this->_db->f('datatype')),
+					'nullable'			=> ($this->_db->f('nullable') == 'True'),
+					//'allow_null'		=> ($this->_db->f('nullable') == 'True'), // FIXME
+					'history'			=> $this->_db->f('history'),
+					'disabled'			=> $this->_db->f('disabled'),
+					'helpmsg'			=> !!$this->_db->f('helpmsg')
 
 				);
 			}
 
-			if ( count($attribs) && $inc_choices )
+			if ( $inc_choices )
 			{
 				foreach ( $attribs as &$attrib )
 				{
-					if ( $attrib['datatype'] == 'R'
-						|| $attrib['datatype'] == 'CH'
-						|| $attrib['datatype'] =='LB')
+					switch ( $attrib['datatype'] )
 					{
-						$attrib['choice'] = $this->read_attrib_choice($appname, $location, $attrib['id']);
+						default:
+							// bail out nothing to do
+							break;
+						case 'R':
+						case 'CH':
+						case 'LB':
+							$attrib['choice'] = $this->_get_choices($location_id, $attrib['id']);
 					}
 				}
 			}
 
-
 			return $attribs;
 		}
-
 		/**
-		* Read a single attribute record
+		 * Get a list of groups availlable for attributes within a location
 		*
-		* @internal TODO document me
-		*/
-		function get_attrib_single($appname, $location, $id, $inc_choices = true)
-		{
-			$appname = $this->db->db_addslashes($appname);
-			$location = $this->db->db_addslashes($location);
-			$id = (int) $id;
-
-			$sql = "SELECT * FROM phpgw_cust_attribute where appname='$appname' AND location='$location' AND id=$id";
-			$this->db->query($sql,__LINE__,__FILE__);
-
-			if ($this->db->next_record())
-			{
-				$attrib['id']						= $this->db->f('id');
-				$attrib['attrib_id']				= $this->db->f('id'); // for now...
-				$attrib['column_name']				= $this->db->f('column_name');
-				$attrib['input_text']				= $this->db->f('input_text', true);
-				$attrib['statustext']				= $this->db->f('statustext', true);
-				$attrib['column_info']['precision']	= $this->db->f('precision_');
-				$attrib['column_info']['scale']		= $this->db->f('scale');
-				$attrib['column_info']['default']	= $this->db->f('default_value');
-				$attrib['column_info']['nullable']	= $this->db->f('nullable');
-				$attrib['column_info']['type']		= $this->db->f('datatype');
-				$attrib['type_id']					= $this->db->f('type_id');
-				$attrib['type_name']				= $this->db->f('type_name');
-				$attrib['lookup_form']				= $this->db->f('lookup_form');
-				$attrib['list']						= $this->db->f('list');
-				$attrib['search']					= $this->db->f('search');
-				$attrib['history']					= $this->db->f('history');
-				$attrib['location']					= $this->db->f('location');
-				$attrib['nullable']					= ($this->db->f('nullable') == 'True');
-				$attrib['allow_null']				= ($this->db->f('nullable') == 'True'); // FIXME: for now...
-				$attrib['disabled']					= $this->db->f('disabled');
-				$attrib['helpmsg']					= stripslashes($this->db->f('helpmsg'));
-				
-				if ( $inc_choices 
-					&& ( $this->db->f('datatype') == 'R' 
-						|| $this->db->f('datatype') == 'CH' 
-						|| $this->db->f('datatype') == 'LB' ) )
-				{
-					$attrib['choice'] = $this->read_attrib_choice($appname, $location, $id);
-				}
-				return $attrib;
-			}
-		}
-
-		/**
-		* Get the name of a table for a location
+		 * @param string $appname      the name of the application
+		 * @param string $location     the name of the location
+		 * @param ?????? $start        ask sigurd
+		 * @param ?????? $query        ask sigurd
+		 * @param ?????? $sort         ask sigurd
+		 * @param ?????? $order        ask sigurd
+		 * @param ?????? $allrows      ask sigurd
 		*
-		* @internal document me
-		* @return string the name of the table
+		 * @return ???? something
 		*/
-		function get_attrib_table($appname,$location)
-		{			
-			$sql = "SELECT c_attrib_table FROM phpgw_acl_location WHERE appname='$appname' AND id='$location'";
-			$this->db->query($sql,__LINE__,__FILE__);
-			if ( $this->db->next_record() )
+		public function find_group($appname, $location, $start = 0, $query = '', $sort = 'ASC', 
+				$order = 'group_sort', $allrows = false)
 			{
-				return $this->db->f('c_attrib_table');
-			}
-			return '';
-		}
+			$location_id	= $GLOBALS['phpgw']->locations->get_id($appname, $location);
+			$start			= (int) $start;
+			$query			= $this->_db->db_addslashes($query);
+			$order			= $this->_db->db_addslashes($order);
+			$allrows		= !!$allrows;
 
-		function read_custom_function($data = '')
-		{
-			if(is_array($data))
+			$ordermethod = 'ORDER BY group_sort ASC';
+			if ( $order )
 			{
-				$start = isset($data['start']) ? (int)$data['start'] : 0;
-				$query = isset($data['query']) ? $this->db->db_addslashes($data['query']) : '';
-				$sort = (isset($data['sort']) && $data['sort'] == 'ASC') ? 'ASC' : 'DESC';
-				$order = isset($data['order']) ? $this->db->db_addslashes($data['order']) : '';
-				$allrows = isset($data['allrows']) ? !!$data['allrows'] : false;
-				$appname = isset($data['appname']) ? $this->db->db_addslashes($data['appname']) : '';
-				$location = isset($data['location']) ? $this->db->db_addslashes($data['location']) : '';
-			}
-			else
+				if ( $sort == 'DESC')
 			{
-				return array();
+					$sort = 'DESC';
 			}
 
-			if( $location == '' || $appname == '' )
-			{
-				return array();
+				$ordermethod = "ORDER BY {$order} {$sort}";
 			}
 
-			$ordermethod = ' ORDER BY custom_sort ASC';
-			if ($order)
+			$querymethod = '';
+			if ( $query )
 			{
-				$ordermethod = " ORDER BY $order $sort";
-
+				$querymethod = "AND (phpgw_cust_attribute_group.name {$this->_like} '%{$query}%'";
 			}
 
-			$table = 'phpgw_cust_function';
+			$sql = "FROM phpgw_cust_attribute_group "
+				. " WHERE location_id = {$location_id} {$querymethod}";
 
-			$querymethod = '';
-			if($query)
+			$this->_total_records = 0;
+			$this->_db->query("SELECT COUNT(*) AS cnt_rec {$sql}",__LINE__,__FILE__);
+			if ( !$this->_db->next_record() )
 			{
-				$querymethod = " AND file_name $this->like '%$query%' OR descr $this->like '%$query%'";
+				return array();
 			}
 
-			$sql = "SELECT * FROM $table WHERE appname='$appname' AND location='$location' $querymethod";
+			$this->_total_records = $this->_db->f('cnt_rec');
 
-			if(!$allrows)
+			$sql = "SELECT * {$sql} {$ordermethod}";
+
+			if ( $allrows )
 			{
-				$this->db->limit_query($sql . $ordermethod,$start,__LINE__,__FILE__);
+				$this->_db->query($sql, __LINE__, __FILE__);
 			}
 			else
 			{
-				$this->db->query($sql . $ordermethod,__LINE__,__FILE__);
+				$this->_db->limit_query($sql, $start, __LINE__, __FILE__);
 			}
 
-			$custom_function = '';
-			while ($this->db->next_record())
+			$attrib_groups = array();
+			while ( $this->_db->next_record() )
 			{
-				$custom_function[] = array
+				$attrib_groups[] = array
 				(
-					'id'		=> $this->db->f('id'),
-					'file_name'	=> $this->db->f('file_name'),
-					'sorting'	=> $this->db->f('custom_sort'),
-					'descr'		=> $this->db->f('descr'),
-					'active'	=> $this->db->f('active')
+					'id'				=> $this->_db->f('id'),
+					'group_sort'		=> (int) $this->_db->f('group_sort'),
+					'name'				=> $this->_db->f('name', true),
+					'descr'				=> $this->_db->f('descr', true),
+					'remark'			=> $this->_db->f('remark', true)
 				);
 			}
-			$this->db->query($sql,__LINE__,__FILE__);
-			$this->total_records = $this->db->num_rows();
 
-			return $custom_function;
+			return $attrib_groups;
 		}
 		
-		function read_attrib_choice($appname, $location, $attrib_id)
+		/**
+		* Read a single attribute group record
+		*
+		* @param string  $appname     the name of the module for the attribute
+		* @param string  $location    the name of the location of the attribute
+		* @param integer $id          the id of the attribute
+		*
+		* @return array the attribute record
+		*/
+		public function get_group($appname, $location, $id)
 		{
-			$appname = $this->db->db_addslashes($appname);
-			$location = $this->db->db_addslashes($location);
-			$ttrib_id = (int)$attrib_id;
+			$location_id = $GLOBALS['phpgw']->locations->get_id($appname, $location);
+			$id = (int) $id;
 			
-			$sql = "SELECT * FROM phpgw_cust_choice WHERE appname='$appname' AND location='$location' AND attrib_id = $attrib_id";
-			$this->db->query($sql,__LINE__,__FILE__);
+			$sql = "SELECT * FROM phpgw_cust_attribute_group "
+				. " WHERE location_id = {$location_id} AND id = {$id}";
+			$this->_db->query($sql, __LINE__, __FILE__);
 
-			$choices = array();
-			while ($this->db->next_record())
+			if ( !$this->_db->next_record() )
 			{
-				$choices[] = array
-				(
-					'id'	=> $this->db->f('id'),
-					'value'	=> $this->db->f('value', true)
-				);
+				return null;
 			}
-			return $choices;
-		}
 
-		function read_single_custom_function($appname, $location, $id)
-		{
-			$appname = $this->db->db_addslashes($appname);
-			$location = $this->db->db_addslashes($location);
-			$id = (int)$id;
-			
-			$sql = "SELECT * FROM phpgw_cust_function WHERE appname='$appname' AND location='$location' AND id = $id";
-
-			$this->db->query($sql,__LINE__,__FILE__);
-
-			if ($this->db->next_record())
-			{
-				return array
+			$group = array
 				(
-					'id'					=> (int)$this->db->f('id'),
-					'descr'					=> $this->db->f('descr', true),
-					'custom_function_file'	=> $this->db->f('file_name'),
-					'active'				=> !!$this->db->f('active')
+				'id'			=> $this->_db->f('id'),
+				'group_name'	=> $this->_db->f('name', true),
+				'descr'			=> $this->_db->f('descr', true),
+				'remark'		=> $this->_db->f('remark', true),
+				'group_sort'	=> $this->_db->f('group_sort')
 				);
-			}
 
+			return $group;
 		}
-
 		/**
-		 * Resort an attribute's position in relation to other attributes
+		* Read a single attribute record
 		 * 
-		 * @param int $id the attribute db pk
-		 * @param string $resort the direction to move the field [up|down]
+		* @param string  $appname     the name of the module for the attribute
+		* @param string  $location    the name of the location of the attribute
+		* @param integer $id          the id of the attribute
+		* @param boolean $inc_choices include choices if a lookup field
+		*
+		* @return array the attribute record
 		 */
-		function resort_attrib($id, $resort, $appname, $location)
+		public function get($appname, $location, $id, $inc_choices = true)
 		{
-			$resort		= $resort == 'down' ? 'down' : 'up';
-			$appname 	= $this->db->db_addslashes($appname);
-			$location	= $this->db->db_addslashes($location);
+			$location_id = $GLOBALS['phpgw']->locations->get_id($appname, $location);
 			$id			= (int) $id;
 
-			$this->db->transaction_begin();
+			$sql = "SELECT phpgw_cust_attribute.* FROM phpgw_cust_attribute " 
+				. " WHERE location_id = {$location_id}"
+					. " AND phpgw_cust_attribute.id=$id";
+			$this->_db->query($sql, __LINE__, __FILE__);
 
-			$sql = "SELECT attrib_sort FROM phpgw_cust_attribute where appname='$appname' AND location='$location' AND id=$id";
-			$this->db->query($sql,__LINE__,__FILE__);
-			$this->db->next_record();
-			$attrib_sort	= $this->db->f('attrib_sort');
-
-			$sql = "SELECT max(attrib_sort) as max_sort FROM phpgw_cust_attribute where appname='$appname' AND location='$location'";
-			$this->db->query($sql,__LINE__,__FILE__);
-			$this->db->next_record();
-			$max_sort	= $this->db->f('max_sort');
-
-			switch($resort)
+			if ( !$this->_db->next_record() )
 			{
-				case 'down':
-					if($max_sort > $attrib_sort)
-					{
-						$sql = "UPDATE phpgw_cust_attribute set attrib_sort=$attrib_sort WHERE appname='$appname' AND location='$location' AND attrib_sort =" . ($attrib_sort+1);
-						$this->db->query($sql,__LINE__,__FILE__);
-						$sql = "UPDATE phpgw_cust_attribute set attrib_sort=" . ($attrib_sort+1) ." WHERE appname='$appname' AND location='$location' AND id=$id";
-						$this->db->query($sql,__LINE__,__FILE__);
-					}
-					break;
-				default:
-				case 'up':
-					if($attrib_sort>1)
-					{
-						$sql = "UPDATE phpgw_cust_attribute set attrib_sort=$attrib_sort WHERE appname='$appname' AND location='$location' AND attrib_sort =" . ($attrib_sort-1);
-						$this->db->query($sql,__LINE__,__FILE__);
-						$sql = "UPDATE phpgw_cust_attribute set attrib_sort=" . ($attrib_sort-1) ." WHERE appname='$appname' AND location='$location' AND id=$id";
-						$this->db->query($sql,__LINE__,__FILE__);
-					}
-					break;
+				return null;
 			}
-			$this->db->transaction_commit();
-		}
 
-		function resort_custom_function($id, $resort, $appname, $location)
-		{
-			$resort = $resort == 'down' ? 'down' : 'up';
-			$appname = $this->db->db_addslashes($appname);
-			$location = $this->db->db_addslashes($location);
-			$id = (int)$id;
+			$attrib = array
+			(
+				'id'			=> $this->_db->f('id'),
+				'group_id'		=> $this->_db->f('group_id'),
+				'column_name'	=> $this->_db->f('column_name', true),
+				'input_text'	=> $this->_db->f('input_text', true),
+				'statustext'	=> $this->_db->f('statustext', true),
+				'type_id'		=> $this->_db->f('type_id'),
+				'type_name'		=> $this->_db->f('type_name'),
+				'lookup_form'	=> $this->_db->f('lookup_form'),
+				'list'			=> !!$this->_db->f('list'),
+				'search'		=> !!$this->_db->f('search'),
+				'history'		=> !!$this->_db->f('history'),
+				'location_id'	=> $this->_db->f('location_id'),
+				// FIXME this is broken it should be a small int and used as a bool
+				'nullable'		=> $this->_db->f('nullable') == 'True',
+				// FIXME this isn't needed
+				//'allow_null'	=> $this->_db->f('nullable') == 'True',
+				'disabled'		=> !!$this->_db->f('disabled'),
+				'helpmsg'		=> $this->_db->f('helpmsg', true),
+				'column_info'	=> array
+									(
+										'precision'	=> $this->_db->f('precision_'),
+										'scale'		=> $this->_db->f('scale'),
+										'default'	=> $this->_db->f('default_value', true),
+										// more duplicated values
+										'nullable'	=> $this->_db->f('nullable'),
+										'type'		=> $this->_db->f('datatype')
+									)
+			);
 
-			if(!$location || !$appname)
+			if ( $inc_choices )
 			{
-				return 	$receipt['error'][] = array('msg' => lang('location or appname is missing'));
-			}
-
-			$this->db->transaction_begin();
-			
-			$sql = "SELECT custom_sort FROM phpgw_cust_function WHERE appname='$appname' AND location='$location' AND id=$id";
-			$this->db->query($sql, __LINE__, __FILE__);
-			$this->db->next_record();
-			$custom_sort	= $this->db->f('custom_sort');
-			$sql = "SELECT MAX(custom_sort) AS max_sort FROM phpgw_cust_function WHERE appname='$appname' AND location='$location'";
-			$this->db->query($sql, __LINE__, __FILE__);
-			$this->db->next_record();
-			$max_sort	= $this->db->f('max_sort');
-
-			switch($resort)
-			{
-				case 'down':
-					if($max_sort > $custom_sort)
+				switch ( $this->_db->f('datatype') )
 					{
-						$sql = "UPDATE phpgw_cust_function set custom_sort=$custom_sort WHERE appname='$appname' AND location='$location' AND custom_sort =" . ($custom_sort+1);
-						$this->db->query($sql,__LINE__,__FILE__);
-						$sql = "UPDATE phpgw_cust_function set custom_sort=" . ($custom_sort+1) ." WHERE appname='$appname' AND location='$location' AND id=$id";
-						$this->db->query($sql,__LINE__,__FILE__);
-					}
-					break;
 				default:
-				case 'up':
-					if($custom_sort>1)
-					{
-						$sql = "UPDATE phpgw_cust_function set custom_sort=$custom_sort WHERE appname='$appname' AND location='$location' AND custom_sort =" . ($custom_sort-1);
-						$this->db->query($sql,__LINE__,__FILE__);
-						$sql = "UPDATE phpgw_cust_function set custom_sort=" . ($custom_sort-1) ." WHERE location='$location' AND id=$id";
-						$this->db->query($sql,__LINE__,__FILE__);
-					}
+						// bail out quickly
+						break;
+					case 'R':
+					case 'CH':
+					case 'LB':
+						$attrib['choice'] = $this->_get_choices($location_id, $id);
 					break;
-			}
-			$this->db->transaction_commit();
-		}
-
-		function select_custom_function($selected='', $appname)
-		{
-			$dirname = PHPGW_SERVER_ROOT . "/{$appname}/inc/custom"; 
-			$myfilearray = array();
-			$dir_handle = dir($dirname);
-			if ($dir_handle)
-			{
-				while ( ($file = $dir_handle->read($dir_handle)) !== false )
-				{
-					if ((substr($file, 0, 1) != '.') && is_file("{$dirname}/{$file}") )
-					{
-						$myfilearray[] = $file;
 					}
 				}
-				$dir_handle->close();
-				sort($myfilearray);
+			return $attrib;
 			}
 
-			$file_list = array();
-			foreach ( $myfilearray as $myfile )
-			{
-				$fname = preg_replace('/_/', ' ', $myfile);
-				$sel_file = '';
-				if ( $myfile == $selected )
-				{
-					$sel_file = 'selected';
-				}
+		/**
+		* Arrange attributes within groups
+		*
+		* @param string  $appname     the name of the module for the attribute
+		* @param string  $location    the name of the location of the attribute
+		* @param array   $attributes  the array of the attributes to be grouped
+		*
+		* @return array the grouped attributes
+		*/
 
-				$file_list[] = array
+		public function get_attribute_groups($appname, $location, $attributes = array())
+		{
+			$no_group = array
+			(
+				array
 				(
-					'id'		=> $myfile,
-					'name'		=> $fname,
-					'selected'	=> $sel_file
+					'id'	=> 0,
+					'name'	=> lang('attributes'),
+					'descr' => lang('attributes')
+				)
 				);
-			}
+			$groups = $this->find_group($appname, $location, 0, '', 'ASC', 'group_sort', true);
+			$groups = array_merge($no_group, $groups);
 
-			foreach ( $file_list as &$file )
-			{
-				if ( $file['selected'] != 'selected' )
+			foreach ($groups as &$group)
 				{
-					unset($file['selected']);
-				}
-			}
-
-			return $file_list;
-		}
-		
-		function translate_datatype($datatype)
+				foreach ($attributes as $attribute)
 		{
-			if ( isset($this->datatype_text[$datatype]) )
+					if($attribute['group_id'] == $group['id'])
 			{
-				return $this->datatype_text[$datatype];
+						$group['attributes'][] = $attribute;
 			}
-			return '';
 		}
-
-		function translate_datatype_insert($datatype)
-		{
-			$datatype_text = array(
-				'V' => 'varchar',
-				'I' => 'int',
-				'C' => 'char',
-				'N' => 'decimal',
-				'D' => 'timestamp',
-				'T' => 'text',
-				'R' => 'int',
-				'CH' => 'text',
-				'LB' => 'int',
-				'AB' => 'int',
-				'VENDOR' => 'int',
-				'email' => 'varchar',
-				'link' => 'varchar'
-			);
-
-			return $datatype_text[$datatype];
 		}
-
-		function translate_datatype_precision($datatype)
-		{
-			$datatype_precision = array(
-				'I' => 4,
-				'R' => 4,
-				'LB' => 4,
-				'AB' => 4,
-				'VENDOR' => 4,
-				'email' => 64,
-				'link' => 255
-			);
-
-			return isset($datatype_precision[$datatype])?$datatype_precision[$datatype]:'';
+			return $groups;
 		}
 
 		/**
-		 * Delete a custom field/attribute
+		 * Get the definition of a table
 		 * 
-		 * @param string $location within an application
-		 * @param string $appname where to delete the attrib
-		 * @param integer $attrib_id id of attrib to delete
-		 * @param bool $doubled sometimes the attribute fits into a history-table as a double
+		 * @param string $table     the name of the table to look up
+		 * @param array  $table_def ask sigurd
+		 *
+		 * @return array the table structure
 		 */
-		function _delete_attrib($location,$appname,$attrib_id,$table = '',$doubled = false )
+		public function get_table_def($table = '', $table_def = array())
 		{
-			$this->_init_process();
-			$this->oProc->m_odb->transaction_begin();
-			$this->db->transaction_begin();
-
-			$sql = "SELECT * FROM phpgw_cust_attribute WHERE appname='$appname' AND location='$location' AND id=$attrib_id";
-
-			$this->db->query($sql,__LINE__,__FILE__);
-			$this->db->next_record();
-
-			$ColumnName		= $this->db->f('column_name');
-			if(!$table)
+			if( !$GLOBALS['phpgw_setup']->_oProc 
+				|| !is_object($GLOBALS['phpgw_setup']->_oProc) )
 			{
-			$table = $this->get_attrib_table($appname,$location);
+				$GLOBALS['phpgw_setup']->oProc =& $this->_oProc;
 			}
 
-			$this->oProc->DropColumn($table,false, $ColumnName);
-
-			$sql = "SELECT attrib_sort FROM phpgw_cust_attribute where appname='$appname' AND location='$location' AND id=$attrib_id";
-			$this->db->query($sql,__LINE__,__FILE__);
-			$this->db->next_record();
-			$attrib_sort	= $this->db->f('attrib_sort');
-
-			$sql = "SELECT max(attrib_sort) as max_sort FROM phpgw_cust_attribute where appname='$appname' AND location='$location'";
-			$this->db->query($sql,__LINE__,__FILE__);
-			$this->db->next_record();
-			$max_sort	= $this->db->f('max_sort');
-
-			if($max_sort>$attrib_sort)
-			{
-				$sql = "UPDATE phpgw_cust_attribute set attrib_sort=attrib_sort-1 WHERE appname='$appname' AND location='$location' AND attrib_sort > $attrib_sort";
-				$this->db->query($sql,__LINE__,__FILE__);
-			}
-
-			if(!$doubled) // else: wait for it - another one is coming
-			{
-				$this->db->query("DELETE FROM phpgw_cust_attribute WHERE appname='$appname' AND location='$location' AND id = " . (int)$attrib_id,__LINE__,__FILE__);
-			}
-	//		$this->db->query("DELETE FROM history...
-			$this->db->transaction_commit();
-			$this->oProc->m_odb->transaction_commit();
-		}
-		
-		function get_table_def($table = '', $table_def = array())
-		{
-			if(!isset($this->oProc) || !is_object($this->oProc))
-			{
-				$this->_init_process();
-				$GLOBALS['phpgw_setup']->oProc = $this->oProc;
-			}
-
 			$setup = createobject('phpgwapi.setup_process');
 			$tableinfo = $setup->sql_to_array($table);
 
@@ -1064,314 +1201,379 @@
 			$table_def[$table]['ix'] = isset($table_def[$table]['ix']) && $table_def[$table]['ix'] ? $table_def[$table]['ix'] : $tableinfo[3];
 			$table_def[$table]['uc'] = isset($table_def[$table]['uc']) && $table_def[$table]['uc'] ? $table_def[$table]['uc'] : $tableinfo[4];
 			
-//	_debug_array($table_def);
 			return $table_def;
 		}
 		
-		function _delete_custom_function($appname,$location,$custom_function_id)
-		{
-			$this->db->transaction_begin();
-			$sql = "SELECT custom_sort FROM phpgw_cust_function where appname='$appname' AND location='$location' AND id=$custom_function_id";
-			$this->db->query($sql,__LINE__,__FILE__);
-			$this->db->next_record();
-			$custom_sort	= $this->db->f('custom_sort');
-			$sql2 = "SELECT max(custom_sort) as max_sort FROM phpgw_cust_function where appname='$appname' AND location='$location'";
-			$this->db->query($sql2,__LINE__,__FILE__);
-			$this->db->next_record();
-			$max_sort	= $this->db->f('max_sort');
-			if($max_sort>$custom_sort)
-			{
-				$sql = "UPDATE phpgw_cust_function set custom_sort=custom_sort-1 WHERE appname='$appname' AND location='$location' AND custom_sort > $custom_sort";
-				$this->db->query($sql,__LINE__,__FILE__);
-			}
-			$this->db->query("DELETE FROM phpgw_cust_function WHERE appname='$appname' AND location='$location' AND id=$custom_function_id",__LINE__,__FILE__);
-			$this->db->transaction_commit();
-		}
-		
-		function _init_process()
-		{
-			$this->oProc 				= createObject('phpgwapi.schema_proc',$GLOBALS['phpgw_info']['server']['db_type']);
-			$this->oProc->m_odb			= clone($this->db); // nested transactions
-			$this->oProc->m_odb->Halt_On_Error	= 'yes';
-		}
-		
 		/**
-		 * Finds the next ID for a record at a table
+		* Preserve attribute values from post in case of an error
 		 * 
-		 * @param string $table tablename in question
-		 * @param array $key conditions
-		 * @return int the next id
+		* @param array $values value set with
+		* @param array $values_attributes attribute definitions and values from posting
+		*
+		* @return array attribute definitions and values
 		 */
+		public function preserve_attribute_values($values, $values_attributes)
+				{
+			if ( !is_array($values_attributes ) )
+					{
+				return array();
+			}
 
-		function next_id($table='',$key='')
-		{
-			$where = '';
-			if(is_array($key))
+			foreach ( $values_attributes as $attribute )
 			{
-				while (is_array($key) && list($column,$value) = each($key))
+				foreach ( $values['attributes'] as &$val_attrib )
 				{
-					if($value)
+					if ( $val_attrib['id'] != $attribute['attrib_id'] )
 					{
-						$condition[] = $column . "='" . $value;
-					}
-				}
-
-				$where='WHERE ' . implode("' AND ", $condition) . "'";
-			}
-
-			$this->db->query("SELECT max(id) as maximum FROM $table $where",__LINE__,__FILE__);
-			$this->db->next_record();
-			$next_id = $this->db->f('maximum')+1;
-			return $next_id;
+						continue;
 		}
 
-		/**
-		 * Prepare custom attributes for ui
-		 * 
-		 * @param array $values values and definitions of custom attributes
-		 * @return array values and definitions of custom attributes prepared for ui
-		 */
-
-		function prepare_attributes($values='',$appname, $location,$view_only='')
+					if( !isset($attribute['value']) )
 		{
-			$contacts		= CreateObject('phpgwapi.contacts');
-			$vendor 		= CreateObject('property.soactor');
-			$vendor->role	= 'vendor';
+						continue;
+					}
 
-			$dateformat = $GLOBALS['phpgw_info']['user']['preferences']['common']['dateformat'];
-
-			$input_type_array = array(
-				'R' => 'radio',
-				'CH' => 'checkbox',
-				'LB' => 'listbox'
-			);
-
-			$m=0;
-			for ($i=0;$i<count($values['attributes']);$i++)
+					if ( is_array($attribute['value']) )
 			{
-				$values['attributes'][$i]['datatype_text'] 	= $this->translate_datatype($values['attributes'][$i]['datatype']);
-				$values['attributes'][$i]['help_url']		= $values['attributes'][$i]['helpmsg'] ? $GLOBALS['phpgw']->link('/index.php', array('menuaction'=> 'manual.uimanual.attrib_help', 'appname'=> $appname, 'location'=> $location, 'id' => $values['attributes'][$i]['id'])): '';
-				if($values['attributes'][$i]['datatype']=='D')
+						foreach ( $val_attrib['choice'] as &$choice )
 				{
-					if(!$view_only)
+							foreach ( $attribute['value'] as $selected )
 					{
-					if ( !isset($GLOBALS['phpgw']->jscal) || !is_object($GLOBALS['phpgw']->jscal) )
+								if ( $selected == $choice['id'] )
 					{
-						$GLOBALS['phpgw']->jscal = createObject('phpgwapi.jscalendar');
+									$choice['checked'] = 'checked';
 					}
-
-					$GLOBALS['phpgw']->jscal->add_listener('values_attribute_' . $i);
-					$values['attributes'][$i]['img_cal']= $GLOBALS['phpgw']->common->image('phpgwapi','cal');
-					$values['attributes'][$i]['lang_datetitle']= lang('Select date');
 					}
-
-					if(isset($values['attributes'][$i]['value']) && $values['attributes'][$i]['value'])
-					{
-						$timestamp_date= mktime(0,0,0,date('m',strtotime($values['attributes'][$i]['value'])),date('d',strtotime($values['attributes'][$i]['value'])),date('y',strtotime($values['attributes'][$i]['value'])));
-						$values['attributes'][$i]['value']	= $GLOBALS['phpgw']->common->show_date($timestamp_date,$dateformat);
 					}
 				}
-				else if($values['attributes'][$i]['datatype']=='AB')
+					else if ( isset($val_attrib['choice'])
+						&& is_array($val_attrib['choice']) )
 				{
-					if($values['attributes'][$i]['value'])
+						foreach ( $val_attrib['choice'] as &$choice)
 					{
-						$contact_data	= $contacts->read_single_entry($values['attributes'][$i]['value'],array('n_given'=>'n_given','n_family'=>'n_family','email'=>'email'));
-						$values['attributes'][$i]['contact_name']	= $contact_data[0]['n_family'] . ', ' . $contact_data[0]['n_given'];
+							if ( $choice['id'] == $attribute['value'] )
+							{
+								$choice['checked'] = 'checked';
 					}
-
-					$insert_record_values[]	= $values['attributes'][$i]['name'];
-					$lookup_link		= $GLOBALS['phpgw']->link('/index.php',array('menuaction'=> 'property.uilookup.addressbook', 'column'=> $values['attributes'][$i]['name']));
-
-					$lookup_functions[$m]['name'] = 'lookup_'. $values['attributes'][$i]['name'] .'()';
-					$lookup_functions[$m]['action'] = 'Window1=window.open('."'" . $lookup_link ."'" .',"Search","width=800,height=700,toolbar=no,scrollbars=yes,resizable=yes");';
-					$m++;
 				}
-				else if($values['attributes'][$i]['datatype']=='VENDOR')
-				{
-					if($values['attributes'][$i]['value'])
-					{
-						$vendor_data	= $vendor->read_single($values['attributes'][$i]['value'],array('attributes' => array(0 => array('column_name' => 'org_name'))));
-
-						for ($n=0;$n<count($vendor_data['attributes']);$n++)
-						{
-							if($vendor_data['attributes'][$n]['column_name'] == 'org_name')
+					}
+					else
 							{
-								$values['attributes'][$i]['vendor_name']= $vendor_data['attributes'][$n]['value'];
-								$n =count($vendor_data['attributes']);
+						$val_attrib['value'] = $attribute['value'];
+					}
 							}
 						}
+			return $values;
 					}
 
-					$insert_record_values[]	= $values['attributes'][$i]['name'];
-					$lookup_link		= $GLOBALS['phpgw']->link('/index.php',array('menuaction'=> 'property.uilookup.vendor', 'column'=> $values['attributes'][$i]['name']));
 
-					$lookup_functions[$m]['name'] = 'lookup_'. $values['attributes'][$i]['name'] .'()';
-					$lookup_functions[$m]['action'] = 'Window1=window.open('."'" . $lookup_link ."'" .',"Search","width=800,height=700,toolbar=no,scrollbars=yes,resizable=yes");';
-					$m++;
-				}
-				else if($values['attributes'][$i]['datatype']=='user')
+
+		/**
+		 * Resort an attribute's position in relation to other attributes
+		 * 
+		 * @param int $id the attribute db pk
+		 * @param string $resort the direction to move the field [up|down]
+		 */
+		public function resort_group($id, $resort, $appname, $location)
+		{
+			$id		= (int) $id;
+
+			if ( $resort == 'down' )
 				{
-					if($values['attributes'][$i]['value'])
+				$resort = 'down';
+			}
+			else
 					{
-						$values['attributes'][$i]['user_name']= $GLOBALS['phpgw']->accounts->id2name($values['attributes'][$i]['value']);
+				$resort	= 'up';
 					}
 
-					$insert_record_values[]	= $values['attributes'][$i]['name'];
-					$lookup_link		= $GLOBALS['phpgw']->link('/index.php',array('menuaction'=> $this->appname.'.uilookup.phpgw_user', 'column'=> $values['attributes'][$i]['name']));
+			$location_id = $GLOBALS['phpgw']->locations->get_id($appname, $location);
 
-					$lookup_functions[$m]['name'] = 'lookup_'. $values['attributes'][$i]['name'] .'()';
-					$lookup_functions[$m]['action'] = 'Window1=window.open('."'" . $lookup_link ."'" .',"Search","width=800,height=700,toolbar=no,scrollbars=yes,resizable=yes");';
-					$m++;
-				}
-				else if($values['attributes'][$i]['datatype']=='R' || $values['attributes'][$i]['datatype']=='CH' || $values['attributes'][$i]['datatype']=='LB')
-				{
-					$values['attributes'][$i]['choice']	= $this->read_attrib_choice($appname, $location,$values['attributes'][$i]['id']);
-					$input_type=$input_type_array[$values['attributes'][$i]['datatype']];
+			$this->_db->transaction_begin();
 
-					if($values['attributes'][$i]['datatype']=='CH')
-					{
-						$values['attributes'][$i]['value']=unserialize($values['attributes'][$i]['value']);
+			$sql = "SELECT group_sort FROM phpgw_cust_attribute_group " 
+				. " WHERE location_id = {$location_id} AND id = {$id}";
+			$this->_db->query($sql, __LINE__, __FILE__);
+			$this->_db->next_record();
+			$attrib_sort	= $this->_db->f('group_sort');
 
-						if (isset($values['attributes'][$i]['choice']) AND is_array($values['attributes'][$i]['choice']))
-						{
-							foreach($values['attributes'][$i]['choice'] as &$choice)
-							{
-								$choice['input_type'] = $input_type;
-								if(isset($values['attributes'][$i]['value']) && is_array($values['attributes'][$i]['value']))
-								{
-									foreach ($values['attributes'][$i]['value'] as &$selected)
+			$sql = "SELECT MAX(group_sort) AS max_sort FROM phpgw_cust_attribute_group " 
+				. " WHERE location_id = {$location_id}";
+			$this->_db->query($sql,__LINE__,__FILE__);
+			$this->_db->next_record();
+			$max_sort	= $this->_db->f('max_sort');
+
+			$update = false;
+			switch($resort)
 									{
-										if($selected == $choice['id'])
+				case 'down':
+					if($max_sort > $attrib_sort)
 										{
-											$choice['checked'] = 'checked';
+						$new_sort = $attrib_sort + 1;
+						$update = true;
 										}
+					break;
+
+				case 'up':
+				default:
+					if($attrib_sort>1)
+					{
+						$new_sort = $attrib_sort - 1;
+						$update = true;
 									}
+					break;
 								}
+
+			if ( !$update )
+			{
+				// nothing to do
+				return true;
 							}
+
+			$sql = "UPDATE phpgw_cust_attribute_group SET group_sort = {$attrib_sort}"
+				. " WHERE location_id = {$location_id} AND group_sort = {$new_sort}";
+			$this->_db->query($sql, __LINE__, __FILE__);
+
+			$sql = "UPDATE phpgw_cust_attribute_group SET group_sort = {$new_sort}"
+				. " WHERE location_id = {$location_id} AND id = {$id}";
+			$this->_db->query($sql, __LINE__, __FILE__);
+
+			return $this->_db->transaction_commit();
 						}
+
+		/**
+		 * Resort an attribute's position in relation to other attributes
+		 * 
+		 * @param int $id the attribute db pk
+		 * @param string $resort the direction to move the field [up|down]
+		 */
+		public function resort($id, $resort, $appname, $location)
+		{
+			$id		= (int) $id;
+
+			if ( $resort == 'down' )
+			{
+				$resort = 'down';
 					}
 					else
 					{
-						for ($j=0;$j<count($values['attributes'][$i]['choice']);$j++)
+				$resort	= 'up';
+			}
+
+			$location_id = $GLOBALS['phpgw']->locations->get_id($appname, $location);
+
+			$this->_db->transaction_begin();
+
+			$sql = "SELECT group_id FROM phpgw_cust_attribute " 
+				. " WHERE location_id = {$location_id} AND id = {$id}";
+			$this->_db->query($sql, __LINE__, __FILE__);
+			$this->_db->next_record();
+			$group_id	= (int) $this->_db->f('group_id');
+
+			$sql = "SELECT attrib_sort FROM phpgw_cust_attribute " 
+				. " WHERE location_id = {$location_id} AND id = {$id} AND group_id = {$group_id}";
+			$this->_db->query($sql, __LINE__, __FILE__);
+			$this->_db->next_record();
+			$attrib_sort	= $this->_db->f('attrib_sort');
+
+			$sql = "SELECT MAX(attrib_sort) AS max_sort FROM phpgw_cust_attribute " 
+				. " WHERE location_id = {$location_id} AND group_id = {$group_id}";
+			$this->_db->query($sql,__LINE__,__FILE__);
+			$this->_db->next_record();
+			$max_sort	= $this->_db->f('max_sort');
+
+			$update = false;
+			switch($resort)
 						{
-							$values['attributes'][$i]['choice'][$j]['input_type']=$input_type;
-							if($values['attributes'][$i]['choice'][$j]['id']==$values['attributes'][$i]['value'])
+				case 'down':
+					if($max_sort > $attrib_sort)
 							{
-								$values['attributes'][$i]['choice'][$j]['checked']='checked';
-							}
+						$new_sort = $attrib_sort + 1;
+						$update = true;
 						}
+					break;
+
+				case 'up':
+				default:
+					if($attrib_sort>1)
+					{
+						$new_sort = $attrib_sort - 1;
+						$update = true;
 					}
+					break;
 				}
-				else if (isset($entity['attributes'][$i]) && $entity['attributes'][$i]['datatype']!='I' && $entity['attributes'][$i]['value'])
+
+			if ( !$update )
 				{
-					$entity['attributes'][$i]['value'] = stripslashes($entity['attributes'][$i]['value']);
+				// nothing to do
+				return true;
 				}
 
-				$values['attributes'][$i]['datatype_text'] = $this->translate_datatype($values['attributes'][$i]['datatype']);
-				$values['attributes'][$i]['counter']	= $i;
-//				$values['attributes'][$i]['type_id']	= $data['type_id'];
+			$sql = "UPDATE phpgw_cust_attribute SET attrib_sort = {$attrib_sort}"
+				. " WHERE location_id = {$location_id} AND attrib_sort = {$new_sort} AND group_id = {$group_id}";
+			$this->_db->query($sql, __LINE__, __FILE__);
+
+			$sql = "UPDATE phpgw_cust_attribute SET attrib_sort = {$new_sort}"
+				. " WHERE location_id = {$location_id} AND id = {$id} AND group_id = {$group_id}";
+			$this->_db->query($sql, __LINE__, __FILE__);
+
+			return $this->_db->transaction_commit();
 			}
 
-			if(isset($lookup_functions) && is_array($lookup_functions))
+		/**
+		 * Convert a datatype to a human readable label
+		 *
+		 * @param string $datatype the dataype to convert
+		 *
+		 * @return string the user readable string
+		 */
+		public function translate_datatype($datatype)
 			{ 
-				for ($j=0;$j<count($lookup_functions);$j++)
+			if ( isset($this->datatype_text[$datatype]) )
 				{
-					$values['lookup_functions'] .= 'function ' . $lookup_functions[$j]['name'] ."\r\n";
-					$values['lookup_functions'] .= '{'."\r\n";
-					$values['lookup_functions'] .= $lookup_functions[$j]['action'] ."\r\n";
-					$values['lookup_functions'] .= '}'."\r\n";
+				return $this->datatype_text[$datatype];
 				}
+			return '';
 			}
 
-			if(isset($lookup_functions) && $lookup_functions)
+		/**
+		 * Get the list of available choices for a lookup field
+		 *
+		 * @param integer $location_id the location for the attribute
+		 * @param integer $attrib_id   the field being looked up
+		 */
+		protected function _get_choices($location_id, $attrib_id)
 			{
-				$GLOBALS['phpgw']->session->appsession('insert_record_values' . $location,$appname,$insert_record_values);
+			$location_id	= (int) $location_id;
+			$ttrib_id		= (int) $attrib_id;
+
+			$sql = "SELECT * FROM phpgw_cust_choice " 
+				. " WHERE location_id = {$location_id}"
+					. " AND attrib_id = {$attrib_id}"
+				. " ORDER BY value";
+			$this->_db->query($sql,__LINE__,__FILE__);
+
+			$choices = array();
+			while ( $this->_db->next_record() )
+			{
+			//	$id = $this->_db->f('id');
+			//	$choices[$id] = array
+				$choices[] = array
+				(
+					'id'	=> $this->_db->f('id'),
+					'value'	=> $this->_db->f('value', true)
+				);
 			}
-
-			return $values;
+			return $choices;
 		}
 
 		/**
-		* Preserve attribute values from post in case of an error
+		 * Finds the next ID for a record at a table
 		*
-		* @param array $values_attribute attribute definition and values from posting
-		* @param array $values value set with 
-		* @return array Array with attribute definition and values
+		 * @param string $table tablename in question
+		 * @param array  $key   conditions for finding the next id
+		 *
+		 * @return int the next id
 		*/
-		function preserve_attribute_values($values,$values_attribute)
-		{
-//_debug_array($values);
-//_debug_array($values_attribute);
-			foreach ( $values_attribute as $key => $attribute )
-			{	
-				for ($i=0;$i<count($values['attributes']);$i++)
-				{
-					if($values['attributes'][$i]['id'] == $attribute['attrib_id'])
-					{
-						if(isset($attribute['value']))
-						{
-							if(is_array($attribute['value']))
+		protected function _next_id($table = null, $key = null)
 							{
-								foreach($values['attributes'][$i]['choice'] as &$choice)
+			if ( !$table )
 								{
-									foreach ($attribute['value'] as &$selected)
-									{
-										if($selected == $choice['id'])
-										{
-											$choice['checked'] = 'checked';
-										}
-									}
-								}
+				return 0;
 							}
-							else if(isset($values['attributes'][$i]['choice']) && is_array($values['attributes'][$i]['choice']))
-							{
 
-								foreach ($values['attributes'][$i]['choice'] as &$choice)
+			$next_id = 0;
+
+			$where = '';
+			if ( is_array($key) )
 						{
-									if($choice['id'] == $attribute['value'])
+				foreach ( $key as $col => $val )
 							{
-										$choice['checked'] = 'checked';	
-									}
-								}
-							}
-							else
+					if ( $val )
 								{
-								$values['attributes'][$i]['value'] = $attribute['value'];
-								}
+						$val = $this->_db->db_addslashes($val);
+						$condition[] = "{$col} = '{$val}";
 							}
 						}
+
+				$where='WHERE ' . implode("' AND ", $condition) . "'";
 					}
+
+			$sql = "SELECT max(id) as maximum FROM {$table} {$where}";
+			$this->_db->query($sql, __LINE__, __FILE__);
+			if ( $this->_db->next_record() )
+			{
+				$next_id = $this->_db->f('maximum');
 				}
-			return $values;
+
+			++$next_id;
+			return $next_id;
 			}
 			
-		function convert_attribute_save($values_attribute='')
-		{
-			if(is_array($values_attribute))
-			{
-				foreach ( $values_attribute as &$attrib )
+		/**
+		 * Preapre a datatype for insert
+		 *
+		 * @param string $datatype the datatype being used
+		 *
+		 * @return string the converted datatype or empty string is invalid
+		 */
+		protected function _translate_datatype_insert($datatype)
 				{
-					if ( $attrib['datatype'] == 'CH' && $attrib['value'] )
+			$datatype_text = array
+			(
+				'V'			=> 'varchar',
+				'I'			=> 'int',
+				'C'			=> 'char',
+				'N'			=> 'decimal',
+				'D'			=> 'timestamp',
+				'T'			=> 'text',
+				'R'			=> 'int',
+				'CH'		=> 'text',
+				'LB'		=> 'int',
+				'AB'		=> 'int',
+				'VENDOR'	=> 'int',
+				'email'		=> 'varchar',
+				'link'		=> 'varchar',
+				'pwd' 		=> 'varchar',
+				'user' 		=> 'int',
+				'event'		=> 'int'
+			);
+
+			if ( !isset($datatype_text[$datatype]) )
 					{
-						$attrib['value'] = serialize($attrib['value'] );
+				return '';
 					}
-					if ( $attrib['datatype'] == 'R' && $attrib['value'] )
-					{
-						$attrib['value'] = $attrib['value'][0];
+
+			return $datatype_text[$datatype];
 					}
 
-					if ( $attrib['datatype'] == 'N' && $attrib['value'] )
+		/**
+		 * Get the precision for a datatype
+		 *
+		 * @param string $datatype the datatype to look up
+		 *
+		 * @return integer the precision - 0 for n/a or invalid
+		 */
+		protected function _translate_datatype_precision($datatype)
 					{
-						$attrib['value'] = str_replace(',', '.', $attrib['value']);
-					}
+			$datatype_precision = array
+			(
+				'I'			=> 4,
+				'R'			=> 4,
+				'LB'		=> 4,
+				'AB'		=> 4,
+				'VENDOR'	=> 4,
+				'email'		=> 64,
+				'link'		=> 255,
+				'pwd' 		=> 32,
+				'user' 		=> 4,
+				'event'		=> 4
+			);
 	
-					if ( $attrib['datatype'] == 'D' && $attrib['value'] )
+			if ( !isset($datatype_precision[$datatype]) )
 					{
-						$attrib['value'] = date($this->dateformat, phpgwapi_datetime::date_to_timestamp($attrib['value']));
+				return 0;
 					}
+			return $datatype_precision[$datatype];
 				}
 			}
-			return $values_attribute;
-		}
-	}
-?>

Added: people/sigurdne/modules/phpgwapi/trunk/inc/class.custom_functions.inc.php
===================================================================
--- people/sigurdne/modules/phpgwapi/trunk/inc/class.custom_functions.inc.php	                        (rev 0)
+++ people/sigurdne/modules/phpgwapi/trunk/inc/class.custom_functions.inc.php	2009-11-20 10:28:10 UTC (rev 20845)
@@ -0,0 +1,447 @@
+<?php
+	/**
+	 * phpGroupWare custom functions
+	 *
+	 * @author Sigurd Nes <[email protected]>
+	 * @author Dave Hall dave.hall at skwashd.com
+	 * @copyright Copyright (C) 2003-2006 Free Software Foundation http://www.fsf.org/
+	 * @license http://www.gnu.org/licenses/gpl.html GNU General Public License v2 or later
+	 * @package phpgroupware
+	 * @subpackage phpgwapi
+	 * @version $Id$
+	 */
+
+	/*
+	   This program is free software: you can redistribute it and/or modify
+	   it under the terms of the GNU General Public License as published by
+	   the Free Software Foundation, either version 2 of the License, or
+	   (at your option) any later version.
+
+	   This program is distributed in the hope that it will be useful,
+	   but WITHOUT ANY WARRANTY; without even the implied warranty of
+	   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+	   GNU Lesser General Public License for more details.
+
+	   You should have received a copy of the GNU General Public License
+	   along with this program.  If not, see <http://www.gnu.org/licenses/>.
+	 */
+
+	/**
+	 * phpGroupWare custom functions
+	 *
+	 * @package phpgroupware
+	 * @subpackage phpgwapi
+	 */
+	class phpgwapi_custom_functions
+	{
+
+		/**
+		 * @var object $_db reference to the global database object
+		 */
+		protected $_db;
+
+		/**
+		 * @var string $_join SQL JOIN statement
+		 */
+		protected $_join;
+
+		/**
+		 * @var string $_like SQL LIKE statement
+		 */
+		protected $_like;
+
+		/**
+		* @var int $_total_records total number of records found
+		*/
+		protected $_total_records = 0;
+
+		/**
+		 * Constructor
+		 *
+		 * @return void
+		 */
+		public function __construct()
+		{
+			$this->_db           	=& $GLOBALS['phpgw']->db;
+			$this->_join			=& $this->_db->join;
+			$this->_like			=& $this->_db->like;
+		}
+
+		/**
+		 * Magic get method
+		 *
+		 * @param string $varname the variable to fetch
+		 *
+		 * @return mixed the value of the variable sought - null if not found
+		 */
+		public function __get($varname)
+		{
+			if ( $varname == 'total_records' )
+			{
+				return $this->_total_records;
+			}
+		}
+
+		/**
+		 * Add a custom function
+		 * 
+		 * @param array $custom_function the data for the custom function
+		 *
+		 * @return integer the id of the function, -1 means invalid data and 0 means it wasn't added
+		 */
+		public function add($custom_function)
+		{
+			if(!$custom_function['location'] || !$custom_function['appname'])
+			{
+				return -1;
+			}
+
+			$location_id = $GLOBALS['phpgw']->locations->get_id($custom_function['appname'], $custom_function['location']);
+
+			if ( isset($custom_function['active']) && $custom_function['active'] )
+			{
+				$custom_function['active'] = true;
+			}
+
+			$this->_db->transaction_begin();
+
+			$custom_function['id'] = 1;
+			$sql = 'SELECT MAX(id) as maximum FROM phpgw_cust_function'
+				. " WHERE location_id = {$location_id}";
+			$this->_db->query($sql, __LINE__, __FILE__);
+			if ( $this->_db->next_record() )
+			{
+				$custom_function['id'] += $this->_db->f('maximum');
+			}
+
+			$custom_sort = 0;
+			$sql = "SELECT MAX(custom_sort) as max_sort FROM phpgw_cust_function"
+				. " WHERE location_id = {$location_id}";
+			$this->_db->query($sql, __LINE__, __FILE__);
+			if ( $this->_db->next_record() )
+			{
+				$custom_sort = $this->_db->f('max_sort') + 1;
+			}
+
+			$values = array
+			(
+				'location_id'	=> $location_id,
+				'id'			=> (int) $custom_function['id'],
+				'file_name'		=> $this->_db->db_addslashes($custom_function['custom_function_file']),
+				'descr'			=> $this->_db->db_addslashes($custom_function['descr']),
+				'active'		=> !!$custom_function['active'],
+				'custom_sort'	=> $custom_sort
+			);
+
+			$columns = implode(',', array_keys($values));
+			$values	= $this->_db->validate_insert($values);
+
+			$this->_db->query("INSERT INTO phpgw_cust_function({$columns}) "
+				. "VALUES ({$values})", __LINE__, __FILE__);
+
+			if ( $this->_db->transaction_commit() )
+			{
+				return $custom_function['id'];
+			}
+
+			return 0;
+		}
+
+		/**
+		 * Delete a custom attribute or custom function
+		 * 
+		 * @param string $appname the application name
+		 * @param string $location the location
+		 * @param int $function_id the db pk of the function to delete
+		 *
+		 * @return bool was the function deleted?
+		 */
+		public function delete($appname, $location, $function_id)
+		{
+			$location_id = $GLOBALS['phpgw']->locations->get_id($appname, $location);
+			$function_id = (int) $function_id;
+
+			$this->_db->transaction_begin();
+
+			$sql = 'SELECT custom_sort FROM phpgw_cust_function'
+				. " WHERE location_id = {$location_id} AND id = {$function_id}";
+			$this->_db->query($sql, __LINE__, __FILE__);
+			if ( !$this->_db->next_record() )
+			{
+				// function has already been deleted
+				return true;
+			}
+
+			$custom_sort = $this->_db->f('custom_sort');
+
+			$sql = 'SELECT MAX(custom_sort) AS max_sort FROM phpgw_cust_function'
+				. " WHERE location_id = {$location_id}";
+			$this->_db->query($sql, __LINE__, __FILE__);
+			$this->_db->next_record();
+			$max_sort	= $this->_db->f('max_sort');
+
+			if ( $max_sort > $custom_sort )
+			{
+				$sql = 'UPDATE phpgw_cust_function SET custom_sort = (custom_sort - 1)'
+					. " WHERE location_id = {$location_id} AND custom_sort > {$custom_sort}";
+				$this->_db->query($sql, __LINE__, __FILE__);
+			}
+
+			$sql = 'DELETE FROM phpgw_cust_function'
+				. " WHERE location_id = {$location_id} AND id = {$function_id}";
+			$this->_db->query($sql, __LINE__, __FILE__);
+
+			return $this->_db->transaction_commit();
+		}
+
+		/**
+		* Edit a custom function
+		*
+		* @param array $custom_function function data
+		*
+		* @return bool was the function updated?
+		*/
+		public function edit($custom_function)
+		{
+			$id = (int) $custom_function['id'];
+
+			if ( isset($custom_function['active']) ) 
+			{
+				$custom_function['active'] = !!$custom_function['active'];
+			}
+
+			$location_id = $GLOBALS['phpgw']->locations->get_id($custom_function['appname'], $custom_function['location']);
+
+			$values = array
+			(
+				'descr'		=> $this->_db->db_addslashes($custom_function['descr']),
+				'file_name'	=> $custom_function['custom_function_file'],
+				'active'	=> $custom_function['active']
+			);
+			unset($custom_function);
+
+			$vals = $this->_db->validate_update($values);
+
+			$sql = "UPDATE phpgw_cust_function SET {$vals}" 
+					. " WHERE location_id = {$location_id} AND id = {$id}";
+
+			$this->_db->transaction_begin();
+
+			$this->_db->query($sql, __LINE__, __FILE__);
+
+			return $this->_db->transaction_commit();
+		}
+
+		/**
+		 * Get a list of available custom functions
+		 *
+		 * @param array $data the search criteria
+		 *
+		 * @return array list of functions
+		 */
+		public function find($data = array())
+		{
+			$custom_functions = array();
+
+			if ( !is_array($data) || !isset($data['appname']) || !isset($data['location']) )
+			{
+				return $custom_functions;
+			}
+
+			$location_id = $GLOBALS['phpgw']->locations->get_id($data['appname'], $data['location']);
+
+			$start = 0;
+			if ( isset($data['start']) )
+			{
+				$start = (int) $data['start'];
+			}
+
+			$query = '';
+			if ( isset($data['query']) )
+			{
+				$query = $this->_db->db_addslashes($data['query']);
+			}
+
+
+			$ordermethod = ' ORDER BY custom_sort ASC';
+			if ( isset($data['order']) && $data['order'] )
+			{
+				$data['sort'] = 'ASC';
+				if ( isset($data['sort']) && $data['sort'] == 'DESC' )
+				{
+					$data['sort'] = 'DESC';
+				}
+
+				$data['order'] = $this->_db->db_addslashes($data['order']);
+				$ordermethod = " ORDER BY {$data['order']} {$data['sort']}";
+			}
+
+			$allrows = false;
+			if ( isset($data['allrows']) )
+			{
+				$allrows = !!$data['allrows'];
+			}
+
+			$querymethod = '';
+			if($query)
+			{
+				$querymethod = " AND file_name {$this->_like} '%{$query}%'"
+							. " OR descr {$this->_like} '%{$query}%'";
+			}
+
+			$sql = 'FROM phpgw_cust_function'
+				. " WHERE location_id = {$location_id} {$querymethod}";
+
+			$this->_total_records = 0;
+			$this->_db->query("SELECT COUNT(*) AS cnt {$sql}", __LINE__,__FILE__);
+			if ( $this->_db->next_record() )
+			{
+				$this->_total_records = $this->_db->f('cnt');
+			}
+
+			if ( true ) //$allrows )
+			{
+				$this->_db->query("SELECT * {$sql} {$ordermethod}", __LINE__, __FILE__);
+			}
+			else
+			{
+				$this->_db->limit_query("SELECT * {$sql} {$ordermethod}", $start, __LINE__, __FILE__);
+			}
+
+			while ( $this->_db->next_record() )
+			{
+				$id = $this->_db->f('id');
+				$custom_functions[] = array
+				(
+					'id'		=> $id,
+					'file_name'	=> $this->_db->f('file_name'),
+					'sorting'	=> $this->_db->f('custom_sort'),
+					'descr'		=> $this->_db->f('descr'),
+					'active'	=> !!$this->_db->f('active')
+				);
+			}
+
+			return $custom_functions;
+		}
+		
+		/**
+		 * Fetch a single custom function record from the database
+		 *
+		 * @param string  $appname  the module the function belongs to
+		 * @param string  $location the location the function is used
+		 * @param integer $id       the ID for the function
+		 *
+		 * @return array the function values - null if not found
+		 */
+		public function get($appname, $location, $id)
+		{
+			$appname = $this->_db->db_addslashes($appname);
+			$location = $this->_db->db_addslashes($location);
+			$id = (int)$id;
+			
+			$sql = 'SELECT * FROM phpgw_cust_function '
+				. " {$this->_join} phpgw_locations ON phpgw_cust_function.location_id = phpgw_locations.location_id"
+				. " {$this->_join} phpgw_applications ON phpgw_applications.app_id = phpgw_locations.app_id"
+				. " WHERE phpgw_applications.app_name = '{$appname}'"
+					. " AND phpgw_locations.name = '{$location}'"
+					. " AND phpgw_cust_function.id = {$id}";
+
+			$this->_db->query($sql,__LINE__,__FILE__);
+
+			if ( !$this->_db->next_record() )
+			{
+				return null;
+			}
+
+			return array
+			(
+				'id'					=> (int)$this->_db->f('id'),
+				'descr'					=> $this->_db->f('descr', true),
+				'custom_function_file'	=> $this->_db->f('file_name'),
+				'active'				=> !!$this->_db->f('active')
+			);
+		}
+
+		/**
+		 * Change the order functions
+		 *
+		 * @param integer $id       the function to reposition
+		 * @param string  $resort   the direction to move the item - up/down
+		 * @param string  $appname  the module for the function
+		 * @param string  $location the location for the function
+		 *
+		 * @return bool was the item moved?
+		 */
+		public function resort($id, $resort, $appname, $location)
+		{
+			if ( !$location || !$appname )
+			{
+				return false;
+			}
+
+			$id		= (int)$id;
+
+			if ( $resort == 'down' )
+			{
+				$resort = 'down';
+			}
+			else
+			{
+				$resort	= 'up';
+			}
+
+			$location_id = $GLOBALS['phpgw']->locations->get_id($appname, $location);
+
+			$this->_db->transaction_begin();
+			
+			$sql = 'SELECT custom_sort FROM phpgw_cust_function'
+				. " WHERE location_id = {$location_id} AND id = {$id}";
+			$this->_db->query($sql, __LINE__, __FILE__);
+			$this->_db->next_record();
+			$custom_sort = $this->_db->f('custom_sort');
+
+			$sql = 'SELECT MAX(custom_sort) AS max_sort FROM phpgw_cust_function'
+				. " WHERE location_id = {$location_id}";
+			$this->_db->query($sql, __LINE__, __FILE__);
+			$this->_db->next_record();
+			$max_sort = $this->_db->f('max_sort');
+
+			$update = false;
+			switch($resort)
+			{
+				case 'down':
+					if($max_sort > $custom_sort)
+					{
+						$new_sort = $custom_sort + 1;
+						$update = true;
+					}
+					break;
+
+				case 'up':
+				default:
+					if($custom_sort>1)
+					{
+						$new_sort = $custom_sort - 1;
+						$update = true;
+					}
+					break;
+			}
+
+			if ( !$update )
+			{
+				// nothing to be done - assume all is ok
+				return true;
+			}
+
+			$sql = "UPDATE phpgw_cust_function SET custom_sort = {$custom_sort}"
+				. " WHERE location_id = {$location_id}"
+					. " AND custom_sort = {$new_sort}";
+			$this->_db->query($sql,__LINE__,__FILE__);
+
+			$sql = "UPDATE phpgw_cust_function SET custom_sort = {$new_sort}" 
+				. " WHERE  location_id = {$location_id} AND id = {$id}";
+			$this->_db->query($sql,__LINE__,__FILE__);
+
+			return $this->_db->transaction_commit();
+		}
+	}


Property changes on: people/sigurdne/modules/phpgwapi/trunk/inc/class.custom_functions.inc.php
___________________________________________________________________
Added: svn:keywords
   + Id Revision
Added: svn:eol-style
   + native

Modified: people/sigurdne/modules/phpgwapi/trunk/inc/class.data_cleaner.inc.php
===================================================================
--- people/sigurdne/modules/phpgwapi/trunk/inc/class.data_cleaner.inc.php	2009-11-20 10:27:41 UTC (rev 20844)
+++ people/sigurdne/modules/phpgwapi/trunk/inc/class.data_cleaner.inc.php	2009-11-20 10:28:10 UTC (rev 20845)
@@ -21,21 +21,6 @@
  * @package phpgwapi
  * @subpackage utilities
  */
-
-	/*
-	   This program is free software: you can redistribute it and/or modify
-	   it under the terms of the GNU General Public License as published by
-	   the Free Software Foundation, either version 3 of the License, or
-	   (at your option) any later version.
-
-	   This program is distributed in the hope that it will be useful,
-	   but WITHOUT ANY WARRANTY; without even the implied warranty of
-	   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-	   GNU General Public License for more details.
-
-	   You should have received a copy of the GNU General Public License
-	   along with this program.  If not, see <http://www.gnu.org/licenses/>.
-	 */
 class data_cleaner
 {
 	/**

Modified: people/sigurdne/modules/phpgwapi/trunk/inc/class.datetime.inc.php
===================================================================
--- people/sigurdne/modules/phpgwapi/trunk/inc/class.datetime.inc.php	2009-11-20 10:27:41 UTC (rev 20844)
+++ people/sigurdne/modules/phpgwapi/trunk/inc/class.datetime.inc.php	2009-11-20 10:28:10 UTC (rev 20845)
@@ -1,10 +1,12 @@
 <?php
 	/**
 	* Datetime class that contains common date/time functions
+	*
+	* @author Dave Hall <[email protected]>
 	* @author Joseph Engo <[email protected]>
 	* @author Mark Peters <[email protected]>
 	* @copyright Copyright (C) 2000,2001 Joseph Engo, Mark Peters
-	* @copyright Portions Copyright (C) 2000-2004 Free Software Foundation, Inc. http://www.fsf.org/
+	* @copyright Portions Copyright (C) 2000-2008 Free Software Foundation, Inc. http://www.fsf.org/
 	* @license http://www.gnu.org/licenses/lgpl.html GNU Lesser General Public License
 	* @package phpgwapi
 	* @subpackage utilities
@@ -14,7 +16,7 @@
 	/*
 	   This program is free software: you can redistribute it and/or modify
 	   it under the terms of the GNU Lesser General Public License as published by
-	   the Free Software Foundation, either version 3 of the License, or
+	   the Free Software Foundation, either version 2 of the License, or
 	   (at your option) any later version.
 
 	   This program is distributed in the hope that it will be useful,
@@ -26,6 +28,13 @@
 	   along with this program.  If not, see <http://www.gnu.org/licenses/>.
 	 */
 
+	/*
+	 * We set the default timezone here to prevent any notices
+	 *
+	 * Everything in phpGroupWare is based on UTC, so lets set it here
+	 */
+	date_default_timezone_set('UTC');
+
 	/**
 	* Datetime class that contains common date/time functions
 	*
@@ -387,6 +396,7 @@
 						break;
 				}
 			}
+
 			return mktime($ta[0],$ta[1],$ta[2],$month[$dta[2]],$dta[1],$dta[3]);
 		}
 
@@ -766,7 +776,7 @@
 		 * @param string $formatTarget Target date format
 		 * @return string Date in target format representation
 		 */
-		function convertDate($date, $formatSource, $formatTarget)
+		public static function convertDate($date, $formatSource, $formatTarget)
 		{
 			// get format separator character
 			$formatSourceSepChar = substr($formatSource,1,1);
@@ -799,10 +809,10 @@
 		}
 
 		/**
-		* Convert a date string to a unix timestamp
+		* Convert a date string to an array containing date parts
 		*
 		* @param string $datestr the date string to convert - must match user's preferred date format
-		* @return int unix timestamp
+		* @return array date parts: year,month and day
 		*/
 		public static function date_array($datestr)
 		{
@@ -836,7 +846,7 @@
 		*/
 		public static function date_to_timestamp($date = array())
 		{
-			if ( !count($date) )
+			if ( !$date )
 			{
 				return 0;
 			}
@@ -924,14 +934,3 @@
 			return lang('Unknown');
 		}
 	}
-	
-	if ( !isset($GLOBALS['phpgw_info']['server']['tz_offset']) )
-	{
-		$tzone = 'UTC';
-	}
-	else
-	{
-		$tzone = 'Etc/GMT' . $GLOBALS['phpgw_info']['server']['tz_offset'];
-	}
-	
-	date_default_timezone_set($tzone);

Modified: people/sigurdne/modules/phpgwapi/trunk/inc/class.db.inc.php
===================================================================
--- people/sigurdne/modules/phpgwapi/trunk/inc/class.db.inc.php	2009-11-20 10:27:41 UTC (rev 20844)
+++ people/sigurdne/modules/phpgwapi/trunk/inc/class.db.inc.php	2009-11-20 10:28:10 UTC (rev 20845)
@@ -1,49 +1,22 @@
 <?php
 	/**
-	* phpGroupWare - Database abstraction class
-	*
+	* Database abstraction class
 	* @author NetUSE AG Boris Erdmann, Kristian Koehntopp
    	* @author Dan Kuykendall, Dave Hall and others
+   	* @author Sigurd Nes
 	* @copyright Copyright (C) 1998-2000 NetUSE AG Boris Erdmann, Kristian Koehntopp
 	* @copyright Portions Copyright (C) 2001-2006 Free Software Foundation, Inc. http://www.fsf.org/
-	* @license http://www.fsf.org/licenses/lgpl.html GNU Lesser General Public License v3 or later
+	* @license http://www.fsf.org/licenses/lgpl.html GNU Lesser General Public License
 	* @link http://www.sanisoft.com/phplib/manual/DB_sql.php
-	* @package phpgroupware
-	* @subpackage phpgwapi
+	* @package phpgwapi
+	* @subpackage database
 	* @version $Id$
 	*/
 
-	/*
-	   This program is free software: you can redistribute it and/or modify
-	   it under the terms of the GNU Lesser General Public License as published by
-	   the Free Software Foundation, either version 3 of the License, or
-	   (at your option) any later version.
-
-	   This program is distributed in the hope that it will be useful,
-	   but WITHOUT ANY WARRANTY; without even the implied warranty of
-	   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-	   GNU Lesser General Public License for more details.
-
-	   You should have received a copy of the GNU Lesser General Public License
-	   along with this program.  If not, see <http://www.gnu.org/licenses/>.
-	 */
-
-	/**
-	* phpGroupWare - Database abstraction class
-	*
-	* @package phpgroupware
-	* @subpackage phpgwapi
-	* @version $Id$
-	*/
-
-	if (empty($GLOBALS['phpgw_info']['server']['db_type']))
+	if ( empty($GLOBALS['phpgw_info']['server']['db_type']) )
 	{
 		$GLOBALS['phpgw_info']['server']['db_type'] = 'mysql';
 	}
-	/**
-	* Include concrete database implementation
-	*/
-	require_once(PHPGW_API_INC . '/adodb/adodb.inc.php');
 
 	/**
 	* Database abstraction class to allow phpGroupWare to use multiple database backends
@@ -53,13 +26,17 @@
 	*/
 	class phpgwapi_db
 	{
-
 		/**
-		* @var object $adodb holds the ADOdb object
+		* @var object $adodb holds the legacy ADOdb object
 		*/
 		var $adodb;
 
 		/**
+		* @var object $db holds the db object
+		*/
+		var $db;
+
+		/**
 		* @var string $Host database hostname
 		*/
 		var $Host;
@@ -69,6 +46,8 @@
 		 */
 		 var $join = ' INNER JOIN ';
 		 
+
+		 var $left_join = ' LEFT JOIN ';
 		/**
 		 * @var string $like the sql syntax to use for a case insensitive LIKE
 		 */
@@ -111,6 +90,9 @@
 		
 		var $resultSet;
 		
+		var $fetchmode = 'BOTH';
+
+		var $Transaction  = false;		
 		/**
 		* Constructor
 		* @param string $query query to be executed (optional)
@@ -125,11 +107,15 @@
 
 			$this->Type = $db_type;
 
-			$this->Database = $GLOBALS['phpgw_info']['server']['db_name']; 
-			$this->Host = $GLOBALS['phpgw_info']['server']['db_host']; 
-			$this->User = $GLOBALS['phpgw_info']['server']['db_user']; 
-			$this->Password = $GLOBALS['phpgw_info']['server']['db_pass']; 
+			$_key = $GLOBALS['phpgw_info']['server']['setup_mcrypt_key'];
+			$_iv  = $GLOBALS['phpgw_info']['server']['mcrypt_iv'];
+			$crypto = createObject('phpgwapi.crypto',array($_key, $_iv));
 
+			$this->Database		= $crypto->decrypt($GLOBALS['phpgw_info']['server']['db_name']);
+			$this->Host			= $crypto->decrypt($GLOBALS['phpgw_info']['server']['db_host']);
+			$this->User			= $crypto->decrypt($GLOBALS['phpgw_info']['server']['db_user']);
+			$this->Password		= $crypto->decrypt($GLOBALS['phpgw_info']['server']['db_pass']);
+
 			// We do it this way to allow it to be easily extended in the future
 			switch ( $this->Type )
 			{
@@ -141,7 +127,7 @@
 					//do nothing for now
 			}
 			
-			$this->new_adodb();
+			$this->connect();
 
 			if ( !is_null($query) )
 			{
@@ -154,52 +140,30 @@
 		*/
 		public function __clone()
 		{
-			$this->new_adodb();
-		}
-
-		/**
-		* Create a new adodb object
-		*/
-		private function new_adodb()
-		{
-			$this->connect();
 			
-			if ( $this->adodb )
-			{
-				// would be good if one day we just use ADODB_FETCH_ASSOC
-				$this->adodb->SetFetchMode(ADODB_FETCH_BOTH);
-			}
 		}
 
+
 		/**
 		* Destructor
 		*/
 		public function __destruct()
 		{
-			$this->disconnect();
+
 		}
 
 		/**
-		* Get current connection id
-		* @return int current connection id
+		* Backward compatibility for get current connection id
+		* @return bool true
 		*/
 		function link_id()
 		{
-			if(!$this->adodb->isConnected())
+			if(!$this->db)
 			{
 				$this->connect();
 			}
-			return $this->adodb->_connectionID;
+			return true;
 		}
-
-		/**
-		* Get current query id
-		* @return int id of current query
-		*/
-		public function query_id()
-		{
-			return $this->Query_ID;
-		}
 		
 		/**
 		* Open a connection to a database
@@ -208,8 +172,6 @@
 		* @param string $Host database host to connect to (optional)
 		* @param string $User name of database user (optional)
 		* @param string $Password password for database user (optional)
-		* 
-		* @return boolean did we connect?
 		*/
 		public function connect($Database = null, $Host = null, $User = null, $Password = null)
 		{
@@ -233,26 +195,123 @@
 				$this->Password = $Password;
 			}
 			
+			$persistent = isset($GLOBALS['phpgw_info']['server']['db_persistent']) && $GLOBALS['phpgw_info']['server']['db_persistent'] ? true : false;
 			switch ( $this->Type )
 			{
+				case 'postgres':
+					try
+					{
+						$this->db = new PDO("pgsql:dbname={$this->Database};host={$this->Host}", $this->User, $this->Password, array(PDO::ATTR_PERSISTENT => $persistent));
+					}
+					catch(PDOException $e){}
+					break;
 				case 'mysql':
-					$type = 'mysqlt';
+					try
+					{
+						$this->db = new PDO("mysql:host={$this->Host};dbname={$this->Database}", $this->User, $this->Password, array(PDO::ATTR_PERSISTENT => $persistent));
+					}
+					catch(PDOException $e){}
 					break;
-
+				case 'sybase':
+				case 'mssql':
+					/*
+					* On Windows, you should use the PDO_ODBC  driver to connect to Microsoft SQL Server and Sybase databases,
+					* as the native Windows DB-LIB is ancient, thread un-safe and no longer supported by Microsoft.
+					*/
+					try
+					{
+						$this->db = new PDO("mssql:host={$this->Host},1433;dbname={$this->Database}", $this->User, $this->Password, array(PDO::ATTR_PERSISTENT => $persistent));
+					}
+					catch(PDOException $e){}
+					break;
+				case 'oracle':
+					try
+					{
+						$this->db = new PDO("OCI:dbname={$this->Database};charset=UTF-8", $this->User, $this->Password);
+					}
+					catch(PDOException $e){}
+					break;
+				case 'db2':
+					try
+					{
+						$port     = 50000; // configurable?
+						$this->db = new PDO("ibm:DRIVER={IBM DB2 ODBC DRIVER};DATABASE={$this->Database}; HOSTNAME={$this->Host};PORT=50000;PROTOCOL=TCPIP;", $this->User, $this->Password);
+					}
+					catch(PDOException $e){}
+					break;
+				case 'MSAccess':
+					try
+					{
+						$this->db = new PDO("odbc:Driver={Microsoft Access Driver (*.mdb)};Dbq=C:\accounts.mdb;Uid=Admin"); // FIXME: parameter for database location
+					}
+					catch(PDOException $e){}
+					break;
+				case 'dblib':
+					try
+					{
+						$port     = 10060; // configurable?
+						$this->db = new PDO("dblib:host={$this->Host}:{$port};dbname={$this->Database}", $this->User, $this->Password);
+					}
+					catch(PDOException $e){}
+					break;
+				case 'Firebird':
+					try
+					{
+						$this->db = new PDO("firebird:dbname=localhost:C:\Programs\Firebird\DATABASE.FDB", $this->User, $this->Password);// FIXME: parameter for database location
+					}
+					catch(PDOException $e){}
+					break;
+				case 'Informix':
+					//connect to an informix database cataloged as InformixDB in odbc.ini
+					try
+					{
+						$this->db = new PDO("informix:DSN=InformixDB", $this->User, $this->Password);
+					}
+					catch(PDOException $e){}
+					break;
+				case 'SQLite':
+					try
+					{
+						$this->db = new PDO("sqlite:/path/to/database.sdb"); // FIXME: parameter for database location
+					}
+					catch(PDOException $e){}
+					break;
+				case 'odbc':
+					try
+					{
+						$dsn = 'something';// FIXME
+						/*$dsn refers to the $dsn data source configured in the ODBC driver manager.*/
+						$this->db = new PDO("odbc:DSN={$dsn}", $this->User, $this->Password);
+					//	$this->db = new PDO("odbc:{$dsn}", $this->User, $this->Password);
+					}
+					catch(PDOException $e){}
+					break;
 				default:
-					$type = $this->Type;
+					//do nothing for now
 			}
 			
-			$this->adodb = newADOConnection($type);
-			if ( isset($GLOBALS['phpgw_info']['server']['db_persistent'])
-				&& $GLOBALS['phpgw_info']['server']['db_persistent'] )
+			if ( isset($e) && $e )
 			{
-				@$this->adodb->PConnect($this->Host, $this->User, $this->Password, $this->Database);
-				return (bool) $this->adodb;
+//				echo 'could not connect to server';
+				echo $e->getMessage();
+				exit;
 			}
+			if($this->Halt_On_Error == 'yes')
+			{
+				$this->db->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
+			}
+			}
 
-			@$this->adodb->Connect($this->Host, $this->User, $this->Password, $this->Database);
-			return (bool) $this->adodb;
+		/**
+		* Legacy supprt for quyering metadata from database
+		*
+		*/
+		protected function _connect_adodb()
+		{
+			require_once PHPGW_API_INC . '/adodb/adodb.inc.php';
+			$this->adodb = newADOConnection($this->Type);
+			$this->adodb->SetFetchMode(ADODB_FETCH_BOTH);
+			return @$this->adodb->connect($this->Host, $this->User, $this->Password, $this->Database);
 		}
 
 		/**
@@ -260,7 +319,7 @@
 		*/
 		public function disconnect()
 		{
-			$this->adodb->close();
+			$this->db = null;
 		}
 
 		/**
@@ -276,11 +335,12 @@
 				return '';
 			}
 
-			if ( !is_object($this->adodb) )  //workaround
+			if ( !is_object($this->db) )  //workaround
 			{
 				return addslashes($str);
 			}
-			return substr($this->adodb->Quote($str), 1, -1);
+
+			return substr($this->db->quote($str), 1, -1);
 		}
 
 		/**
@@ -291,7 +351,7 @@
 		*/
 		public function to_timestamp($epoch)
 		{
-			return substr($this->adodb->DBTimeStamp($epoch), 1, -1);
+			return date($this->datetime_format(), $epoch);
 		}
 
 		/**
@@ -302,10 +362,21 @@
 		*/
 		public function from_timestamp($timestamp)
 		{
-			return $this->adodb->UnixTimeStamp($timestamp);
+			return strtotime($timestamp);
 		}
 
 		/**
+		* Execute a query with limited result set
+		* @param integer $start Row to start from
+		* @deprecated
+		* @see limit_query()
+		*/
+		public function limit($start)
+		{
+			die('where is the sql string?');
+		}
+
+		/**
 		* Discard the current query result
 		*/
 		public function free()
@@ -320,28 +391,63 @@
 		* @param string $sql the query to be executed
 		* @param mixed $line the line method was called from - use __LINE__
 		* @param string $file the file method was called from - use __FILE__
+		* @param bool $exec true for exec, false for query
 		* @return integer current query id if sucesful and null if fails
 		*/
-		public function query($sql, $line = '', $file = '')
+		public function query($sql, $line = '', $file = '', $exec = false)
 		{
-			if ( !$this->adodb->isConnected() )
+
+			if ( !$this->db )
 			{
 				$this->connect();
 			}
 
-			$this->resultSet = $this->adodb->Execute($sql);
+			if(!$exec)
+			{
+				if(preg_match('/(^INSERT INTO|^DELETE FROM|^CREATE TABLE|^DROP TABLE|^ALTER TABLE|^UPDATE)/i', $sql)) // need it for MySQL
+				{
+					$exec = true;
+				}
+			}
 
-			if ( !$this->resultSet && $this->Halt_On_Error == 'yes' )
+			try
 			{
+				if($exec)
+				{
+					$this->affected_rows = $this->db->exec($sql);
+					return true;
+				}
+				else
+				{
+					$statement_object = $this->db->query($sql);
+					if($this->fetchmode == 'ASSOC')
+					{
+						$this->resultSet = $statement_object->fetchAll(PDO::FETCH_ASSOC);
+					}
+					else
+					{
+						$this->resultSet = $statement_object->fetchAll(PDO::FETCH_BOTH);
+					}
+				}
+			}
+
+			catch(PDOException $e)
+			{
+				if ( $e && $this->Halt_On_Error == 'yes' )
+			{
 				if($file)
 				{
-					trigger_error("$sql\n in File: $file\n on Line: $line\n". $this->adodb->ErrorMsg(), E_USER_ERROR);
+						trigger_error('Error: ' . $e->getMessage() . "<br>SQL: $sql\n in File: $file\n on Line: $line\n", E_USER_ERROR);
 				}
 				else
 				{
-					trigger_error("$sql\n". $this->adodb->ErrorMsg(), E_USER_ERROR);
+						trigger_error("$sql\n". $e->getMessage(), E_USER_ERROR);
+					}
+					$this->transaction_abort();
+					exit;
 				}
 			}
+
 			$this->delayPointer = true;
 			return true;
 		}
@@ -354,27 +460,73 @@
 		* @param integer $line the line method was called from - use __LINE__
 		* @param string $file the file method was called from - use __FILE__
 		* @param integer $num_rows number of rows to return (optional), if unset will use $GLOBALS['phpgw_info']['user']['preferences']['common']['maxmatchs']
-		* 
 		* @return integer current query id if sucesful and null if fails
 		*/
-		public function limit_query($Query_String, $offset = -1, $line = '', $file = '', $num_rows = -1)
+
+		function limit_query($Query_String, $offset, $line = '', $file = '', $num_rows = 0)
 		{
-			if ( (int) $num_rows <= 0 )
+			$offset		= intval($offset);
+			$num_rows	= intval($num_rows);
+
+			if ($num_rows == 0)
 			{
-				$num_rows = $GLOBALS['phpgw_info']['user']['preferences']['common']['maxmatchs'];
+				$maxmatches = $GLOBALS['phpgw_info']['user']['preferences']['common']['maxmatchs'];
+				$num_rows = (isset($maxmatches)?intval($maxmatches):15);
 			}
 			
-			if ( !$this->adodb->isConnected() )
+			if( $this->Type == 'mssql' )
 			{
-				$this->connect();
+				$Query_String = str_replace('SELECT ', 'SELECT TOP ', $Query_String);
+				$Query_String = str_replace('SELECT TOP DISTINCT', 'SELECT DISTINCT TOP ', $Query_String);
+				$Query_String = str_replace('TOP ', 'TOP ' . ($offset + $num_rows) . ' ', $Query_String);
+
 			}
+			else
+			{
+				if ($offset == 0)
+				{
+					$Query_String .= ' LIMIT ' . $num_rows;
+				}
+				else
+				{
+					$Query_String .= ' LIMIT ' . $num_rows . ' OFFSET ' . $offset;
+				}
+			}
 			
-			$this->resultSet = $this->adodb->SelectLimit($Query_String, $num_rows, $offset);
-			if(!$this->resultSet && $this->Halt_On_Error == 'yes')
+			if ($this->debug)
 			{
-				trigger_error("$Query_String\n" . $this->adodb->ErrorMsg(), E_USER_ERROR);
-				return false;
+				printf("Debug: limit_query = %s<br />offset=%d, num_rows=%d<br />\n", $Query_String, $offset, $num_rows);
 			}
+
+			try
+			{
+				$statement_object = $this->db->query($Query_String);
+				if($this->fetchmode == 'ASSOC')
+				{
+					$this->resultSet = $statement_object->fetchAll(PDO::FETCH_ASSOC);
+				}
+				else
+				{
+					$this->resultSet = $statement_object->fetchAll(PDO::FETCH_BOTH);
+				}
+			}
+
+			catch(PDOException $e)
+			{
+				if ( $e && $this->Halt_On_Error == 'yes' )
+				{
+					if($file)
+					{
+						trigger_error('Error: ' . $e->getMessage() . "<br>SQL: $sql\n in File: $file\n on Line: $line\n", E_USER_ERROR);
+					}
+					else
+					{
+						trigger_error("$sql\n". $e->getMessage(), E_USER_ERROR);
+					}
+					$this->transaction_abort();
+					exit;
+				}
+			}
 			
 			$this->delayPointer = true;
 			return true;
@@ -387,22 +539,19 @@
 		*/
 		public function next_record()
 		{
-			if($this->resultSet && $this->resultSet->RecordCount())
+			if($this->resultSet && current($this->resultSet))
 			{
 				if($this->delayPointer)
 				{
 					$this->delayPointer = false;
-					$this->Record =& $this->resultSet->fields;
+					$this->Record = current($this->resultSet);
 					return true;
 				}
 	
-				if(!$this->resultSet->EOF)
-				{
-					$row = $this->resultSet->MoveNext();
-					$this->Record =& $this->resultSet->fields;
+				$row = next($this->resultSet);
+				$this->Record =& $row;
 					return !!$row;
 				}
-			}
 			return false;
 		}
 
@@ -416,7 +565,12 @@
 		{
 			if($this->resultSet)
 			{
-				return $this->resultSet->Move($pos);
+				reset($this->resultSet);
+				for ($i=0; $i<$pos; $i++)
+				{
+					$row = next($this->resultSet);
+				}
+				return $row;
 			}
 			return false;
 		}
@@ -428,7 +582,13 @@
 		*/
 		public function transaction_begin()
 		{
-			return $this->adodb->StartTrans();
+/*
+			$bt = debug_backtrace();
+			echo "<b>db::{$bt[0]['function']} Called from file: {$bt[0]['file']} line: {$bt[0]['line']}</b><br/>";
+			unset($bt);
+*/
+			$this->Transaction = $this->db->beginTransaction();
+			return $this->Transaction;
 		}
 		
 		/**
@@ -438,7 +598,13 @@
 		*/ 
 		public function transaction_commit()
 		{
-			return $this->adodb->CompleteTrans();
+/*
+			$bt = debug_backtrace();
+			echo "<b>db::{$bt[0]['function']} Called from file: {$bt[0]['file']} line: {$bt[0]['line']}</b><br/>";
+			unset($bt);
+*/
+			$this->Transaction = false;
+			return $this->db->commit();
 		}
 		
 		/**
@@ -448,76 +614,69 @@
 		*/
 		public function transaction_abort()
 		{
-			$this->adodb->FailTrans();
-			return $this->adodb->HasFailedTrans();
+			$this->Transaction = false;
+			return $this->db->rollBack();
 		}
 
 		/**
-		* Find the primary key of the last insertion on the current db connection
+		* Find the value of the last insertion on the current db connection
+		* To use this function safely in Postgresql you MUST wrap it in a beginTransaction() commit() block
 		*
 		* @param string $table name of table the insert was performed on
-		* @param string $field the autoincrement primary key of the table
+		* @param string $field not needed - kept for backward compatibility
 		* @return integer the id, -1 if fails
 		*/
-		public function get_last_insert_id($table, $field)
+		public function get_last_insert_id($table, $field = '')
 		{
 			switch ( $GLOBALS['phpgw_info']['server']['db_type'] )
 			{
 				case 'postgres':
-					$params = explode('.',$this->adodb->pgVersion);
-	
-					if ($params[0] < 8 || ($params[0] == 8 && $params[1] ==0))
-					{
-						$oid = pg_getlastoid($this->adodb->_resultid);
-						if ($oid == -1)
-						{
-							return -1;
-						}
-	
-						$result = @pg_Exec($this->adodb->_connectionID, "select $field from $table where oid=$oid");
+					$sequence = $this->_get_sequence_field_for_table($table, $field);
+					$ret = $this->db->lastInsertId($sequence);
+					break;
+				case 'mssql':
+					$this->query("SELECT @@identity", __LINE__, __FILE__);
+					$this->next_record();
+					$ret = $this->f(0);
+					break;
+				default:
+					$ret = $this->db->lastInsertId();
 					}
-					else
-					{
-						$result = @pg_Exec($this->adodb->_connectionID, "select lastval()");
-					}
 	
-					if (!$result)
+			if($ret)
 					{
-						return -1;
+				return $ret;
 					}
-	
-					$Record = @pg_fetch_array($result, 0);
-	
-					@pg_freeresult($result);
-					if (!is_array($Record)) /* OID not found? */
-					{
 						return -1;
 					}
-					return $Record[0];
-					break;
 
-				case 'mssql':
-					/*  MSSQL uses a query to retrieve the last
-					 *  identity on the connection, so table and field are ignored here as well.
+		/**
+		* Find the name of sequense for postgres
+		*
+		* @param string $table name of table
+		* @return string name of the sequense, false if fails
 					 */
-					if(!isset($table) || $table == '' || !isset($field) || $field == '')
+		protected function _get_sequence_field_for_table($table, $field ='')
 					{
-						return -1;
-					}
-					
-					$result = @mssql_query("select @@identity", $this->adodb->_queryID);
-					if(!$result)
+			//old naming of sequenses
+			$sql = "SELECT relname FROM pg_class WHERE NOT relname ~ 'pg_.*'"
+				. " AND relname = '{$table}_{$field}_seq' AND relkind='S' ORDER BY relname";
+			$this->query($sql,__LINE__,__FILE__);
+			if ($this->next_record())
 					{
-						return -1;
+				return $this->f('relname');
 					}
-					return mssql_result($result, 0, 0);
-					break;
-
-				default:
-					return $this->adodb->Insert_ID($table, $field);
+			$sql = "SELECT relname FROM pg_class WHERE NOT relname ~ 'pg_.*'"
+				. " AND relname = 'seq_{$table}' AND relkind='S' ORDER BY relname";
+			$this->query($sql,__LINE__,__FILE__);
+			if ($this->next_record())
+			{
+				return $this->f('relname');
 			}
+			return false;
 		}
 
+
 		/**
 		* Lock a table
 		*
@@ -527,7 +686,7 @@
 		*/
 		public function lock($table, $mode='write')
 		{
-			//$this->adodb->BeginTrans();
+			$this->transaction_begin();
 		}
 		
 		
@@ -538,18 +697,17 @@
 		*/
 		public function unlock()
 		{
-			//$this->adodb->CommitTrans();
+			$this->transaction_commit();
 		}
 		
 		/**
-		 * Prepare the VALUES component of an INSERT sql statement
+		 * Prepare the VALUES component of an INSERT sql statement by guessing data types
 		 * 
+		 * It is not a good idea to rely on the data types determined by this method if 
+		 * you are inserting numeric data into varchar/text fields, such as street numbers
+		 *
 		 * @param array $value_set array of values to insert into the database
-		 *
 		 * @return string the prepared sql, empty string for invalid input
-		 *
-		 * @internal this method tries to guess target data types, 
-		 * so the results may not match the db schema - use with caution
 		 */
 		public function validate_insert($values)
 		{
@@ -561,15 +719,15 @@
 			$insert_value = array();
 			foreach ( $values as $value )
 			{
-				if ( $value || $value === 0)
+				if($value || (is_numeric($value) && $value == 0) )
 				{
 					if ( is_numeric($value) )
 					{
-						$insert_value[]	= "$value";
+						$insert_value[]	= "'$value'";
 					}
 					else
 					{
-						$insert_value[]	= "'$value'";
+						$insert_value[]	= "'" . $this->db_addslashes(stripslashes($value)) . "'"; //in case slashes are already added.
 					}
 				}
 				else
@@ -596,12 +754,19 @@
 			$value_entry = array();
 			foreach ( $value_set as $field => $value )
 			{
-				if($value || $value === 0)
+				if($value || (is_numeric($value) && $value == 0) )
 				{
 					if ( is_numeric($value) )
 					{
+						if((strlen($value) > 1 && strpos($value,'0') === 0))
+						{
+							$value_entry[]= "{$field}='{$value}'";
+						}
+						else
+						{
 						$value_entry[]= "{$field}={$value}";
 					}
+					}
 					else
 					{
 						$value_entry[]= "{$field}='{$value}'";
@@ -622,7 +787,7 @@
 		*/
 		public function affected_rows()
 		{
-			return $this->adodb->Affected_Rows();
+			return $this->affected_rows;
 		}
 		
 		/**
@@ -634,7 +799,7 @@
 		{
 			if($this->resultSet)
 			{
-				return $this->resultSet->RecordCount();
+				return count($this->resultSet);
 			}
 			return 0;
 		}
@@ -680,22 +845,22 @@
 		*/
 		public function f($name, $strip_slashes = False)
 		{
-			if($this->resultSet && get_class($this->resultSet) != 'adorecordset_empty')
+			if($this->resultSet)
 			{
-				if( isset($this->resultSet->fields[$name]) )
+				if( isset($this->Record[$name]) )
 				{
 					if ($strip_slashes || ($this->auto_stripslashes && ! $strip_slashes))
 					{
-						return stripslashes($this->resultSet->fields[$name]);
+						return stripslashes($this->Record[$name]);
 					}
 					else
 					{
-						return $this->resultSet->fields[$name];
-					}
+						return $this->Record[$name];
 				}
 			}
 			return '';
 		}
+		}
 
 		/**
 		* Print the value of a field
@@ -717,6 +882,7 @@
 		*/
 		public function nextid($seq_name)
 		{
+			//echo "depi: nextid";
 		}
 
 		/**
@@ -728,14 +894,15 @@
 		*/  
 		public function metadata($table = '',$full = false)
 		{
-			if(!$this->adodb->IsConnected())
+			if(!$this->adodb || !$this->adodb->IsConnected())
 			{
-				$this->connect();
+				$this->_connect_adodb();
 			}
-			if(!($return =& $this->adodb->MetaColumns($table,$full)))
+			if(!($return = $this->adodb->MetaColumns($table,$full)))
 			{
 				$return = array();
 			}
+			$this->adodb->close();
 			return $return;
 			
 			/*
@@ -773,37 +940,71 @@
 		* @param boolean $upper optional, default False. If $upper is true, then the table names (array keys) are upper-cased.
 		* @return array Table meta data
 		*/  
-		public function MetaForeignKeys($table = '', $owner=false, $upper=false)
+		public function MetaForeignKeys($table, $owner=false, $upper=false)
 		{
-			if(!$this->adodb->IsConnected())
+			if(!$this->adodb || !$this->adodb->IsConnected())
 			{
-				$this->connect();
+				$this->_connect_adodb();
 			}
-			if(!($return =& $this->adodb->MetaForeignKeys($table, $owner, $upper)))
+			if(!($return = $this->adodb->MetaForeignKeys($table, $owner, $upper)))
 			{
 				$return = array();
 			}
+			$this->adodb->close();
 			return $return;
 		}
+		/**
+		* Returns an associate array of foreign keys, or false if not supported.
+		*
+		* @param string $table name of table to describe
+		* @param boolean $primary optional, default False.
+		* @return array Index data
+		*/  
 
+		public function metaindexes($table, $primary = false)
+		{
+			if(!$this->adodb || !$this->adodb->IsConnected())
+			{
+				$this->_connect_adodb();
+			}
+			if(!($return = $this->adodb->MetaIndexes($table, $primary)))
+			{
+				$return = array();
+			}
+			$this->adodb->close();
+			return $return;
+		}
+
 		/**
+		* Error handler
+		*
+		* @param string $msg error message
+		* @param int $line line of calling method/function (optional)
+		* @param string $file file of calling method/function (optional)
+		*/
+		public function halt($msg, $line = '', $file = '')
+		{
+			$this->db->rollBack();
+		}
+		
+		/**
 		* Get a list of table names in the current database
 		*
 		* @return array list of the tables
 		*/
 		public function table_names()
 		{
-			if ( !$this->adodb->IsConnected() )
+			if(!$this->adodb || !$this->adodb->IsConnected())
 			{
-				$this->connect();
+				$this->_connect_adodb();
 			}
 
 			$return = $this->adodb->MetaTables('TABLES');
+			$this->adodb->close();
 			if ( !$return )
 			{
 				return array();
 			}
-
 			return $return;
 		}
 
@@ -824,69 +1025,49 @@
 		* @param string $adminname Name of database administrator user (optional)
 		* @param string $adminpasswd Password for the database administrator user (optional)
 		* @returns bool was the new db created?
+		* @throws Exception invalid db-name
 		*/
 		public function create_database($adminname = '', $adminpasswd = '')
 		{			
 			//THIS IS CALLED BY SETUP DON'T KILL IT!
-			if ( $this->adodb->IsConnected() )
+			if ( $this->db )
 			{
-				$this->adodb->Disconnect(); //close the dead connection to be safe
+				$this->db = null; //close the dead connection to be safe
 			}
 
-			$this->adodb = newADOConnection($GLOBALS['phpgw_info']['server']['db_type']);
-			if ( $adminpasswd )
-			{
-				$this->adodb->NConnect($this->Host, $adminname, $adminpasswd);
-			}
-			else
-			{
-				// this is insecure, but some people don't have an admin password set
-				$this->adodb->NConnect($this->Host, $adminname);
-			}
+			$this->connect();
 			
-			if ( !$this->adodb->IsConnected() )
+			if ( !$this->db )
 			{
 				echo 'Connection FAILED<br />';
-				return false;
+				return False;
 			}
 			
-			$db = $this->db_addslashes($this->Database);
-
-			//create the db
-			$this->adodb->query("CREATE DATABASE {$db}");
-			
-			$server = 'localhost';
-			if ( $this->Host != 'localhost' )
+			if( !preg_match('/^[a-z0-9_]+$/i', $this->Database) )
 			{
-				$server = $this->db_addslashes(phpgw::get_var('SERVER_NAME', 'string', 'SERVER'));
+				throw new Exception(lang('ERROR: the name %1 contains illegal charackter for cross platform db-support', $this->Database));
 			}
 			
-			$user = $this->db_addslashes($this->User);
-			$pass = $this->db_addslashes($this->Password);
-
+			//create the db
+			$this->db->exec("CREATE DATABASE {$this->Database}");
 		
 			//Grant rights on the db
-			switch ($this->Type)
+			switch ($GLOBALS['phpgw_info']['server']['db_type'])
 			{
 				case 'mysql':
-					$this->adodb->Execute("GRANT ALL ON {$db}.*"
-							. " TO '{$user}'@'{$server}'"
-							. " IDENTIFIED BY '{$pass}'");
-					break;
-
+					$this->db->exec("GRANT ALL ON {$this->Database}.*"
+							. " TO {$this->User}@{$_SERVER['SERVER_NAME']}"
+							. " IDENTIFIED BY '{$this->Password}'");
 				default:
 					//do nothing
 			}
-			
-			$this->adodb->Disconnect();
-			return true;
+			$this->db = null;
+			return True;
 		}
-
 		/**
 		* Get the correct date format for DATE field for a particular RDBMS
 		*
 		* @internal the string is compatiable with PHP's date()
-		* 
 		* @return string the date format string
 		*/
 		public static function date_format()
@@ -894,16 +1075,16 @@
 			static $date_format = null;
 			if ( is_null($date_format) )
 			{
-				switch ( $GLOBALS['phpgw_info']['server']['db_type'] )
+				switch($GLOBALS['phpgw_info']['server']['db_type'])
 				{
+					case 'mssql':
+						$date_format 		= 'M d Y';
+						break;
 					case 'mysql':
 					case 'pgsql':
 					case 'postgres':
 					default:
 						$date_format 		= 'Y-m-d';
-						break;
-					case 'mssql':
-						$date_format 		= 'M d Y';
 				}
 			}
 			return $date_format;
@@ -936,28 +1117,115 @@
 	 	}
 				
 	 	/**
-		* Prepare SQL statement
+		* Get the correct datetime format for MONEY field for a particular RDBMS
 		*
-		* @param string $query SQL query
-		* @return integer|boolean Result identifier for query_prepared_statement() or FALSE
-		* @see query_prepared_statement()
+		* @return string the formatted string
 		*/
-		public function prepare_sql_statement($query)
+		public static function money_format($amount)
 		{
-			return false;
+			if ($GLOBALS['phpgw_info']['server']['db_type']=='mssql')
+			{
+				return "CONVERT(MONEY,'{$amount}',0)";
+			}
+			else
+			{
+				return "'{$amount}'";
+			}
 		}
 
 		/**
-		 * Execute prepared SQL statement
+		 * Execute prepared SQL statement for insert
 		 *
-		 * @param resource $result_id Result identifier from prepare_sql_statement()
-		 * @param array $parameters_array Parameters for the prepared SQL statement
+		 * @param string $sql_string 
+		 * @param array $valueset  values,id and datatypes for the insert 
+		 * Use type = PDO::PARAM_STR for strings and type = PDO::PARAM_INT for integers
 		 * @return boolean TRUE on success or FALSE on failure
-		 * @see prepare_sql_statement()
 		 */
-		public function query_prepared_statement($result_id, $parameters_array)
+
+		public function insert($sql_string, $valueset, $line = '', $file = '')
 		{
-			return false;
+			try
+			{
+				$statement_object = $this->db->prepare($sql_string);
+				foreach($valueset as $fields)
+				{
+					foreach($fields as $field => $entry)
+					{
+						$statement_object->bindParam($field, $entry['value'], $entry['type']);
+					}
+					$ret = $statement_object->execute();
+				}
+			}
+
+			catch(PDOException $e)
+			{
+				trigger_error('Error: ' . $e->getMessage() . "<br>SQL: $sql\n in File: $file\n on Line: $line\n", E_USER_ERROR);
+			}
+			return $ret;
+		}
+
+		/**
+		 * Execute prepared SQL statement for select
+		 *
+		 * @param string $sql_string 
+		 * @param array $params conditions for the select 
+		 * @return boolean TRUE on success or FALSE on failure
+		 */
+
+		public function select($sql_string, $params, $line = '', $file = '')
+		{		
+			try
+			{
+				$statement_object = $this->db->prepare($sql_string);
+				$statement_object->execute($params);
+				if($this->fetchmode == 'ASSOC')
+				{
+					$this->resultSet = $statement_object->fetchAll(PDO::FETCH_ASSOC);
+				}
+				else
+				{
+					$this->resultSet = $statement_object->fetchAll(PDO::FETCH_BOTH);
+				}
+			}
+			catch(PDOException $e)
+			{
+				trigger_error('Error: ' . $e->getMessage() . "<br>SQL: $sql\n in File: $file\n on Line: $line\n", E_USER_ERROR);
+			}
+			$this->delayPointer = true;
+		}
+
+		/**
+		* Finds the next ID for a record at a table
+		*
+		* @param string $table tablename in question
+		* @param array $key conditions
+		* @return int the next id
+		*/
+
+		public function next_id($table='',$key='')
+		{
+			$where = '';
+			$condition = array();
+			if(is_array($key))
+			{
+				foreach ($key as $column => $value)
+				{
+					if($value)
+					{
+						$condition[] = $column . "='" . $value;
+					}
+				}
+
+				if( $condition )
+				{
+					$where='WHERE ' . implode("' AND ", $condition) . "'";
+				}
+			}
+
+			$this->query("SELECT max(id) as maximum FROM $table $where",__LINE__,__FILE__);
+			$this->next_record();
+			$next_id = $this->f('maximum')+1;
+			return $next_id;
 		}  
 
 	}

Modified: people/sigurdne/modules/phpgwapi/trunk/inc/class.error.inc.php
===================================================================
--- people/sigurdne/modules/phpgwapi/trunk/inc/class.error.inc.php	2009-11-20 10:27:41 UTC (rev 20844)
+++ people/sigurdne/modules/phpgwapi/trunk/inc/class.error.inc.php	2009-11-20 10:28:10 UTC (rev 20845)
@@ -8,21 +8,6 @@
 	* @package phpgwapi
 	* @subpackage application
 	* @version $Id$
-	*/
-
-	/*
-	   This program is free software: you can redistribute it and/or modify
-	   it under the terms of the GNU Lesser General Public License as published by
-	   the Free Software Foundation, either version 3 of the License, or
-	   (at your option) any later version.
-
-	   This program is distributed in the hope that it will be useful,
-	   but WITHOUT ANY WARRANTY; without even the implied warranty of
-	   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-	   GNU General Public License for more details.
-
-	   You should have received a copy of the GNU Lesser General Public License
-	   along with this program.  If not, see <http://www.gnu.org/licenses/>.
 	 */
 
 	/**

Modified: people/sigurdne/modules/phpgwapi/trunk/inc/class.errorlog.inc.php
===================================================================
--- people/sigurdne/modules/phpgwapi/trunk/inc/class.errorlog.inc.php	2009-11-20 10:27:41 UTC (rev 20844)
+++ people/sigurdne/modules/phpgwapi/trunk/inc/class.errorlog.inc.php	2009-11-20 10:28:10 UTC (rev 20845)
@@ -8,21 +8,6 @@
 	* @package phpgwapi
 	* @subpackage application
 	* @version $Id$
-	*/
-
-	/*
-	   This program is free software: you can redistribute it and/or modify
-	   it under the terms of the GNU General Public License as published by
-	   the Free Software Foundation, either version 3 of the License, or
-	   (at your option) any later version.
-
-	   This program is distributed in the hope that it will be useful,
-	   but WITHOUT ANY WARRANTY; without even the implied warranty of
-	   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-	   GNU General Public License for more details.
-
-	   You should have received a copy of the GNU General Public License
-	   along with this program.  If not, see <http://www.gnu.org/licenses/>.
 	 */
 
 	/**
@@ -123,7 +108,7 @@
 			$db =& $GLOBALS['phpgw']->db;
 //			$db->lock('phpgw_log');
 			$db->query("insert into phpgw_log (log_date, log_user, log_app, log_severity) values "
-				."('". $GLOBALS['phpgw']->db->to_timestamp(time())
+				."('". date($db->datetime_format())
 				."',".intval($GLOBALS['phpgw']->session->account_id)
 				.",'".$GLOBALS['phpgw_info']['flags']['currentapp']."'"
 				.",'".$this->severity()."'"

Modified: people/sigurdne/modules/phpgwapi/trunk/inc/class.excel.inc.php
===================================================================
--- people/sigurdne/modules/phpgwapi/trunk/inc/class.excel.inc.php	2009-11-20 10:27:41 UTC (rev 20844)
+++ people/sigurdne/modules/phpgwapi/trunk/inc/class.excel.inc.php	2009-11-20 10:28:10 UTC (rev 20845)
@@ -5,6 +5,7 @@
 	* @author Sigurd Nes <[email protected]>
 	* @copyright Copyright (C) 2003-2005 Free Software Foundation, Inc. http://www.fsf.org/
 	* @license http://www.gnu.org/licenses/gpl.html GNU General Public License
+	* @internal Development of this application was funded by http://www.bergen.kommune.no/bbb_/ekstern/
 	* @package phpgwapi
 	* @subpackage utilities
  	* @version $Id$
@@ -31,21 +32,7 @@
 	* </code>
 	*/
 
-	/*
-	   This program is free software: you can redistribute it and/or modify
-	   it under the terms of the GNU General Public License as published by
-	   the Free Software Foundation, either version 3 of the License, or
-	   (at your option) any later version.
 
-	   This program is distributed in the hope that it will be useful,
-	   but WITHOUT ANY WARRANTY; without even the implied warranty of
-	   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-	   GNU General Public License for more details.
-
-	   You should have received a copy of the GNU General Public License
-	   along with this program.  If not, see <http://www.gnu.org/licenses/>.
-	 */
-
 	/**
 	* @see worksheet
 	*/
@@ -55,3 +42,4 @@
 	* @see workbook
 	*/
 	require_once(PHPGW_API_INC . '/excel/Workbook.php');
+?>

Modified: people/sigurdne/modules/phpgwapi/trunk/inc/class.excelreader.inc.php
===================================================================
--- people/sigurdne/modules/phpgwapi/trunk/inc/class.excelreader.inc.php	2009-11-20 10:27:41 UTC (rev 20844)
+++ people/sigurdne/modules/phpgwapi/trunk/inc/class.excelreader.inc.php	2009-11-20 10:28:10 UTC (rev 20845)
@@ -6,32 +6,23 @@
 	* Based on the Java version by Andy Khan (http://www.andykhan.com).  Now
 	* maintained by David Sanders.  Reads only Biff 7 and Biff 8 formats.
 	*
+	* PHP versions 4 and 5
+	*
 	* @author Vadim Tkachenko <[email protected]>
 	* @author Sigurd Nes <[email protected]>
 	* @copyright Copyright (C) 2003-2005 Free Software Foundation, Inc. http://www.fsf.org/
 	* @license http://www.gnu.org/licenses/lgpl.html GNU Lesser General Public License
+	* @internal Development of this application was funded by http://www.bergen.kommune.no/bbb_/ekstern/
 	* @package phpgwapi
 	* @subpackage utilities
  	* @version $Id$
 	*
 	*/
 
-	/*
-	   This program is free software: you can redistribute it and/or modify
-	   it under the terms of the GNU Lesser General Public License as published by
-	   the Free Software Foundation, either version 3 of the License, or
-	   (at your option) any later version.
 
-	   This program is distributed in the hope that it will be useful,
-	   but WITHOUT ANY WARRANTY; without even the implied warranty of
-	   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-	   GNU General Public License for more details.
-
-	   You should have received a copy of the GNU Lesser General Public License
-	   along with this program.  If not, see <http://www.gnu.org/licenses/>.
-	 */
-
 	/**
-	* Include reader class from module directory 
+	* 
 	*/
 	require_once(PHPGW_API_INC . '/excelreader/reader.php');
+
+?>

Modified: people/sigurdne/modules/phpgwapi/trunk/inc/class.gdbutton.inc.php
===================================================================
--- people/sigurdne/modules/phpgwapi/trunk/inc/class.gdbutton.inc.php	2009-11-20 10:27:41 UTC (rev 20844)
+++ people/sigurdne/modules/phpgwapi/trunk/inc/class.gdbutton.inc.php	2009-11-20 10:28:10 UTC (rev 20845)
@@ -10,21 +10,7 @@
 	* @internal Some methods based on former class.graphics 2001 Lars Kneschke
 	*/
 
-	/*
-	   This program is free software: you can redistribute it and/or modify
-	   it under the terms of the GNU General Public License as published by
-	   the Free Software Foundation, either version 3 of the License, or
-	   (at your option) any later version.
 
-	   This program is distributed in the hope that it will be useful,
-	   but WITHOUT ANY WARRANTY; without even the implied warranty of
-	   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-	   GNU General Public License for more details.
-
-	   You should have received a copy of the GNU General Public License
-	   along with this program.  If not, see <http://www.gnu.org/licenses/>.
-	 */
-
 	/**
 	* Creates graphical buttons by using GD and TTF fonts
 	*

Modified: people/sigurdne/modules/phpgwapi/trunk/inc/class.gdgraph.inc.php
===================================================================
--- people/sigurdne/modules/phpgwapi/trunk/inc/class.gdgraph.inc.php	2009-11-20 10:27:41 UTC (rev 20844)
+++ people/sigurdne/modules/phpgwapi/trunk/inc/class.gdgraph.inc.php	2009-11-20 10:28:10 UTC (rev 20845)
@@ -10,21 +10,7 @@
 	* @internal This class based on boGraph.php3 - Double Choco Latte - Source Configuration Management System Copyright (C) 1999  Michael L. Dean & Tim R. Norman
 	*/
 
-	/*
-	   This program is free software: you can redistribute it and/or modify
-	   it under the terms of the GNU General Public License as published by
-	   the Free Software Foundation, either version 3 of the License, or
-	   (at your option) any later version.
 
-	   This program is distributed in the hope that it will be useful,
-	   but WITHOUT ANY WARRANTY; without even the implied warranty of
-	   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-	   GNU General Public License for more details.
-
-	   You should have received a copy of the GNU General Public License
-	   along with this program.  If not, see <http://www.gnu.org/licenses/>.
-	 */
-
 	/**
 	* Creates graphical statistics using GD graphics library
 	*

Modified: people/sigurdne/modules/phpgwapi/trunk/inc/class.gdimage.inc.php
===================================================================
--- people/sigurdne/modules/phpgwapi/trunk/inc/class.gdimage.inc.php	2009-11-20 10:27:41 UTC (rev 20844)
+++ people/sigurdne/modules/phpgwapi/trunk/inc/class.gdimage.inc.php	2009-11-20 10:28:10 UTC (rev 20845)
@@ -10,22 +10,7 @@
 	* @internal This class based on htmlGD.php3 - Double Choco Latte - Source Configuration Management System - Copyright (C) 1999  Michael L. Dean & Tim R. Norman
 	*/
 
-	/*
-	   This program is free software: you can redistribute it and/or modify
-	   it under the terms of the GNU General Public License as published by
-	   the Free Software Foundation, either version 3 of the License, or
-	   (at your option) any later version.
 
-	   This program is distributed in the hope that it will be useful,
-	   but WITHOUT ANY WARRANTY; without even the implied warranty of
-	   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-	   GNU General Public License for more details.
-
-	   You should have received a copy of the GNU General Public License
-	   along with this program.  If not, see <http://www.gnu.org/licenses/>.
-	 */
-
-
 	/**
 	* Creates images using GD graphics library
 	*

Modified: people/sigurdne/modules/phpgwapi/trunk/inc/class.globally_denied.inc.php
===================================================================
--- people/sigurdne/modules/phpgwapi/trunk/inc/class.globally_denied.inc.php	2009-11-20 10:27:41 UTC (rev 20844)
+++ people/sigurdne/modules/phpgwapi/trunk/inc/class.globally_denied.inc.php	2009-11-20 10:28:10 UTC (rev 20845)
@@ -7,16 +7,16 @@
 	* @author Philipp Kamps <[email protected]>
 	* @author Dave Hall <[email protected]>
 	* @copyright Copyright (C) 2000-2008 Free Software Foundation, Inc. http://www.fsf.org/
-	* @license http://www.gnu.org/licenses/lgpl.html GNU Lesser General Public License v3 or later
+	* @license http://www.gnu.org/licenses/lgpl.html GNU Lesser General Public License v2 or later
 	* @package phpgwapi
 	* @subpackage utility
-	* @version $Id: class.accounts_.inc.php 779 2008-02-26 09:53:55Z dave $
+	* @version $Id: class.globally_denied.inc.php 2588 2009-04-14 11:00:02Z sigurd $
 	*/
 
 	/*
 	   This program is free software: you can redistribute it and/or modify
 	   it under the terms of the GNU Lesser General Public License as published by
-	   the Free Software Foundation, either version 3 of the License, or
+	   the Free Software Foundation, either version 2 of the License, or
 	   (at your option) any later version.
 
 	   This program is distributed in the hope that it will be useful,

Modified: people/sigurdne/modules/phpgwapi/trunk/inc/class.historylog.inc.php
===================================================================
--- people/sigurdne/modules/phpgwapi/trunk/inc/class.historylog.inc.php	2009-11-20 10:27:41 UTC (rev 20844)
+++ people/sigurdne/modules/phpgwapi/trunk/inc/class.historylog.inc.php	2009-11-20 10:28:10 UTC (rev 20845)
@@ -7,21 +7,6 @@
 	* @package phpgwapi
 	* @subpackage application
 	* @version $Id$
-	*/
-
-	/*
-	   This program is free software: you can redistribute it and/or modify
-	   it under the terms of the GNU Lesser General Public License as published by
-	   the Free Software Foundation, either version 3 of the License, or
-	   (at your option) any later version.
-
-	   This program is distributed in the hope that it will be useful,
-	   but WITHOUT ANY WARRANTY; without even the implied warranty of
-	   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-	   GNU General Public License for more details.
-
-	   You should have received a copy of the GNU Lesser General Public License
-	   along with this program.  If not, see <http://www.gnu.org/licenses/>.
 	 */
 
 	/**
@@ -33,7 +18,7 @@
 	class historylog
 	{
 		var $db;
-		var $appname;
+		var $location_id;
 		var $template;
 		var $nextmatchs;
 		var $types = array(
@@ -43,21 +28,22 @@
 		);
 		var $alternate_handlers = array();
 
-		function historylog($appname)
+		function historylog($appname, $location = '.')
 		{
 			if (! $appname)
 			{
 				$appname = $GLOBALS['phpgw_info']['flags']['currentapp'];
 			}
 
-			$this->appname = $appname;
+			$location_id = $GLOBALS['phpgw']->locations->get_id($appname, $location);
+			$this->location_id = (int) $location_id;
 			$this->db      =& $GLOBALS['phpgw']->db;
 		}
 
 		function delete($record_id)
 		{
 			$this->db->query("DELETE FROM phpgw_history_log WHERE history_record_id='".(int)$record_id."' and "
-				. "app_id='" . $GLOBALS['phpgw']->applications->name2id($this->appname) . "'",__LINE__,__FILE__);
+				. "location_id=" . $this->location_id ,__LINE__,__FILE__);
 		}
 
 		function add($status,$record_id,$new_value,$old_value)
@@ -65,10 +51,10 @@
 			if ($new_value != $old_value)
 			{
 				$this->db->query("INSERT INTO phpgw_history_log (history_record_id,"
-					. "app_id,history_owner,history_status,history_new_value,history_old_value,history_timestamp) "
-					. "VALUES ('".(int)$record_id."','" . $GLOBALS['phpgw']->applications->name2id($this->appname) . "','"
+					. "location_id,history_owner,history_status,history_new_value,history_old_value,history_timestamp) "
+					. "VALUES ('".(int)$record_id."'," . $this->location_id . ",'"
 					. $GLOBALS['phpgw_info']['user']['account_id'] . "','$status','"
-					. $this->db->db_addslashes($new_value) . "','" . $this->db->db_addslashes($old_value) . "','" . $this->db->to_timestamp(time())
+					. $this->db->db_addslashes($new_value) . "','" . $this->db->db_addslashes($old_value) . "','" . date($this->db->datetime_format())
 					. "')",__LINE__,__FILE__);
 			}
 		}
@@ -114,7 +100,7 @@
 			}
 
 			$this->db->query('SELECT * FROM phpgw_history_log'
-				. " WHERE app_id='{$GLOBALS['phpgw']->applications->name2id($this->appname)}' AND history_record_id = {$record_id} $filter $only_show_filter "
+				. " WHERE location_id= {$this->location_id} AND history_record_id = {$record_id} $filter $only_show_filter "
 				. $orderby, __LINE__, __FILE__);
 
 			$return_values = array();
@@ -127,8 +113,8 @@
 					'owner'      => $GLOBALS['phpgw']->accounts->id2name($this->db->f('history_owner')),
 //					'status'     => lang($this->types[$this->db->f('history_status')]),
 					'status'     => ereg_replace(' ','',$this->db->f('history_status')),
-					'new_value'  => $this->db->f('history_new_value'),
-					'old_value'  => $this->db->f('history_old_value'),
+					'new_value'  => htmlspecialchars_decode($this->db->f('history_new_value',true)),
+					'old_value'  => htmlspecialchars_decode($this->db->f('history_old_value',true)),
 					'datetime'   => $this->db->from_timestamp($this->db->f('history_timestamp'))
 				);
 			}
@@ -174,7 +160,7 @@
 				$this->template->set_var('row_date',$GLOBALS['phpgw']->common->show_date($value['datetime']));
 				$this->template->set_var('row_owner',$value['owner']);
 
-				if (isset($this->alternate_handlers[$value['status']]))
+				if ($this->alternate_handlers[$value['status']])
 				{
 					eval('\$s = ' . $this->alternate_handlers[$value['status']] . '(' . $value['new_value'] . ');');
 					$this->template->set_var('row_new_value',$s);

Modified: people/sigurdne/modules/phpgwapi/trunk/inc/class.hooks.inc.php
===================================================================
--- people/sigurdne/modules/phpgwapi/trunk/inc/class.hooks.inc.php	2009-11-20 10:27:41 UTC (rev 20844)
+++ people/sigurdne/modules/phpgwapi/trunk/inc/class.hooks.inc.php	2009-11-20 10:28:10 UTC (rev 20845)
@@ -6,13 +6,13 @@
 	* @license http://www.fsf.org/licenses/lgpl.html GNU Lesser General Public License
 	* @package phpgwapi
 	* @subpackage application
-	* @version $Id$
+	 * @version $Id$
 	*/
 
 	/*
 	   This program is free software: you can redistribute it and/or modify
 	   it under the terms of the GNU Lesser General Public License as published by
-	   the Free Software Foundation, either version 3 of the License, or
+	   the Free Software Foundation, either version 2 of the License, or
 	   (at your option) any later version.
 
 	   This program is distributed in the hope that it will be useful,
@@ -20,7 +20,7 @@
 	   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 	   GNU General Public License for more details.
 
-	   You should have received a copy of the GNU Lesser General Public License
+	   You should have received a copy of the GNU General Public License
 	   along with this program.  If not, see <http://www.gnu.org/licenses/>.
 	 */
 
@@ -32,39 +32,17 @@
 	*/
 	class phpgwapi_hooks
 	{
-		/**
-		 * @var array $found_hooks the list of available hooks
-		 *
-		 * @todo work out if this should be protected
-		 */
-		public $found_hooks = array();
-
-		/**
-		 * @var object $db reference to global db object
-		 */
+		var $found_hooks = Array();
 		protected $db = null;
 
-		/**
-		 * Constructor
-		 *
-		 * @return void
-		 */
 		public function __construct($db = null)
 		{
-			// this is to allow setup to set the db
-			$this->db = $db;
-			if ( is_null($this->db) )
-			{
-				$this->db = $GLOBALS['phpgw']->db;
-			}
-
+			$this->db = !is_null($db) ? $db : $GLOBALS['phpgw']->db;	// this is to allow setup to set the db
 			$this->read();
 		}
 
 		/**
 		* Read all the hooks
-		*
-		* @return array list of hooks
 		*/
 		public function read()
 		{
@@ -73,8 +51,9 @@
 			{
 				$this->found_hooks[$this->db->f('hook_appname')][$this->db->f('hook_location')] = $this->db->f('hook_filename');
 			}
-
-			//echo '<pre>' . print_r($this->found_hooks, true) . '</pre>';
+			//echo '<pre>';
+			//print_r($this->found_hooks);
+			//echo '</pre>';
 			return $this->found_hooks;
 		}
 		
@@ -231,6 +210,7 @@
 			{
 				return False;
 			}
+
 			$db_appname = $this->db->db_addslashes($appname);
 			$this->db->query("DELETE FROM phpgw_hooks WHERE hook_appname='$db_appname'",__LINE__,__FILE__);
 
@@ -238,7 +218,6 @@
 			{
 				return True;
 			}
-
 			foreach ( $hooks as $key => $hook )
 			{
 				if ( !is_numeric($key) )	// new method based hook
@@ -251,7 +230,6 @@
 					$location = $hook;
 					$filename = "hook_$hook.inc.php";
 				}
-
 				$this->db->query("INSERT INTO phpgw_hooks (hook_appname,hook_location,hook_filename)".
 					" VALUES ('$appname','$location','$filename')",__LINE__,__FILE__);
 			}
@@ -265,6 +243,11 @@
 		 */
 		public function register_all_hooks()
 		{
+			if ( !isset($GLOBALS['phpgw_info']['apps']) || !is_array($GLOBALS['phpgw_info']['apps']) )
+			{
+				$GLOBALS['phpgw']->applications->read_installed_apps();
+			}
+
 			$app_list = array_keys($GLOBALS['phpgw_info']['apps']);
 			$app_list[] = 'phpgwapi';
 			

Modified: people/sigurdne/modules/phpgwapi/trunk/inc/class.html2text.inc.php
===================================================================
--- people/sigurdne/modules/phpgwapi/trunk/inc/class.html2text.inc.php	2009-11-20 10:27:41 UTC (rev 20844)
+++ people/sigurdne/modules/phpgwapi/trunk/inc/class.html2text.inc.php	2009-11-20 10:28:10 UTC (rev 20845)
@@ -11,6 +11,19 @@
  * Copyright (c) 2005 Jon Abernathy <[email protected]>                  *
  * All rights reserved.                                                  *
  *                                                                       *
+ * This script is free software; you can redistribute it and/or modify   *
+ * it under the terms of the GNU General Public License as published by  *
+ * the Free Software Foundation; either version 2 of the License, or     *
+ * (at your option) any later version.                                   *
+ *                                                                       *
+ * The GNU General Public License can be found at                        *
+ * http://www.gnu.org/copyleft/gpl.html.                                 *
+ *                                                                       *
+ * This script is distributed in the hope that it will be useful,        *
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of        *
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the          *
+ * GNU General Public License for more details.                          *
+ *                                                                       *
  * Author(s): Jon Abernathy <[email protected]>                          *
  *                                                                       *
  * Last modified: 04/06/05                                               *
@@ -19,22 +32,7 @@
  * @subpackage utilities                                                 *
  ************************************************************************/
 
-/*
-   This program is free software: you can redistribute it and/or modify
-   it under the terms of the GNU Lesser General Public License as published by
-   the Free Software Foundation, either version 3 of the License, or
-   (at your option) any later version.
 
-   This program is distributed in the hope that it will be useful,
-   but WITHOUT ANY WARRANTY; without even the implied warranty of
-   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-   GNU General Public License for more details.
-
-   You should have received a copy of the GNU Lesser General Public License
-   along with this program.  If not, see <http://www.gnu.org/licenses/>.
- */
-
-
 /**
  *  Takes HTML and converts it to formatted, plain text.
  *
@@ -431,3 +429,5 @@
 	}
 
 }
+
+?>

Modified: people/sigurdne/modules/phpgwapi/trunk/inc/class.http.inc.php
===================================================================
--- people/sigurdne/modules/phpgwapi/trunk/inc/class.http.inc.php	2009-11-20 10:27:41 UTC (rev 20844)
+++ people/sigurdne/modules/phpgwapi/trunk/inc/class.http.inc.php	2009-11-20 10:28:10 UTC (rev 20845)
@@ -8,21 +8,6 @@
 	* @package phpgwapi
 	* @subpackage network
 	* @version $Id$
-	*/
-
-	/*
-	   This program is free software: you can redistribute it and/or modify
-	   it under the terms of the GNU Lesser General Public License as published by
-	   the Free Software Foundation, either version 3 of the License, or
-	   (at your option) any later version.
-
-	   This program is distributed in the hope that it will be useful,
-	   but WITHOUT ANY WARRANTY; without even the implied warranty of
-	   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-	   GNU General Public License for more details.
-
-	   You should have received a copy of the GNU Lesser General Public License
-	   along with this program.  If not, see <http://www.gnu.org/licenses/>.
 	 */
 
 	/**

Modified: people/sigurdne/modules/phpgwapi/trunk/inc/class.http_dav_client.inc.php
===================================================================
--- people/sigurdne/modules/phpgwapi/trunk/inc/class.http_dav_client.inc.php	2009-11-20 10:27:41 UTC (rev 20844)
+++ people/sigurdne/modules/phpgwapi/trunk/inc/class.http_dav_client.inc.php	2009-11-20 10:28:10 UTC (rev 20845)
@@ -11,21 +11,6 @@
 	* @internal At the moment much of this is simply a wrapper around the NET_HTTP_Client class, with some other methods for parsing the returned XML etc Ideally this will eventually use groupware's inbuilt HTTP class
 	*/
 
-	/*
-	   This program is free software: you can redistribute it and/or modify
-	   it under the terms of the GNU Lesser General Public License as published by
-	   the Free Software Foundation, either version 3 of the License, or
-	   (at your option) any later version.
-
-	   This program is distributed in the hope that it will be useful,
-	   but WITHOUT ANY WARRANTY; without even the implied warranty of
-	   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-	   GNU General Public License for more details.
-
-	   You should have received a copy of the GNU Lesser General Public License
-	   along with this program.  If not, see <http://www.gnu.org/licenses/>.
-	 */
-
 	/**
 	* Debug flag for dav client
 	*/
@@ -44,6 +29,18 @@
 	*/
   define ('DEBUG_CACHEPROP', 0);
 
+	// FIXME - code should be updated to the new PHP5/DOM to parse the XML.
+	if (!function_exists('domxml_open_mem'))
+	{
+		if(is_file(PHPGW_API_INC.'/domxml-php4-to-php5.php'))
+		{
+			require_once PHPGW_API_INC.'/domxml-php4-to-php5.php'; //Load a PHP5 converter
+		}
+		else
+		{
+			throw new Exception(lang('ERROR: you need the DOM XML Functions or a converter'));
+		}
+	}
 
 	/**
 	* DAV parser

Modified: people/sigurdne/modules/phpgwapi/trunk/inc/class.http_svn_client.inc.php
===================================================================
--- people/sigurdne/modules/phpgwapi/trunk/inc/class.http_svn_client.inc.php	2009-11-20 10:27:41 UTC (rev 20844)
+++ people/sigurdne/modules/phpgwapi/trunk/inc/class.http_svn_client.inc.php	2009-11-20 10:28:10 UTC (rev 20845)
@@ -11,21 +11,6 @@
 	* @internal At the moment much of this is simply a wrapper around the NET_HTTP_Client class, with some other methods for parsing the returned XML etc Ideally this will eventually use groupware's inbuilt HTTP class
 	*/
 
-	/*
-	   This program is free software: you can redistribute it and/or modify
-	   it under the terms of the GNU Lesser General Public License as published by
-	   the Free Software Foundation, either version 3 of the License, or
-	   (at your option) any later version.
-
-	   This program is distributed in the hope that it will be useful,
-	   but WITHOUT ANY WARRANTY; without even the implied warranty of
-	   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-	   GNU General Public License for more details.
-
-	   You should have received a copy of the GNU Lesser General Public License
-	   along with this program.  If not, see <http://www.gnu.org/licenses/>.
-	 */
-
 	/**
 	* Debug flag for svn client
 	*/
@@ -151,7 +136,10 @@
 		{
 			$svnxml = '<?xml version="1.0" encoding="utf-8" ?>
 			<S:log-report xmlns:S="svn:" xmlns:D="DAV">';
+			if($startvers)
+			{
 			$svnxml .= '<S:start-revision>'.$startvers.'</S:start-revision>'; 
+			}
 			$svnxml .= '<S:end-revision>'.$endvers.'</S:end-revision>';   
 			$svnxml .= '<S:path/>';
 			$svnxml.='<S:strict-node-history/>';
@@ -189,6 +177,7 @@
 		{
 			$ret=$this->report($uri,$startvers,$endvers);
 			$xml_result=$this->http_client->getBody();			
+
 			if ( !is_object($this->svn_processor))
 			{
 				$this->svn_processor = new SVNParser();

Modified: people/sigurdne/modules/phpgwapi/trunk/inc/class.interlink.inc.php
===================================================================
--- people/sigurdne/modules/phpgwapi/trunk/inc/class.interlink.inc.php	2009-11-20 10:27:41 UTC (rev 20844)
+++ people/sigurdne/modules/phpgwapi/trunk/inc/class.interlink.inc.php	2009-11-20 10:28:10 UTC (rev 20845)
@@ -4,8 +4,8 @@
 	*
 	* @author Dave Hall <[email protected]>
 	* @copyright (c) 2007 Dave Hall http://davehall.com.au
-	* @license http://www.gnu.org/licenses/gpl.html GNU General Public License Version 3 or later
-	* @version $Id$
+	* @license http://www.gnu.org/licenses/gpl.html GNU General Public License Version 2 or later
+	* @version $Id: class.interlink.inc.php 2588 2009-04-14 11:00:02Z sigurd $
 	* @package phpgwapi
 	* @subpackage utility
 	*/
@@ -13,7 +13,7 @@
 	/*
 		This program is free software: you can redistribute it and/or modify
 		it under the terms of the GNU General Public License as published by
-		the Free Software Foundation, either version 3 of the License, or
+		the Free Software Foundation, either version 2 of the License, or
 		(at your option) any later version.
 
 		This program is distributed in the hope that it will be useful,

Modified: people/sigurdne/modules/phpgwapi/trunk/inc/class.interserver.inc.php
===================================================================
--- people/sigurdne/modules/phpgwapi/trunk/inc/class.interserver.inc.php	2009-11-20 10:27:41 UTC (rev 20844)
+++ people/sigurdne/modules/phpgwapi/trunk/inc/class.interserver.inc.php	2009-11-20 10:28:10 UTC (rev 20845)
@@ -10,21 +10,9 @@
 	* @version $Id$
 	*/
 
-	/*
-	   This program is free software: you can redistribute it and/or modify
-	   it under the terms of the GNU Lesser General Public License as published by
-	   the Free Software Foundation, either version 3 of the License, or
-	   (at your option) any later version.
 
-	   This program is distributed in the hope that it will be useful,
-	   but WITHOUT ANY WARRANTY; without even the implied warranty of
-	   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-	   GNU General Public License for more details.
+	phpgw::import_class('phpgwapi.xmlrpc_client');
 
-	   You should have received a copy of the GNU Lesser General Public License
-	   along with this program.  If not, see <http://www.gnu.org/licenses/>.
-	 */
-
 	/**
 	* Inter-server communications - Maintain list and provide send interface to remote phpgw servers
 	* 
@@ -42,16 +30,13 @@
 		var $servers = array();
 		var $serverid = 0;
 		var $security = '';
-		var $mode = '';
+		var $mode = 'soap';
 		var $authed = False;
 		var $sessionid = '';
 		var $kp3 = '';
 
 		/* These are now entered as defaults if the admin forgot to enter the full URL */
-		var $urlparts = array(
-			'xmlrpc' => '/phpgroupware/xmlrpc.php',
-			'soap'   => '/phpgroupware/soap.php'
-		);
+		var $urlparts = array();
 
 		/*
 		0/none == no access
@@ -92,6 +77,11 @@
 
 		function interserver($serverid='')
 		{
+			$this->urlparts = array(
+				'xmlrpc' => "{$GLOBALS['phpgw_info']['server']['webserver_url']}/xmlrpc.php?domain=default",
+				'soap'   => "http://{$_SERVER['HTTP_HOST']}" . parse_url($GLOBALS['phpgw_info']['server']['webserver_url'], PHP_URL_PATH) . '/soap.php?domain=default'
+			);
+
 			$this->db =& $GLOBALS['phpgw']->db;
 			if($serverid)
 			{
@@ -169,8 +159,8 @@
 			list($uri,$hostpart) = $this->_split_url($url);
 			if(gettype($args) != 'array')
 			{
-				$arr[] = createObject('phpgwapi.xmlrpcval',$args,'string');
-				$f = createObject('phpgwapi.xmlrpcmsg', $method_name, $arr,'string');
+				$arr[] = new xmlrpcval($args,'string');
+				$f = new xmlrpcmsg($method_name, $arr,'string');
 			}
 			else
 			{
@@ -180,22 +170,23 @@
 					{
 						while(list($x,$y) = each($val))
 						{
-							$tmp[$x] = createObject('phpgwapi.xmlrpcval',$y, 'string');
+							$tmp[$x] = new xmlrpcval($y, 'string');
 						}
-						$ele[$key] = createObject('phpgwapi.xmlrpcval',$tmp,'struct');
+						$ele[$key] = new xmlrpcval($tmp,'struct');
 					}
 					else
 					{
-						$ele[$key] = createObject('phpgwapi.xmlrpcval',$val, 'string');
+						$ele[$key] = new xmlrpcval($val, 'string');
 					}
 				}
-				$arr[] = createObject('phpgwapi.xmlrpcval',$ele,'struct');
-				$f = createObject('phpgwapi.xmlrpcmsg', $method_name, $arr,'struct');
+				$arr[] = new xmlrpcval($ele,'struct');
+				$f = new xmlrpcmsg($method_name, $arr,'struct');
 			}
 
 			$this->debug("<pre>" . htmlentities($f->serialize()) . "</pre>\n",$debug);
-			$c = createObject('phpgwapi.xmlrpc_client',$uri, $hostpart, 443);
-			$c->setCredentials($this->sessionid,$this->kp3);
+			$c = new xmlrpc_client($uri, $hostpart, 443);
+			$c->setCredentials($args['username'],$args['password']);
+
 			$c->setDebug(0);
 			$r = $c->send($f,0,'https');
 			if (!$r)
@@ -221,8 +212,8 @@
 			list($uri,$hostpart) = $this->_split_url($url);
 			if(gettype($args) != 'array')
 			{
-				$arr[] = createObject('phpgwapi.xmlrpcval',$args,'string');
-				$f = createObject('phpgwapi.xmlrpcmsg', $method_name, $arr,'string');
+				$arr[] = new xmlrpcval($args,'string');
+				$f = new xmlrpcmsg($method_name, $arr,'string');
 			}
 			else
 			{
@@ -232,22 +223,22 @@
 					{
 						while(list($x,$y) = each($val))
 						{
-							$tmp[$x] = createObject('phpgwapi.xmlrpcval',$y, 'string');
+							$tmp[$x] = new xmlrpcval($y, 'string');
 						}
-						$ele[$key] = createObject('phpgwapi.xmlrpcval',$tmp,'struct');
+						$ele[$key] = new xmlrpcval($tmp,'struct');
 					}
 					else
 					{
-						$ele[$key] = createObject('phpgwapi.xmlrpcval',$val, 'string');
+						$ele[$key] = new xmlrpcval($val, 'string');
 					}
 				}
-				$arr[] = createObject('phpgwapi.xmlrpcval',$ele,'struct');
-				$f = createObject('phpgwapi.xmlrpcmsg', $method_name, $arr,'struct');
+				$arr[] = new xmlrpcval($ele,'struct');
+				$f = new xmlrpcmsg($method_name, $arr,'struct');
 			}
 
 			$this->debug('<pre>' . htmlentities($f->serialize()) . '</pre>' . "\n",$debug);
-			$c = createObject('phpgwapi.xmlrpc_client',$uri, $hostpart, 80);
-			$c->setCredentials($this->sessionid,$this->kp3);
+			$c = new xmlrpc_client($uri, $hostpart, 80);
+			$c->setCredentials($args['username'],$args['password']);
 //			_debug_array($c);
 			$c->setDebug(0);
 			$r = $c->send($f);
@@ -273,128 +264,26 @@
 		{
 			$method_name = str_replace('.','_',$method_name);
 			list($uri,$hostpart) = $this->_split_url($url);
-			if(gettype($args) != 'array')
-			{
-				$arr[] = createObject('phpgwapi.soapval','','string',$args);
-			}
-			else
-			{
-				while(list($key,$val) = @each($args))
-				{
-					if(gettype($val) == 'array')
-					{
-						while(list($x,$y) = each($val))
-						{
-							$tmp[] = createObject('phpgwapi.soapval',$x,'string',$y);
-						}
-						$arr[] = createObject('phpgwapi.soapval',$key, 'array',$tmp);
-					}
-					else
-					{
-						$arr[] = createObject('phpgwapi.soapval',$key, 'string',$val);
-					}
-				}
-			}
-
-			$soap_message = createObject('phpgwapi.soapmsg',$method_name,$arr);
-			/* print_r($soap_message);exit; */
-			$soap = createObject('phpgwapi.soap_client',$uri,$hostpart);
-			$soap->username = $this->sessionid;
-			$soap->password = $this->kp3;
-			/* _debug_array($soap);exit; */
-			if($r = $soap->send($soap_message,$method_name))
-			{
-				$this->debug('<hr>I got this value back<br><pre>' . htmlentities($r->serialize()) . '</pre><hr>',$debug);
-				$this->result = $r->decode();
+			$soap = createObject('phpgwapi.soap_client',array('uri' => $uri, 'location' => $url),false);
+			$soap->login	= $args['username'];
+			$soap->password = $args['password'];
+			$soap->init();
+			$this->result =  $soap->call($method_name, $args);
 				return $this->result;
 			}
-			else
-			{
-				$this->debug('Fault Code: ' . $r->ernno . ' Reason "' . $r->errstring . '"<br>',$debug);
-			}
-		}
 
 		function _send_soap_($method_name, $args, $url, $debug=True)
 		{
 			$method_name = str_replace('.','_',$method_name);
 			list($uri,$hostpart) = $this->_split_url($url);
-
-			if(!$args)
-			{
-				$arr = '';
-			}
-			elseif(is_array($args))
-			{
-				while(list($key,$val) = @each($args))
-				{
-					if(gettype($val) == 'array')
-					{
-						while(list($x,$y) = each($val))
-						{
-							$tmp[] = createObject('phpgwapi.soapval',$x,'string',$y);
-						}
-						$ele[] = createObject('phpgwapi.soapval',$key, 'array',$tmp);
-						$complex = True;
-					}
-					else
-					{
-						$ele[] = createObject('phpgwapi.soapval',$key, 'string',$val);
-					}
-				}
-				$arr[] = createObject('phpgwapi.soapval','','struct',$ele);
-			}
-			else
-			{
-				$arr[] = createObject('phpgwapi.soapval','','string',$args);
-			}
-			$this->request = $arr;
-
-			$soap_message = createObject('phpgwapi.soapmsg',$method_name,$this->request);
-			$soap = createObject('phpgwapi.soap_client',$uri,$hostpart);
-			$soap->username = $this->sessionid;
-			$soap->password = $this->kp3;
-			if($r = $soap->send($soap_message,$method_name))
-			{
-				_debug_array(htmlentities($soap->outgoing_payload));
-				_debug_array(htmlentities($soap->incoming_payload));
-				$this->debug('<hr>I got this value back<br><pre>' . htmlentities($r->serialize()) . '</pre><hr>',$debug);
-				$this->result = $r->decode();
+			$soap = createObject('phpgwapi.soap_client',array('uri' => $uri, 'location' => $url),false);
+			$soap->login	= $args['username'];
+			$soap->password = $args['password'];
+			$soap->init();
+			$this->result =  $soap->call($method_name, $args);
 				return $this->result;
 			}
-			else
-			{
-				_debug_array($soap->outgoing_payload);
-				$this->debug('Fault Code: ' . $r->ernno . ' Reason "' . $r->errstring . '"<br>',$debug);
-			}
-		}
 
-		function build_request($_req,$recursed=False,$ext='')
-		{
-			if(is_array($_req))
-			{
-				$ele = array();
-				@reset($_req);
-				while(list($key,$val) = @each($_req))
-				{
-					$ele[$key] = $this->build_request($val,True,$key);
-				}
-				$this->request[] = createObject('phpgwapi.soapval',$ext,'struct',$ele);
-				$ext = '';
-			}
-			else
-			{
-				$_type = (is_long($_req)?'int':gettype($_req));
-				if($recursed)
-				{
-					return CreateObject('phpgwapi.soapval',$ext,$_type,$_req);
-				}
-				else
-				{
-					$this->request[$ext] = createObject('phpgwapi.soapval',$ext,$_type,$_req);
-				}
-			}
-		}
-
 		/* Following are for server list management and query */
 		function read_repository($serverid='')
 		{

Modified: people/sigurdne/modules/phpgwapi/trunk/inc/class.ipc_.inc.php
===================================================================
--- people/sigurdne/modules/phpgwapi/trunk/inc/class.ipc_.inc.php	2009-11-20 10:27:41 UTC (rev 20844)
+++ people/sigurdne/modules/phpgwapi/trunk/inc/class.ipc_.inc.php	2009-11-20 10:28:10 UTC (rev 20845)
@@ -9,37 +9,20 @@
 	* @version $Id$
 	*/
 
-	/*
-	   This program is free software: you can redistribute it and/or modify
-	   it under the terms of the GNU Lesser General Public License as published by
-	   the Free Software Foundation, either version 3 of the License, or
-	   (at your option) any later version.
 
-	   This program is distributed in the hope that it will be useful,
-	   but WITHOUT ANY WARRANTY; without even the implied warranty of
-	   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-	   GNU General Public License for more details.
-
-	   You should have received a copy of the GNU Lesser General Public License
-	   along with this program.  If not, see <http://www.gnu.org/licenses/>.
-	 */
-
 	/**
 	* Abstract IPC Application class for the IPC Layer
 	* @package phpgwapi
 	* @subpackage communication
 	*/
-	abstract class ipc_
+	abstract class phpgwapi_ipc_
 	{
 		/**
 		* Constructor
 		*
 		* @access public
 		*/
-		function ipc_()
-		{
-			die('call abstract method: '.__class__.'::'.__function__);
-		}
+		abstract public function __construct();
 
 		/**
 		* Add data in a certain mime type format to the application.
@@ -48,10 +31,7 @@
 		* @param   string   $type  specifies the mime type of the passed data
 		* @return  integer         id of the added data
 		*/
-		function addData($data, $type)
-		{
-			die('call abstract method: '.__class__.'::'.__function__);
-		}
+		abstract public function addData($data, $type);
 
 		/**
 		* Convert data from a mime type to another.
@@ -62,10 +42,7 @@
 		* @param   string   $typeOut  specifies the output mime type of the passed data
 		* @return  mixed              converted data from application, the datatype depends on the passed output mime type
 		*/
-		function convertData($data, $typeIn, $typeOut)
-		{
-			die('call abstract method: '.__class__.'::'.__function__);
-		}
+		abstract public function convertData($data, $typeIn, $typeOut);
 
 		/**
 		* Checks if data for the passed id exists.
@@ -73,10 +50,7 @@
 		* @param   integer  $id  id to check
 		* @return  boolean       true if the data with id exist, otherwise false
 		*/
-		function existData($id)
-		{
-			die('call abstract method: '.__class__.'::'.__function__);
-		}
+		abstract public function existData($id);
 
 		/**
 		* Get data from the application in a certain mime type format.
@@ -85,10 +59,7 @@
 		* @param   string   $type  specifies the mime type of the returned data
 		* @return  mixed           data from application, the datatype depends on the passed mime type, false if no data exists for the passed id
 		*/
-		function getData($id, $type)
-		{
-			die('call abstract method: '.__class__.'::'.__function__);
-		}
+		abstract public function getData($id, $type);
 
 		/**
 		* Return a list with the available id's in the application.
@@ -98,10 +69,7 @@
 		* @param   integer  $lastmod  last modification time, default is -1 and means return all data id's
 		* @return  array              list of data id's
 		*/
-		function getIdList($time=-1)
-		{
-			die('call abstract method: '.__class__.'::'.__function__);
-		}
+		abstract public function getIdList($time = -1);
 
 		/**
 		* Remove data of the passed id.
@@ -109,10 +77,7 @@
 		* @param   integer  $id  id of data to remove from the application
 		* @return  boolean       true if the data is removed, otherwise false
 		*/
-		function removeData($id)
-		{
-			die('call abstract method: '.__class__.'::'.__function__);
-		}
+		abstract public function removeData($id);
 
 		/**
 		* Replace the existing data of the passed id with the passed data in a certain mime type format.
@@ -122,9 +87,5 @@
 		* @param   string   $type  specifies the mime type of the passed data
 		* @return  boolean         true if the data is replaced, otherwise false
 		*/
-		function replaceData($id, $data, $type)
-		{
-			die('call abstract method: '.__class__.'::'.__function__);
-		}
+		abstract public function replaceData($id, $data, $type);
 	}
-?>

Modified: people/sigurdne/modules/phpgwapi/trunk/inc/class.ipc_manager.inc.php
===================================================================
--- people/sigurdne/modules/phpgwapi/trunk/inc/class.ipc_manager.inc.php	2009-11-20 10:27:41 UTC (rev 20844)
+++ people/sigurdne/modules/phpgwapi/trunk/inc/class.ipc_manager.inc.php	2009-11-20 10:28:10 UTC (rev 20845)
@@ -7,21 +7,6 @@
 	* @package phpgwapi
 	* @subpackage communication
 	* @version $Id$
-	*/
-
-	/*
-	   This program is free software: you can redistribute it and/or modify
-	   it under the terms of the GNU Lesser General Public License as published by
-	   the Free Software Foundation, either version 3 of the License, or
-	   (at your option) any later version.
-
-	   This program is distributed in the hope that it will be useful,
-	   but WITHOUT ANY WARRANTY; without even the implied warranty of
-	   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-	   GNU General Public License for more details.
-
-	   You should have received a copy of the GNU Lesser General Public License
-	   along with this program.  If not, see <http://www.gnu.org/licenses/>.
 	 */
 
 	/**

Modified: people/sigurdne/modules/phpgwapi/trunk/inc/class.js.inc.php
===================================================================
--- people/sigurdne/modules/phpgwapi/trunk/inc/class.js.inc.php	2009-11-20 10:27:41 UTC (rev 20844)
+++ people/sigurdne/modules/phpgwapi/trunk/inc/class.js.inc.php	2009-11-20 10:28:10 UTC (rev 20845)
@@ -13,7 +13,7 @@
 	/*
 	   This program is free software: you can redistribute it and/or modify
 	   it under the terms of the GNU General Public License as published by
-	   the Free Software Foundation, either version 3 of the License, or
+	   the Free Software Foundation, either version 2 of the License, or
 	   (at your option) any later version.
 
 	   This program is distributed in the hope that it will be useful,
@@ -238,4 +238,14 @@
 				return False;
 			}
 		}
+
+		public function add_code($namespace, $code)
+		{
+			$GLOBALS['phpgw_info']['flags']['java_script'] .= "\n"
+				. '<script type="text/javascript">' ."\n"
+				. '//<[CDATA[' ."\n"
+				. $code ."\n"
+				. '//]]' ."\n"
+				. "</script>\n";
+		}
 	}

Modified: people/sigurdne/modules/phpgwapi/trunk/inc/class.jscal.inc.php
===================================================================
--- people/sigurdne/modules/phpgwapi/trunk/inc/class.jscal.inc.php	2009-11-20 10:27:41 UTC (rev 20844)
+++ people/sigurdne/modules/phpgwapi/trunk/inc/class.jscal.inc.php	2009-11-20 10:28:10 UTC (rev 20845)
@@ -7,22 +7,7 @@
 	* @license http://www.fsf.org/licenses/gpl.html GNU General Public License
 	* @package phpgwapi
 	* @subpackage gui
-	* @version $Id: class.jscal.inc.php 682 2008-02-01 12:19:55Z dave $
-	*/
-
-	/*
-	   This program is free software: you can redistribute it and/or modify
-	   it under the terms of the GNU General Public License as published by
-	   the Free Software Foundation, either version 3 of the License, or
-	   (at your option) any later version.
-
-	   This program is distributed in the hope that it will be useful,
-	   but WITHOUT ANY WARRANTY; without even the implied warranty of
-	   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-	   GNU General Public License for more details.
-
-	   You should have received a copy of the GNU General Public License
-	   along with this program.  If not, see <http://www.gnu.org/licenses/>.
+	* @version $Id: class.jscal.inc.php 3415 2009-08-23 17:09:49Z sigurd $
 	 */
 
 	/**
@@ -36,19 +21,24 @@
 	* @package phpgwapi
 	* @subpackage gui
 	*/
-	class phpgwapi_calendar
+	class phpgwapi_jscal
 	{
 
-		public static function input($id, $date, $format = 'input', $title = null)
+		public static function input($id, $date = '', $format = 'input', $title = null)
 		{
 			$date_format =& $GLOBALS['phpgw_info']['user']['preferences']['common']['dateformat'];
+			if(!$date)
+			{
+				$date = $GLOBALS['phpgw']->common->show_date(time(),$date_format);
+			}
+			
 			if ( !$title )
 			{
 				$title = 'Select a date';
 			}
 			$title = lang($title);
-			$datels = self::get_translated_dates();
-			$date_pos = self::_get_date_pos();
+			$datels = self::_get_translated_dates();
+			$date_pos = self::_get_date_pos($date_format);
 
 			$range_sep = '-';
 			switch ( substr($date_format, 1, 1) )
@@ -68,24 +58,35 @@
 			}
 			
 
-			$date_selected = date(str_replace('M', 'm', $date_format), $date);
+			$GLOBALS['phpgw']->css->add_external_file('phpgwapi/js/yahoo/calendar/assets/skins/sam/calendar.css');
+			$date_selected = $date;//date(str_replace('M', 'm', $date_format), $date);
 
-
-			$namespace = phpgwapi_yui::import_widget('calendar');
+			$namespace = phpgwapi_yui::load_widget('calendar');
 			$code = <<<JS
-			YAHOO.namespace('{$namespace}');
+			YAHOO.namespace('{$namespace}.{$id}');
 
 			YAHOO.$namespace.$id.init = function()
 			{
-				YAHOO.$namespace.$id = new YAHOO.widget.Calendar('{$id}-cal','{$id}-container', { title:'{$title}', close:true } );
+				YAHOO.$namespace.$id = new YAHOO.widget.Calendar(
+					'{$id}-cal',
+					'{$id}-container',
+					{
+						navigator:true, 
+						title:'{$title}',
+						close:true,
+						start_weekday:1, 
+						LOCALE_WEEKDAYS:"short"
+					}
+				);
+
 				YAHOO.$namespace.$id.cfg.setProperty('DATE_FIELD_DELIMITER', '.');
 
 				YAHOO.$namespace.$id.cfg.setProperty('MDY_DAY_POSITION', {$date_pos['d']});
-				YAHOO.$namespace.$id.cfg.setProperty('MDY_MONTH_POSITION', {$date_post['m']});
+				YAHOO.$namespace.$id.cfg.setProperty('MDY_MONTH_POSITION', {$date_pos['m']});
 				YAHOO.$namespace.$id.cfg.setProperty('MDY_YEAR_POSITION', {$date_pos['y']});
 
 				YAHOO.$namespace.$id.cfg.setProperty('MD_DAY_POSITION', {$date_pos['d']});
-				YAHOO.$namespace.$id.cfg.setProperty('MD_MONTH_POSITION', {$date_post['m']});
+				YAHOO.$namespace.$id.cfg.setProperty('MD_MONTH_POSITION', {$date_pos['m']});
 
 				YAHOO.$namespace.$id.cfg.setProperty('MONTHS_SHORT',   ['{$datels['months'][1]}', '{$datels['months'][2]}', '{$datels['months'][3]}', '{$datels['months'][4]}', '{$datels['months'][5]}', '{$datels['months'][6]}', '{$datels['months'][7]}', '{$datels['months'][8]}', '{$datels['months'][9]}', '{$datels['months'][10]}', '{$datels['months'][11]}', '{$datels['months'][12]}']);
 				YAHOO.$namespace.$id.cfg.setProperty('MONTHS_LONG',    ['{$datels['monthl'][1]}', '{$datels['monthl'][2]}', '{$datels['monthl'][3]}', '{$datels['monthl'][4]}', '{$datels['monthl'][5]}', '{$datels['monthl'][6]}', '{$datels['monthl'][7]}', '{$datels['monthl'][8]}', '{$datels['monthl'][9]}', '{$datels['monthl'][10]}', '{$datels['monthl'][11]}', '{$datels['monthl'][12]}']);
@@ -120,7 +121,7 @@
 
 HTML;
 
-			$date_str = date(str_replace('M', 'm', $GLOBALS['phpgw_info']['user']['preferences']['common']['dateformat']), $date);
+			$date_str =  $date;//date(str_replace('M', 'm', $GLOBALS['phpgw_info']['user']['preferences']['common']['dateformat']), $date);
 
 			switch ( $format )
 			{
@@ -131,7 +132,7 @@
 						switch ( $pos )
 						{
 							case 'd':
-								$html .= phpgwapi_sbox2::
+								$html .= phpgwapi_sbox::getDays($name, $selected = null);
 						}
 					}
 
@@ -144,7 +145,7 @@
 
 			}
 
-			$img = $GLOBALS['phpgw']->common->image('phpgwapi', 'calendar', 'png', false)
+			$img = $GLOBALS['phpgw']->common->image('phpgwapi', 'cal');
 			$alt = lang('date selector trigger');
 
 
@@ -208,7 +209,7 @@
 		/**
 		* Get the positions of the components of the date
 		*/
-		private static get_date_pos()
+		private static function get_date_pos()
 		{
 			static $positions = null;
 			if ( !is_null($positions) )
@@ -244,7 +245,7 @@
 			return $positions;
 		}
 
-		private static function get_translated_dates()
+		private static function _get_translated_dates()
 		{
 			static $datels = null;
 			if ( is_null($datels) )
@@ -253,75 +254,102 @@
 				(
 					'months'	=> array
 					(
-						'Jan'	=> lang('Jan'),
-						'Feb'	=> lang('Feb'),
-						'Mar'	=> lang('Mar'),
-						'Apr'	=> lang('Apr'),
-						'May'	=> lang('May'),
-						'Jun'	=> lang('Jun'),
-						'Jul'	=> lang('Jul'),
-						'Aug'	=> lang('Aug'),
-						'Sep'	=> lang('Sep'),
-						'Oct'	=> lang('Oct'),
-						'Nov'	=> lang('Nov'),
-						'Dec'	=> lang('Dec')
+						'1'	=> lang('Jan'),
+						'2'	=> lang('Feb'),
+						'3'	=> lang('Mar'),
+						'4'	=> lang('Apr'),
+						'5'	=> lang('May'),
+						'6'	=> lang('Jun'),
+						'7'	=> lang('Jul'),
+						'8'	=> lang('Aug'),
+						'9'	=> lang('Sep'),
+						'10'	=> lang('Oct'),
+						'11'	=> lang('Nov'),
+						'12'	=> lang('Dec')
 					),
 					'monthl'	=> array
 					(
-						'Jan'	=> lang('January'),
-						'Feb'	=> lang('Febuary'),
-						'Mar'	=> lang('March'),
-						'Apr'	=> lang('April'),
-						'May'	=> lang('May'),
-						'Jun'	=> lang('June'),
-						'Jul'	=> lang('July'),
-						'Aug'	=> lang('August'),
-						'Sep'	=> lang('September'),
-						'Oct'	=> lang('October'),
-						'Nov'	=> lang('November'),
-						'Dec'	=> lang('December')
+						'1'	=> lang('January'),
+						'2'	=> lang('Febuary'),
+						'3'	=> lang('March'),
+						'4'	=> lang('April'),
+						'5'	=> lang('May'),
+						'6'	=> lang('June'),
+						'7'	=> lang('July'),
+						'8'	=> lang('August'),
+						'9'	=> lang('September'),
+						'10'	=> lang('October'),
+						'11'	=> lang('November'),
+						'12'	=> lang('December')
 					),
 					'days'	=> array
 					(
-						'Sun'	=> lang('Su'),
-						'Mon'	=> lang('Mo'),
-						'Tue'	=> lang('Tu'),
-						'Wed'	=> lang('We'),
-						'Thu'	=> lang('Th'),
-						'Fri'	=> lang('Fr'),
-						'Sat'	=> lang('Sa'),
-						'Sun'	=> lang('Su'),
+						'1'	=> lang('Su'),
+						'2'	=> lang('Mo'),
+						'3'	=> lang('Tu'),
+						'4'	=> lang('We'),
+						'5'	=> lang('Th'),
+						'6'	=> lang('Fr'),
+						'7'	=> lang('Sa')
 					),
 					'daym'	=> array
 					(
-						'Sun'	=> lang('Sun'),
-						'Mon'	=> lang('Mon'),
-						'Tue'	=> lang('Tue'),
-						'Wed'	=> lang('Wed'),
-						'Thu'	=> lang('Thu'),
-						'Fri'	=> lang('Fri'),
-						'Sat'	=> lang('Sat'),
-						'Sun'	=> lang('Sun'),
+						'1'	=> lang('Sun'),
+						'2'	=> lang('Mon'),
+						'3'	=> lang('Tue'),
+						'4'	=> lang('Wed'),
+						'5'	=> lang('Thu'),
+						'6'	=> lang('Fri'),
+						'7'	=> lang('Sat')
 					),
 					'dayl'	=> array
 					(
-						'Sun'	=> lang('Sunday'),
-						'Mon'	=> lang('Monday'),
-						'Tue'	=> lang('Tuesday'),
-						'Wed'	=> lang('Wednesday'),
-						'Thu'	=> lang('Thursday'),
-						'Fri'	=> lang('Friday'),
-						'Sat'	=> lang('Saturday'),
-						'Sun'	=> lang('Sunday'),
+						'1'	=> lang('Sunday'),
+						'2'	=> lang('Monday'),
+						'3'	=> lang('Tuesday'),
+						'4'	=> lang('Wednesday'),
+						'5'	=> lang('Thursday'),
+						'6'	=> lang('Friday'),
+						'7'	=> lang('Saturday')
 					)
 				);
 
-				foreach ( $dayls['days'] as $day => $native )
+				foreach ( $datels['dayl'] as $day => $native )
 				{
-					$dayls['day1'][$day] = substr($native, 0, 1);
+					$datels['day1'][$day] = substr($native, 0, 1);
 				}
 			}
 			return $datels;
 		}
+
+
+		private static function _get_date_pos($dateformat)
+		{
+			$dateformat = strtolower($dateformat);
+			$sep = '/';
+			$dlarr[strpos($dateformat,'y')] = 'y';
+			$dlarr[strpos($dateformat,'m')] = 'm';
+			$dlarr[strpos($dateformat,'d')] = 'd';
+			ksort($dlarr);
+			$i = 1;
+			$date_pos = array();
+			foreach ($dlarr as $entry)
+			{
+				$date_pos[$entry] = $i;
+				$i++;
+			}
+			return $date_pos;
+		}
+
+		/**
+		* Add an event listener to the trigger icon - used for XSLT
+		*
+		* @access private
+		* @param string $name the element ID
+		*/
+		function _input_modern($id)
+		{
+			$GLOBALS['phpgw']->js->add_event('load', "Calendar.setup({inputField : '$id', button : '{$id}-trigger'});");
+		}
+
 	}
-?>

Modified: people/sigurdne/modules/phpgwapi/trunk/inc/class.jscalendar.inc.php
===================================================================
--- people/sigurdne/modules/phpgwapi/trunk/inc/class.jscalendar.inc.php	2009-11-20 10:27:41 UTC (rev 20844)
+++ people/sigurdne/modules/phpgwapi/trunk/inc/class.jscalendar.inc.php	2009-11-20 10:28:10 UTC (rev 20845)
@@ -8,21 +8,6 @@
 	* @package phpgwapi
 	* @subpackage gui
 	* @version $Id$
-	*/
-
-	/*
-	   This program is free software: you can redistribute it and/or modify
-	   it under the terms of the GNU General Public License as published by
-	   the Free Software Foundation, either version 3 of the License, or
-	   (at your option) any later version.
-
-	   This program is distributed in the hope that it will be useful,
-	   but WITHOUT ANY WARRANTY; without even the implied warranty of
-	   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-	   GNU General Public License for more details.
-
-	   You should have received a copy of the GNU General Public License
-	   along with this program.  If not, see <http://www.gnu.org/licenses/>.
 	 */
 
 	/**
@@ -32,15 +17,15 @@
 	* @subpackage gui
 	* @internal The constructor load the necessary javascript-files
 	*/
-	class phpgwapi_jscalendar
-	{
+class jscalendar
+{
 		/**
 		 * @author ralfbecker
 		 * constructor of the class
 		*
 		 * @param $do_header if true, necessary javascript and css gets loaded, only needed for input
 		 */
-		function __construct($do_header=True)
+	function jscalendar($do_header=True)
 		{
 			$GLOBALS['phpgw']->js->validate_file('jscalendar', 'calendar_stripped');
 			$this->phpgw_js_url = $GLOBALS['phpgw_info']['server']['webserver_url'].'/phpgwapi/js';
@@ -196,4 +181,5 @@
 		{
 			$GLOBALS['phpgw']->js->add_event('load', "Calendar.setup({inputField : '$id', button : '{$id}-trigger'});");
 		}
-	}
+}
+

Modified: people/sigurdne/modules/phpgwapi/trunk/inc/class.listbox.inc.php
===================================================================
--- people/sigurdne/modules/phpgwapi/trunk/inc/class.listbox.inc.php	2009-11-20 10:27:41 UTC (rev 20844)
+++ people/sigurdne/modules/phpgwapi/trunk/inc/class.listbox.inc.php	2009-11-20 10:28:10 UTC (rev 20845)
@@ -8,21 +8,6 @@
 	* @package phpgwapi
 	* @subpackage gui
 	* @version $Id$
-	*/
-
-	/*
-	   This program is free software: you can redistribute it and/or modify
-	   it under the terms of the GNU Lesser General Public License as published by
-	   the Free Software Foundation, either version 3 of the License, or
-	   (at your option) any later version.
-
-	   This program is distributed in the hope that it will be useful,
-	   but WITHOUT ANY WARRANTY; without even the implied warranty of
-	   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-	   GNU General Public License for more details.
-
-	   You should have received a copy of the GNU Lesser General Public License
-	   along with this program.  If not, see <http://www.gnu.org/licenses/>.
 	 */
 
 	CreateObject('phpgwapi.portalbox');

Modified: people/sigurdne/modules/phpgwapi/trunk/inc/class.locations.inc.php
===================================================================
--- people/sigurdne/modules/phpgwapi/trunk/inc/class.locations.inc.php	2009-11-20 10:27:41 UTC (rev 20844)
+++ people/sigurdne/modules/phpgwapi/trunk/inc/class.locations.inc.php	2009-11-20 10:28:10 UTC (rev 20845)
@@ -3,17 +3,18 @@
 	* phpGroupWare API - Locations
 	* @author Dan Kuykendall <[email protected]>
 	* @author Dave Hall <[email protected]>
+	* @author Sigurd Nes <[email protected]>
 	* @copyright Copyright (C) 2000-2008 Free Software Foundation, Inc. http://www.fsf.org/
-	* @license http://www.gnu.org/licenses/lgpl.html GNU Lesser General Public License v3 or later
+	* @license http://www.gnu.org/licenses/lgpl.html GNU Lesser General Public License v2 or later
 	* @package phpgroupware
 	* @subpackage phpgwapi
-	* @version $Id: class.acl.inc.php 682 2008-02-01 12:19:55Z dave $
+	* @version $Id: class.locations.inc.php 3815 2009-10-05 12:41:40Z yngve.espelid $
 	*/
 
 	/*
 		This program is free software: you can redistribute it and/or modify
 		it under the terms of the GNU Lesser General Public License as published by
-		the Free Software Foundation, either version 3 of the License, or
+		the Free Software Foundation, either version 2 of the License, or
 		(at your option) any later version.
 
 		This program is distributed in the hope that it will be useful,
@@ -30,23 +31,25 @@
 	*
 	* @package phpgroupware
 	* @subpackage phpgwapi
-	* @internal syntax: CreateObject('phpgwapi.acl',int account_id);
-	* @internal example: $acl = createObject('phpgwapi.acl');  // user id is the current user
-	* @internal example: $acl = createObject('phpgwapi.acl',10);  // 10 is the user id
 	*/
 	class phpgwapi_locations
 	{
 		/**
-		* @var object Database connection
+		* @var object $_db Database connection
 		*/
 		protected $_db;
 
 		/**
-		* @var string $join syntax for database joins
+		* @var string $_join syntax for database joins
 		*/
 		protected $_join = 'JOIN';
 
 		/**
+		* @var string $_like syntax for like clause in queries
+		*/
+		protected $_like = 'LIKE';
+
+		/**
 		* Constructor
 		*
 		* @return null
@@ -55,6 +58,7 @@
 		{
 			$this->_db =& $GLOBALS['phpgw']->db;
 			$this->_join =& $this->_db->join;
+			$this->_like =& $this->_db->like;
 		}
 
 		/**
@@ -64,7 +68,7 @@
 		 *
 		 * @return array Array with xmlrpc or soap functions. Might also be empty.
 		 */
-		public function list_methods($_type='xmlrpc')
+		public function list_methods($_type = 'xmlrpc')
 		{
 			// TODO implement me
 			return array();
@@ -81,18 +85,14 @@
 		 *
 		 * @return int the new location id
 		 */
-		public function add($location, $descr, $appname, $allow_grant = true, $custom_tbl = null)
-		{
-		 	if ( $appname === '' )
+		public function add($location, $descr, $appname, $allow_grant = true, $custom_tbl = null, $c_function = false)
 		 	{
-		 		$appname = $GLOBALS['phpgw']['flags']['currentapp'];
-		 	}
-
 			$app = $GLOBALS['phpgw']->applications->name2id($appname);
 
 		 	$location = $this->_db->db_addslashes($location);
 			$descr = $this->_db->db_addslashes($descr);
 		 	$allow_grant = (int) $allow_grant;
+		 	$c_function = (int) $c_function;
 
 		 	$this->_db->query('SELECT location_id FROM phpgw_locations'
 		 			. " WHERE app_id = {$app} AND name = '{$location}'", __LINE__, __FILE__);
@@ -104,14 +104,14 @@
 
 		 	if ( is_null($custom_tbl) )
 		 	{
-		 		$sql = 'INSERT INTO phpgw_locations (app_id, name, descr, allow_grant)'
-		 			. " VALUES ({$app}, '{$location}', '{$descr}', {$allow_grant})";
+		 		$sql = 'INSERT INTO phpgw_locations (app_id, name, descr, allow_grant,allow_c_function)'
+		 			. " VALUES ({$app}, '{$location}', '{$descr}', {$allow_grant}, {$c_function})";
 		 	}
 		 	else
 		 	{
 		 		$custom_tbl = $this->_db->db_addslashes($custom_tbl);
-		 		$sql = 'INSERT INTO phpgw_locations (app_id, name, descr, allow_grant, allow_c_attrib, c_attrib_table)'
-		 			. " VALUES ({$app}, '{$location}', '{$descr}', {$allow_grant}, 1, '{$custom_tbl}')";
+		 		$sql = 'INSERT INTO phpgw_locations (app_id, name, descr, allow_grant, allow_c_attrib, c_attrib_table, allow_c_function)'
+		 			. " VALUES ({$app}, '{$location}', '{$descr}', {$allow_grant}, 1, '{$custom_tbl}', $c_function)";
 		 	}
 			$this->_db->query($sql, __LINE__, __FILE__);
 
@@ -144,7 +144,8 @@
 
 			$this->_db->transaction_begin();
 
-			if ( $drop_table )
+			// if there is a table and the user wants it dropped we drop it
+			if ( $tbl && $drop_table )
 			{
 				$oProc = createObject('phpgwapi.schema_proc',
 							$GLOBALS['phpgw_info']['server']['db_type']);
@@ -155,18 +156,45 @@
 				$oProc->DropTable($tbl);
 			}
 
+			$GLOBALS['phpgw']->acl->delete_repository($appname, $location);
+
 			$sql = 'DELETE FROM phpgw_locations'
 				. " WHERE app_id = {$app} AND name = '{$location}'";
 			$this->_db->query($sql, __LINE__, __FILE__);
 
-			$this->delete_repository($appname, $location);
-
 			$this->_db->transaction_commit();
 
 			return true;
 		}
 
 		/**
+		 * Get the custom attributes table name for a given location
+		 *
+		 * @param string $appname  the application name for the location
+		 * @param string $location the location name
+		 *
+		 * @return string the name of the table - not found returns an empty string
+		 */
+		public function get_attrib_table($appname, $location)
+		{
+			$appname  = $this->_db->db_addslashes($appname);
+			$location = $this->_db->db_addslashes($location);
+
+			$sql = 'SELECT c_attrib_table '
+					. ' FROM phpgw_locations '
+					. " {$this->_join} phpgw_applications ON phpgw_applications.app_id = phpgw_locations.app_id"
+					. " WHERE phpgw_applications.app_name = '{$appname}'"
+						. " AND phpgw_locations.name = '{$location}'";
+			$this->_db->query($sql, __LINE__, __FILE__);
+			if ( $this->_db->next_record() )
+			{
+				return $this->_db->f('c_attrib_table');
+			}
+
+			return '';
+		}
+
+		/**
 		 * Get the ID of a location
 		 *
 		 * @param string $appname  the name of the module being looked up
@@ -176,6 +204,15 @@
 		 */
 		public function get_id($appname, $location)
 		{
+			static $map = array();
+
+			if ( isset($map[$appname][$location]) )
+			{
+				return $map[$appname][$location];
+			}
+
+			$map[$appname][$location] = 0;
+
 			$appname  = $this->_db->db_addslashes($appname);
 			$location = $this->_db->db_addslashes($location);
 
@@ -188,47 +225,113 @@
 			$this->_db->query($sql, __LINE__, __FILE__);
 			if ( $this->_db->next_record() )
 			{
-				return (int) $this->_db->f('location_id');
+				$map[$appname][$location] = $this->_db->f('location_id');
 			}
-			throw new Exception("get_id (${appname}, ${location}) returned 0");
-			return 0;
+			else
+			{
+//				throw new Exception("get_id ({$appname}, {$location}) returned 0");
+			}
+			return $map[$appname][$location];
 		}
 
 		/**
-		 * Get the app / location of an ID -> this is not id2name since where's not returning only the name ...
+		 * Get the name of a location - useful for testing
 		 *
-		 * @param int $location_id the location id
+		 * @param integer $location_id the location id to look up
 		 *
-		 * @return array 'app_id' => contains the id of the application for the location - 'name' => contains the name of the location
+		 * @return array the location - empty if not found
 		 */
 		public function get_name($location_id)
 		{
-			$location_id = (int)$location_id;
-			$ret = array();
-			$sql = "SELECT app_id, name from phpgw_locations WHERE location_id = ${location_id}";
+			$location_id = (int) $location_id;
+
+			$sql = 'SELECT phpgw_applications.app_name, phpgw_locations.name, phpgw_locations.descr'
+					. ' FROM phpgw_locations '
+					. " {$this->_join} phpgw_applications ON phpgw_applications.app_id = phpgw_locations.app_id"
+					. " WHERE phpgw_locations.location_id = {$location_id}";
 			$this->_db->query($sql, __LINE__, __FILE__);
-			if( $this->_db->next_record() )
+			if ( $this->_db->next_record() )
 			{
-				$ret['app_id'] = (int)$this->_db->f('app_id');
-				$ret['name'] = $this->_db->f('name');
+				return array
+				(
+					'appname'	=> $this->_db->f('app_name', true),
+					'location'	=> $this->_db->f('name', true),
+					'descr'		=> $this->_db->f('descr', true)
+				);
 			}
-			return $ret;
+
+			return array();
 		}
 
 		/**
-		 * Get the subs for a location/application accociation
+		 * Get a list of sub locations for a give location
 		 *
-		 * @param string $appname  the name of the application for the location
-		 * @param string $location location within application
+		 * @param string $appname  the name of the module being looked up
+		 * @param string $location the location within the module to look up
 		 *
-		 * @return array with the subs
+		 * @return array map of locations (id => namne)
 		 */
 		public function get_subs($appname, $location)
 		{
-			// TODO : fill in the empty shell
-			return array();
+			static $map = array();
+
+			if ( isset($map[$appname][$location]) )
+			{
+				return $map[$appname][$location];
+			}
+
+			$map[$appname][$location] = array();
+
+			$entries =& $map[$appname][$location]; 
+			$appname  = $this->_db->db_addslashes($appname);
+			$location = $this->_db->db_addslashes($location);
+
+			$sql = 'SELECT phpgw_locations.location_id, phpgw_locations.name'
+				. ' FROM phpgw_locations, phpgw_applications'
+				. ' WHERE phpgw_locations.app_id = phpgw_applications.app_id'
+					. " AND phpgw_locations.name {$this->_like} '{$location}%'"
+					. " AND phpgw_locations.name != '{$location}'"
+					. " AND phpgw_applications.app_name='{$appname}'";
+					
+			$this->_db->query($sql, __LINE__, __FILE__);
+
+			while ( $this->_db->next_record() )
+			{
+				$entries[$this->_db->f('location_id')] = $this->_db->f('name', true);
+			}
+			return $entries;
 		}
+		
+		/**
+		 * Get a list of locations that matches a given location pattern
+		 *
+		 * @param string $appname  the name of the module being looked up
+		 * @param string $location the location within the module to look up
+		 *
+		 * @return array map of locations (id => namne)
+		 */
+		public function get_subs_from_pattern($appname, $pattern)
+		{
+			$appname  = $this->_db->db_addslashes($appname);
+			$pattern  = $this->_db->db_addslashes($pattern);
 
+			$sql = 'SELECT phpgw_locations.location_id, phpgw_locations.name, phpgw_locations.descr'
+				. ' FROM phpgw_locations, phpgw_applications'
+				. ' WHERE phpgw_locations.app_id = phpgw_applications.app_id'
+					. " AND phpgw_locations.name {$this->_like} '{$pattern}'"
+					. " AND phpgw_applications.app_name='{$appname}'";
+			$this->_db->query($sql, __LINE__, __FILE__);
+			while ( $this->_db->next_record() )
+			{
+				$entries[] = array(
+					'location_id' => $this->_db->f('location_id'), 
+					'name' => $this->_db->f('name', true),
+					'descr' => $this->_db->f('descr',true)
+				);
+			}
+			return $entries;
+		}
+
 		/**
 		 * Update the description of a location
 		 *
@@ -241,26 +344,24 @@
 		public function update_description($location, $descr, $appname)
 		{
 		 	$location	= $this->_db->db_addslashes($location);
-			$descr		= $this->_db->db_addslashes($description);
+			$descr		= $this->_db->db_addslashes($descr);
 		 	$appname	= $this->_db->db_addslashes($appname);
 
-		 	$this->_db->query('UPDATE phpgw_locations, phpgw_applications'
-		 			. " SET descr = '{$descr}'"
-		 			. ' WHERE phpgw_locations.app_id = phpgw_applications.app_id '
-						. " AND phpgw_applications.appname = '{$appname}'"
-						. " AND phpgw_locations.name = '{$location}'", __LINE__, __FILE__);
-			return $this->_db->rows_affected() == 1;
+		 	$location_id = $this->get_id($appname, $location);
+
+		 	$this->_db->query("UPDATE phpgw_locations SET descr = '{$descr}'"
+					. " WHERE phpgw_locations.location_id = {$location_id}", __LINE__, __FILE__);
+			return $this->_db->affected_rows() == 1;
 		}
 
 		/**
-		* This does something - ask sigurd he wrote the code
-		* XXX Caeies JAN09 : I guess this is more or less a broken design. It should be better do to this work when installing the application
-		* So a developper could explicitly ask for an acl management ... my 2c€. Anyway, I fixed it.
+		* Check that top level location are present for installed apps
+		* If the location is missing - it will be inserted
 		*
-		* @param something $apps     a paramater
-		* @param string?   $location something - ask sigurd
+		* @param array    $apps apps to check
+		* @param string   $location the location name to check
 		*
-		* @return null - should really be a boolean? skwashd may08
+		* @return void
 		*/
 		public function verify($apps, $location = '.')
 		{
@@ -270,26 +371,22 @@
 			{
 				$apps = array();
 			}
+
 			foreach ( $apps as $appname => $values )
 			{
 				$appname = $this->_db->db_addslashes($appname);
 				$app_id = $GLOBALS['phpgw']->applications->name2id($appname);
-				//If the application is not installed, skip it
-				if($app_id == 0)
+				if( $app_id > 0 )
 				{
-					continue;
-				}
-				$sql = 'SELECT phpgw_applications.app_name'
-					. ' FROM phpgw_applications'
-					. " {$this->_join} phpgw_locations ON phpgw_applications.app_id = phpgw_locations.app_id"
-					. " WHERE phpgw_applications.app_name = '{$appname}'"
-						. " AND phpgw_locations.name = '{$location}'";
+					$sql = 'SELECT name FROM phpgw_locations'
+						. " WHERE app_id = {$app_id} AND name = '{$location}'";
 
 				$this->_db->query($sql, __LINE__, __FILE__);
 
 				if ( !$this->_db->next_record() )
 				{
 					$top = (int) $values['top_grant'];
+
 					$sql = 'INSERT INTO phpgw_locations (app_id, name, descr, allow_grant)'
 						. " VALUES ({$app_id}, '{$location}', 'Top', {$top})";
 
@@ -297,16 +394,28 @@
 				}
 			}
 		}
+		}
 
 		/**
-		* Ask sigurd for what is should be used ...
+		* Find locations within an application
+		*
+		* @param bool   $grant          Used for finding locations where users can grant rights to others
+		* @param string $appname        Name of application in question
+		* @param bool   $allow_c_attrib Used for finding locations where custom attributes can be applied
+		*
+		* @return array Array locations
 		*/
-		public function get_locations_by_apps($appname, $allow_c_attrib, $grant)
+
+		public function get_locations($grant = false, $appname = '', $allow_c_attrib = false, $c_function = false)
 		{
-			$location = array();
-			$app_id = $GLOBALS['phpgw']->applications->name2id($appname);
+			if ( !$appname )
+			{
+		 		$appname = $GLOBALS['phpgw']['flags']['currentapp'];
+			}
+
+			$appname = $this->_db->db_addslashes($appname);
 			
-			$filter = " WHERE app_id = ${app_id} ";
+			$filter = " WHERE app_name='{$appname}' AND phpgw_locations.name != 'run'";
 			
 			if($allow_c_attrib)
 			{
@@ -317,12 +426,23 @@
 			{
 				$filter .= ' AND allow_grant = 1';
 			}
-			$this->_db->query("SELECT location_id, descr FROM phpgw_locations $filter ORDER BY location_id");
 			
+			if($c_function)
+			{
+				$filter .= ' AND c_function = 1';
+			}
+
+			$sql = "SELECT location_id, phpgw_locations.name, phpgw_locations.descr FROM phpgw_locations"
+				. " $this->_join phpgw_applications ON phpgw_locations.app_id = phpgw_applications.app_id"
+				. " $filter ORDER BY phpgw_locations.name";
+
+			$this->_db->query($sql, __LINE__, __FILE__);
+			
+			$locations = array();
 			while ($this->_db->next_record())
 			{
-				$location[$this->_db->f('location_id')] = $this->_db->f('descr', true);
+				$locations[$this->_db->f('name')] = $this->_db->f('descr', true);
 			}
-			return $location;
+			return $locations;
 		}
 	}

Modified: people/sigurdne/modules/phpgwapi/trunk/inc/class.log.inc.php
===================================================================
--- people/sigurdne/modules/phpgwapi/trunk/inc/class.log.inc.php	2009-11-20 10:27:41 UTC (rev 20844)
+++ people/sigurdne/modules/phpgwapi/trunk/inc/class.log.inc.php	2009-11-20 10:28:10 UTC (rev 20845)
@@ -8,21 +8,6 @@
 	* @package phpgwapi
 	* @subpackage application
 	* @version $Id$
-	*/
-
-	/*
-	   This program is free software: you can redistribute it and/or modify
-	   it under the terms of the GNU General Public License as published by
-	   the Free Software Foundation, either version 3 of the License, or
-	   (at your option) any later version.
-
-	   This program is distributed in the hope that it will be useful,
-	   but WITHOUT ANY WARRANTY; without even the implied warranty of
-	   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-	   GNU General Public License for more details.
-
-	   You should have received a copy of the GNU General Public License
-	   along with this program.  If not, see <http://www.gnu.org/licenses/>.
 	 */
 
 	/**
@@ -43,6 +28,7 @@
 			'debug',
 			'info',
 			'notice',
+			'strict',
 			'warn',
 			'error',
 			'fatal',
@@ -60,7 +46,8 @@
 			'W' => 3,
 			'N'	=> 4,
 			'I' => 5,
-			'D' => 6
+			'D' => 6,
+			'S'	=> 7
 		);
 
 		// these are used by the admin appliation when showing the log file. 
@@ -72,9 +59,21 @@
 			'W' => 'warn',
 			'N'	=> 'notice',
 			'I' => 'info',
-			'D' => 'debug'
+			'D' => 'debug',
+			'S'	=> 'strict'
 		);
 		
+		/**
+		 * Constructor
+		 */
+		
+		public function __construct()
+		{
+//			date_default_timezone_set(date_default_timezone_get());
+			date_default_timezone_set('UTC');
+		}
+
+
 		function checkprefs()
 		{
 			//validate defaults
@@ -134,9 +133,6 @@
 			}
 		}
 
-		function log()
-		{}
-
 		function make_parms($arg_array)
 		{
 			if ( count($arg_array) == 0 ) 
@@ -184,6 +180,12 @@
 			return $this->log_if_level('N',  $this->make_parms($arg_array));
 		}
 
+		function strict()
+		{
+			$arg_array = func_get_args();
+			return $this->log_if_level('S',  $this->make_parms($arg_array));
+		}
+
 		function warn()
 		{
 			$arg_array = func_get_args();
@@ -225,10 +227,10 @@
 				return;
 			}
 			$db->query("insert into phpgw_log (log_date, log_app, log_account_id, log_account_lid, log_severity, log_file, log_line, log_msg) values "
-				. "('" . $db->to_timestamp(time()) . "'"
+				. "('" . date($db->datetime_format()) . "'"
 				. ",'" . $db->db_addslashes($GLOBALS['phpgw_info']['flags']['currentapp']) . "'"
-				. ","  . ( isset($GLOBALS['phpgw']->session->account_id) ? $GLOBALS['phpgw']->session->account_id : -1)
-				. ",'" . $db->db_addslashes(isset($GLOBALS['phpgw']->session->account_lid) ? $GLOBALS['phpgw']->session->account_lid : 'not authenticated') . "'"
+				. ","  . ( isset($GLOBALS['phpgw_info']['user']['id']) ? $GLOBALS['phpgw_info']['user']['id'] : -1)
+				. ",'" . $db->db_addslashes(isset($GLOBALS['phpgw_info']['user']['lid']) ? $GLOBALS['phpgw_info']['user']['lid'] : 'not authenticated') . "'"
 				. ",'" . $err->severity . "'"
 				. ",'" . $db->db_addslashes($err->fname) . "'"
 				. ","  . intval($err->line)
@@ -305,6 +307,4 @@
 		{
 			return true;
 		}
-
-
 	}

Modified: people/sigurdne/modules/phpgwapi/trunk/inc/class.log_message.inc.php
===================================================================
--- people/sigurdne/modules/phpgwapi/trunk/inc/class.log_message.inc.php	2009-11-20 10:27:41 UTC (rev 20844)
+++ people/sigurdne/modules/phpgwapi/trunk/inc/class.log_message.inc.php	2009-11-20 10:28:10 UTC (rev 20845)
@@ -8,21 +8,6 @@
 	* @package phpgwapi
 	* @subpackage application
 	* @version $Id$
-	*/
-
-	/*
-	   This program is free software: you can redistribute it and/or modify
-	   it under the terms of the GNU General Public License as published by
-	   the Free Software Foundation, either version 3 of the License, or
-	   (at your option) any later version.
-
-	   This program is distributed in the hope that it will be useful,
-	   but WITHOUT ANY WARRANTY; without even the implied warranty of
-	   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-	   GNU General Public License for more details.
-
-	   You should have received a copy of the GNU General Public License
-	   along with this program.  If not, see <http://www.gnu.org/licenses/>.
 	 */
 
 	/**

Modified: people/sigurdne/modules/phpgwapi/trunk/inc/class.mail2array.inc.php
===================================================================
--- people/sigurdne/modules/phpgwapi/trunk/inc/class.mail2array.inc.php	2009-11-20 10:27:41 UTC (rev 20844)
+++ people/sigurdne/modules/phpgwapi/trunk/inc/class.mail2array.inc.php	2009-11-20 10:28:10 UTC (rev 20845)
@@ -11,21 +11,6 @@
 	* @package phpgwapi
 	* @subpackage mail
 	* @version $Id$
-	*/
-
-	/*
-	   This program is free software: you can redistribute it and/or modify
-	   it under the terms of the GNU General Public License as published by
-	   the Free Software Foundation, either version 3 of the License, or
-	   (at your option) any later version.
-
-	   This program is distributed in the hope that it will be useful,
-	   but WITHOUT ANY WARRANTY; without even the implied warranty of
-	   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-	   GNU General Public License for more details.
-
-	   You should have received a copy of the GNU General Public License
-	   along with this program.  If not, see <http://www.gnu.org/licenses/>.
 	 */
 
 	class phpgwapi_mail2array

Modified: people/sigurdne/modules/phpgwapi/trunk/inc/class.mailer_smtp.inc.php
===================================================================
--- people/sigurdne/modules/phpgwapi/trunk/inc/class.mailer_smtp.inc.php	2009-11-20 10:27:41 UTC (rev 20844)
+++ people/sigurdne/modules/phpgwapi/trunk/inc/class.mailer_smtp.inc.php	2009-11-20 10:28:10 UTC (rev 20845)
@@ -7,27 +7,12 @@
 	* @package phpgwapi
 	* @subpackage communication
 	* @version $Id$
-	*/
-
-	/*
-	   This program is free software: you can redistribute it and/or modify
-	   it under the terms of the GNU General Public License as published by
-	   the Free Software Foundation, either version 3 of the License, or
-	   (at your option) any later version.
-
-	   This program is distributed in the hope that it will be useful,
-	   but WITHOUT ANY WARRANTY; without even the implied warranty of
-	   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-	   GNU General Public License for more details.
-
-	   You should have received a copy of the GNU General Public License
-	   along with this program.  If not, see <http://www.gnu.org/licenses/>.
 	 */
 
 	/**
 	* @see phpmailer
 	*/
-	include_once(PHPGW_INCLUDE_ROOT . '/phpgwapi/inc/phpmailer/class.phpmailer.php');
+	require_once PHPGW_INCLUDE_ROOT . '/phpgwapi/inc/phpmailer/class.phpmailer.php';
 	
 	/**
 	* Send email messages via SMTP
@@ -36,17 +21,16 @@
 	* @package phpgwapi
 	* @subpackage communication
 	*/
-	class mailer_smtp extends PHPMailer
+	class phpgwapi_mailer_smtp extends PHPMailer
 	{
 		/**
 		* Constructor
 		*/
-		function mailer_smtp()
+		public function __construct()
 		{
 			$this->IsSMTP(true);
 			$this->Host = $GLOBALS['phpgw_info']['server']['smtp_server'];
-			$this->Port = isset($GLOBALS['phpgw_info']['server']['smtp_port'])?$GLOBALS['phpgw_info']['server']['smtp_port']:'';
+			$this->Port = isset($GLOBALS['phpgw_info']['server']['smtp_port']) ? $GLOBALS['phpgw_info']['server']['smtp_port'] : 25;
 			$this->Version = 'custom - phpGroupWare 1.73';
 		}
 	}
-?>

Modified: people/sigurdne/modules/phpgwapi/trunk/inc/class.matrixview.inc.php
===================================================================
--- people/sigurdne/modules/phpgwapi/trunk/inc/class.matrixview.inc.php	2009-11-20 10:27:41 UTC (rev 20844)
+++ people/sigurdne/modules/phpgwapi/trunk/inc/class.matrixview.inc.php	2009-11-20 10:28:10 UTC (rev 20845)
@@ -8,21 +8,6 @@
 	* @package phpgwapi
 	* @subpackage gui
 	* @version $Id$
-	*/
-
-	/*
-	   This program is free software: you can redistribute it and/or modify
-	   it under the terms of the GNU Lesser General Public License as published by
-	   the Free Software Foundation, either version 3 of the License, or
-	   (at your option) any later version.
-
-	   This program is distributed in the hope that it will be useful,
-	   but WITHOUT ANY WARRANTY; without even the implied warranty of
-	   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-	   GNU General Public License for more details.
-
-	   You should have received a copy of the GNU Lesser General Public License
-	   along with this program.  If not, see <http://www.gnu.org/licenses/>.
 	 */
 
 	/**
@@ -312,7 +297,7 @@
 				echo '<td colspan="2" align="right">' . "\n";
 				echo '<select name="month">'; 
 
-				for($i=0;$i<13;$i++)
+				for($i=1;$i<13;$i++)
 				{
 					if ($this->month == $i)
 					{

Modified: people/sigurdne/modules/phpgwapi/trunk/inc/class.menu.inc.php
===================================================================
--- people/sigurdne/modules/phpgwapi/trunk/inc/class.menu.inc.php	2009-11-20 10:27:41 UTC (rev 20844)
+++ people/sigurdne/modules/phpgwapi/trunk/inc/class.menu.inc.php	2009-11-20 10:28:10 UTC (rev 20845)
@@ -5,15 +5,15 @@
 	 * @author Dave Hall <[email protected]>
 	 * @copyright Copyright (C) 2007-2008 Free Software Foundation, Inc. http://www.fsf.org/
 	 * @license http://www.fsf.org/licenses/gpl.html GNU General Public License
-	 * @package phpgwapi
-	 * @subpackage utitlity
-	 * @version $Id: class.menu.inc.php 727 2008-02-08 04:13:28Z dave $
+	 * @package phpgroupware
+	 * @subpackage phpgwapi
+	 * @version $Id: class.menu.inc.php 1789 2008-11-04 13:07:09Z sigurd $
 	 */
 
 	/*
 	   This program is free software: you can redistribute it and/or modify
 	   it under the terms of the GNU General Public License as published by
-	   the Free Software Foundation, either version 3 of the License, or
+	   the Free Software Foundation, either version 2 of the License, or
 	   (at your option) any later version.
 
 	   This program is distributed in the hope that it will be useful,
@@ -28,33 +28,41 @@
 	/*
 	 * phpGroupWare menu handler class
 	 *
-	 * @package phpgwapi
-	 * @subpackage utitlity
+	 * @package phpgroupware
+	 * @subpackage phpgwapi
 	 */
 	class phpgwapi_menu
 	{
 		/**
 		* Clear the user's menu so it can be regenerated cleanly
+		*
+		* @return void
 		*/
 		public function clear()
 		{
-			$GLOBALS['phpgw']->session->appsession('phpgwapi', 'menu', null);
+			$account_id = $GLOBALS['phpgw_info']['user']['account_id'];
+			phpgwapi_cache::user_clear('phpgwapi', 'menu', $account_id);
 		}
 
 		/**
 		* Get the menu structure and return it
 		*
 		* @param string $mtype the type of menu sought - default all returned
+		*
 		* @return array menu structure
 		*/
 		public function get($mtype = null)
 		{
-			//$menu = $GLOBALS['phpgw']->session->appsession('phpgwapi', 'menu');
-			$menu = null;
+		//	static $menu = null;
+
+			//$menu = null; 
+			$account_id = $GLOBALS['phpgw_info']['user']['account_id'];
+			$menu = phpgwapi_cache::user_get('phpgwapi', 'menu', $account_id);
+
 			if ( !$menu )
 			{
 				$menu = self::load();
-				$GLOBALS['phpgw']->session->appsession('phpgwapi', 'menu', $menu);
+				phpgwapi_cache::user_set('phpgwapi', 'menu', $menu, $account_id);
 			}
 
 			if ( !is_null($mtype) && isset($menu[$mtype]) )
@@ -68,13 +76,15 @@
 		* Get categories available for the current user
 		*
 		* @param string $module the module the categories are sought for
+		*
 		* @return array menu class compatiable array of categories
 		*/
 		public static function get_categories($module)
 		{
 			$catobj = createObject('phpgwapi.categories', $GLOBALS['phpgw_info']['user']['account_id'], $module);
 			$cats = $catobj->return_sorted_array(0, false, '', 'ASC', 'cat_main, cat_level, cat_name', true);
-			//echo "module: $module <pre>" . print_r($cats, true) . '</pre>';
+
+			return $cats;
 		}
 		
 		/**
@@ -86,8 +96,11 @@
 		{
 			$menus = array();
 			$raw_menus = $GLOBALS['phpgw']->hooks->process('menu');
-			foreach ( $raw_menus as $app => $raw_menu )
+
+			foreach ( $GLOBALS['phpgw_info']['user']['apps'] as $app => $app_info )
+		//	foreach ( $raw_menus as $app => $raw_menu )
 			{
+				$raw_menu = $raw_menus[$app];
 				// Ignore invalid entries
 				if ( !is_array($raw_menu) )
 				{
@@ -116,7 +129,8 @@
 							$menus['navigation']['admin'][$app] = array
 							(
 								'text'	=> $GLOBALS['phpgw']->translation->translate($app, array(), true),
-								'url'	=> $GLOBALS['phpgw']->link('/index.php', array('menuaction' => 'admin.uiconfig.index', 'appname' => $app)),
+								'url'	=> $GLOBALS['phpgw']->link('/index.php',
+											array('menuaction' => 'admin.uiconfig.index', 'appname' => $app)),
 								'image'	=> $raw_menu['navbar'][$app]['image'],
 								'children'	=> $menu
 							);
@@ -128,4 +142,97 @@
 			}
 			return $menus;
 		}
+
+		/**
+		 * Render  a menu for an application
+		 *
+		 * @param array  $item the menu item
+		 * @param string $id   identificator for current location
+		 * @param string $children rendered sub menu
+		 * @param bool   $show_appname show appname as top level
+		 */
+		public function render_menu($app, $navigation, $navbar, $show_appname = false)
+		{
+			$treemenu = '';
+			$submenu = isset($navigation) ? self::_render_submenu($app, $navigation) : '';
+			$treemenu .= self::_render_item($navbar, "navbar::{$app}", $submenu, $show_appname);
+			$html = <<<HTML
+			<ul id="menu">
+				{$treemenu}
+			</ul>
+
+HTML;
+			return $html;
+		}
+
+		/**
+		 * Render items from a menu and append the children
+		 *
+		 * @param array  $item         the menu item
+		 * @param string $id           identificator for current location
+		 * @param string $children     rendered sub menu
+		 * @param bool   $show_appname show appname as top level
+		 */
+		protected static function _render_item($item, $id='', $children='', $show_appname = false)
+		{
+			$current_class = '';
+			if ( $id == "navbar::{$GLOBALS['phpgw_info']['flags']['menu_selection']}" )
+			{
+				$current_class = 'current';
+			}
+
+			$link_class =" class=\"{$current_class}\"";
+
+			if(isset($item['group']) && $show_appname) // at application
+			{
+				return <<<HTML
+				<li class="parent">
+					<span>{$item['text']}</span>
+				{$children}
+				</li>
+HTML;
+			}
+			if(isset($item['group']) && !$show_appname)
+			{
+				return <<<HTML
+				{$children}
+HTML;
+			}
+			else if (isset($item['url']))
+			{
+				return <<<HTML
+				<li>
+					<a href="{$item['url']}"{$link_class} id="{$id}">
+						<span>{$item['text']}</span>
+					</a>
+					{$children}
+				</li>
+HTML;
+			}
+		}
+
+		/**
+		 * Get sub items from a menu 
+		 *
+		 * @param string $parent  name of parent item
+		 * @param array  $menu the menu items to add to structure
+		 * @param bool   $show_appname show appname as top level
+		 */
+		protected static function _render_submenu($parent, $menu, $show_appname = false)
+		{
+			$out = '';
+			foreach ( $menu as $key => $item )
+			{
+				$children = isset($item['children']) ? self::_render_submenu("{$parent}::{$key}", $item['children'], $show_appname) : '';
+				$out .= self::_render_item($item, "navbar::{$parent}::{$key}", $children, $show_appname);
+			}
+
+			$out = <<<HTML
+			<ul>
+				{$out}
+			</ul>
+
+HTML;
+			return $out;
+		}
 	}

Modified: people/sigurdne/modules/phpgwapi/trunk/inc/class.menu_apps.inc.php
===================================================================
--- people/sigurdne/modules/phpgwapi/trunk/inc/class.menu_apps.inc.php	2009-11-20 10:27:41 UTC (rev 20844)
+++ people/sigurdne/modules/phpgwapi/trunk/inc/class.menu_apps.inc.php	2009-11-20 10:28:10 UTC (rev 20845)
@@ -6,13 +6,13 @@
 	 * @copyright Copyright (C) 2007 Free Software Foundation, Inc. http://www.fsf.org/
 	 * @license http://www.gnu.org/licenses/gpl.html GNU General Public License
 	 * @package phpgwapi 
-	 * @version $Id: class.menu_apps.inc.php 682 2008-02-01 12:19:55Z dave $
+	 * @version $Id: class.menu_apps.inc.php 1781 2008-11-02 19:51:19Z sigurd $
 	 */
 
 	/*
 	   This program is free software: you can redistribute it and/or modify
 	   it under the terms of the GNU General Public License as published by
-	   the Free Software Foundation, either version 3 of the License, or
+	   the Free Software Foundation, either version 2 of the License, or
 	   (at your option) any later version.
 
 	   This program is distributed in the hope that it will be useful,
@@ -24,6 +24,7 @@
 	   along with this program.  If not, see <http://www.gnu.org/licenses/>.
 	 */
 
+
 	/**
 	 * Menus
 	 *

Modified: people/sigurdne/modules/phpgwapi/trunk/inc/class.menutree.inc.php
===================================================================
--- people/sigurdne/modules/phpgwapi/trunk/inc/class.menutree.inc.php	2009-11-20 10:27:41 UTC (rev 20844)
+++ people/sigurdne/modules/phpgwapi/trunk/inc/class.menutree.inc.php	2009-11-20 10:28:10 UTC (rev 20845)
@@ -8,21 +8,6 @@
 	* @package phpgwapi
 	* @subpackage gui
 	* @version $Id$
-	*/
-
-	/*
-	   This program is free software: you can redistribute it and/or modify
-	   it under the terms of the GNU General Public License as published by
-	   the Free Software Foundation, either version 3 of the License, or
-	   (at your option) any later version.
-
-	   This program is distributed in the hope that it will be useful,
-	   but WITHOUT ANY WARRANTY; without even the implied warranty of
-	   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-	   GNU General Public License for more details.
-
-	   You should have received a copy of the GNU General Public License
-	   along with this program.  If not, see <http://www.gnu.org/licenses/>.
 	 */
 
 	/**

Modified: people/sigurdne/modules/phpgwapi/trunk/inc/class.mime_magic.inc.php
===================================================================
--- people/sigurdne/modules/phpgwapi/trunk/inc/class.mime_magic.inc.php	2009-11-20 10:27:41 UTC (rev 20844)
+++ people/sigurdne/modules/phpgwapi/trunk/inc/class.mime_magic.inc.php	2009-11-20 10:28:10 UTC (rev 20845)
@@ -17,21 +17,6 @@
 	* @internal Note: this class was relicensed as GPL by Dave Hall - all mods GPL
 	*/
 
-	/*
-	   This program is free software: you can redistribute it and/or modify
-	   it under the terms of the GNU General Public License as published by
-	   the Free Software Foundation, either version 3 of the License, or
-	   (at your option) any later version.
-
-	   This program is distributed in the hope that it will be useful,
-	   but WITHOUT ANY WARRANTY; without even the implied warranty of
-	   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-	   GNU General Public License for more details.
-
-	   You should have received a copy of the GNU General Public License
-	   along with this program.  If not, see <http://www.gnu.org/licenses/>.
-	 */
-
 	/**
 	* mime magic
 	* 

Added: people/sigurdne/modules/phpgwapi/trunk/inc/class.ms_exchange.inc.php
===================================================================
--- people/sigurdne/modules/phpgwapi/trunk/inc/class.ms_exchange.inc.php	                        (rev 0)
+++ people/sigurdne/modules/phpgwapi/trunk/inc/class.ms_exchange.inc.php	2009-11-20 10:28:10 UTC (rev 20845)
@@ -0,0 +1,476 @@
+<?php
+	/**
+	* phpGroupWare MS Exchange integration
+	*
+	* @author Troy Wolf <[email protected]>
+	* @author Sigurd Nes <[email protected]>
+	* @copyright Copyright (C) 2009 Free Software Foundation, Inc. http://www.fsf.org/
+	* @license http://www.gnu.org/licenses/lgpl.html GNU Lesser General Public License Version 2 or later
+	* @package phpgroupware
+	* @subpackage phpgwapi
+	* @version $Id$
+	*/
+
+	/*
+		This program is free software: you can redistribute it and/or modify
+		it under the terms of the GNU Lesser General Public License as published by
+		the Free Software Foundation, either version 2 of the License, or
+		(at your option) any later version.
+
+		This program is distributed in the hope that it will be useful,
+		but WITHOUT ANY WARRANTY; without even the implied warranty of
+		MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+		GNU Lesser General Public License for more details.
+
+		You should have received a copy of the GNU Lesser General Public License
+		along with this program.  If not, see <http://www.gnu.org/licenses/>.
+	 */
+
+	/**
+	* phpGroupWare caching system
+	*
+	* Implementing Webdav protocoll for communicate with Microsoft Exchange
+	* The code is mostly written / inspired by Troy Wolf ([email protected])
+	*
+	* @package phpgroupware
+	* @subpackage phpgwapi
+	* @category communication
+	*/
+
+	require_once PHPGW_API_INC . '/exchange/class_http.php';
+	require_once PHPGW_API_INC . '/exchange/class_xml.php';
+
+	class phpgwapi_ms_exchange
+	{
+		public $exchange_server = "http://NameOfYourExchangeServer";
+	//	public $exchange_domain = "domain";
+		public $exchange_username = "YourExchangeUsername";
+		public $exchange_password = "YourExchangePassword";
+
+		public function __construct()
+		{
+			$this->http = new http();
+			$this->http->headers["Content-Type"] = 'text/xml; charset="UTF-8"'; 
+
+			$this->xml = new xml();
+		}
+
+		/**
+		 * Iterate the folders in a user's inbox
+		 *
+		 * @return object that is an array of objects and arrays that makes it easy to access the parts you need
+		 */
+		public function list_folders()
+		{
+			// http://msdn.microsoft.com/library/default.asp?url=/library/en-us/e2k3/e2k3/_webdav_depth_header.asp
+			$this->http->headers["Depth"] = "0";
+
+			$this->http->headers["Translate"] = "f";
+
+			// The trickiest part is forming your WebDAV query. This example shows how to
+			// find all the folders in the inbox for a user name.
+			$this->http->xmlrequest = '<?xml version="1.0"?>';
+			$this->http->xmlrequest .= <<<END
+			<a:searchrequest xmlns:a="DAV:" xmlns:s="http://schemas.microsoft.com/exchange/security/">
+			   <a:sql>
+			       SELECT "DAV:displayname"
+			       FROM SCOPE('hierarchical traversal of "{$this->exchange_server}/Exchange/{$this->exchange_username}/inbox"')
+			   </a:sql>
+			</a:searchrequest>
+END;
+			// IMPORTANT -- The END line above must be completely left-aligned. No white-space.
+
+			// The 'fetch' method does the work of sending and receiving the request.
+			// NOTICE the last parameter passed--'SEARCH' in this example. That is the
+			// HTTP verb that you must correctly set according to the type of WebDAV request
+			// you are making.  The examples on this page use either 'PROPFIND' or 'SEARCH'.
+			if (!$this->http->fetch("{$this->exchange_server}/Exchange/{$this->exchange_username}/inbox", 0, null, $this->exchange_username, $this->exchange_password, "SEARCH")) 
+			{
+			  echo "<h2>There is a problem with the http request!</h2>";
+			  echo $this->http->log;
+			  exit();
+			}
+
+			// Note: The following lines can be uncommented to aid in debugging.
+			#echo "<pre>".$this->http->log."</pre><hr />\n";
+			#echo "<pre>".$this->http->header."</pre><hr />\n";
+			#echo "<pre>".$this->http->body."</pre><hr />\n";
+			#exit();
+			// Or, these next lines will display the result as an XML doc in the browser.
+			#header('Content-type: text/xml');
+			#echo $this->http->body;
+			#exit();
+
+			// The assumption now is that we've got an XML result back from the Exchange
+			// Server, so let's parse the XML into an object we can more easily access.
+
+			if (!$this->xml->fetch($this->http->body))
+			{
+			    echo "<h2>There was a problem parsing your XML!</h2>";
+			    echo "<pre>".$this->http->log."</pre><hr />\n";
+			    echo "<pre>".$this->http->header."</pre><hr />\n";
+			    echo "<pre>".$this->http->body."</pre><hr />\n";
+			    echo "<pre>".$this->xml->log."</pre><hr />\n";
+			    exit();
+			}
+
+			// You should now have an object that is an array of objects and arrays that
+			// makes it easy to access the parts you need. These next lines can be
+			// uncommented to make a raw display of the data object.
+			#echo "<pre>\n";
+			#print_r($this->xml->data);
+			#echo "</pre>\n";
+			#exit();
+
+			// And finally, an example of iterating the inbox folder names and url's to
+			// display in the browser. I also show you 2 methods to link to the folders.
+			// One uses the href provided in the response which opens the folder using OWA.
+			// The other is an Outlook style link to open the folder in the Outlook desktop
+			// client.
+			echo '<table border="1">';
+			foreach($this->xml->data->A_MULTISTATUS[0]->A_RESPONSE as $idx=>$item)
+			{
+			    echo '<tr>'
+			        .'<td>'.$item->A_PROPSTAT[0]->A_PROP[0]->A_DISPLAYNAME[0]->_text.'</td>'
+			        .'<td><a href="'.$item->A_HREF[0]->_text.'">Click to open via OWA</a></td>'
+			        .'<td><a href="Outlook:Inbox/'.$item->A_PROPSTAT[0]->A_PROP[0]->A_DISPLAYNAME[0]->_text.'">Click to open via Outlook</a></td>'
+			        ."</tr>\n";
+			}
+			echo "<table>\n"; 
+
+		}
+
+		/**
+		 * Iterate the email items in a user's inbox
+		 *
+		 * @return object that is an array of objects and arrays that makes it easy to access the parts you need
+		 */
+		public function list_email()
+		{
+			$this->http->headers["Depth"] = "0";
+			$this->http->headers["Translate"] = "f";
+
+			// Find all the email items in the inbox for a user name.
+			$this->http->xmlrequest = '<?xml version="1.0"?>';
+			$this->http->xmlrequest .= <<<END
+			<a:searchrequest xmlns:a="DAV:" xmlns:s="http://schemas.microsoft.com/exchange/security/">
+			   <a:sql>
+			       SELECT "DAV:displayname"
+			       ,"urn:schemas:httpmail:subject"
+			       FROM "{$this->exchange_server}/Exchange/{$this->exchange_username}/inbox"
+			   </a:sql>
+			</a:searchrequest>
+END;
+			// IMPORTANT -- The END line above must be completely left-aligned. No white-space.
+
+			// The 'fetch' method does the work of sending and receiving the request.
+			// NOTICE the last parameter passed--'SEARCH' in this example. That is the
+			// HTTP verb that you must correctly set according to the type of WebDAV request
+			// you are making.  The examples on this page use either 'PROPFIND' or 'SEARCH'.
+			if (!$this->http->fetch("{$this->exchange_server}/Exchange/{$this->exchange_username}/inbox", 0, null, $this->exchange_username, $this->exchange_password, "SEARCH"))
+			{
+			  echo "<h2>There is a problem with the http request!</h2>";
+			  echo $this->http->log;
+			  exit();
+			}
+
+			// The assumption now is that we've got an XML result back from the Exchange
+			// Server, so let's parse the XML into an object we can more easily access.
+			// For this task, we'll use Troy's xml class object.
+			$x = new xml();
+			if (!$this->xml->fetch($this->http->body))
+			{
+			    echo "<h2>There was a problem parsing your XML!</h2>";
+			    echo "<pre>".$this->http->log."</pre><hr />\n";
+			    echo "<pre>".$this->http->header."</pre><hr />\n";
+			    echo "<pre>".$this->http->body."</pre><hr />\n";
+			    echo "<pre>".$this->xml->log."</pre><hr />\n";
+			    exit();
+			}
+
+			// And finally, an example of iterating the email items to display in the
+			// browser. I also show you 2 methods to link to the items. One uses the href
+			// provided in the response which opens the folder using OWA. The other is an
+			// Outlook style link to open the folder in the Outlook desktop client.
+			echo '<table border="1">';
+			foreach($this->xml->data->A_MULTISTATUS[0]->A_RESPONSE as $idx=>$item)
+			{
+			    echo '<tr>'
+			        .'<td>'.$item->A_PROPSTAT[0]->A_PROP[0]->D_SUBJECT[0]->_text.'</td>'
+			        .'<td><a href="'.$item->A_HREF[0]->_text.'">Click to open via OWA</a></td>'
+			        .'<td><a href="Outlook:Inbox/~'.$item->A_PROPSTAT[0]->A_PROP[0]->D_SUBJECT[0]->_text.'">Click to open via Outlook</a></td>'
+			        ."</tr>\n";
+			}
+			echo "<table>\n";
+
+		}
+
+		/**
+		 * Search for contacts that match a certain criteria
+		 *
+		 * @return object that is an array of objects and arrays that makes it easy to access the parts you need
+		 */
+		public function list_contacts()
+		{
+			$this->http->headers["Depth"] = "0";
+			$this->http->headers["Translate"] = "f";
+
+			// Find all the contacts for a specific company in a specific folder.
+			// http://msdn.microsoft.com/library/default.asp?url=/library/en-us/e2k3/e2k3/_exch2k_urn_content-classes_person.asp
+			$this->http->xmlrequest = '<?xml version="1.0"?>';
+			$this->http->xmlrequest .= <<<END
+			<a:searchrequest xmlns:a="DAV:">
+			    <a:sql>
+			        SELECT "a:href"
+			        ,"urn:schemas:contacts:o"
+			        ,"urn:schemas:contacts:cn"
+			        ,"urn:schemas:contacts:fileas"
+			        ,"urn:schemas:contacts:title"
+			        ,"urn:schemas:contacts:email1"
+			        ,"urn:schemas:contacts:telephoneNumber"
+			        FROM "{$this->exchange_server}/public/Customer%20Contacts/"
+			        WHERE "urn:schemas:contacts:o" = 'XYZ Industries, Inc.'
+			        ORDER BY "urn:schemas:contacts:cn"
+			    </a:sql>
+			</a:searchrequest>
+END;
+			// IMPORTANT -- The END line above must be completely left-aligned. No white-space.
+
+			// The 'fetch' method does the work of sending and receiving the request.
+			// NOTICE the last parameter passed--'SEARCH' in this example. That is the
+			// HTTP verb that you must correctly set according to the type of WebDAV request
+			// you are making.  The examples on this page use either 'PROPFIND' or 'SEARCH'.
+			if (!$this->http->fetch("{$this->exchange_server}/public/Customer%20Contacts", 0, null, $this->exchange_username, $this->exchange_password, "SEARCH"))
+			{
+			  echo "<h2>There is a problem with the http request!</h2>";
+			  echo $this->http->log;
+			  exit();
+			}
+
+			// The assumption now is that we've got an XML result back from the Exchange
+			// Server, so let's parse the XML into an object we can more easily access.
+			// For this task, we'll use Troy's xml class object.
+			$x = new xml();
+			if (!$this->xml->fetch($this->http->body))
+			{
+			    echo "<h2>There was a problem parsing your XML!</h2>";
+			    echo "<pre>".$this->http->log."</pre><hr />\n";
+			    echo "<pre>".$this->http->header."</pre><hr />\n";
+			    echo "<pre>".$this->http->body."</pre><hr />\n";
+			    echo "<pre>".$this->xml->log."</pre><hr />\n";
+			    exit();
+			}
+
+			// And finally, an example of iterating the contact items to display in the browser.
+			echo '<table border="1">';
+			echo "<tr><th>Company</th><th>Name</th><th>Title</th><th>Email</th><th>Phone</th></tr>\n";
+			foreach($this->xml->data->A_MULTISTATUS[0]->A_RESPONSE as $idx=>$contact)
+			{
+			    echo '<tr>'
+			        .'<td>'.$contact->A_PROPSTAT[0]->A_PROP[0]->E_O[0]->_text.'</td>'
+			        .'<td><a href="outlook://Public%20Folders/All%20Public%20Folders/Account_Contacts/~'.str_replace(" ","%20",$contact->A_PROPSTAT[0]->A_PROP[0]->E_CN[0]->_text).'">'
+			        .$contact->A_PROPSTAT[0]->A_PROP[0]->E_CN[0]->_text.'</a></td>'
+			        .'<td>'.$contact->A_PROPSTAT[0]->A_PROP[0]->E_TITLE[0]->_text.'</td>'
+			        .'<td>'.$contact->A_PROPSTAT[0]->A_PROP[0]->E_EMAIL1[0]->_text.'</td>'
+			        .'<td>'.$contact->A_PROPSTAT[0]->A_PROP[0]->E_TELEPHONENUMBER[0]->_text.'</td>'
+			        ."</tr>\n";
+			}
+			echo "<table>\n";
+
+					}
+
+		/**
+		 * Grab all properties for an item
+		 *
+		 * @return object that is an array of objects and arrays that makes it easy to access the parts you need
+		 */
+		public function allprop()
+		{
+			$this->http->headers["Depth"] = "0";
+			$this->http->headers["Translate"] = "f";
+
+			// Find all the properties for a specific item.
+			$this->http->xmlrequest = '<?xml version="1.0"?>';
+			$this->http->xmlrequest .= <<<END
+			<a:propfind xmlns:a="DAV:">
+			    <a:allprop/>
+			</a:propfind>
+END;
+			// IMPORTANT -- The END line above must be completely left-aligned. No white-space.
+
+			// The 'fetch' method does the work of sending and receiving the request.
+			// NOTICE the last parameter passed--'PROPFIND' in this example. That is the
+			// HTTP verb that you must correctly set according to the type of WebDAV request
+			// you are making.  The examples on this page use either 'PROPFIND' or 'SEARCH'.
+			if (!$this->http->fetch("{$this->exchange_server}/public/Email%20Log/Some%20Message-668992879.EML", 0, null, $this->exchange_username, $this->exchange_password, "PROPFIND"))
+			{
+			  echo "<h2>There is a problem with the http request!</h2>";
+			  echo $this->http->log;
+			  exit();
+			}
+
+			// The assumption now is that we've got an XML result back from the Exchange
+			// Server, so let's parse the XML into an object we can more easily access.
+			// For this task, we'll use Troy's xml class object.
+			$x = new xml();
+			if (!$this->xml->fetch($this->http->body))
+			{
+			    echo "<h2>There was a problem parsing your XML!</h2>";
+			    echo "<pre>".$this->http->log."</pre><hr />\n";
+			    echo "<pre>".$this->http->header."</pre><hr />\n";
+			    echo "<pre>".$this->http->body."</pre><hr />\n";
+			    echo "<pre>".$this->xml->log."</pre><hr />\n";
+			    exit();
+			}
+
+			echo "<pre>";
+			print_r($this->xml->data);
+			echo "</pre>";
+
+
+		}
+
+		/**
+		 * Create a new contact if the URL does not exist or update an existing contact
+		 * Notice the last 2 properties. Those are custom fields that must be pre-defined for the folder.
+		 *
+		 * @return object that is an array of objects and arrays that makes it easy to access the parts you need
+		 */
+		public function set_contact()
+		{
+			$this->http->headers["Depth"] = "0";
+			$this->http->headers["Translate"] = "f";
+
+			// Build the XML request.
+			// This section must be against the left margin.
+			$this->http->xmlrequest = '<?xml version="1.0"?>';
+			$this->http->xmlrequest .= <<<END
+			<g:propertyupdate   xmlns:g="DAV:"
+			                    xmlns:b="urn:uuid:c2f41010-65b3-11d1-a29f-00aa00c14882/"
+			                    xmlns:c="urn:schemas:contacts:"
+			                    xmlns:e="http://schemas.microsoft.com/exchange/"
+			                    xmlns:mapi="http://schemas.microsoft.com/mapi/"
+			                    xmlns:o="urn:schemas-microsoft-com:office:office"
+			                    xmlns:cust="urn:schemas:customproperty"
+			                    xmlns:ed="urn:schemas-microsoft-com:exch-data:"
+			                    xmlns:repl="http://schemas.microsoft.com/repl/"
+			                    xmlns:x="xml:"
+			                    xmlns:cal="urn:schemas:calendar:"
+			                    xmlns:mail="urn:schemas:httpmail:"
+			                    xmlns:ec="urn:schemas-microsoft-com:exch-data:expected-content-class"
+			                    xmlns:j="urn:content-classes:propertydef"
+			                    xmlns:mailheader="urn:schemas:mailheader:">
+			    <g:set>
+			        <g:prop>
+			            <g:contentclass>urn:content-classes:person</g:contentclass>
+			            <e:outlookmessageclass>IPM.Contact</e:outlookmessageclass>
+			            <e:keywords-utf8>
+			            <x:v>Buddies</x:v><x:v>Engineers</x:v>
+			            </e:keywords-utf8>
+			            <c:language>US English</c:language>
+			            <c:o>Innotech, Inc.</c:o>
+			            <c:givenName>John</c:givenName>
+			            <c:sn>Doe</c:sn>
+			            <c:cn>John Doe</c:cn>
+			            <c:fileas>Doe, John</c:fileas>
+			            <c:street>100 N. Main</c:street>
+			            <c:postofficebox>PO Box 555</c:postofficebox>
+			            <c:l>Kansas City</c:l>
+			            <c:st>MO</c:st>
+			            <c:postalcode>64118</c:postalcode>
+			            <c:co>USA</c:co>
+			            <c:telephoneNumber>425-555-1110</c:telephoneNumber>
+			            <c:facsimiletelephonenumber>425-555-1112</c:facsimiletelephonenumber>
+			            <c:homePhone>425-555-1113</c:homePhone>
+			            <c:mobile>425-555-1117</c:mobile>
+			            <mapi:email1addrtype>SMTP</mapi:email1addrtype>
+			            <mapi:email1emailaddress>[email protected]</mapi:email1emailaddress>
+			            <mapi:email1originaldisplayname>John Doe</mapi:email1originaldisplayname>
+			            <favoritecolor>Blue</favoritecolor>
+			            <newsletter b:dt="boolean">1</newsletter>
+			        </g:prop>
+			    </g:set>
+			</g:propertyupdate>
+END;
+			// IMPORTANT -- The END line above must be completely left-aligned. No white-space.
+
+			// The http object's 'fetch' method does the work of sending and receiving the
+			// request. We use the WebDAV PROPPATCH method to create or update Exchange items.
+			$url = "{$this->exchange_server}/public/Company%20Contacts/john%20doe.EML";
+			if (!$this->http->fetch($url, 0, null, $this->exchange_username, $this->exchange_password, "PROPPATCH"))
+			{
+			  echo "<h2>There is a problem with the http request!</h2>";
+			  echo $this->http->log;
+			  exit();
+			}
+
+			// You can print out the response to help troubleshoot.
+			echo "<pre>".$this->http->header."</pre><hr />\n";
+			echo "<pre>".$this->http->body."</pre><hr />\n";
+
+		}
+
+		/**
+		 * Create a new email message
+		 *
+		 * @return object that is an array of objects and arrays that makes it easy to access the parts you need
+		 */
+		public function new_email()
+		{
+			$this->http->headers["Depth"] = "0";
+			$this->http->headers["Translate"] = "f";
+
+			$subject = "Some subject";
+			$htmldescription = "This is spam. Please delete this email.";
+			// Build the XML request.
+			// This section must be against the left margin.
+			$this->http->xmlrequest = '<?xml version="1.0"?>';
+			$this->http->xmlrequest .= <<<END
+			<a:propertyupdate   xmlns:a="DAV:"
+			                    xmlns:b="urn:uuid:c2f41010-65b3-11d1-a29f-00aa00c14882/"
+			                    xmlns:g="http://schemas.microsoft.com/mapi/"
+			                    xmlns:e="urn:schemas:httpmail:"
+			                    xmlns:d="urn:schemas:mailheader:"
+			                    xmlns:c="xml:"
+			                    xmlns:f="http://schemas.microsoft.com/mapi/proptag/"
+			                    xmlns:h="http://schemas.microsoft.com/exchange/"
+			                    xmlns:i="urn:schemas-microsoft-com:office:office"
+			                    xmlns:k="http://schemas.microsoft.com/repl/"
+			                    xmlns:j="urn:schemas:calendar:"
+			                    xmlns:l="urn:schemas-microsoft-com:exch-data:">
+			    <a:set>
+			        <a:prop>
+			            <a:contentclass>urn:content-classes:message</a:contentclass>
+			            <h:outlookmessageclass>IPM.Note</h:outlookmessageclass>
+			            <d:to>[email protected]</d:to>
+			            <d:cc>[email protected]</d:cc>
+			            <d:bcc>[email protected]</d:bcc>
+			            <g:subject>$subject</g:subject>
+			            <e:htmldescription>$htmldescription</e:htmldescription>
+			        </a:prop>
+			    </a:set>
+			</a:propertyupdate>
+END;
+			// IMPORTANT -- The END line above must be completely left-aligned. No white-space.
+
+			// The http object's 'fetch' method does the work of sending and receiving the
+			// request. We use the WebDAV PROPPATCH method to create or update Exchange items.
+			$url = "{$this->exchange_server}/Exchange/{$this->exchange_username}/Drafts/".urlencode($subject).".EML";
+			if (!$this->http->fetch($url, 0, null, $this->exchange_username, $this->exchange_password, "PROPPATCH"))
+			{
+			  echo "<h2>There is a problem with the http request!</h2>";
+			  echo $this->http->log;
+			  exit();
+			}
+
+			// You can print out the response to help troubleshoot.
+			echo "<pre>".$this->http->header."</pre><hr />\n";
+			echo "<pre>".$this->http->body."</pre><hr />\n";
+
+			// Bonus tip! You can automatically open this new draft message for your user by
+			// formulating an outlook URL. Then either redirect to the URL by uncommenting the
+			// header line below, or pop the URL in client-side javascript using window.open.
+			#header("Location: outlook:drafts/~".urlencode($subject));
+
+		}
+	}


Property changes on: people/sigurdne/modules/phpgwapi/trunk/inc/class.ms_exchange.inc.php
___________________________________________________________________
Added: svn:keywords
   + Id Revision
Added: svn:eol-style
   + native

Modified: people/sigurdne/modules/phpgwapi/trunk/inc/class.net_http_client.inc.php
===================================================================
--- people/sigurdne/modules/phpgwapi/trunk/inc/class.net_http_client.inc.php	2009-11-20 10:27:41 UTC (rev 20844)
+++ people/sigurdne/modules/phpgwapi/trunk/inc/class.net_http_client.inc.php	2009-11-20 10:28:10 UTC (rev 20845)
@@ -12,22 +12,7 @@
 	* @todo remaining WebDAV methods: UNLOCK PROPPATCH
 	*/
 
-	/*
-	   This program is free software: you can redistribute it and/or modify
-	   it under the terms of the GNU General Public License as published by
-	   the Free Software Foundation, either version 3 of the License, or
-	   (at your option) any later version.
 
-	   This program is distributed in the hope that it will be useful,
-	   but WITHOUT ANY WARRANTY; without even the implied warranty of
-	   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-	   GNU General Public License for more details.
-
-	   You should have received a copy of the GNU General Public License
-	   along with this program.  If not, see <http://www.gnu.org/licenses/>.
-	 */
-
-
 	/**
 	* Debug level - debug methods calls
 	*/

Modified: people/sigurdne/modules/phpgwapi/trunk/inc/class.network.inc.php
===================================================================
--- people/sigurdne/modules/phpgwapi/trunk/inc/class.network.inc.php	2009-11-20 10:27:41 UTC (rev 20844)
+++ people/sigurdne/modules/phpgwapi/trunk/inc/class.network.inc.php	2009-11-20 10:28:10 UTC (rev 20845)
@@ -8,21 +8,6 @@
 	* @package phpgwapi
 	* @subpackage network
 	* @version $Id$
-	*/
-
-	/*
-	   This program is free software: you can redistribute it and/or modify
-	   it under the terms of the GNU Lesser General Public License as published by
-	   the Free Software Foundation, either version 3 of the License, or
-	   (at your option) any later version.
-
-	   This program is distributed in the hope that it will be useful,
-	   but WITHOUT ANY WARRANTY; without even the implied warranty of
-	   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-	   GNU General Public License for more details.
-
-	   You should have received a copy of the GNU Lesser General Public License
-	   along with this program.  If not, see <http://www.gnu.org/licenses/>.
 	 */
 
 	/**

Modified: people/sigurdne/modules/phpgwapi/trunk/inc/class.nextmatchs.inc.php
===================================================================
--- people/sigurdne/modules/phpgwapi/trunk/inc/class.nextmatchs.inc.php	2009-11-20 10:27:41 UTC (rev 20844)
+++ people/sigurdne/modules/phpgwapi/trunk/inc/class.nextmatchs.inc.php	2009-11-20 10:28:10 UTC (rev 20845)
@@ -4,26 +4,11 @@
 	* @author Joseph Engo <[email protected]>
 	* @author Bettina Gille <[email protected]>
 	* @author Dave Hall skwashd phpgroupware.org
-	* @copyright Copyright (C) 2000-2006 Free Software Foundation, Inc. http://www.fsf.org/
+	* @copyright Copyright (C) 2000-2008 Free Software Foundation, Inc. http://www.fsf.org/
 	* @license http://www.fsf.org/licenses/lgpl.html GNU Lesser General Public License
 	* @package phpgwapi
 	* @subpackage gui
 	* @version $Id$
-	*/
-
-	/*
-	   This program is free software: you can redistribute it and/or modify
-	   it under the terms of the GNU Lesser General Public License as published by
-	   the Free Software Foundation, either version 3 of the License, or
-	   (at your option) any later version.
-
-	   This program is distributed in the hope that it will be useful,
-	   but WITHOUT ANY WARRANTY; without even the implied warranty of
-	   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-	   GNU General Public License for more details.
-
-	   You should have received a copy of the GNU Lesser General Public License
-	   along with this program.  If not, see <http://www.gnu.org/licenses/>.
 	 */
 
 	/**
@@ -31,7 +16,7 @@
 	* @see nextmatchs_xslt
 	* @todo make a generic abstract base class which both classes extend, not this wacky relationship
 	*/
-	include_once(PHPGW_API_INC . '/class.nextmatchs_xslt.inc.php');
+	phpgw::import_class('phpgwapi.nextmatchs_xslt');
 
 	/**
 	* Handles limiting number of rows displayed
@@ -39,7 +24,7 @@
 	* @package phpgwapi
 	* @subpackage gui
 	*/
-	class nextmatchs extends nextmatchs_xslt
+	class phpgwapi_nextmatchs extends phpgwapi_nextmatchs_xslt
 	{
 		/**
 		* @var int $maxmatches the maximum number of records to return
@@ -71,33 +56,39 @@
 		*
 		* @param bool $website ???
 		*/
-		function nextmatchs($website = False)
+		public function __construct($website = false)
 		{
-			if(!$website)
+			if ( !$website )
+		{
+				if ( !isset($GLOBALS['phpgw']->template)
+					|| is_object($GLOBALS['phpgw']->template) )
 			{
-				$this->template = createObject('phpgwapi.Template',PHPGW_TEMPLATE_DIR);
-				$this->template->set_file(array(
+					$GLOBALS['phpgw']->template = createObject('phpgwapi.Template', PHPGW_TEMPLATE_DIR);
+				}
+				$this->template =& $GLOBALS['phpgw']->template;
+				$this->template->set_file(array
+				(
 					'_nextmatchs' => 'nextmatchs.tpl'
 				));
 				$this->template->set_block('_nextmatchs','nextmatchs');
-				$this->template->set_block('_nextmatchs','filter');
-				$this->template->set_block('_nextmatchs','form');
-				$this->template->set_block('_nextmatchs','icon');
-				$this->template->set_block('_nextmatchs','link');
-				$this->template->set_block('_nextmatchs','search');
-				$this->template->set_block('_nextmatchs','cats');
-				$this->template->set_block('_nextmatchs','search_filter');
-				$this->template->set_block('_nextmatchs','cats_search_filter');
+				$this->template->set_block('_nextmatchs','nm_filter');
+				$this->template->set_block('_nextmatchs','nm_form');
+				$this->template->set_block('_nextmatchs','nm_icon');
+				$this->template->set_block('_nextmatchs','nm_link');
+				$this->template->set_block('_nextmatchs','nm_search');
+				$this->template->set_block('_nextmatchs','nm_cats');
+				$this->template->set_block('_nextmatchs','nm_search_filter');
+				$this->template->set_block('_nextmatchs','nm_cats_search_filter');
 			}
 
 			$this->maxmatches = 15;
-			if(isset($GLOBALS['phpgw_info']['user']['preferences']['common']['maxmatchs']) &&
-				intval($GLOBALS['phpgw_info']['user']['preferences']['common']['maxmatchs']) > 0)
+			if ( isset($GLOBALS['phpgw_info']['user']['preferences']['common']['maxmatchs']) &&
+				(int) $GLOBALS['phpgw_info']['user']['preferences']['common']['maxmatchs'] > 0 )
 			{
 				$this->maxmatches =& $GLOBALS['phpgw_info']['user']['preferences']['common']['maxmatchs'];
 			}
 
-			if(isset($GLOBALS['phpgw_info']['menuaction']))
+			if ( isset($GLOBALS['phpgw_info']['menuaction']) )
 			{
 				$this->action = $GLOBALS['phpgw_info']['menuaction'];
 			}
@@ -107,8 +98,10 @@
 		 * Fetch commonly-used REQUEST vars
 		 *
 		 * This calls get_var() from functions.inc.php
+		 *
+		 * @return array the variables fetched (filter, qfield, start, order, sort)
 		 */
-		function get_var()
+		protected function _get_var()
 		{
 			return array
 			(
@@ -122,29 +115,6 @@
 		}
 
 		/**
-		 * Create a button icon
-		 *
-		 * @deprecated
-		 * @internal use CSS instead
-		 *
-		 * @param string $align the alignment of the icon
-		 * @param string $img_src the url to the image
-		 * @param string $label the alt text for the image
-		 */
-		function set_icon($align, $img, $label)
-		{
-			$var = array
-			(
-				'align'  => $align,
-				'img'    => $GLOBALS['phpgw']->common->image('phpgwapi',$img),
-				'label'  => lang($label),
-				'border' => 0
-			);
-			$this->template->set_var($var);
-			return $this->template->fp('out','link');
-		}
-
-		/**
 		 * Wrapper for phpgw::link() which sets the menuaction to the current menuaction
 		 *
 		 * @see phpgw::link
@@ -170,33 +140,6 @@
 		}
 
 		/**
-		 * Create a single image button form
-		 *
-		 * @param string $img_src the url of the image
-		 * @param string $label the alt text for the image
-		 * @param string $link the url for the link
-		 * @param array $extravars the extra args for the url
-		 */
-		function set_link($align,$img,$link,$alt,$extravars)
-		{
-			$hidden = '';
-
-			$var = array
-			(
-				'align'     => $align,
-				'action'    => strlen($this->action) ? $this->page($extravars) : $GLOBALS['phpgw']->link($link, $extravars),
-				'form_name' => $img,
-				'hidden'    => $hidden,
-				'img'       => $GLOBALS['phpgw']->common->image('phpgwapi',$img),
-				'label'     => $alt,
-				'border'    => 0,
-				'start'     => $extravars['start']
-			);
-			$this->template->set_var($var);
-			return $this->template->fp('out','form');
-		}
-
-		/**
 		 * ?
 		*
 		 * @param $sn ?
@@ -211,7 +154,7 @@
 		 */
 		function show_tpl($sn,$localstart,$total,$extra, $twidth, $bgtheme,$search_obj=0,$filter_obj=1,$showsearch=1,$yours=0,$cat_id=0,$cat_field='fcat_id')
 		{
-			list($filter,$qfield,$start,$order,$sort,$query) = $this->get_var();
+			list($filter,$qfield,$start,$order,$sort,$query) = $this->_get_var();
 
 			$start = $localstart;
 
@@ -241,8 +184,8 @@
 				'right'         => $this->right($sn,$start,$total,$extra)
 			);
 			$this->template->set_var($var);
-			$this->template->parse('cats','cats');
-			$this->template->parse('cats_search_filter_data','cats_search_filter');
+			$this->template->parse('cats', 'nm_cats');
+			$this->template->parse('cats_search_filter_data', 'nm_cats_search_filter');
 			return $this->template->fp('out','nextmatchs');
 		}
 
@@ -334,7 +277,7 @@
 		 */
 		function left($scriptname,$start,$total,$extradata = '')
 		{
-			list($filter,$qfield,,$order,$sort,$query) = $this->get_var();
+			list($filter,$qfield,,$order,$sort,$query) = $this->_get_var();
 
 			$extravars = array
 			(
@@ -345,18 +288,18 @@
 				'query'   => $query
 			);
 
-			$extravars = $this->split_extras($extravars,$extradata);
+			$extravars = $this->split_extras($extravars, $extradata);
 			$ret_str = '';
 
 			if (($start != 0) &&
 				($start > $this->maxmatches))
 			{
 				$extravars['start'] = 0;
-				$ret_str .= $this->set_link('left','first',$scriptname,lang('First page'),$extravars);
+				$ret_str .= $this->_set_link('left','first',$scriptname,lang('First page'),$extravars);
 			}
 			else
 			{
-				$ret_str .= $this->set_icon('left','first-grey',lang('First page'));
+				$ret_str .= $this->_set_icon('left','first-grey',lang('First page'));
 			}
 
 			if ($start != 0)
@@ -370,11 +313,11 @@
 				{
 					$extravars['start'] = ($start - $this->maxmatches);
 				}
-				$ret_str .= $this->set_link('left','left',$scriptname,lang('Previous page'),$extravars);
+				$ret_str .= $this->_set_link('left','left',$scriptname,lang('Previous page'),$extravars);
 			}
 			else
 			{
-				$ret_str .= $this->set_icon('left','left-grey',lang('Previous page'));
+				$ret_str .= $this->_set_icon('left','left-grey',lang('Previous page'));
 			}
 			return $ret_str;
 		} /* left() */
@@ -389,7 +332,7 @@
 		 */
 		function right($scriptname,$start,$total,$extradata = '')
 		{
-			list($filter,$qfield,,$order,$sort,$query) = $this->get_var();
+			list($filter,$qfield,,$order,$sort,$query) = $this->_get_var();
 
 			$extravars = Array(
 				'order'   => $order,
@@ -407,22 +350,22 @@
 				($total > $start + $this->maxmatches))
 			{
 				$extravars['start'] = ($start + $this->maxmatches);
-				$ret_str .= $this->set_link('right','right',$scriptname,lang('Next page'),$extravars);
+				$ret_str .= $this->_set_link('right','right',$scriptname,lang('Next page'),$extravars);
 			}
 			else
 			{
-				$ret_str .= $this->set_icon('right','right-grey',lang('Next page'));
+				$ret_str .= $this->_set_icon('right','right-grey',lang('Next page'));
 			}
 
 			if (($start != $total - $this->maxmatches) &&
 				(($total - $this->maxmatches) > ($start + $this->maxmatches)))
 			{
 				$extravars['start'] = ($total - $this->maxmatches);
-				$ret_str .= $this->set_link('right','last',$scriptname,lang('Last page'),$extravars);
+				$ret_str .= $this->_set_link('right','last',$scriptname,lang('Last page'),$extravars);
 			}
 			else
 			{
-				$ret_str .= $this->set_icon('right','last-grey',lang('Last page'));
+				$ret_str .= $this->_set_icon('right','last-grey',lang('Last page'));
 			}
 			return $ret_str;
 		} /* right() */
@@ -434,7 +377,7 @@
 		 */
 		function search_filter($search_obj=0,$filter_obj=1,$yours=0,$link='',$extra='')
 		{
-			list($filter,$qfield,$start,$order,$sort,$query) = $this->get_var();
+			list($filter,$qfield,$start,$order,$sort,$query) = $this->_get_var();
 
 			$start = $localstart;
 			$var = array(
@@ -450,7 +393,7 @@
 				'filter'       => ($filter_obj?$this->filter($filter_obj,$yours):'')
 			);
 			$this->template->set_var($var);
-			return $this->template->fp('out','search_filter');
+			return $this->template->fp('out','nm_search_filter');
 		}
 
 		/**
@@ -460,7 +403,7 @@
 		 */
 		function cats_search_filter($search_obj=0,$filter_obj=1,$yours=0,$cat_id=0,$cat_field='fcat_id',$link='',$extra='')
 		{
-			list($filter,$qfield,$start,$order,$sort,$query) = $this->get_var();
+			list($filter,$qfield,$start,$order,$sort,$query) = $this->_get_var();
 
 			$start = $localstart;
 			$cats  = createObject('phpgwapi.categories');
@@ -482,7 +425,7 @@
 				'filter'        => ($filter_obj?$this->filter($filter_obj,$yours):'')
 			);
 			$this->template->set_var($var);
-			return $this->template->fp('out','cats_search_filter');
+			return $this->template->fp('out','nm_cats_search_filter');
 		}
 
 		/**
@@ -511,7 +454,7 @@
 			}
 
 			$this->template->set_var($var);
-			return $this->template->fp('out','search');
+			return $this->template->fp('out','nm_search');
 		} /* search() */
 
 		/**
@@ -639,7 +582,7 @@
 				$this->template->set_var('lang_filter',lang('Filter'));
 			}
 
-			return $this->template->fp('out','filter');
+			return $this->template->fp('out','nm_filter');
 		} /* filter() */
 
 		/* replacement for function filter */
@@ -698,7 +641,7 @@
 			$this->template->set_var('select',$str);
 			$this->template->set_var('lang_filter',lang('Filter'));
 
-			return $this->template->fp('out','filter');
+			return $this->template->fp('out','nm_filter');
 		} /* filter() */
 
 		/**
@@ -788,7 +731,7 @@
 				unset($temp_format);
 			}
 
-			list($filter,$qfield,$start,$NULL1,$NULL,$query) = $this->get_var();
+			list($filter,$qfield,$start,$NULL1,$NULL,$query) = $this->_get_var();
 
 			if(($order == $var) && ($sort == 'ASC'))
 			{
@@ -935,11 +878,11 @@
 				($feed_vars['start'] > $this->maxmatches))
 			{
 				$out_vars['start'] = 0;
-				$return_array['first_page'] = $this->set_link_imap('left','first',lang('First page'),$out_vars);
+				$return_array['first_page'] = $this->_set_link_imap('left','first',lang('First page'),$out_vars);
 			}
 			else
 			{
-				$return_array['first_page'] = $this->set_icon_imap('left','first-grey',lang('First page'));
+				$return_array['first_page'] = $this->_set_icon_imap('left','first-grey',lang('First page'));
 			}
 			// previous page
 			if($feed_vars['start'] != 0)
@@ -953,11 +896,11 @@
 				{
 					$out_vars['start'] = ($feed_vars['start'] - $this->maxmatches);
 				}
-				$return_array['prev_page'] = $this->set_link_imap('left','left',lang('Previous page'),$out_vars);
+				$return_array['prev_page'] = $this->_set_link_imap('left','left',lang('Previous page'),$out_vars);
 			}
 			else
 			{
-				$return_array['prev_page'] = $this->set_icon_imap('left','left-grey',lang('Previous page'));
+				$return_array['prev_page'] = $this->_set_icon_imap('left','left-grey',lang('Previous page'));
 			}
 
 			// re-initialize the out_vars
@@ -968,46 +911,127 @@
 				($feed_vars['total'] > $feed_vars['start'] + $this->maxmatches))
 			{
 				$out_vars['start'] = ($feed_vars['start'] + $this->maxmatches);
-				$return_array['next_page'] = $this->set_link_imap('right','right',lang('Next page'),$out_vars);
+				$return_array['next_page'] = $this->_set_link_imap('right','right',lang('Next page'),$out_vars);
 			}
 			else
 			{
-				$return_array['next_page'] = $this->set_icon_imap('right','right-grey',lang('Next page'));
+				$return_array['next_page'] = $this->_set_icon_imap('right','right-grey',lang('Next page'));
 			}
 			// last page
 			if(($feed_vars['start'] != $feed_vars['total'] - $this->maxmatches) &&
 				(($feed_vars['total'] - $this->maxmatches) > ($feed_vars['start'] + $this->maxmatches)))
 			{
 				$out_vars['start'] = ($feed_vars['total'] - $this->maxmatches);
-				$return_array['last_page'] = $this->set_link_imap('right','last',lang('Last page'),$out_vars);
+				$return_array['last_page'] = $this->_set_link_imap('right','last',lang('Last page'),$out_vars);
 			}
 			else
 			{
-				$return_array['last_page'] = $this->set_icon_imap('right','last-grey',lang('Last page'));
+				$return_array['last_page'] = $this->_set_icon_imap('right','last-grey',lang('Last page'));
 			}
 			return $return_array;
 		}
 
 		/**
-		 * ?
+		 * Create a button icon
+		 *
+		 * @param string $align the alignment of the icon
+		 * @param string $img   the url to the image
+		 * @param string $label the alt text for the image
 		*
-		 * @param $img_src ?
-		 * @param $label ?
-		 * @param $link ?
-		 * @param $extravars ?
+		 * @return string html icon snippet
+		 *
+		 * @todo FIXME use CSS instead
 		 */
-		function set_link_imap($align,$img,$alt_text,$out_vars)
+		protected function _set_icon($align, $img, $label)
 		{
-			$img_full = $GLOBALS['phpgw']->common->image('phpgwapi',$img);
-			$image_part = '<img src="'.$img_full.'" border="0" alt="'.$alt_text.'" width="12" height="12">';
-			return '<a href="'.$out_vars['common_uri'].'&start='.$out_vars['start'].'">'.$image_part.'</a>';
+			$var = array
+			(
+				'align'  => $align,
+				'img'    => $GLOBALS['phpgw']->common->image('phpgwapi', $img),
+				'label'  => lang($label),
+			);
+
+			$this->template->set_var($var);
+			return $this->template->fp('out', 'nm_link');
 		}
 
-		function set_icon_imap($align,$img,$alt_text)
+		/**
+		 * I do something with imap and icons
+		 *
+		 * @param ??? $align    ?
+		 * @param ??? $img      ?
+		 * @param ??? $alt_text ?
+		 *
+		 * @return string html
+		 */
+		protected function _set_icon_imap($align, $img, $alt_text)
 		{
-			$img_full = $GLOBALS['phpgw']->common->image('phpgwapi',$img);
-			return '<img src="'.$img_full.'" border="0" width="12" height="12" alt="'.$alt_text.'">'."\r\n";
+			$img_full = $GLOBALS['phpgw']->common->image('phpgwapi', $img);
+
+			return "<img src=\"{$img_full}\" alt=\"{$alt_text}\">\n";
 		}
 
-	} // End of nextmatchs class
-?>
+		/**
+		 * Create a single image button form
+		 *
+		 * @param string $align     the alignment of the link
+		 * @param string $img       the url of the image
+		 * @param string $link      the url for the link
+		 * @param string $alt       the alt text for the image
+		 * @param array  $extravars the extra args for the url
+		 *
+		 * @return string html snippet for a nextmatch button "link"
+		 */
+		protected function _set_link($align, $img, $link, $alt, $extravars)
+		{
+			$hidden = '';
+
+			$action = '';
+			if ( strlen($this->action) )
+			{
+				$action = $this->page($extravars);
+			}
+			else
+			{
+				$action = $GLOBALS['phpgw']->link($link, $extravars);
+			}
+
+			$var = array
+			(
+				'align'     => $align,
+				'action'    => $action,
+				'form_name' => $img,
+				'hidden'    => $hidden,
+				'img'       => $GLOBALS['phpgw']->common->image('phpgwapi', $img),
+				'label'     => $alt,
+				'start'     => $extravars['start']
+			);
+
+			$this->template->set_var($var);
+			return $this->template->fp('out', 'nm_form');
+		}
+
+		/**
+		 * I do something with imap and links
+		 *
+		 * @param ??? $align    ?
+		 * @param ??? $img      ?
+		 * @param ??? $alt_text ?
+		 * @param ??? $out_vars ?
+		 *
+		 * @return string html
+		 */
+		protected function _set_link_imap($align, $img, $alt_text, $out_vars)
+		{
+			$img_full = $GLOBALS['phpgw']->common->image('phpgwapi', $img);
+
+			$image_part = '';
+
+			return <<<HTML
+				<a href="{$out_vars['common_uri']}&amp;start={$out_vars['start']}">
+					<img src="{$img_full}" alt="{$alt_text}">
+				</a>
+
+HTML;
+		}
+	}

Modified: people/sigurdne/modules/phpgwapi/trunk/inc/class.nextmatchs_xslt.inc.php
===================================================================
--- people/sigurdne/modules/phpgwapi/trunk/inc/class.nextmatchs_xslt.inc.php	2009-11-20 10:27:41 UTC (rev 20844)
+++ people/sigurdne/modules/phpgwapi/trunk/inc/class.nextmatchs_xslt.inc.php	2009-11-20 10:28:10 UTC (rev 20845)
@@ -7,21 +7,6 @@
 	* @package phpgwapi
 	* @subpackage gui
 	* @version $Id$
-	*/
-
-	/*
-	   This program is free software: you can redistribute it and/or modify
-	   it under the terms of the GNU General Public License as published by
-	   the Free Software Foundation, either version 3 of the License, or
-	   (at your option) any later version.
-
-	   This program is distributed in the hope that it will be useful,
-	   but WITHOUT ANY WARRANTY; without even the implied warranty of
-	   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-	   GNU General Public License for more details.
-
-	   You should have received a copy of the GNU General Public License
-	   along with this program.  If not, see <http://www.gnu.org/licenses/>.
 	 */
 
 	/**
@@ -30,7 +15,7 @@
 	* @package phpgwapi
 	* @subpackage gui
 	*/
-	class nextmatchs_xslt
+	class phpgwapi_nextmatchs_xslt
 	{
 		var $maxmatches;
 		var $action;
@@ -121,12 +106,14 @@
 		{
 			$GLOBALS['phpgw']->xslttpl->add_file('nextmatchs', PHPGW_TEMPLATE_DIR);
 
-			$start = isset($values['start']) ? (int) $values['start'] : 0;
+			$start = isset($values['start']) && $values['start'] ? (int) $values['start'] : 0;
+
 			$nm_data = array
 			(
 				'img_width'			=> $GLOBALS['phpgw_info']['user']['preferences']['common']['template_set'] == 'funkwerk' ? '' : '12',
 				'img_height'		=> $GLOBALS['phpgw_info']['user']['preferences']['common']['template_set'] == 'funkwerk' ? '' : '12',
-				'allow_all_rows'	=> isset($values['allow_all_rows']) ? false : 'yes',
+				'allow_all_rows'	=> isset($values['allow_all_rows']) ? true : false,
+				'allrows'			=> isset($values['allrows']) ? true : false,
 				'start_record'		=> $start,
 				'record_limit'		=> $this->maxmatches,
 				'num_records'		=> (int) $values['num_records'],

Modified: people/sigurdne/modules/phpgwapi/trunk/inc/class.object_factory.inc.php
===================================================================
--- people/sigurdne/modules/phpgwapi/trunk/inc/class.object_factory.inc.php	2009-11-20 10:27:41 UTC (rev 20844)
+++ people/sigurdne/modules/phpgwapi/trunk/inc/class.object_factory.inc.php	2009-11-20 10:28:10 UTC (rev 20845)
@@ -8,7 +8,7 @@
 	 * @author milosch
 	 * @author (thanks to jengo and ralf)
 	 * @copyright Copyright (C) 2003-2008 Free Software Foundation, Inc. http://www.fsf.org/
-	 * @license http://www.gnu.org/licenses/lgpl.html GNU Lesser General Public License v3 or later
+	 * @license http://www.gnu.org/licenses/lgpl.html GNU Lesser General Public License v2 or later
 	 * @package phpgroupware
 	 * @subpackage phpgwapi
 	 * @version $Id$
@@ -17,7 +17,7 @@
 	/*
 	   This program is free software: you can redistribute it and/or modify
 	   it under the terms of the GNU Lesser General Public License as published by
-	   the Free Software Foundation, either version 3 of the License, or
+	   the Free Software Foundation, either version 2 of the License, or
 	   (at your option) any later version.
 
 	   This program is distributed in the hope that it will be useful,

Modified: people/sigurdne/modules/phpgwapi/trunk/inc/class.ofphpgwapi.inc.php
===================================================================
--- people/sigurdne/modules/phpgwapi/trunk/inc/class.ofphpgwapi.inc.php	2009-11-20 10:27:41 UTC (rev 20844)
+++ people/sigurdne/modules/phpgwapi/trunk/inc/class.ofphpgwapi.inc.php	2009-11-20 10:28:10 UTC (rev 20845)
@@ -8,7 +8,7 @@
 	 * @author milosch
 	 * @author (thanks to jengo and ralf)
 	 * @copyright Copyright (C) 2003-2008 Free Software Foundation, Inc. http://www.fsf.org/
-	 * @license http://www.gnu.org/licenses/lgpl.html GNU Lesser General Public License v3 or later
+	 * @license http://www.gnu.org/licenses/lgpl.html GNU Lesser General Public License v2 or later
 	 * @package phpgroupware
 	 * @subpackage phpgwapi
 	 * @version $Id$
@@ -17,7 +17,7 @@
 	/*
 	   This program is free software: you can redistribute it and/or modify
 	   it under the terms of the GNU Lesser General Public License as published by
-	   the Free Software Foundation, either version 3 of the License, or
+	   the Free Software Foundation, either version 2 of the License, or
 	   (at your option) any later version.
 
 	   This program is distributed in the hope that it will be useful,
@@ -144,7 +144,7 @@
 					//fall through
 
 				case 'ldap':
-					include_once PHPGW_API_INC . "/aaccounts/class.accounts_ldap.inc.php";
+					include_once PHPGW_API_INC . "/accounts/class.accounts_ldap.inc.php";
 					break;
 
 				default:

Added: people/sigurdne/modules/phpgwapi/trunk/inc/class.pclzip.inc.php
===================================================================
--- people/sigurdne/modules/phpgwapi/trunk/inc/class.pclzip.inc.php	                        (rev 0)
+++ people/sigurdne/modules/phpgwapi/trunk/inc/class.pclzip.inc.php	2009-11-20 10:28:10 UTC (rev 20845)
@@ -0,0 +1,55 @@
+<?php
+	/**
+	 * phpGroupWare
+	 *
+	 * @author Sigurd Nes <[email protected]>
+	 * @copyright Copyright (C) 2007,2008 Free Software Foundation, Inc. http://www.fsf.org/
+	 * @license http://www.fsf.org/licenses/gpl.html GNU General Public License
+	 * @package phpgroupware
+	 * @subpackage phpgwapi
+	 * @category utilities
+ 	 * @version $Id$
+	 */
+
+	/*
+	   This program is free software: you can redistribute it and/or modify
+	   it under the terms of the GNU General Public License as published by
+	   the Free Software Foundation, either version 2 of the License, or
+	   (at your option) any later version.
+
+	   This program is distributed in the hope that it will be useful,
+	   but WITHOUT ANY WARRANTY; without even the implied warranty of
+	   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+	   GNU General Public License for more details.
+
+	   You should have received a copy of the GNU General Public License
+	   along with this program.  If not, see <http://www.gnu.org/licenses/>.
+	 */
+
+	/**
+	* Document me!
+	*
+	* @package phpgwapi
+	* @subpackage utilities
+	*/
+	if ( !isset($GLOBALS['phpgw_info']['server']['temp_dir'])  
+			|| !is_dir($GLOBALS['phpgw_info']['server']['temp_dir']) )
+	{
+		if ( substr(PHP_OS, 3) == 'WIN' )
+		{
+			$GLOBALS['phpgw_info']['server']['temp_dir'] = 'c:/temp';
+		}
+		else
+		{
+			$GLOBALS['phpgw_info']['server']['temp_dir'] = '/tmp/';
+		}
+	}
+
+
+	/**
+	* Include the pclzip class
+	* @see pclzip
+	*/
+	require_once PHPGW_API_INC . '/pclzip/pclzip.lib.php';
+
+


Property changes on: people/sigurdne/modules/phpgwapi/trunk/inc/class.pclzip.inc.php
___________________________________________________________________
Added: svn:keywords
   + Id Revision
Added: svn:eol-style
   + native

Modified: people/sigurdne/modules/phpgwapi/trunk/inc/class.pdf.inc.php
===================================================================
--- people/sigurdne/modules/phpgwapi/trunk/inc/class.pdf.inc.php	2009-11-20 10:27:41 UTC (rev 20844)
+++ people/sigurdne/modules/phpgwapi/trunk/inc/class.pdf.inc.php	2009-11-20 10:28:10 UTC (rev 20845)
@@ -5,6 +5,7 @@
 	* @author Sigurd Nes <[email protected]>
 	* @copyright Copyright (C) 2003-2005 Free Software Foundation, Inc. http://www.fsf.org/
 	* @license http://www.gnu.org/licenses/gpl.html GNU General Public License
+	* @internal Development of this application was funded by http://www.bergen.kommune.no/bbb_/ekstern/
 	* @package phpgwapi
 	* @subpackage utilities
  	* @version $Id$
@@ -31,21 +32,6 @@
 	* </code>
 	*/
 
-	/*
-	   This program is free software: you can redistribute it and/or modify
-	   it under the terms of the GNU General Public License as published by
-	   the Free Software Foundation, either version 3 of the License, or
-	   (at your option) any later version.
-
-	   This program is distributed in the hope that it will be useful,
-	   but WITHOUT ANY WARRANTY; without even the implied warranty of
-	   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-	   GNU General Public License for more details.
-
-	   You should have received a copy of the GNU General Public License
-	   along with this program.  If not, see <http://www.gnu.org/licenses/>.
-	 */
-
 	/**
 	* Document me!
 	*
@@ -54,12 +40,6 @@
 	*/
 	class pdf__
 	{
-		protected $dir = '';
-
-		public function __construct()
-		{
-			$this->_dir = PHPGW_API_INC  . '/pdf/pdf_files';
-		}
  
 		/**
 		* Output a pdf
@@ -80,17 +60,18 @@
 			else
 			{
  				//save the file
- 				if ( !is_dir($this->_dir) )
+				$dir = PHPGW_API_INC  . '/pdf/pdf_files';
+ 				if ( !is_dir($dir) )
  				{
  					die(lang('Directory for temporary pdf-files is missing - pleace notify the Administrator'));
  				}
 
- 				if ( !is_writeable($this->_dir) )
+ 				if ( !is_writeable($dir) )
  				{
   					die(lang('Directory for temporary pdf-files is not writeable by the webserver - pleace notify the Administrator'));
  				}
 
- 				$fname = tempnam($this->_dir, 'PDF_') . '.pdf';
+ 				$fname = tempnam($dir, 'PDF_') . '.pdf';
 				file_put_contents($fname, $document, LOCK_EX);
 
   				//TODO consider using phpgw::redirect_link() ?
@@ -98,7 +79,7 @@
  				echo <<<HTML
 		<html>
 			<head>
-				<script type="application/javascript">
+				<script language="javascript">
 				<!--
 					function go_now()
 					{
@@ -108,23 +89,23 @@
 				</script>
 			</head>
 			<body onload="go_now()";>
-				<a href="'.$fname.'">click here</a> if you are not re-directed.
+				<a href="$fname">click here</a> if you are not re-directed.
 			</body>
 		</html>
 
 HTML;
 
-				$this->_clear_cache();
+				$this->_clear_cache($dir);
 			}
 		}
 
 		/**
 		 * Remove files that are older than a day
 		 */
-		protected function _clear_cache()
+		protected function _clear_cache($dir)
 		{
 			$min_ctime = 60 * 60;
-			$dir = new DirectoryIterator($this->_dir);
+			$dir = new DirectoryIterator($dir);
 			foreach ( $dir as $file )
 			{
 				if ( preg_match('/^PDF_/', $file)
@@ -147,3 +128,4 @@
 	* @see @pdf
 	*/
 	require_once PHPGW_API_INC . '/pdf/class.ezpdf.php';
+

Modified: people/sigurdne/modules/phpgwapi/trunk/inc/class.phpgw.inc.php
===================================================================
--- people/sigurdne/modules/phpgwapi/trunk/inc/class.phpgw.inc.php	2009-11-20 10:27:41 UTC (rev 20844)
+++ people/sigurdne/modules/phpgwapi/trunk/inc/class.phpgw.inc.php	2009-11-20 10:28:10 UTC (rev 20845)
@@ -15,7 +15,7 @@
 	/*
 	   This program is free software: you can redistribute it and/or modify
 	   it under the terms of the GNU Lesser General Public License as published by
-	   the Free Software Foundation, either version 3 of the License, or
+	   the Free Software Foundation, either version 2 of the License, or
 	   (at your option) any later version.
 
 	   This program is distributed in the hope that it will be useful,
@@ -49,9 +49,7 @@
 		 * @access public
 		 */	
 		public $debug = 0;		// This will turn on debugging information.
-		//XXX Remove the public vars, so autoload occurs ...
-		//public $contacts;
-		public $nextmatchs;
+		public $contacts;
 		public $preferences;
 
 		// FIXME find all instances and change to sessions then we can drop this
@@ -147,6 +145,12 @@
 		 */
 		public static function clean_html($html, $base_url = '')
 		{
+			if ( !isset($GLOBALS['phpgw_info']['server']['html_filtering']) 
+				|| !$GLOBALS['phpgw_info']['server']['html_filtering'])
+			{
+				return $html;
+			}
+			
 			if ( !$base_url )
 			{
 				$base_url = $GLOBALS['phpgw_info']['server']['webserver_url'];

Modified: people/sigurdne/modules/phpgwapi/trunk/inc/class.ping.inc.php
===================================================================
--- people/sigurdne/modules/phpgwapi/trunk/inc/class.ping.inc.php	2009-11-20 10:27:41 UTC (rev 20844)
+++ people/sigurdne/modules/phpgwapi/trunk/inc/class.ping.inc.php	2009-11-20 10:28:10 UTC (rev 20845)
@@ -7,21 +7,6 @@
 	* @package phpgwapi
 	* @subpackage network
 	* @version $Id$
-	*/
-
-	/*
-	   This program is free software: you can redistribute it and/or modify
-	   it under the terms of the GNU Lesser General Public License as published by
-	   the Free Software Foundation, either version 3 of the License, or
-	   (at your option) any later version.
-
-	   This program is distributed in the hope that it will be useful,
-	   but WITHOUT ANY WARRANTY; without even the implied warranty of
-	   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-	   GNU General Public License for more details.
-
-	   You should have received a copy of the GNU Lesser General Public License
-	   along with this program.  If not, see <http://www.gnu.org/licenses/>.
 	 */
 
 	/**

Modified: people/sigurdne/modules/phpgwapi/trunk/inc/class.portalbox.inc.php
===================================================================
--- people/sigurdne/modules/phpgwapi/trunk/inc/class.portalbox.inc.php	2009-11-20 10:27:41 UTC (rev 20844)
+++ people/sigurdne/modules/phpgwapi/trunk/inc/class.portalbox.inc.php	2009-11-20 10:28:10 UTC (rev 20845)
@@ -7,21 +7,6 @@
 	* @package phpgwapi
 	* @subpackage gui
 	* @version $Id$
-	*/
-
-	/*
-	   This program is free software: you can redistribute it and/or modify
-	   it under the terms of the GNU Lesser General Public License as published by
-	   the Free Software Foundation, either version 3 of the License, or
-	   (at your option) any later version.
-
-	   This program is distributed in the hope that it will be useful,
-	   but WITHOUT ANY WARRANTY; without even the implied warranty of
-	   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-	   GNU General Public License for more details.
-
-	   You should have received a copy of the GNU Lesser General Public License
-	   along with this program.  If not, see <http://www.gnu.org/licenses/>.
 	 */
 
 	/**

Modified: people/sigurdne/modules/phpgwapi/trunk/inc/class.preferences.inc.php
===================================================================
--- people/sigurdne/modules/phpgwapi/trunk/inc/class.preferences.inc.php	2009-11-20 10:27:41 UTC (rev 20844)
+++ people/sigurdne/modules/phpgwapi/trunk/inc/class.preferences.inc.php	2009-11-20 10:28:10 UTC (rev 20845)
@@ -10,21 +10,6 @@
 	 * @version $Id$
 	 */
 
-	/*
-	   This program is free software: you can redistribute it and/or modify
-	   it under the terms of the GNU Lesser General Public License as published by
-	   the Free Software Foundation, either version 3 of the License, or
-	   (at your option) any later version.
-
-	   This program is distributed in the hope that it will be useful,
-	   but WITHOUT ANY WARRANTY; without even the implied warranty of
-	   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-	   GNU General Public License for more details.
-
-	   You should have received a copy of the GNU Lesser General Public License
-	   along with this program.  If not, see <http://www.gnu.org/licenses/>.
-	 */
-
 	/**
 	 * Preferences class for setting application preferences
 	 * 
@@ -75,6 +60,8 @@
 
 		var $values,$vars;	// standard notify substitues, will be set by standard_substitues()
 
+		protected $global_lock = false;
+
 		/**
 		 * Standard constructor for setting $this->account_id
 		 *
@@ -92,9 +79,13 @@
 		*
 		* @param int $account_id the account id - 0 = current user's id
 		*/
-		public function set_account_id($account_id = 0)
+		public function set_account_id($account_id = 0, $read_repo = false)
 		{
 			$this->account_id = get_account_id($account_id);
+			if ( $read_repo )
+			{
+				$this->read_repository();
+			}
 		}
 
 		/*
@@ -110,7 +101,7 @@
 		 * @param $use_standard_values should the standard values are used
 		 * @return the parsed notify-msg
 		 */
-		private function parse_notify($msg, $values = '', $use_standard_values = true)
+		function parse_notify($msg, $values = '', $use_standard_values = true)
 		{
 			$vals = $values ? $values : array();
 
@@ -135,8 +126,7 @@
 		 * @param $un_lang if true translate back
 		 * @return the result
 		 */
-		//XXX Caeies 03/09 put this method public since it's used by preferences/preferences.php
-		public function lang_notify($msg,$vals=array(),$un_lang=False)
+		function lang_notify($msg,$vals=array(),$un_lang=False)
 		{
 			foreach($vals as $key => $val)
 			{
@@ -157,7 +147,7 @@
 		 * define some standard substitues-values and use them on the prefs, if needed
 		 *
 		 */
-		private function standard_substitutes()
+		function standard_substitutes()
 		{
 			if ( !isset($GLOBALS['phpgw_info']['server']['mail_suffix'])
 					|| !$GLOBALS['phpgw_info']['server']['mail_suffix'] )
@@ -172,13 +162,14 @@
 				$GLOBALS['phpgw']->translation->userlang = $GLOBALS['phpgw_info']['user']['preferences']['common']['lang'];
 			}
 			// we cant use phpgw_info/user/fullname, as it's not set when we run
-			//XXX Caeies nov08 Fixing the preference system, get the account object, and use it for our benefit
-			$oAccount = $GLOBALS['phpgw']->accounts->get($this->account_id);
+			$user = $GLOBALS['phpgw']->accounts->get($this->account_id);
 
-			$this->values = array(	// standard notify replacements
-					'fullname'  => (string)$oAccount,
-					'firstname' => $oAccount->firstname,
-					'lastname'  => $oAccount->lastname,
+			// standard notify replacements
+			$this->values = array
+			(
+				'fullname'  => $user->__toString(),
+				'firstname' => $user->firstname,
+				'lastname'  => $user->lastname,
 					'domain'    => $GLOBALS['phpgw_info']['server']['mail_suffix'],
 					'email'     => $this->email_address($this->account_id),
 					'date'      => $GLOBALS['phpgw']->common->show_date('',$GLOBALS['phpgw_info']['user']['preferences']['common']['dateformat'])
@@ -187,7 +178,9 @@
 			//
 			$this->values['email'] = $this->parse_notify($this->values['email']);
 
-			$this->vars = array(	// langs have to be in common !!!
+			// langs have to be in common !!!
+			$this->vars = array
+			(
 					'fullname'  => lang('name of the user, eg. %1',$this->values['fullname']),
 					'firstname' => lang('first name of the user, eg. %1',$this->values['firstname']),
 					'lastname'  => lang('last name of the user, eg. %1',$this->values['lastname']),
@@ -252,6 +245,7 @@
 		 */
 		protected function read_repository()
 		{
+			//FIXME - ever used?
 			if($GLOBALS['phpgw']->acl->check('session_only_preferences',1,'preferences') && strlen($GLOBALS['phpgw']->session->appsession('session_prefs','initiated')))
 			{
 				$this->user		= $GLOBALS['phpgw']->session->appsession('session_prefs','user');
@@ -340,7 +334,8 @@
 			{
 				reset($this->data);
 			}
-			if ($this->debug && substr($GLOBALS['phpgw_info']['flags']['currentapp'],0,3) != 'log') {
+			if ($this->debug && substr($GLOBALS['phpgw_info']['flags']['currentapp'],0,3) != 'log') 
+			{
 				echo "user<pre>";    print_r($this->user); echo "</pre>\n";
 				echo "forced<pre>";  print_r($this->forced); echo "</pre>\n";
 				echo "default<pre>"; print_r($this->default); echo "</pre>\n";
@@ -596,7 +591,15 @@
 
 			if (! $GLOBALS['phpgw']->acl->check('session_only_preferences',1,'preferences'))
 			{
+				if ( $this->db->Transaction )
+				{
+					$this->global_lock = true;
+				}
+				else
+				{
 				$this->db->transaction_begin();
+				}
+
 				$this->db->query("delete from phpgw_preferences where preference_owner='$account_id'",
 						__LINE__,__FILE__);
 
@@ -611,8 +614,12 @@
 							" (preference_owner,preference_app,preference_value)".
 							" VALUES ($account_id,'$app','$value')",__LINE__,__FILE__);
 				}
+
+				if ( !$this->global_lock )
+				{
 				$this->db->transaction_commit();
 			}
+			}
 			else
 			{
 				switch($type)
@@ -628,10 +635,12 @@
 						break;
 				}
 
-				$GLOBALS['phpgw_info']['user']['preferences'] = $this->data;
+			//	$GLOBALS['phpgw_info']['user']['preferences'] = $this->data;
 				$GLOBALS['phpgw']->session->save_repositories();
 			}
 
+			$GLOBALS['phpgw_info']['user']['preferences'] = $this->data;
+
 			if (($type == 'user' || !$type) && isset($GLOBALS['phpgw_info']['server']['cache_phpgw_info']) && $GLOBALS['phpgw_info']['server']['cache_phpgw_info']  && $this->account_id == $GLOBALS['phpgw_info']['user']['account_id'])
 			{
 				$GLOBALS['phpgw']->session->delete_cache($this->account_id);
@@ -688,11 +697,11 @@
 		}
 
 		/* legacy support */
-		private function change($app_name,$var,$value = "")
+		public function change($app_name,$var,$value = "")
 		{
 			return $this->add($app_name,$var,$value);
 		}
-		private function commit($update_session_info = True)
+		public function commit($update_session_info = True)
 		{
 			//return $this->save_repository($update_session_info);
 		}
@@ -708,7 +717,8 @@
 		function verify_basic_settings()
 		{
 			$preferences_update = False;
-			if (!is_array($GLOBALS['phpgw_info']['user']['preferences']))
+			if ( !is_array($GLOBALS['phpgw_info']['user']['preferences']) 
+				|| isset($GLOBALS['phpgw_info']['server']['cache_phpgw_info']) )
 			{
 				$GLOBALS['phpgw_info']['user']['preferences'] = $this->read_repository();
 				$preferences_update = True;
@@ -778,7 +788,7 @@
 		 * @author  Angles
 		 * @access Private
 		 */
-		private function sub_get_mailsvr_port($prefs, $acctnum=0)
+		function sub_get_mailsvr_port($prefs, $acctnum=0)
 		{
 			$port_number = 0;
 			// first we try the port number supplied in preferences
@@ -835,7 +845,7 @@
 		 * @param $accountid - as determined in and/or passed to "create_email_preferences"
 		 * @access Private
 		 */
-		private function sub_default_userid($account_id='')
+		function sub_default_userid($account_id='')
 		{
 			$prefs_email_userid = $GLOBALS['phpgw']->accounts->id2lid($account_id, true);
 
@@ -879,7 +889,7 @@
 			return $prefs_email_address;
 		}
 
-		private function sub_default_address($account_id='')
+		function sub_default_address($account_id='')
 		{
 			return $this->email_address($account_id);
 		}
@@ -984,7 +994,7 @@
 			// the user does not directly manipulate this pref for the default email account
 			if ((string)$acctnum == '0')
 			{
-				$prefs['email']['fullname'] = $GLOBALS['phpgw_info']['user']['fullname'];
+				$prefs['email']['fullname'] = (string) $GLOBALS['phpgw']->accounts->get($account_id);
 			}
 
 
@@ -1332,4 +1342,3 @@
 	return $prefs;
 	*/
 	} /* end of preferences class */
-?>

Modified: people/sigurdne/modules/phpgwapi/trunk/inc/class.resultbox.inc.php
===================================================================
--- people/sigurdne/modules/phpgwapi/trunk/inc/class.resultbox.inc.php	2009-11-20 10:27:41 UTC (rev 20844)
+++ people/sigurdne/modules/phpgwapi/trunk/inc/class.resultbox.inc.php	2009-11-20 10:28:10 UTC (rev 20845)
@@ -8,21 +8,6 @@
 	* @package phpgwapi
 	* @subpackage gui
 	* @version $Id$
-	*/
-
-	/*
-	   This program is free software: you can redistribute it and/or modify
-	   it under the terms of the GNU Lesser General Public License as published by
-	   the Free Software Foundation, either version 3 of the License, or
-	   (at your option) any later version.
-
-	   This program is distributed in the hope that it will be useful,
-	   but WITHOUT ANY WARRANTY; without even the implied warranty of
-	   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-	   GNU General Public License for more details.
-
-	   You should have received a copy of the GNU Lesser General Public License
-	   along with this program.  If not, see <http://www.gnu.org/licenses/>.
 	 */
 
 	CreateObject('phpgwapi.portalbox');

Modified: people/sigurdne/modules/phpgwapi/trunk/inc/class.richtext.inc.php
===================================================================
--- people/sigurdne/modules/phpgwapi/trunk/inc/class.richtext.inc.php	2009-11-20 10:27:41 UTC (rev 20844)
+++ people/sigurdne/modules/phpgwapi/trunk/inc/class.richtext.inc.php	2009-11-20 10:28:10 UTC (rev 20845)
@@ -11,21 +11,6 @@
 	* @package phpgroupware
 	* @subpackage phpgwapi
 	* @version $Id$
-	*/
-
-	/*
-	   This program is free software: you can redistribute it and/or modify
-	   it under the terms of the GNU General Public License as published by
-	   the Free Software Foundation, either version 3 of the License, or
-	   (at your option) any later version.
-
-	   This program is distributed in the hope that it will be useful,
-	   but WITHOUT ANY WARRANTY; without even the implied warranty of
-	   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-	   GNU General Public License for more details.
-
-	   You should have received a copy of the GNU General Public License
-	   along with this program.  If not, see <http://www.gnu.org/licenses/>.
 	 */
 
 	/**
@@ -80,10 +65,10 @@
 				Event = YAHOO.util.Event;
 				
 				var editorConfig = {
-					width: '100em',
-					height: '10em',
-					dompath: true,
+					height: '300px',
+					width: '600px',
 					animate: true,
+					dompath: true,
 					handleSubmit: true
 				};
 				

Modified: people/sigurdne/modules/phpgwapi/trunk/inc/class.rssparser.inc.php
===================================================================
--- people/sigurdne/modules/phpgwapi/trunk/inc/class.rssparser.inc.php	2009-11-20 10:27:41 UTC (rev 20844)
+++ people/sigurdne/modules/phpgwapi/trunk/inc/class.rssparser.inc.php	2009-11-20 10:28:10 UTC (rev 20845)
@@ -14,21 +14,6 @@
 	* @internal This requires PHP's XML routines. You must configure PHP with --with-xml.
 	*/
 
-	/*
-	   This program is free software: you can redistribute it and/or modify
-	   it under the terms of the GNU Lesser General Public License as published by
-	   the Free Software Foundation, either version 3 of the License, or
-	   (at your option) any later version.
-
-	   This program is distributed in the hope that it will be useful,
-	   but WITHOUT ANY WARRANTY; without even the implied warranty of
-	   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-	   GNU General Public License for more details.
-
-	   You should have received a copy of the GNU Lesser General Public License
-	   along with this program.  If not, see <http://www.gnu.org/licenses/>.
-	 */
-
 	/**
 	* Add element start to $GLOBALS['_rss']
 	*

Modified: people/sigurdne/modules/phpgwapi/trunk/inc/class.sbox.inc.php
===================================================================
--- people/sigurdne/modules/phpgwapi/trunk/inc/class.sbox.inc.php	2009-11-20 10:27:41 UTC (rev 20844)
+++ people/sigurdne/modules/phpgwapi/trunk/inc/class.sbox.inc.php	2009-11-20 10:28:10 UTC (rev 20845)
@@ -8,21 +8,6 @@
 	* @package phpgwapi
 	* @subpackage gui
 	* @version $Id$
-	*/
-
-	/*
-	   This program is free software: you can redistribute it and/or modify
-	   it under the terms of the GNU Lesser General Public License as published by
-	   the Free Software Foundation, either version 3 of the License, or
-	   (at your option) any later version.
-
-	   This program is distributed in the hope that it will be useful,
-	   but WITHOUT ANY WARRANTY; without even the implied warranty of
-	   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-	   GNU General Public License for more details.
-
-	   You should have received a copy of the GNU Lesser General Public License
-	   along with this program.  If not, see <http://www.gnu.org/licenses/>.
 	 */
 
 	phpgw::import_class('phpgwapi.datetime');
@@ -186,7 +171,7 @@
 			{
 				$slctd = $id == $selected ? ' selected' : '';
 				$html .= <<<HTML
-				<option value="{$id}"{$selected}>$dow</option>
+				<option value="{$id}"{$slctd}>$dow</option>
 
 HTML;
 			}
@@ -337,7 +322,7 @@
 
 			for ( $i = 0; $i <= 100; $i += $interval)
 			{
-				$slctd = $i == $selected ? ' selected=""' : '';
+				$slctd = $i == $selected ? ' selected' : '';
 				$html .= <<<HTML
 				<option value="{$i}"{$slctd}>$i</option>
 
@@ -367,7 +352,7 @@
 HTML;
 			foreach ( $priorities as $id => $priority )
 			{
-				$slctd = $id == $selected ? ' selected=""' : '';
+				$slctd = $i == $selected ? ' selected' : '';
 				$html .= <<<HTML
 				<option value="{$id}"{$slctd}>$priority</option>
 
@@ -408,9 +393,9 @@
 
 			foreach ( $options as $id => $option )
 			{
-				$slctd = $id == $selected ? ' selected=""' : '';
+				$slctd = $id == $selected ? ' selected' : '';
 				$html .= <<<HTML
-				<option value="{$id}">$option</option>
+				<option value="{$id}"{$slctd}>$option</option>
 HTML;
 			}
 			$html .= <<<HTML
@@ -435,7 +420,7 @@
 			}
 			$selected = trim($selected);
 
-			$slctd = !$selected ? '' : ' selected=""';
+			$slctd = !$selected ? '' : ' selected';
 			$lang_select1 = lang('Select One');
 			$select = <<<HTML
 				<select name="{$name}">
@@ -444,9 +429,9 @@
 HTML;
 			foreach ( phpgwapi_country::get_translated_list() as $code => $country )
 			{
-				$slctd = $code == $selected ? '' : ' selected=""';
+				$slctd = $code == $selected ? '' : ' selected';
 				$select .= <<<HTML
-					<option value="{$code}"{$selected}>{$country}</option>
+					<option value="{$code}"{$slctd}>{$country}</option>
 
 HTML;
 			}
@@ -499,18 +484,27 @@
 
 HTML;
 
+			$check = array();
+
 			if (!is_array($selected))
 			{
-				$key = array($selected);
+				$check[$selected] = true;	
 			}
+			else
+			{
+				foreach ($selected as $sel)
+				{
+					$check[$sel] = true;
+				}
+			}
 
 			foreach ( $options as $value => $option )
 			{
-				$selected = isset( $selected[$value] ) ? ' selected=""' : '';
+				$check2 = isset( $check[$value] ) ? ' selected' : '';
 				$option = $no_lang ? $option : lang($option);
 
 				$html .= <<<HTML
-					<option value="{$value}"{$selected}>{$option}<option>
+					<option value="{$value}"{$check2}>{$option}</option>
 
 HTML;
 			}

Modified: people/sigurdne/modules/phpgwapi/trunk/inc/class.sbox2.inc.php
===================================================================
--- people/sigurdne/modules/phpgwapi/trunk/inc/class.sbox2.inc.php	2009-11-20 10:27:41 UTC (rev 20844)
+++ people/sigurdne/modules/phpgwapi/trunk/inc/class.sbox2.inc.php	2009-11-20 10:28:10 UTC (rev 20845)
@@ -7,28 +7,13 @@
 	* @package phpgwapi
 	* @subpackage gui
 	* @version $Id$
-	*/
-
-	/*
-	   This program is free software: you can redistribute it and/or modify
-	   it under the terms of the GNU Lesser General Public License as published by
-	   the Free Software Foundation, either version 3 of the License, or
-	   (at your option) any later version.
-
-	   This program is distributed in the hope that it will be useful,
-	   but WITHOUT ANY WARRANTY; without even the implied warranty of
-	   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-	   GNU General Public License for more details.
-
-	   You should have received a copy of the GNU Lesser General Public License
-	   along with this program.  If not, see <http://www.gnu.org/licenses/>.
 	 */
 
 	/**
 	* Include parent class
 	* @see sbox
 	*/
-	include(PHPGW_API_INC . '/class.sbox.inc.php');
+	phpgw::import_class('phpgwapi.sbox');
 
 	/**
 	* Class for creating select boxes for addresse, projects, array items, ...
@@ -38,4 +23,9 @@
 	*/
 	class phpgwapi_sbox2 extends phpgwapi_sbox
 	{
+		public function __construct()
+		{
+			trigger_error('phpgwapi_sbox2 is no longer used, please port your code to phpgw_sbox', E_USER_NOTICE);
+			parent::__construct();
+		}
 	}

Modified: people/sigurdne/modules/phpgwapi/trunk/inc/class.schema_proc.inc.php
===================================================================
--- people/sigurdne/modules/phpgwapi/trunk/inc/class.schema_proc.inc.php	2009-11-20 10:27:41 UTC (rev 20844)
+++ people/sigurdne/modules/phpgwapi/trunk/inc/class.schema_proc.inc.php	2009-11-20 10:28:10 UTC (rev 20845)
@@ -9,21 +9,6 @@
 	* @package phpgwapi
 	* @subpackage database
 	* @version $Id$
-	*/
-
-	/*
-	   This program is free software: you can redistribute it and/or modify
-	   it under the terms of the GNU General Public License as published by
-	   the Free Software Foundation, either version 3 of the License, or
-	   (at your option) any later version.
-
-	   This program is distributed in the hope that it will be useful,
-	   but WITHOUT ANY WARRANTY; without even the implied warranty of
-	   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-	   GNU General Public License for more details.
-
-	   You should have received a copy of the GNU General Public License
-	   along with this program.  If not, see <http://www.gnu.org/licenses/>.
 	 */
 
 	/**
@@ -86,6 +71,7 @@
 			{
 				$sSequenceSQL = '';
 				$sTriggerSQL = '';
+				$this->m_oTranslator->indexes_sql = array();
 				if($this->_GetTableSQL($sTableName, $aTableDef, $sTableSQL, $sSequenceSQL, $sTriggerSQL))
 				{
 					$sTableSQL = "CREATE TABLE $sTableName (\n$sTableSQL\n)"
@@ -101,6 +87,17 @@
 					}
 					
 					$sAllTableSQL .= $sTableSQL . "\n\n";
+
+					// postgres and mssql
+					if(isset($this->m_oTranslator->indexes_sql) && is_array($this->m_oTranslator->indexes_sql) && count($this->m_oTranslator->indexes_sql)>0)
+					{
+						foreach($this->m_oTranslator->indexes_sql as $key => $sIndexSQL)
+						{
+							$ix_name = $key.'_'.$sTableName.'_idx';
+							$IndexSQL = str_replace(array('__index_name__','__table_name__'), array($ix_name,$sTableName), $sIndexSQL);
+							$sAllTableSQL .= $IndexSQL . "\n\n";
+						}
+					}
 				}
 				else
 				{
@@ -122,7 +119,7 @@
 			return True;
 		}
 
-		function ExecuteScripts($aTables, $bOutputHTML=False)
+		function ExecuteScripts($aTables, $bOutputHTML=false)
 		{
 			if(!is_array($aTables) || !IsSet($this->m_odb))
 			{
@@ -132,7 +129,7 @@
 			reset($aTables);
 			$this->m_aTables = $aTables;
 
-			while(list($sTableName, $aTableDef) = each($aTables))
+			foreach ($aTables as $sTableName => $aTableDef)
 			{
 				if($this->CreateTable($sTableName, $aTableDef))
 				{
@@ -165,7 +162,8 @@
 			$this->m_aTables = $aTables;
 
 			reset($this->m_aTables);
-			while(list($sTableName, $aTableDef) = each($this->m_aTables))
+
+			foreach ( $this->m_aTables as $sTableName => $aTableDef)
 			{
 				if($this->DropTable($sTableName))
 				{
@@ -668,7 +666,7 @@
 				$this->query($sIXSQL, __LINE__, __FILE__);
 			}
 			
-			// postgres
+			// postgres and mssql
 			if(isset($this->m_oTranslator->indexes_sql) && is_array($this->m_oTranslator->indexes_sql) && count($this->m_oTranslator->indexes_sql)>0)
 			{
 				foreach($this->m_oTranslator->indexes_sql as $key => $sIndexSQL)

Modified: people/sigurdne/modules/phpgwapi/trunk/inc/class.schema_proc_array.inc.php
===================================================================
--- people/sigurdne/modules/phpgwapi/trunk/inc/class.schema_proc_array.inc.php	2009-11-20 10:27:41 UTC (rev 20844)
+++ people/sigurdne/modules/phpgwapi/trunk/inc/class.schema_proc_array.inc.php	2009-11-20 10:28:10 UTC (rev 20845)
@@ -9,21 +9,6 @@
 	* @package phpgwapi
 	* @subpackage database
 	* @version $Id$
-	*/
-
-	/*
-	   This program is free software: you can redistribute it and/or modify
-	   it under the terms of the GNU General Public License as published by
-	   the Free Software Foundation, either version 3 of the License, or
-	   (at your option) any later version.
-
-	   This program is distributed in the hope that it will be useful,
-	   but WITHOUT ANY WARRANTY; without even the implied warranty of
-	   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-	   GNU General Public License for more details.
-
-	   You should have received a copy of the GNU General Public License
-	   along with this program.  If not, see <http://www.gnu.org/licenses/>.
 	 */
 
 	/**

Modified: people/sigurdne/modules/phpgwapi/trunk/inc/class.schema_proc_mssql.inc.php
===================================================================
--- people/sigurdne/modules/phpgwapi/trunk/inc/class.schema_proc_mssql.inc.php	2009-11-20 10:27:41 UTC (rev 20844)
+++ people/sigurdne/modules/phpgwapi/trunk/inc/class.schema_proc_mssql.inc.php	2009-11-20 10:28:10 UTC (rev 20845)
@@ -9,21 +9,6 @@
 	* @package phpgwapi
 	* @subpackage database
 	* @version $Id$
-	*/
-
-	/*
-	   This program is free software: you can redistribute it and/or modify
-	   it under the terms of the GNU General Public License as published by
-	   the Free Software Foundation, either version 3 of the License, or
-	   (at your option) any later version.
-
-	   This program is distributed in the hope that it will be useful,
-	   but WITHOUT ANY WARRANTY; without even the implied warranty of
-	   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-	   GNU General Public License for more details.
-
-	   You should have received a copy of the GNU General Public License
-	   along with this program.  If not, see <http://www.gnu.org/licenses/>.
 	 */
 
 	/**
@@ -102,6 +87,9 @@
 				case 'text':
 					$sTranslated = 'text';
 					break;
+				case 'time':
+					$sTranslated = 'time';
+					break;
 				case 'timestamp':
 					$sTranslated = 'datetime';
 					break;
@@ -301,7 +289,7 @@
 					$keypair = explode('=',$keypair);
 					$keystr[] = "'" . $keypair[0] . "' => '" . $keypair[1] . "'";
 				}
-				$this->fk[] = $table . "' => array(" . implode(', ',$keystr)  . ')';
+				$this->fk[] = "'" . $table . "' => array(" . implode(', ',$keystr)  . ')';
 			}
 
 			/*FIXME: not working as expected */

Modified: people/sigurdne/modules/phpgwapi/trunk/inc/class.schema_proc_mysql.inc.php
===================================================================
--- people/sigurdne/modules/phpgwapi/trunk/inc/class.schema_proc_mysql.inc.php	2009-11-20 10:27:41 UTC (rev 20844)
+++ people/sigurdne/modules/phpgwapi/trunk/inc/class.schema_proc_mysql.inc.php	2009-11-20 10:28:10 UTC (rev 20845)
@@ -9,21 +9,6 @@
 	* @package phpgwapi
 	* @subpackage database
 	* @version $Id$
-	*/
-
-	/*
-	   This program is free software: you can redistribute it and/or modify
-	   it under the terms of the GNU General Public License as published by
-	   the Free Software Foundation, either version 3 of the License, or
-	   (at your option) any later version.
-
-	   This program is distributed in the hope that it will be useful,
-	   but WITHOUT ANY WARRANTY; without even the implied warranty of
-	   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-	   GNU General Public License for more details.
-
-	   You should have received a copy of the GNU General Public License
-	   along with this program.  If not, see <http://www.gnu.org/licenses/>.
 	 */
  
 	/**
@@ -78,6 +63,9 @@
 				case 'auto':
 					$sTranslated = 'int(11) auto_increment';
 					break;
+				case 'bool':
+					$sTranslated = 'bool';
+					break;
 				case 'blob':
 					$sTranslated = 'blob';
 					break;
@@ -128,6 +116,9 @@
 				case 'text':
 					$sTranslated = 'text';
 					break;
+				case 'time':
+					$sTranslated = 'time';
+					break;
 				case 'timestamp':
 					$sTranslated = 'timestamp';
 					break;
@@ -206,6 +197,7 @@
 					$sTranslated = "'type' => 'float', 'precision' => $iPrecision";
 					break;
 				case 'datetime':
+				case 'timestamp':
 					$sTranslated = "'type' => 'timestamp'";
 					break;
 				case 'enum':
@@ -240,7 +232,7 @@
 
 		function GetUCSQL($sFields)
 		{
-			return "UNIQUE($sFields)";
+			return "UNIQUE KEY ($sFields)";
 		}
 
 		function GetIXSQL($sFields, $sTableName = '')
@@ -251,7 +243,7 @@
 			}
 			else
 			{
-				return "INDEX ($sFields)";			
+				return "KEY ($sFields)";			
 			}
 		}
 
@@ -362,7 +354,7 @@
 
 		function DropTable($oProc, &$aTables, $sTableName)
 		{
-			return !!($oProc->m_odb->query("DROP TABLE " . $sTableName, __LINE__, __FILE__));
+			return !!($oProc->m_odb->query("DROP TABLE " . $sTableName, __LINE__, __FILE__, true));
 		}
 
 		function DropColumn($oProc, &$aTables, $sTableName, $aNewTableDef, $sColumnName, $bCopyData = true)
@@ -425,6 +417,8 @@
 
 		function CreateTable($oProc, &$aTables, $sTableName, $aTableDef)
 		{
+			global $DEBUG;
+
 			if ($oProc->_GetTableSQL($sTableName, $aTableDef, $sTableSQL, $sSequenceSQL, $sTriggerSQL))
 			{
 				/* create sequence first since it will be needed for default */
@@ -433,8 +427,11 @@
 					$oProc->m_odb->query($sSequenceSQL, __LINE__, __FILE__);
 				}
 
-				$query = "CREATE TABLE $sTableName ($sTableSQL)";
-				return !!($oProc->m_odb->query($query, __LINE__, __FILE__));
+				$query = "CREATE TABLE $sTableName ($sTableSQL) ENGINE=InnoDB DEFAULT CHARSET=utf8";
+
+				if($DEBUG) { echo '<br>CREATE TABLE STATEMENT: ' ; var_dump($query); }
+
+				return !!($oProc->m_odb->query($query, __LINE__, __FILE__, true));
 			}
 
 			return false;

Modified: people/sigurdne/modules/phpgwapi/trunk/inc/class.schema_proc_oracle.inc.php
===================================================================
--- people/sigurdne/modules/phpgwapi/trunk/inc/class.schema_proc_oracle.inc.php	2009-11-20 10:27:41 UTC (rev 20844)
+++ people/sigurdne/modules/phpgwapi/trunk/inc/class.schema_proc_oracle.inc.php	2009-11-20 10:28:10 UTC (rev 20845)
@@ -7,21 +7,6 @@
 	* @package phpgwapi
 	* @subpackage database
 	* @version $Id$
-	*/
-
-	/*
-	   This program is free software: you can redistribute it and/or modify
-	   it under the terms of the GNU General Public License as published by
-	   the Free Software Foundation, either version 3 of the License, or
-	   (at your option) any later version.
-
-	   This program is distributed in the hope that it will be useful,
-	   but WITHOUT ANY WARRANTY; without even the implied warranty of
-	   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-	   GNU General Public License for more details.
-
-	   You should have received a copy of the GNU General Public License
-	   along with this program.  If not, see <http://www.gnu.org/licenses/>.
 	 */
  
 	/**

Modified: people/sigurdne/modules/phpgwapi/trunk/inc/class.schema_proc_pgsql.inc.php
===================================================================
--- people/sigurdne/modules/phpgwapi/trunk/inc/class.schema_proc_pgsql.inc.php	2009-11-20 10:27:41 UTC (rev 20844)
+++ people/sigurdne/modules/phpgwapi/trunk/inc/class.schema_proc_pgsql.inc.php	2009-11-20 10:28:10 UTC (rev 20845)
@@ -1,7 +1,6 @@
 <?php
 	/**
 	* Database schema abstraction class for PostgreSQL
-	*
 	* @author Tobias Ratschiller <[email protected]>
 	* @author Dan Wilson <[email protected]>
 	* @author Michael Dean <[email protected]>
@@ -9,30 +8,15 @@
 	* @copyright Copyright (C) 1998-1999 Tobias Ratschiller
 	* @copyright Copyright (C) 1999-2000 Dan Wilson
 	* @copyright Copyright (C) ? Michael Dean, Miles Lott
-	* @copyright Portions Copyright (C) 2003 - 2008 Free Software Foundation, Inc. http://www.fsf.org/
-	* @license http://www.fsf.org/licenses/gpl.html GNU General Public License v3 or later
-	* @package phpgroupware
-	* @subpackage phpgwapi
+	* @copyright Portions Copyright (C) 2003,2004 Free Software Foundation, Inc. http://www.fsf.org/
+	* @license http://www.fsf.org/licenses/gpl.html GNU General Public License
+	* @package phpgwapi
+	* @subpackage database
 	* @version $Id$
 	* @link http://www.greatbridge.org/project/phppgadmin
 	* @internal SQL for table properties taken from phpPgAdmin Version 2.2.1
 	*/
 
-	/*
-	   This program is free software: you can redistribute it and/or modify
-	   it under the terms of the GNU General Public License as published by
-	   the Free Software Foundation, either version 3 of the License, or
-	   (at your option) any later version.
-
-	   This program is distributed in the hope that it will be useful,
-	   but WITHOUT ANY WARRANTY; without even the implied warranty of
-	   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-	   GNU General Public License for more details.
-
-	   You should have received a copy of the GNU General Public License
-	   along with this program.  If not, see <http://www.gnu.org/licenses/>.
-	 */
-
 	/**
 	* Database schema abstraction class for PostgreSQL
 	* 
@@ -100,6 +84,9 @@
 				case 'text':
 					$sTranslated = 'text';
 					break;
+				case 'time':
+					$sTranslated = 'time';
+					break;
 				case 'timestamp':
 					$sTranslated = 'timestamp';
 					break;
@@ -179,6 +166,9 @@
 				case 'timestamp':
 					$sTranslated = "'type' => 'timestamp'";
 					break;
+				case 'time':
+					$sTranslated = "'type' => 'time'";
+					break;
 				case 'varchar':
 					if ($iPrecision > 0 && $iPrecision < 256)
 					{
@@ -194,6 +184,7 @@
 				case 'date':
 					$sTranslated = "'type' => '$sType'";
 					break;
+				case 'bool':
 				case 'boolean':
 					$sTranslated = "'type' => 'bool'";
 					break;
@@ -295,11 +286,11 @@
 
 				if ($sdb->f(5) == 'f')
 				{
-					$null = "'nullable' => True";
+					$null = "'nullable' => False";
 				}
 				else
 				{
-					$null = "'nullable' => False";
+					$null = "'nullable' => True";
 				}
 
 				if ($sdb->f(2) == 'numeric')
@@ -335,7 +326,7 @@
 					";
 				$sdc->query($sql_get_default, __LINE__, __FILE__);
 				$sdc->next_record();
-				if ($sdc->f(0))
+				if ($sdc->f(0) != '')
 				{
 					if (ereg('nextval',$sdc->f(0)))
 					{
@@ -345,7 +336,15 @@
 					}
 					else
 					{
-						$default = "'default' => '" . str_replace(array('::bpchar','::character varying','now()',"('now'::text)::timestamp(6) without time zone"),array('','','current_timestamp','current_timestamp'),$sdc->f(0));
+						if(preg_match('/(now()|::timestamp(6) without time zone$|::timestamp without time zone$)/i', $sdc->f(0)))
+						{
+							$default =  "'default' =>'current_timestamp'";
+						}
+						else
+						{
+							$default = "'default' => '" . str_replace(array('::bpchar','::character varying'),array('',''),$sdc->f(0));						
+						}
+						
 						// For db-functions - add an apos
 						if(substr($default,-1)!= "'")
 						{
@@ -400,6 +399,7 @@
 				}
 			}
 
+/*
 			$ForeignKeys = $sdc->MetaForeignKeys($sTableName);
 
 			foreach($ForeignKeys as $table => $keys)
@@ -412,11 +412,64 @@
 				}
 				$this->fk[] = $table . "' => array(" . implode(', ',$keystr)  . ')';
 			}
+*/
 
-			$MetaIndexes = $sdc->adodb->MetaIndexes($sTableName);
+			$sql_f_keys = "SELECT
+				pc.conname,
+				pg_catalog.pg_get_constraintdef(pc.oid, true) AS consrc,
+				pc.contype,
+				CASE WHEN pc.contype='u' OR pc.contype='p' THEN (
+					SELECT
+						indisclustered
+					FROM
+						pg_catalog.pg_depend pd,
+						pg_catalog.pg_class pl,
+						pg_catalog.pg_index pi
+					WHERE
+						pd.refclassid=pc.tableoid
+						AND pd.refobjid=pc.oid
+						AND pd.objid=pl.oid
+						AND pl.oid=pi.indexrelid
+				) ELSE
+					NULL
+				END AS indisclustered
+			FROM
+				pg_catalog.pg_constraint pc
+			WHERE
+				pc.conrelid = (SELECT oid FROM pg_catalog.pg_class WHERE relname='$sTableName'
+					AND relnamespace = (SELECT oid FROM pg_catalog.pg_namespace
+					WHERE nspname='public'))
+			ORDER BY
+				1";
 
+			$oProc->m_odb->query($sql_f_keys, __LINE__, __FILE__);
+			while ($oProc->m_odb->next_record())
+			{
+				if($oProc->m_odb->f('contype') == 'f')
+				{
+					$f_temp = preg_split("/FOREIGN KEY|REFERENCES|[()]/",$oProc->m_odb->f('consrc'));
+					$f_temp_primary = explode(', ',$f_temp[2]);
+					$f_temp_foreign = explode(', ',$f_temp[5]);
+
+					$keystr = '';
+					for ($i=0;$i<count($f_temp_primary);$i++)
+					{
+						$keystr[] = "'" . $f_temp_primary[$i] . "' => '" . $f_temp_foreign[$i] . "'";
+					}				
+					
+					$this->fk[] = "'" . trim($f_temp[4]) . "' => array(" . implode(', ',$keystr)  . ')';
+				}
+			}
+			unset($keystr);
+			unset($f_temp);
+			unset($f_temp_primary);
+			unset($f_temp_foreign);
+
+
+			$metaindexes = $sdc->metaindexes($sTableName);
+
 			//FIXME: looks like unique is reported as index
-			foreach($MetaIndexes as $key => $index)
+			foreach($metaindexes as $key => $index)
 			{
 				if(count($index['columns']) > 1)
 				{
@@ -627,53 +680,27 @@
 
 		function AddColumn($oProc, &$aTables, $sTableName, $sColumnName, &$aColumnDef)
 		{
-			$default = '';
-			$Ok = '';
-			if (isset($aColumnDef['default']) && $aColumnDef['default'])	// pgsql cant add a colum with a default
+			if (!isset($aColumnDef['nullable']) || (isset($aColumnDef['nullable']) && ($aColumnDef['nullable'] === 'False' || $aColumnDef['nullable'] === false)) )	// pgsql cant add a column not nullable if there is data in the table
 			{
-				$default = $aColumnDef['default'];
-				unset($aColumnDef['default']);
-			}
-			if (isset($aColumnDef['nullable']) && !$aColumnDef['nullable'])	// pgsql cant add a column not nullable
+				if(!isset($aColumnDef['default']))
 			{
-				$notnull = !$aColumnDef['nullable'];
-				unset($aColumnDef['nullable']);
-			}
-			$oProc->_GetFieldSQL($aColumnDef, $sFieldSQL);
-			$query = "ALTER TABLE $sTableName ADD COLUMN $sColumnName $sFieldSQL";
-
-			if (($Ok = !!$oProc->m_odb->query($query, __LINE__, __FILE__)) && isset($default) && $default)
-			{
-				if($default == '0')
+					$oProc->m_odb->query("SELECT count(*) as cnt FROM $sTableName", __LINE__, __FILE__);
+					$oProc->m_odb->next_record();
+					if($oProc->m_odb->f(0))
 				{
-					$defaultSQL = " DEFAULT 0";
+						throw new Exception(lang('ERROR: The column %1 in table %2 cannot be added as NOT NULL as there is data in the table', $sColumnName, $sTableName));
 				}								
-				elseif(!is_numeric($default) && $default != '')
-				{
-					$sTranslatedDefault = $this->TranslateDefault($default);
-					$defaultSQL = " DEFAULT $sTranslatedDefault";
 				}
-				elseif($default)
+				else
 				{
-					$defaultSQL = " DEFAULT $default";
+					trigger_error(lang('column %1 for table %2 will be added as NULLABLE with DEFAULT value %3', $classname, $sTableName, $aColumnDef['default']), E_USER_WARNING);
 				}
+				}
 
-				$query = "ALTER TABLE $sTableName ALTER COLUMN $sColumnName SET $defaultSQL;\n";
+			$oProc->_GetFieldSQL($aColumnDef, $sFieldSQL);
+			$query = "ALTER TABLE $sTableName ADD COLUMN $sColumnName $sFieldSQL";
 
-				$query .= "UPDATE $sTableName SET $sColumnName='$default';\n";
-
-				$Ok = !!$oProc->m_odb->query($query, __LINE__, __FILE__);
-
-				if ($OK && $notnull)
-				{
-					// unfortunally this is pgSQL >= 7.3
-					//$query .= "ALTER TABLE $sTableName ALTER COLUMN $sColumnName SET NOT NULL;\n";
-					//$Ok = !!($oProc->m_odb->query($query));
-					// so we do it the slow way
-					AlterColumn($oProc, $aTables, $sTableName, $sColumnName, $aColumnDef);
-				}
-			}
-			return $Ok;
+			return !!$oProc->m_odb->query($query, __LINE__, __FILE__);
 		}
 
 		function GetSequenceSQL($sTableName, &$sSequenceSQL)

Modified: people/sigurdne/modules/phpgwapi/trunk/inc/class.schema_proc_sapdb.inc.php
===================================================================
--- people/sigurdne/modules/phpgwapi/trunk/inc/class.schema_proc_sapdb.inc.php	2009-11-20 10:27:41 UTC (rev 20844)
+++ people/sigurdne/modules/phpgwapi/trunk/inc/class.schema_proc_sapdb.inc.php	2009-11-20 10:28:10 UTC (rev 20845)
@@ -7,21 +7,6 @@
 	* @package phpgwapi
 	* @subpackage database
 	* @version $Id$
-	*/
-
-	/*
-	   This program is free software: you can redistribute it and/or modify
-	   it under the terms of the GNU Lesser General Public License as published by
-	   the Free Software Foundation, either version 3 of the License, or
-	   (at your option) any later version.
-
-	   This program is distributed in the hope that it will be useful,
-	   but WITHOUT ANY WARRANTY; without even the implied warranty of
-	   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-	   GNU General Public License for more details.
-
-	   You should have received a copy of the GNU Lesser General Public License
-	   along with this program.  If not, see <http://www.gnu.org/licenses/>.
 	 */
 
 	/**

Modified: people/sigurdne/modules/phpgwapi/trunk/inc/class.send.inc.php
===================================================================
--- people/sigurdne/modules/phpgwapi/trunk/inc/class.send.inc.php	2009-11-20 10:27:41 UTC (rev 20844)
+++ people/sigurdne/modules/phpgwapi/trunk/inc/class.send.inc.php	2009-11-20 10:28:10 UTC (rev 20845)
@@ -9,21 +9,6 @@
 	* @package phpgwapi
 	* @subpackage communication
 	* @version $Id$
-	*/
-
-	/*
-	   This program is free software: you can redistribute it and/or modify
-	   it under the terms of the GNU Lesser General Public License as published by
-	   the Free Software Foundation, either version 3 of the License, or
-	   (at your option) any later version.
-
-	   This program is distributed in the hope that it will be useful,
-	   but WITHOUT ANY WARRANTY; without even the implied warranty of
-	   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-	   GNU General Public License for more details.
-
-	   You should have received a copy of the GNU Lesser General Public License
-	   along with this program.  If not, see <http://www.gnu.org/licenses/>.
 	 */
 
 	/**
@@ -49,7 +34,7 @@
 			$this->err['desc'] = ' ';
 		}
 
-		function msg($service, $to, $subject, $body, $msgtype='', $cc='', $bcc='', $from='', $sender='', $content_type='', $boundary='Message-Boundary',$attachments='')
+		function msg($service, $to, $subject, $body, $msgtype='', $cc='', $bcc='', $from='', $sender='', $content_type='', $boundary='Message-Boundary',$attachments=array(), $receive_notification = false)
 		{
 			if ($from == '')
 			{
@@ -63,12 +48,12 @@
 			switch( $service )
 			{
 				case 'email':
-					return $this->send_email($to, $subject, $body, $msgtype, $cc, $bcc, $from, $sender, $content_type, $boundary='Message-Boundary',$attachments);
+					return $this->send_email($to, $subject, $body, $msgtype, $cc, $bcc, $from, $sender, $content_type, $boundary='Message-Boundary', $attachments, $receive_notification);
 					break;
 			}
 		}
 
-		function send_email($to, $subject, $body, $msgtype, $cc, $bcc, $from, $sender, $content_type, $ignored,$attachments)
+		function send_email($to, $subject, $body, $msgtype, $cc, $bcc, $from, $sender, $content_type, $ignored,$attachments, $receive_notification)
 		{
 			$smtp = createObject('phpgwapi.mailer_smtp');
 			$from_array = split('<', $from);
@@ -160,6 +145,10 @@
 			$smtp->Subject = $subject;
 			$smtp->Body    = $body;
 			$smtp->AddCustomHeader('X-Mailer: phpGroupWare (http://www.phpgroupware.org)');
+			if($receive_notification)
+			{
+				$smtp->AddCustomHeader("Disposition-Notification-To: {$smtp->From}");
+			}
 			$smtp->Port = $GLOBALS['phpgw_info']['server']['smtp_port'] ? $GLOBALS['phpgw_info']['server']['smtp_port'] : 25;
 			$smtp->Host 	= $GLOBALS['phpgw_info']['server']['smtp_server'];
 			$smtp->Encoding = '8bit';
@@ -176,9 +165,9 @@
 				$smtp->WordWrap = 76;
 			}
 
-			if (isset($attachments) && is_array($attachments))
+			if($attachments && is_array($attachments))
 			{
-				while(list($key,$value) = each($attachments))
+				foreach($attachments as $key => $value)
 				{
 					$smtp->AddAttachment
 					(
@@ -513,3 +502,4 @@
 			return True;
 		}
 	} /* end of class */
+

Modified: people/sigurdne/modules/phpgwapi/trunk/inc/class.service.inc.php
===================================================================
--- people/sigurdne/modules/phpgwapi/trunk/inc/class.service.inc.php	2009-11-20 10:27:41 UTC (rev 20844)
+++ people/sigurdne/modules/phpgwapi/trunk/inc/class.service.inc.php	2009-11-20 10:28:10 UTC (rev 20845)
@@ -8,21 +8,6 @@
 	* @package phpgwapi
 	* @subpackage application
 	* @version $Id$
-	*/
-
-	/*
-	   This program is free software: you can redistribute it and/or modify
-	   it under the terms of the GNU Lesser General Public License as published by
-	   the Free Software Foundation, either version 3 of the License, or
-	   (at your option) any later version.
-
-	   This program is distributed in the hope that it will be useful,
-	   but WITHOUT ANY WARRANTY; without even the implied warranty of
-	   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-	   GNU General Public License for more details.
-
-	   You should have received a copy of the GNU Lesser General Public License
-	   along with this program.  If not, see <http://www.gnu.org/licenses/>.
 	 */
 
 	/**
@@ -68,3 +53,4 @@
 			return $this->function_map;
 		}
 	}
+?>

Modified: people/sigurdne/modules/phpgwapi/trunk/inc/class.service_contacts.inc.php
===================================================================
--- people/sigurdne/modules/phpgwapi/trunk/inc/class.service_contacts.inc.php	2009-11-20 10:27:41 UTC (rev 20844)
+++ people/sigurdne/modules/phpgwapi/trunk/inc/class.service_contacts.inc.php	2009-11-20 10:28:10 UTC (rev 20845)
@@ -8,21 +8,6 @@
 	* @package phpgwapi
 	* @subpackage application
 	* @version $Id$
-	*/
-
-	/*
-	   This program is free software: you can redistribute it and/or modify
-	   it under the terms of the GNU Lesser General Public License as published by
-	   the Free Software Foundation, either version 3 of the License, or
-	   (at your option) any later version.
-
-	   This program is distributed in the hope that it will be useful,
-	   but WITHOUT ANY WARRANTY; without even the implied warranty of
-	   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-	   GNU General Public License for more details.
-
-	   You should have received a copy of the GNU Lesser General Public License
-	   along with this program.  If not, see <http://www.gnu.org/licenses/>.
 	 */
 
 	/**

Modified: people/sigurdne/modules/phpgwapi/trunk/inc/class.service_notes.inc.php
===================================================================
--- people/sigurdne/modules/phpgwapi/trunk/inc/class.service_notes.inc.php	2009-11-20 10:27:41 UTC (rev 20844)
+++ people/sigurdne/modules/phpgwapi/trunk/inc/class.service_notes.inc.php	2009-11-20 10:28:10 UTC (rev 20845)
@@ -8,21 +8,6 @@
 	* @package phpgwapi
 	* @subpackage application
 	* @version $Id$
-	*/
-
-	/*
-	   This program is free software: you can redistribute it and/or modify
-	   it under the terms of the GNU Lesser General Public License as published by
-	   the Free Software Foundation, either version 3 of the License, or
-	   (at your option) any later version.
-
-	   This program is distributed in the hope that it will be useful,
-	   but WITHOUT ANY WARRANTY; without even the implied warranty of
-	   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-	   GNU General Public License for more details.
-
-	   You should have received a copy of the GNU Lesser General Public License
-	   along with this program.  If not, see <http://www.gnu.org/licenses/>.
 	 */
 
 	/**

Modified: people/sigurdne/modules/phpgwapi/trunk/inc/class.service_schedule.inc.php
===================================================================
--- people/sigurdne/modules/phpgwapi/trunk/inc/class.service_schedule.inc.php	2009-11-20 10:27:41 UTC (rev 20844)
+++ people/sigurdne/modules/phpgwapi/trunk/inc/class.service_schedule.inc.php	2009-11-20 10:28:10 UTC (rev 20845)
@@ -8,21 +8,6 @@
 	* @package phpgwapi
 	* @subpackage application
 	* @version $Id$
-	*/
-
-	/*
-	   This program is free software: you can redistribute it and/or modify
-	   it under the terms of the GNU Lesser General Public License as published by
-	   the Free Software Foundation, either version 3 of the License, or
-	   (at your option) any later version.
-
-	   This program is distributed in the hope that it will be useful,
-	   but WITHOUT ANY WARRANTY; without even the implied warranty of
-	   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-	   GNU General Public License for more details.
-
-	   You should have received a copy of the GNU Lesser General Public License
-	   along with this program.  If not, see <http://www.gnu.org/licenses/>.
 	 */
 
 	/**

Modified: people/sigurdne/modules/phpgwapi/trunk/inc/class.session_handler_db.inc.php
===================================================================
--- people/sigurdne/modules/phpgwapi/trunk/inc/class.session_handler_db.inc.php	2009-11-20 10:27:41 UTC (rev 20844)
+++ people/sigurdne/modules/phpgwapi/trunk/inc/class.session_handler_db.inc.php	2009-11-20 10:28:10 UTC (rev 20845)
@@ -6,14 +6,14 @@
 	* @license http://www.fsf.org/licenses/lgpl.html GNU Lesser General Public License
 	* @package phpgwapi
 	* @subpackage sessions
-	* @version $Id: class.sessions_db.inc.php 682 2008-02-01 12:19:55Z dave $
+	* @version $Id: class.session_handler_db.inc.php 3056 2009-06-12 21:58:10Z sigurd $
 	* @link http://php.net/session_set_save_handler
 	*/
 
 	/*
 	   This program is free software: you can redistribute it and/or modify
 	   it under the terms of the GNU Lesser General Public License as published by
-	   the Free Software Foundation, either version 3 of the License, or
+	   the Free Software Foundation, either version 2 of the License, or
 	   (at your option) any later version.
 
 	   This program is distributed in the hope that it will be useful,
@@ -90,8 +90,19 @@
 			$GLOBALS['phpgw']->db->query($sql, __LINE__, __FILE__);
 			while ($GLOBALS['phpgw']->db->next_record())
 			{
-				$data = $GLOBALS['phpgw']->crypto->decrypt($GLOBALS['phpgw']->db->f('data', true));
+				$rawdata = $GLOBALS['phpgw']->crypto->decrypt($GLOBALS['phpgw']->db->f('data', true));
 
+				//taken from http://no.php.net/manual/en/function.session-decode.php#79244
+				$vars = preg_split('/([a-zA-Z_\x7f-\xff][a-zA-Z0-9_\x7f-\xff^|]*)\|/',
+				$rawdata, -1, PREG_SPLIT_NO_EMPTY | PREG_SPLIT_DELIM_CAPTURE);
+				$data = array();
+
+				if(isset($vars[3]))
+				{
+					$data[$vars[0]]=unserialize($vars[1]);
+					$data[$vars[2]]=unserialize($vars[3]);
+				}
+
 				// skip invalid or anonymous sessions
 				if ( !isset($data['phpgw_session'])
 					|| !isset($data['phpgw_session']['session_flags'])
@@ -100,11 +111,11 @@
 					continue;
 				}
 
-				$values[$GLOBALS['phpgw']->db->f('session_id', true)] = array
+				$values[$data['phpgw_session']['session_id']] = array
 				(
-					'id'		=> $GLOBALS['phpgw']->db->f('id', true),
+					'id'		=> $data['phpgw_session']['session_id'],
 					'lid'		=> $data['phpgw_session']['session_lid'],
-					'ip'		=> $GLOBALS['phpgw']->db->f('ip', true),
+					'ip'		=> $data['phpgw_session']['session_ip'],
 					'action'	=> $data['phpgw_session']['session_action'],
 					'dla'		=> $data['phpgw_session']['session_dla'],
 					'logints'	=> $data['phpgw_session']['session_logintime']
@@ -145,7 +156,8 @@
 			$GLOBALS['phpgw']->db->query($sql, __LINE__, __FILE__);
 			if ( $GLOBALS['phpgw']->db->next_record() )
 			{
-				return $GLOBALS['phpgw']->crypto->decrypt($GLOBALS['phpgw']->db->f('data', true));
+			//	return $GLOBALS['phpgw']->crypto->decrypt($GLOBALS['phpgw']->db->f('data', true));
+				return unserialize($GLOBALS['phpgw']->db->f('data', true));
 			}
 			return '';
 		}
@@ -159,12 +171,16 @@
 		 */
 		public static function write($id, $data)
 		{
-			$id = $GLOBALS['phpgw']->db->db_addslashes($id);
-			$data = $GLOBALS['phpgw']->db->db_addslashes($GLOBALS['phpgw']->crypto->encrypt($data));
+			$db 	= & $GLOBALS['phpgw']->db;
+		//	$crypto = & $GLOBALS['phpgw']->crypto;
+
+			$id   = $db->db_addslashes($id);
+		//	$data = $db->db_addslashes($crypto->encrypt($data));
+			$data = $db->db_addslashes(serialize($data));
 			$ts = time();
 
-			$GLOBALS['phpgw']->db->query("SELECT session_id FROM phpgw_sessions WHERE session_id = '{$id}'", __LINE__, __FILE__);
-			if ( $GLOBALS['phpgw']->db->next_record() )
+			$db->query("SELECT session_id FROM phpgw_sessions WHERE session_id = '{$id}'", __LINE__, __FILE__);
+			if ( $db->next_record() )
 			{
 				$sql = 'UPDATE phpgw_sessions'
 					. " SET data = '{$data}', lastmodts = {$ts}"
@@ -176,7 +192,7 @@
 				$sql = "INSERT INTO phpgw_sessions VALUES('{$id}', '{$ip}', '{$data}', {$ts})";
 			}
 
-			$ret = $GLOBALS['phpgw']->db->query($sql, __LINE__, __FILE__);
+			$ret = $db->query($sql, __LINE__, __FILE__);
 			return $ret;
 		}
 	}

Modified: people/sigurdne/modules/phpgwapi/trunk/inc/class.sessions.inc.php
===================================================================
--- people/sigurdne/modules/phpgwapi/trunk/inc/class.sessions.inc.php	2009-11-20 10:27:41 UTC (rev 20844)
+++ people/sigurdne/modules/phpgwapi/trunk/inc/class.sessions.inc.php	2009-11-20 10:28:10 UTC (rev 20845)
@@ -16,7 +16,7 @@
 	/*
 	   This program is free software: you can redistribute it and/or modify
 	   it under the terms of the GNU Lesser General Public License as published by
-	   the Free Software Foundation, either version 3 of the License, or
+	   the Free Software Foundation, either version 2 of the License, or
 	   (at your option) any later version.
 
 	   This program is distributed in the hope that it will be useful,
@@ -31,7 +31,14 @@
 	/**
 	* Set the session name to something unique for phpgw
 	*/
-	session_name('phpgwsessid');
+	if ( isset($GLOBALS['phpgw_info']['flags']['session_name']) && $GLOBALS['phpgw_info']['flags']['session_name'] )
+	{
+		session_name($GLOBALS['phpgw_info']['flags']['session_name']);
+	}
+	else
+	{
+		session_name('sessionphpgwsessid');
+	}
 
 	/*
 	 * Include the db session handler if required
@@ -139,16 +146,20 @@
 		public function __construct()
 		{
 			$this->_db			=& $GLOBALS['phpgw']->db;
-			$this->_sessionid	= phpgw::get_var(session_name());
-
-			$this->_phpgw_set_cookie_params();
-
 			$use_cookies = false;
 			if ( isset($GLOBALS['phpgw_info']['server']['usecookies'])
 				&& $GLOBALS['phpgw_info']['server']['usecookies'] == 'True' )
 			{
 				$use_cookies = true;
+				$this->_sessionid	= phpgw::get_var(session_name(), 'string', 'COOKIE');
 			}
+			else
+			{
+				$this->_sessionid	= phpgw::get_var(session_name()); // GET or POST
+			}
+
+			$this->_phpgw_set_cookie_params();
+
 			//respect the config option for cookies
 			ini_set('session.use_cookies', $use_cookies);
 
@@ -236,6 +247,7 @@
 			}
 
 			if ( phpgwapi_globally_denied::user($this->_account_lid)
+				|| !$accounts->name2id($this->_account_lid)
 				|| ( !$skip_auth && !$GLOBALS['phpgw']->auth->authenticate($this->_account_lid, $this->_passwd) )
 				|| get_class($accounts->get($accounts->name2id($this->_account_lid)))
 					== phpgwapi_account::CLASS_TYPE_GROUP )
@@ -265,7 +277,7 @@
 			if ( isset($GLOBALS['phpgw_info']['server']['usecookies'])
 				&& $GLOBALS['phpgw_info']['server']['usecookies'] )
 			{
-				//$this->phpgw_setcookie(session_name(), $this->_sessionid);
+				$this->phpgw_setcookie(session_name(), $this->_sessionid);
 				$this->phpgw_setcookie('domain', $this->_account_domain);
 			}
 
@@ -433,15 +445,19 @@
 				session_destroy();
 				$this->phpgw_setcookie(session_name());
 			}
-			else
+			else if ( $GLOBALS['phpgw_info']['server']['sessions_type'] == 'php' )
 			{
 				$sessions = $this->list_sessions(0, '', '', true);
 
 				if ( isset($sessions[$sessionid]) )
 				{
-					unlink($sessions[$sessionid]['php_session_file']);
+					unlink($sessions[$sessionid]['session_file']);
 				}
 			}
+			else
+			{
+				phpgwapi_session_handler_db::destroy($sessionid);
+			}
 
 			return true;
 		}
@@ -456,7 +472,7 @@
 			if(!isset($this->_history_id))
 			{
 				$this->_history_id = md5($this->_login . time());
-				$history = (array) $this->appsession('history', 'phpgwapi');
+				$history = $this->appsession('history', 'phpgwapi');
 
 				if(count($history) >= $GLOBALS['phpgw_info']['server']['max_history'])
 				{
@@ -653,7 +669,7 @@
 		public function list_sessions($start, $order, $sort, $all_no_sort = false)
 		{
 			// We cache the data for 5mins system wide as this is an expensive operation
-			$last_updated = phpgwapi_cache::system_get('phpgwapi', 'session_list_saved');
+			$last_updated = 0; //phpgwapi_cache::system_get('phpgwapi', 'session_list_saved');
 
 			if ( is_null($last_updated) 
 				|| $last_updated < 60 * 5 )
@@ -790,12 +806,34 @@
 		*/
 		public function phpgw_setcookie($cookiename, $cookievalue='', $cookietime=0)
 		{
-			$secure = phpgw::get_var('HTTPS', 'bool', 'SERVER');
-			setcookie($cookiename, $cookievalue, $cookietime, $GLOBALS['phpgw_info']['server']['webserver_url'],
-					$this->_cookie_domain, $secure, true);
+/*			$secure = phpgw::get_var('HTTPS', 'bool', 'SERVER');
+
+			if( isset( $GLOBALS['phpgw_info']['server']['webserver_url'] ) )
+			{
+				$webserver_url = $GLOBALS['phpgw_info']['server']['webserver_url'] . '/';
+			}
+			else
+			{
+				$webserver_url = '/';
+			}
+*/
+//			setcookie($cookiename, $cookievalue, $cookietime, parse_url($webserver_url, PHP_URL_PATH),
+//					$this->_cookie_domain, $secure, true);
+			setcookie($cookiename, $cookievalue, $cookietime);
 		}
 
+
 		/**
+		* Set the current user id
+		*
+		* @param int $account_id the account id - 0 = current user's id
+		*/
+		public function set_account_id($account_id = 0)
+		{
+			$this->_account_id = get_account_id($account_id);
+		}
+
+		/**
 		* Read session data
 		*
 		* @param boolean $cached      use cached data
@@ -1019,9 +1057,11 @@
 		{
 			session_id($this->_sessionid);
 
-			if ( isset($GLOBALS['phpgw_info']['menuaction']) )
+			$menuaction = phpgw::get_var('menuaction');
+
+			if ( $menuaction )
 			{
-				$action = $GLOBALS['phpgw_info']['menuaction'];
+				$action = $menuaction;
 			}
 			else
 			{
@@ -1101,7 +1141,8 @@
 			$GLOBALS['phpgw_info']['user']['account_id'] = $this->_account_id;
 
 			/* init the crypto object before appsession call below */
-			$this->_key = md5($this->_sessionid . $GLOBALS['phpgw_info']['server']['encryptkey']);
+			//$this->_key = md5($this->_sessionid . $GLOBALS['phpgw_info']['server']['encryptkey']); //Sigurd: not good for permanent data
+			$this->_key = $GLOBALS['phpgw_info']['server']['encryptkey'];
 			$this->_iv  = $GLOBALS['phpgw_info']['server']['mcrypt_iv'];
 			$GLOBALS['phpgw']->crypto->init(array($this->_key, $this->_iv));
 
@@ -1220,11 +1261,13 @@
 					return false;
 				}
 			}
-
+/*
 			$GLOBALS['phpgw']->acl->set_account_id($this->_account_id);
 			$GLOBALS['phpgw']->accounts->set_account($this->_account_id);
 			$GLOBALS['phpgw']->preferences->set_account_id($this->_account_id);
 			$GLOBALS['phpgw']->applications->set_account_id($this->_account_id);
+*/
+			$GLOBALS['phpgw']->translation->populate_cache();
 
 			if (! $this->_account_lid)
 			{
@@ -1293,20 +1336,37 @@
 				return $values;
 			}
 
-			$dir = new RecursiveDirectoryIterator();
-			foreach ( $dir as $filename )
+			$dir = new RecursiveDirectoryIterator($path);
+			foreach ( $dir as $file )
 			{
+				$filename = $file->getFilename();
 				// only try php session files
 				if ( !preg_match('/^sess_([a-f0-9]+)$/', $filename) )
 				{
 					continue;
 				}
 
-				$data = unserialize(file_get_contents($filename));
+				$rawdata = file_get_contents("{$path}/{$filename}");
 
+				//taken from http://no.php.net/manual/en/function.session-decode.php#79244
+				$vars = preg_split('/([a-zA-Z_\x7f-\xff][a-zA-Z0-9_\x7f-\xff^|]*)\|/',
+				$rawdata, -1, PREG_SPLIT_NO_EMPTY | PREG_SPLIT_DELIM_CAPTURE);
+				$data = array();
+
+		/*		for($i=0; $vars[$i]; $i++)
+				{
+					$data[$vars[$i++]]=unserialize($vars[$i]);
+				}
+		*/
+				if(isset($vars[3]))
+				{
+					$data[$vars[0]]=unserialize($vars[1]);
+					$data[$vars[2]]=unserialize($vars[3]);
+				}
+
 				// skip invalid or anonymous sessions
 				if ( !isset($data['phpgw_session'])
-					|| $data['phpgw_session']['session_install_id'] != $this->_install_id
+					|| $data['phpgw_session']['session_install_id'] != $GLOBALS['phpgw_info']['server']['install_id']
 					|| !isset($data['phpgw_session']['session_flags'])
 					|| $data['phpgw_session']['session_flags'] == 'A' )
 				{
@@ -1320,11 +1380,11 @@
 					'ip'		=> $data['phpgw_session']['session_ip'],
 					'action'	=> $data['phpgw_session']['session_action'],
 					'dla'		=> $data['phpgw_session']['session_dla'],
-					'logints'	=> $data['phpgw_session']['session_logintime']
+					'logints'			=> $data['phpgw_session']['session_logintime'],
+					'session_file'		=> "{$path}/{$filename}"
 				);
 			}
 			return $values;
-
 		}
 
 		/**
@@ -1414,7 +1474,7 @@
 				}
 				// save time of mail, to not send to many mails
 				$config = createObject('phpgwapi.config', 'phpgwapi');
-				$config->read();
+				$config->read_repository();
 				$config->value('login_blocked_mail_time', time());
 				$config->save_repository();
 			}
@@ -1439,13 +1499,26 @@
 			}
 			else
 			{
-				$this->_cookie_domain = phpgw::get_var('HTTP_HOST', 'string', 'SERVER');
+				$parts = explode(':', phpgw::get_var('HTTP_HOST', 'string', 'SERVER')); // strip portnumber if it exists in url (as in 'http://127.0.0.1:8080/')
+				$this->_cookie_domain = $parts[0];
 			}
 
+			if($this->_cookie_domain == 'localhost')
+			{
+				$this->_cookie_domain = ''; // Sigurd august 08: somehow setcookie does not accept localhost as a valid domain.
+			}
 			$secure = phpgw::get_var('HTTPS', 'bool', 'SERVER');
 			
-			session_set_cookie_params(0, "/", $this->_cookie_domain, $secure, true);
+			if( isset( $GLOBALS['phpgw_info']['server']['webserver_url'] ) )
+			{
+				$webserver_url = $GLOBALS['phpgw_info']['server']['webserver_url'] . '/';
+			}
+			else
+			{
+				$webserver_url = '/';
+			}
 
+			session_set_cookie_params(0, parse_url($webserver_url, PHP_URL_PATH), $this->_cookie_domain, $secure, true);
 			return $this->_cookie_domain;
 		}
 
@@ -1459,9 +1532,8 @@
 		protected function _setup_cache($write_cache = true)
 		{
 			$this->_data                = $GLOBALS['phpgw']->accounts->read()->toArray();
-			//XXX Caeies Feb09 : add the fullname since its published in the API docs
-			$this->_data['fullname']	= (string)$GLOBALS['phpgw']->accounts->read();
-			$this->_data['acl']         = $GLOBALS['phpgw']->acl->read();
+			$this->_data['fullname']	= $GLOBALS['phpgw']->accounts->read()->__toString();
+//			$this->_data['acl']         = $GLOBALS['phpgw']->acl->read(); // This one is never used
 			$this->_data['preferences'] = $GLOBALS['phpgw']->preferences->read();
 			$this->_data['apps']        = $GLOBALS['phpgw']->applications->read();
 
@@ -1500,4 +1572,15 @@
 			$this->_account_lid = $login;
 			$this->_account_domain = $GLOBALS['phpgw_info']['server']['default_domain'];
 		}
+
+		/**
+		* commit the sessiondata to the session handler
+		*
+		* @return bool
+		*/
+		function commit_session()
+		{
+			session_write_close();
+			return true;
+		}
 	}

Modified: people/sigurdne/modules/phpgwapi/trunk/inc/class.setup.inc.php
===================================================================
--- people/sigurdne/modules/phpgwapi/trunk/inc/class.setup.inc.php	2009-11-20 10:27:41 UTC (rev 20844)
+++ people/sigurdne/modules/phpgwapi/trunk/inc/class.setup.inc.php	2009-11-20 10:28:10 UTC (rev 20845)
@@ -10,21 +10,6 @@
 	* @package phpgwapi
 	* @subpackage application
 	* @version $Id$
-	*/
-
-	/*
-	   This program is free software: you can redistribute it and/or modify
-	   it under the terms of the GNU General Public License as published by
-	   the Free Software Foundation, either version 3 of the License, or
-	   (at your option) any later version.
-
-	   This program is distributed in the hope that it will be useful,
-	   but WITHOUT ANY WARRANTY; without even the implied warranty of
-	   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-	   GNU General Public License for more details.
-
-	   You should have received a copy of the GNU General Public License
-	   along with this program.  If not, see <http://www.gnu.org/licenses/>.
 	 */
 
 	/**
@@ -72,6 +57,7 @@
 		{
 			$form_domain = phpgw::get_var('FormDomain', 'string', 'POST', '');
 			$ConfigDomain = phpgw::get_var('ConfigDomain', 'string', 'REQUEST', $form_domain);
+			$ConfigDomain   = $ConfigDomain ? $ConfigDomain : phpgw::get_var('ConfigDomain', 'string', 'COOKIE');
 
 			$GLOBALS['phpgw_info']['server']['db_type'] = $GLOBALS['phpgw_domain'][$ConfigDomain]['db_type'];
 			$GLOBALS['phpgw_info']['server']['db_host']	= $GLOBALS['phpgw_domain'][$ConfigDomain]['db_host'];
@@ -91,23 +77,33 @@
 		 */
 		function auth($auth_type='Config')
 		{
-			$remote_ip     = $_SERVER['REMOTE_ADDR'];
+			$remoteip     = $_SERVER['REMOTE_ADDR'];
 
 			$FormLogout   = phpgw::get_var('FormLogout');
 			$ConfigLogin  = phpgw::get_var('ConfigLogin',	'string', 'POST');
 			$HeaderLogin  = phpgw::get_var('HeaderLogin',	'string', 'POST');
 			$FormDomain   = phpgw::get_var('FormDomain',	'string', 'POST');
-			$FormPW       = stripslashes(phpgw::get_var('FormPW',		'string', 'POST'));
+			$FormPW       = phpgw::get_var('FormPW',		'string', 'POST');
 
 			$ConfigDomain = phpgw::get_var('ConfigDomain');
 			$ConfigPW     = phpgw::get_var('ConfigPW');
 			$HeaderPW     = phpgw::get_var('HeaderPW');
 			$ConfigLang   = phpgw::get_var('ConfigLang');
 
-			if( $remote_ip && !$this->checkip($remote_ip) )
+			// In case the cookies are not included in $_REQUEST
+			$FormLogout   = $FormLogout ? $FormLogout : phpgw::get_var('FormLogout',	'string', 'COOKIE');
+			$ConfigDomain = $ConfigDomain ? $ConfigDomain: phpgw::get_var('ConfigDomain',	'string', 'COOKIE');
+			$ConfigPW     = $ConfigPW ? $ConfigPW : phpgw::get_var('ConfigPW',	'string', 'COOKIE');
+			$HeaderPW     = $HeaderPW ? $HeaderPW : phpgw::get_var('HeaderPW',	'string', 'COOKIE');
+			$ConfigLang   = $ConfigLang ? $ConfigLang : phpgw::get_var('ConfigLang',	'string', 'COOKIE');
+
+
+			/*
+			if(!empty($remoteip) && !$this->checkip($remoteip))
 			{
-				return false;
+				return False;
 			}
+			*/
 
 			/* 6 cases:
 				1. Logging into header admin
@@ -123,7 +119,7 @@
 			if(!empty($HeaderLogin) && $auth_type == 'Header')
 			{
 				/* header admin login */
-				if($FormPW == stripslashes($GLOBALS['phpgw_info']['server']['header_admin_password']))
+				if($FormPW == $GLOBALS['phpgw']->crypto->decrypt($GLOBALS['phpgw_info']['server']['header_admin_password']))
 				{
 					setcookie('HeaderPW',md5($FormPW),$expire);
 					setcookie('ConfigLang',$ConfigLang,$expire);
@@ -139,7 +135,8 @@
 			elseif(!empty($ConfigLogin) && $auth_type == 'Config')
 			{
 				/* config login */
-				if($FormPW == stripslashes(@$GLOBALS['phpgw_domain'][$FormDomain]['config_passwd']))
+//				if($FormPW == stripslashes(@$GLOBALS['phpgw_domain'][$FormDomain]['config_passwd']))
+				if($FormPW == $GLOBALS['phpgw']->crypto->decrypt($GLOBALS['phpgw_domain'][$FormDomain]['config_passwd']))
 				{
 					setcookie('ConfigPW', md5($FormPW), $expire);
 					setcookie('ConfigDomain', $FormDomain, $expire);
@@ -182,7 +179,7 @@
 			elseif(!empty($ConfigPW) && $auth_type == 'Config')
 			{
 				/* Returning after login to config */
-				if($ConfigPW == md5(stripslashes($GLOBALS['phpgw_domain'][$ConfigDomain]['config_passwd'])))
+				if($ConfigPW == md5($GLOBALS['phpgw']->crypto->decrypt($GLOBALS['phpgw_domain'][$ConfigDomain]['config_passwd'])))
 				{
 					setcookie('ConfigPW', $ConfigPW,  $expire);
 					setcookie('ConfigDomain', $ConfigDomain, $expire);
@@ -199,12 +196,18 @@
 			elseif(!empty($HeaderPW) && $auth_type == 'Header')
 			{
 				/* Returning after login to header admin */
-				if($HeaderPW == md5(stripslashes($GLOBALS['phpgw_info']['server']['header_admin_password'])))
+				if($HeaderPW == md5(@$GLOBALS['phpgw']->crypto->decrypt($GLOBALS['phpgw_info']['server']['header_admin_password'])))
 				{
 					setcookie('HeaderPW', $HeaderPW , $expire);
 					setcookie('ConfigLang', $ConfigLang, $expire);
 					return True;
 				}
+				else if($HeaderPW == md5(stripslashes($GLOBALS['phpgw_info']['server']['header_admin_password'])))
+				{
+					setcookie('HeaderPW', $HeaderPW , $expire);
+					setcookie('ConfigLang', $ConfigLang, $expire);
+					return True;
+				}
 				else
 				{
 					$GLOBALS['phpgw_info']['setup']['HeaderLoginMSG'] = lang('Invalid password');
@@ -218,47 +221,38 @@
 				$GLOBALS['phpgw_info']['setup']['ConfigLoginMSG'] = '';
 				return False;
 			}
-
-			return false;
 		}
 
-		function checkip($remoteip = '')
+		function checkip($remoteip='')
 		{
-			if ( !isset($GLOBALS['phpgw_info']['server']['setup_acl']) )
+			$allowed_ips = split(',',$GLOBALS['phpgw_info']['server']['setup_acl']);
+			if(is_array($allowed_ips))
 			{
-				return true;
-			}
-
-			$allowed_ips = split(',', $GLOBALS['phpgw_info']['server']['setup_acl']);
-			if(!is_array($allowed_ips))
+				$foundip = False;
+				while(list(,$value) = @each($allowed_ips))
 			{
-				return true;
-			}
-
-			foreach ( $allowed_ips as $value )
-			{
-				$test = explode('.', $value);
+					$test = split("\.",$value);
 				if(count($test) < 3)
 				{
-					$value .= '.0.0';
-					$tmp = explode('.', $remoteip);
+						$value .= ".0.0";
+						$tmp = split("\.",$remoteip);
 					$tmp[2] = 0;
 					$tmp[3] = 0;
-					$testremoteip = implode('.', $tmp);
+						$testremoteip = join('.',$tmp);
 				}
 				elseif(count($test) < 4)
 				{
-					$value .= '.0';
-					$tmp = explode('.', $remoteip);
+						$value .= ".0";
+						$tmp = split("\.",$remoteip);
 					$tmp[3] = 0;
-					$testremoteip = implode('.',$tmp);
+						$testremoteip = join('.',$tmp);
 				}
 				elseif(count($test) == 4 &&
 					intval($test[3]) == 0)
 				{
-					$tmp = explode('.', $remoteip);
+						$tmp = split("\.",$remoteip);
 					$tmp[3] = 0;
-					$testremoteip = implode('.', $tmp);
+						$testremoteip = join('.',$tmp);
 				}
 				else
 				{
@@ -267,16 +261,20 @@
 
 				//echo '<br>testing: ' . $testremoteip . ' compared to ' . $value;
 
-				if ( $testremoteip == $value )
+					if($testremoteip == $value)
 				{
 					//echo ' - PASSED!';
-					return true;
+						$foundip = True;
 				}
 			}
-
+				if(!$foundip)
+				{
 			$GLOBALS['phpgw_info']['setup']['HeaderLoginMSG'] = '';
 			$GLOBALS['phpgw_info']['setup']['ConfigLoginMSG'] = lang('Invalid IP address');
-			return false;
+					return False;
+				}
+			}
+			return True;
 		}
 
 		/**
@@ -307,7 +305,7 @@
 		{
 			$tables = Array();
 			$tablenames = $this->db->table_names();
-			foreach($tablenames as $val)
+			foreach($tablenames as $key => $val)
 			{
 				$tables[] = $val;
 			}
@@ -377,18 +375,13 @@
 					. intval($setup_info[$appname]['app_order']) . ", "
 					. "'$tables', "
 					. "'{$setup_info[$appname]['version']}')"
-					,__LINE__,__FILE__
+					,__LINE__,__FILE__, true
 				);
 				$this->clear_session_cache();
 			}
-
 			// hack to make phpgwapi_applications::name2id to work properly
 			unset($GLOBALS['phpgw_info']['apps']);
-			//XXX nov08 Caeies : add the run location, since if not you are killed ...
-			//XXX nov08 Caeies : be carefull for deregister_app :(
-			//XXX nov08 Caeies : Last but not least ... is this the place intended for this ???
-			$GLOBALS['phpgw']->locations->add('run', $appname, $appname);
-			return true;
+			$GLOBALS['phpgw']->locations->add('run', "Automatically added on install - run {$appname}", $appname, false);
 		}
 
 		/**
@@ -399,16 +392,16 @@
 		 */
 		function app_registered($appname)
 		{
+			$setup_info = $GLOBALS['setup_info'];
+
 			if(!$appname)
 			{
 				return False;
 			}
 
-			$debug = isset($GLOBALS['DEBUG']) && $GLOBALS['DEBUG'];
-
-			if ( $debug )
+			if ( isset($GLOBALS['DEBUG']) && $GLOBALS['DEBUG'] )
 			{
-				echo "<br>\napp_registered(): checking {$appname}";
+				echo '<br>app_registered(): checking ' . $appname . ', table: ' . $appstbl;
 				// _debug_array($setup_info[$appname]);
 			}
 
@@ -416,14 +409,13 @@
 			$this->db->next_record();
 			if($this->db->f(0))
 			{
-				if( $debug )
+				if(@$GLOBALS['DEBUG'])
 				{
 					echo '... app previously registered.';
 				}
 				return True;
 			}
-
-			if( $debug )
+			if(@$GLOBALS['DEBUG'])
 			{
 				echo '... app not registered';
 			}
@@ -442,7 +434,7 @@
 
 			if(!$appname)
 			{
-				return false;
+				return False;
 			}
 
 			if($this->alessthanb($setup_info['phpgwapi']['currentver'],'0.9.10pre8') && ($setup_info['phpgwapi']['currentver'] != ''))
@@ -464,7 +456,7 @@
 			$this->db->next_record();
 			if(!$this->db->f(0))
 			{
-				return false;
+				return False;
 			}
 
 			if($setup_info[$appname]['version'])
@@ -488,7 +480,6 @@
 
 				$this->db->query($sql,__LINE__,__FILE__);
 			}
-			return true;
 		}
 
 		/**
@@ -537,12 +528,11 @@
 				return false;
 			}
 			$appname = $this->db->db_addslashes($appname);
+			$setup_info =& $GLOBALS['setup_info'];
 
 			//echo 'DELETING application: ' . $appname;
 			$this->db->query("DELETE FROM phpgw_applications WHERE app_name='{$appname}'",__LINE__,__FILE__);
 			$this->clear_session_cache();
-
-			return true;
 		}
 
 		/**
@@ -585,19 +575,23 @@
 		 */
 		function deregister_hooks($appname)
 		{
+			if(isset($setup_info['phpgwapi']['currentver']) && $this->alessthanb($setup_info['phpgwapi']['currentver'],'0.9.8pre5'))
+			{
+				/* No phpgw_hooks table yet. */
+				return False;
+			}
+
 			if(!$appname)
 			{
-				return false;
+				return False;
 			}
 
 			//echo "DELETING hooks for: " . $setup_info[$appname]['name'];
 			if (!is_object($this->hooks))
 			{
-				$this->hooks = createObject('phpgwapi.hooks', $this->db);
+				$this->hooks = createObject('phpgwapi.hooks',$this->db);
 			}
 			$this->hooks->register_hooks($appname);
-
-			return true;
 		}
 
 		/**
@@ -792,6 +786,15 @@
 
 		function get_hooks_table_name()
 		{
+			
+			if ( isset($GLOBALS['setup_info']['phpgwapi']['currentver']) 
+				&& $this->alessthanb($GLOBALS['setup_info']['phpgwapi']['currentver'], '0.9.8pre5') 
+				&& ($GLOBALS['setup_info']['phpgwapi']['currentver'] != ''))
+			{
+				/* No phpgw_hooks table yet. */
+				return False;
+			}
 			return 'phpgw_hooks';
 		}
 }
+?>

Modified: people/sigurdne/modules/phpgwapi/trunk/inc/class.setup_detection.inc.php
===================================================================
--- people/sigurdne/modules/phpgwapi/trunk/inc/class.setup_detection.inc.php	2009-11-20 10:27:41 UTC (rev 20844)
+++ people/sigurdne/modules/phpgwapi/trunk/inc/class.setup_detection.inc.php	2009-11-20 10:28:10 UTC (rev 20845)
@@ -8,21 +8,6 @@
 	* @package phpgwapi
 	* @subpackage application
 	* @version $Id$
-	*/
-
-	/*
-	   This program is free software: you can redistribute it and/or modify
-	   it under the terms of the GNU General Public License as published by
-	   the Free Software Foundation, either version 3 of the License, or
-	   (at your option) any later version.
-
-	   This program is distributed in the hope that it will be useful,
-	   but WITHOUT ANY WARRANTY; without even the implied warranty of
-	   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-	   GNU General Public License for more details.
-
-	   You should have received a copy of the GNU General Public License
-	   along with this program.  If not, see <http://www.gnu.org/licenses/>.
 	 */
 
 	/**
@@ -43,7 +28,7 @@
 					$f = PHPGW_SERVER_ROOT . '/' . $entry . '/setup/setup.inc.php';
 					if ( file_exists($f) )
 					{
-						include($f);
+						require $f;
 						$setup_info[$entry]['filename'] = $f;
 					}
 				}

Modified: people/sigurdne/modules/phpgwapi/trunk/inc/class.setup_html.inc.php
===================================================================
--- people/sigurdne/modules/phpgwapi/trunk/inc/class.setup_html.inc.php	2009-11-20 10:27:41 UTC (rev 20844)
+++ people/sigurdne/modules/phpgwapi/trunk/inc/class.setup_html.inc.php	2009-11-20 10:28:10 UTC (rev 20845)
@@ -8,21 +8,6 @@
 	* @package phpgwapi
 	* @subpackage application
 	* @version $Id$
-	*/
-
-	/*
-	   This program is free software: you can redistribute it and/or modify
-	   it under the terms of the GNU General Public License as published by
-	   the Free Software Foundation, either version 3 of the License, or
-	   (at your option) any later version.
-
-	   This program is distributed in the hope that it will be useful,
-	   but WITHOUT ANY WARRANTY; without even the implied warranty of
-	   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-	   GNU General Public License for more details.
-
-	   You should have received a copy of the GNU General Public License
-	   along with this program.  If not, see <http://www.gnu.org/licenses/>.
 	 */
 
 	/**
@@ -50,7 +35,9 @@
 				$domains = array();
 			}
 
+			$setting = phpgw::get_var('setting', 'string', 'POST');
 			$settings = phpgw::get_var("settings", 'string', 'POST');
+
 			foreach($domains as $k => $v)
 			{
 				if(isset($deletedomain[$k]))
@@ -61,6 +48,10 @@
 				$GLOBALS['header_template']->set_var('DB_DOMAIN',$v);
 				foreach($dom as $x => $y)
 				{
+					if( $setting['enable_mcrypt'] == 'True' && ($x == 'db_pass' || $x == 'db_host' || $x == 'db_name' || $x == 'db_user' || $x == 'config_pass'))
+					{
+						$y = $GLOBALS['phpgw']->crypto->encrypt($y);
+					}
 					$GLOBALS['header_template']->set_var(strtoupper($x),$y);
 				}
 				$GLOBALS['header_template']->parse('domains','domain',True);
@@ -68,15 +59,19 @@
 
 			$GLOBALS['header_template']->set_var('domain','');
 
-			$setting = phpgw::get_var('setting', 'string', 'POST');
 			if(!empty($setting) && is_array($setting))
 			{
 				foreach($setting as $k => $v)
 				{
-					if ( $k == 'server_root' 
+					if ($setting['enable_mcrypt'] == 'True' && $k == 'HEADER_ADMIN_PASSWORD')
+					{
+						$v = $GLOBALS['phpgw']->crypto->encrypt($v);
+					}
+					
+					if( in_array( $k, array( 'server_root', 'include_root' ) )
 						&& substr(PHP_OS, 0, 3) == 'WIN' )
 					{
-						$v = preg_replace('/\\/', '/', $v);
+						$v = str_replace( '\\', '/', $v );
 					}
 					$var[strtoupper($k)] = $v;
 				}

Modified: people/sigurdne/modules/phpgwapi/trunk/inc/class.setup_process.inc.php
===================================================================
--- people/sigurdne/modules/phpgwapi/trunk/inc/class.setup_process.inc.php	2009-11-20 10:27:41 UTC (rev 20844)
+++ people/sigurdne/modules/phpgwapi/trunk/inc/class.setup_process.inc.php	2009-11-20 10:28:10 UTC (rev 20845)
@@ -1,32 +1,19 @@
 <?php
 	/**
-	 * phpGroupWare - Setup process
-	 *
+	* Setup process
 	 * @author Miles Lott <[email protected]>
-	 * @author Dave Hall <[email protected]>
-	 * @copyright Portions Copyright (C) 2004 - 2008 Free Software Foundation, Inc. http://www.fsf.org/
-	 * @license http://www.fsf.org/licenses/gpl.html GNU General Public License v3 or later
-	 * @package phpgroupware
-	 * @subpackage phpgwapi
-	 * @version $Id$
+	* @copyright Portions Copyright (C) 2004 Free Software Foundation, Inc. http://www.fsf.org/
+	* @license http://www.fsf.org/licenses/gpl.html GNU General Public License
+	* @package phpgwapi
+	* @subpackage application
+	* @version $Id$
 	 */
 
-	/*
-	   This program is free software: you can redistribute it and/or modify
-	   it under the terms of the GNU General Public License as published by
-	   the Free Software Foundation, either version 3 of the License, or
-	   (at your option) any later version.
-
-	   This program is distributed in the hope that it will be useful,
-	   but WITHOUT ANY WARRANTY; without even the implied warranty of
-	   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-	   GNU Lesser General Public License for more details.
-
-	   You should have received a copy of the GNU Lesser General Public License
-	   along with this program.  If not, see <http://www.gnu.org/licenses/>.
-	 */
-
-	/*
+	/**
+	* Setup process
+	* 
+	* @package phpgwapi
+	* @subpackage application
 	 * app status values:
 	 * U : Upgrade required/available
 	 * R : upgrade in pRogress
@@ -36,46 +23,39 @@
 	 * V : Version mismatch at end of upgrade (Not used, proposed only)
 	 * M : Missing files at start of upgrade (Not used, proposed only)
 	 */
-
-	/**
-	 * Setup process
-	 * 
-	 * @package phpgroupware
-	 * @subpackage phpgwapi
-	 */
-	class phpgwapi_setup_process
+	class setup_process
 	{
 		var $oProc;
 		var $tables;
 		var $updateincluded = array();
 		var $translation;
 
-		/**
-		 * Constructor
-		 *
-		 * @return void
-		 */
- 		public function __construct()
+ 		function setup_process()
 		{
-			$this->translation = &$GLOBALS['phpgw']->setup_translation;
+			$this->translation = createObject('phpgwapi.setup_translation');
 		}
 
 		/**
 		 * create schema_proc object
 		 *
-		 * @return void
+		 * @param none
 		 */
-		public function init_process()
+		function init_process()
 		{
-			$ConfigDomain = phpgw::get_var('ConfigDomain');
+			$ConfigDomain = phpgw::get_var('ConfigDomain','string', 'COOKIE');
 			$phpgw_domain = $GLOBALS['phpgw_domain'];
 
+			$_key = $GLOBALS['phpgw_info']['server']['setup_mcrypt_key'];
+			$_iv  = $GLOBALS['phpgw_info']['server']['mcrypt_iv'];
+			$crypto = createObject('phpgwapi.crypto',array($_key, $_iv));
+
+
 			$GLOBALS['phpgw_setup']->oProc = createObject('phpgwapi.schema_proc',$phpgw_domain[$ConfigDomain]['db_type']);
 			$GLOBALS['phpgw_setup']->oProc->m_odb           = $GLOBALS['phpgw_setup']->db;
-			$GLOBALS['phpgw_setup']->oProc->m_odb->Host     = $phpgw_domain[$ConfigDomain]['db_host'];
-			$GLOBALS['phpgw_setup']->oProc->m_odb->Database = $phpgw_domain[$ConfigDomain]['db_name'];
-			$GLOBALS['phpgw_setup']->oProc->m_odb->User     = $phpgw_domain[$ConfigDomain]['db_user'];
-			$GLOBALS['phpgw_setup']->oProc->m_odb->Password = $phpgw_domain[$ConfigDomain]['db_pass'];
+			$GLOBALS['phpgw_setup']->oProc->m_odb->Host     = $crypto->decrypt($phpgw_domain[$ConfigDomain]['db_host']);
+			$GLOBALS['phpgw_setup']->oProc->m_odb->Database = $crypto->decrypt($phpgw_domain[$ConfigDomain]['db_name']);
+			$GLOBALS['phpgw_setup']->oProc->m_odb->User     = $crypto->decrypt($phpgw_domain[$ConfigDomain]['db_user']);
+			$GLOBALS['phpgw_setup']->oProc->m_odb->Password = $crypto->decrypt($phpgw_domain[$ConfigDomain]['db_pass']);
 			$GLOBALS['phpgw_setup']->oProc->m_odb->Halt_On_Error = 'yes';
 			$GLOBALS['phpgw_setup']->oProc->m_odb->connect();
 		}
@@ -87,14 +67,12 @@
 		 * @param $type		optional, defaults to new(install), could also be 'upgrade'
 		 * @param $DEBUG		optional, print debugging info
 		 * @param $force_en	optional, install english language files
-		 *
-		 * @return array processed setup values
 		 */
-		public function pass($setup_info, $method = 'new', $DEBUG = false, $force_en = false)
+		function pass($setup_info, $method = 'new', $DEBUG = false, $force_en = false)
 		{
 			if(!$method)
 			{
-				return false;
+				return False;
 			}
 			$setup_info = $GLOBALS['phpgw_setup']->detection->get_versions($setup_info);
 			/* Check current versions and dependencies */
@@ -120,6 +98,7 @@
 				{
 					echo '<br>process->pass(): #' . $i . ' for ' . $method . ' processing' . "\n"; 
 				}
+				//if($i==2) { _debug_array($passed);exit; }
 
 				/* stuff the rest of the apps, but only those with available upgrades */
 				foreach($setup_info as $key => $value)
@@ -135,6 +114,13 @@
 							$pass[$value['name']] = $setup_info[$value['name']];
 						}
 					}
+					/*
+					Now if we are on the 2nd or more passes, add api in
+					if (!$pass['phpgwapi'])
+					{
+						$pass['phpgwapi'] = $setup_info['phpgwapi'];
+					}
+					*/
 				}
 
 				switch ($method)
@@ -153,7 +139,7 @@
 						break;
 					default:
 						/* What the heck are you doing? */
-						return false;
+						return False;
 						break;
 				}
 
@@ -213,18 +199,15 @@
 		/**
 		 * drop tables per application, check that they are in the db first
 		*
-		 * @param array $setup_info application info from setup.inc.php files, etc.
-		 * @param boolean $DEBUG enable debugging
-		 *
-		 * @return array processed setup_info values
+		 * @param $setup_info	array of application info from setup.inc.php files, etc.
 		 */
-		public function droptables($setup_info, $DEBUG = false)
+		function droptables($setup_info,$DEBUG=False)
 		{
 			if( !isset($GLOBALS['phpgw_setup']->oProc) || !$GLOBALS['phpgw_setup']->oProc )
 			{
 				$this->init_process();
 			}
-			$GLOBALS['phpgw_setup']->oProc->m_bDeltaOnly = false;
+			$GLOBALS['phpgw_setup']->oProc->m_bDeltaOnly = False;
 
 			/* The following is built so below we won't try to drop a table that isn't there. */
 			$tablenames = $GLOBALS['phpgw_setup']->db->table_names();
@@ -243,7 +226,7 @@
 				if ( isset($setup_info[$key]['tables'])
 					&& is_array($setup_info[$key]['tables']) )
 				{
-					// Tables has to be dropped in reversed order (mssql) if they are referenced by others
+					// Sigurd: Tables has to be dropped in reversed order (mssql) if they are referenced by others
 					foreach ( array_reverse($setup_info[$key]['tables']) as $table )
 					{
 						//echo $table;
@@ -266,17 +249,15 @@
 		 * process current table setup in each application/setup dir
 		 *
 		 * @param $appinfo	array of application info from setup.inc.php files, etc.
-		 * @param boolean $DEBUG enable debugging
-		 *
-		 * @return array processed setup_info values
+		 * This duplicates the old newtables behavior, using schema_proc
 		 */
-		public function current($setup_info, $DEBUG=false)
+		function current($setup_info, $DEBUG=False)
 		{
 			if( !isset($GLOBALS['phpgw_setup']->oProc) || !$GLOBALS['phpgw_setup']->oProc )
 			{
 				$this->init_process();
 			}
-			$GLOBALS['phpgw_setup']->oProc->m_bDeltaOnly = false;
+			$GLOBALS['phpgw_setup']->oProc->m_bDeltaOnly = False;
 
 			if ( !is_array($setup_info) )
 			{
@@ -284,7 +265,7 @@
 			}
 			foreach ( array_keys($setup_info) as $key )
 			{
-				$enabled = false;
+				$enabled = False;
 				$appname  = isset($setup_info[$key]['name']) ? $setup_info[$key]['name'] : '';
 				$apptitle = isset($setup_info[$key]['title']) ? $setup_info[$key]['title'] : '';
 
@@ -297,7 +278,7 @@
 					&& file_exists("{$appdir}tables_current.inc.php") )
 				{
 					if($DEBUG) { echo '<br>process->current(): Including: ' . $appdir.'tables_current.inc.php'; }
-					include_once("{$appdir}tables_current.inc.php");
+					require_once "{$appdir}tables_current.inc.php";
 					$ret = $this->post_process($phpgw_baseline,$DEBUG);
 					if($ret)
 					{
@@ -332,7 +313,7 @@
 					if ( isset($setup_info[$key]['tables'][0])
 						&& $setup_info[$key]['tables'][0] != '' )
 					{
-						$enabled = false;
+						$enabled = False;
 					}
 					if($GLOBALS['phpgw_setup']->app_registered($appname))
 					{
@@ -357,17 +338,14 @@
 		 * process default_records.inc.php in each application/setup dir
 		 *
 		 * @param $setup_info	array of application info from setup.inc.php files, etc.
-		 * @param boolean $DEBUG enable debugging
-		 *
-		 * @return array processed setup_info values
 		 */
-		public function default_records($setup_info,$DEBUG=false)
+		function default_records($setup_info,$DEBUG=False)
 		{
 			if( !isset($GLOBALS['phpgw_setup']->oProc) || !$GLOBALS['phpgw_setup']->oProc)
 			{
 				$this->init_process();
 			}
-			$GLOBALS['phpgw_setup']->oProc->m_bDeltaOnly = false;
+			$GLOBALS['phpgw_setup']->oProc->m_bDeltaOnly = False;
 
 			if ( !is_array($setup_info) )
 			{
@@ -386,10 +364,9 @@
 					{
 						echo '<br>process->default_records(): Including default records for ' . $appname . "\n";
 					}
-					$GLOBALS['phpgw_setup']->oProc->m_odb->transaction_begin();
+
 					$oProc = &$GLOBALS['phpgw_setup']->oProc;	// to be compatible with old apps
-					include_once($appdir.'default_records.inc.php');
-					$GLOBALS['phpgw_setup']->oProc->m_odb->transaction_commit();
+					require_once $appdir.'default_records.inc.php';
 				}
 				/* $setup_info[$key]['status'] = 'C'; */
 			}
@@ -402,12 +379,8 @@
 		 * process application lang files and uninstall
 		 *
 		 * @param $setup_info	array of application info from setup.inc.php files, etc.
-		 * @param boolean $DEBUG enable debugging
-		 * @param boolean $force_en force english to be loaded
-		 *
-		 * @return array processed setup_info values
 		 */
-		public function add_langs($setup_info, $DEBUG = false, $force_en = false)
+		function add_langs($setup_info, $DEBUG = false, $force_en = false)
 		{
 			foreach ( array_keys($setup_info) as $key )
 			{
@@ -426,11 +399,8 @@
 		 * process application lang files and install
 		 *
 		 * @param $setup_info	array of application info from setup.inc.php files, etc.
-		 * @param boolean $DEBUG enable debugging
-		 *
-		 * @return array processed setup_info values
 		 */
-		public function drop_langs($setup_info,$DEBUG=false)
+		function drop_langs($setup_info,$DEBUG=False)
 		{
 			@reset($setup_info);
 			while(list($key,$null) = @each($setup_info))
@@ -450,11 +420,8 @@
 		 * process application lang files and reinstall
 		 *
 		 * @param $setup_info	array of application info from setup.inc.php files, etc.
-		 * @param boolean $DEBUG enable debugging
-		 *
-		 * @return array processed setup_info values
 		 */
-		public function upgrade_langs($setup_info,$DEBUG=false)
+		function upgrade_langs($setup_info,$DEBUG=False)
 		{
 			@reset($setup_info);
 			while(list($key,$null) = @each($setup_info))
@@ -481,17 +448,14 @@
 		 *
 		 * This data should work with the baseline tables
 		 * @param $setup_info	array of application info from setup.inc.php files, etc.
-		 * @param boolean $DEBUG enable debugging
-		 *
-		 * @return array processed setup_info values
 		 */
-		public function test_data($setup_info,$DEBUG=false)
+		function test_data($setup_info,$DEBUG=False)
 		{
 			if( !isset($GLOBALS['phpgw_setup']->oProc) || !$GLOBALS['phpgw_setup']->oProc)
 			{
 				$this->init_process();
 			}
-			$GLOBALS['phpgw_setup']->oProc->m_bDeltaOnly = false;
+			$GLOBALS['phpgw_setup']->oProc->m_bDeltaOnly = False;
 
 			if ( !is_array($setup_info) )
 			{
@@ -509,7 +473,7 @@
 						echo '<br>process->test_data(): Including baseline test data for ' . $appname . "\n";
 					}
 					$GLOBALS['phpgw_setup']->oProc->m_odb->transaction_begin();
-					include_once($appdir.'test_data.inc.php');
+					require_once $appdir.'test_data.inc.php';
 					$GLOBALS['phpgw_setup']->oProc->m_odb->transaction_commit();
 				}
 			}
@@ -522,11 +486,8 @@
 		 * process baseline table setup in each application/setup dir
 		 *
 		 * @param $appinfo	array of application info from setup.inc.php files, etc.
-		 * @param boolean $DEBUG enable debugging
-		 *
-		 * @return array processed setup_info values
 		 */
-		public function baseline($setup_info,$DEBUG=false)
+		function baseline($setup_info,$DEBUG=False)
 		{
 			if ( !isset($GLOBALS['phpgw_setup']->oProc) || !$GLOBALS['phpgw_setup'] )
 			{
@@ -548,7 +509,7 @@
 					{
 						echo '<br>process->baseline(): Including baseline tables for ' . $appname . "\n";
 					}
-					include_once($appdir.'tables_baseline.inc.php');
+					require_once "{$appdir}tables_baseline.inc.php";
 					$GLOBALS['phpgw_setup']->oProc->GenerateScripts($phpgw_baseline, $DEBUG);
 					$this->post_process($phpgw_baseline,$DEBUG);
 
@@ -573,18 +534,15 @@
 		 * process available upgrades in each application/setup dir
 		 *
 		 * @param $appinfo	array of application info from setup.inc.php files, etc.
-		 * @param boolean $DEBUG enable debugging
-		 *
-		 * @return array processed setup_info values
 		 */
-		public function upgrade($setup_info, $DEBUG = false)
+		function upgrade($setup_info, $DEBUG = false)
 		{
 			if( !isset($GLOBALS['phpgw_setup']->oProc) || !$GLOBALS['phpgw_setup']->oProc )
 			{
 				$this->init_process();
 			}
 			$GLOBALS['phpgw_setup']->oProc->m_odb->HaltOnError = 'report';
-			$GLOBALS['phpgw_setup']->oProc->m_bDeltaOnly = true;
+			$GLOBALS['phpgw_setup']->oProc->m_bDeltaOnly = True;
 
 			if ( !is_array($setup_info) )
 			{
@@ -639,7 +597,7 @@
 						{
 							echo '<br>process->baseline(): Including baseline tables for ' . $appname . "\n";
 						}
-						include_once($appdir.'tables_baseline.inc.php');
+						require_once "{$appdir}tables_baseline.inc.php";
 						$GLOBALS['phpgw_setup']->oProc->m_aTables = $phpgw_baseline;
 						/* $GLOBALS['phpgw_setup']->oProc->GenerateScripts($phpgw_baseline, $DEBUG); */
 					}
@@ -653,9 +611,9 @@
 						break;
 						*/
 					}
-					if ( file_exists($appdir . 'tables_update.inc.php') )
+					if ( file_exists("{$appdir}tables_update.inc.php") )
 					{
-						include_once $appdir . 'tables_update.inc.php';
+						require_once("{$appdir}tables_update.inc.php");
 
 						if ( isset($test) && is_array($test) && count($test) )
 						{
@@ -664,8 +622,8 @@
 							{
 								$currentver = isset($setup_info[$key]['currentver']) ? $setup_info[$key]['currentver'] : '';
 
-								/* build upgrade public function name */
-								$function = $appname . '_upgrade' . preg_replace("/\./", '_', $value);
+								/* build upgrade function name */
+								$function = $appname . '_upgrade' . ereg_replace("\.", '_', $value);
 
 								if($DEBUG)
 								{
@@ -679,7 +637,7 @@
 
 								if($value == $targetver)
 								{
-									$GLOBALS['phpgw_setup']->oProc->m_bDeltaOnly = false;
+									$GLOBALS['phpgw_setup']->oProc->m_bDeltaOnly = False;
 									/* Done upgrading */
 									if($DEBUG)
 									{
@@ -703,9 +661,9 @@
 								elseif ( ($value == $currentver) || !$currentver)
 								{
 									/* start upgrading db in addition to bas eline */
-									$GLOBALS['phpgw_setup']->oProc->m_bDeltaOnly = false;
+									$GLOBALS['phpgw_setup']->oProc->m_bDeltaOnly = False;
 									if($DEBUG) { echo '<br>process->upgrade(): running ' . $function; }
-									/* run upgrade public function */
+									/* run upgrade function */
 									$success = $function();
 									if ( $success )
 									{
@@ -754,8 +712,8 @@
 								elseif ( $GLOBALS['phpgw_setup']->alessthanb($value, $currentver) )
 								{
 								/*
-									if($DEBUG) { echo '<br>process->upgrade(): running baseline delta only: ' . $public function . '...'; }
-									$GLOBALS['phpgw_setup']->oProc->m_bDeltaOnly = true;
+									if($DEBUG) { echo '<br>process->upgrade(): running baseline delta only: ' . $function . '...'; }
+									$GLOBALS['phpgw_setup']->oProc->m_bDeltaOnly = True;
 									$success = $function();
 								*/
 								}
@@ -821,18 +779,14 @@
 		}
 
 		/**
-		 * Create new tables in the database
+		 * commit above processing to the db
 		 *
-		 * @param array   $tables the tables to create
-		 * @param boolean $DEBUG enable debugging
-		 *
-		 * @return array processed setup_info values
 		 */
-		public function post_process($tables,$DEBUG=false)
+		function post_process($tables,$DEBUG=False)
 		{
 			if(!$tables)
 			{
-				return false;
+				return False;
 			}
 
 			$ret = $GLOBALS['phpgw_setup']->oProc->GenerateScripts($tables,$DEBUG);
@@ -841,31 +795,29 @@
 				$oret = $GLOBALS['phpgw_setup']->oProc->ExecuteScripts($tables,$DEBUG);
 				if($oret)
 				{
-					return true;
+					return True;
 				}
 				else
 				{
-					return false;
+					return False;
 				}
 			}
 			else
 			{
-				return false;
+				return False;
 			}
 		}
 
 		/**
 		 * send this a table name, returns printable column spec and keys for the table from schema_proc
 		 *
-		 * @param string $tablename name of table to fetch structure for
-		 *
-		 * @return array the table structure as an array
+		 * @param	$tablename	table whose array you want to see
 		 */
-		public function sql_to_array($tablename='')
+		function sql_to_array($tablename='')
 		{
 			if(!$tablename)
 			{
-				return false;
+				return False;
 			}
 
 			if(!$GLOBALS['phpgw_setup']->oProc)

Modified: people/sigurdne/modules/phpgwapi/trunk/inc/class.setup_translation.inc.php
===================================================================
--- people/sigurdne/modules/phpgwapi/trunk/inc/class.setup_translation.inc.php	2009-11-20 10:27:41 UTC (rev 20844)
+++ people/sigurdne/modules/phpgwapi/trunk/inc/class.setup_translation.inc.php	2009-11-20 10:28:10 UTC (rev 20845)
@@ -1,30 +1,13 @@
 <?php
 	/**
 	* Setup translation - Handles multi-language support using flat files
-	*
-	* @author Dave Hall <[email protected]>
 	* @author Miles Lott <[email protected]>
 	* @author Dan Kuykendall <[email protected]>
 	* @copyright Portions Copyright (C) 2001-2004 Free Software Foundation, Inc. http://www.fsf.org/
-	* @license http://www.fsf.org/licenses/lgpl.html GNU Lesser General Public License v3 or later
-	* @package phpgroupware
-	* @subpackage phpgwapi
+	* @license http://www.fsf.org/licenses/lgpl.html GNU Lesser General Public License
+	* @package phpgwapi
+	* @subpackage application
 	* @version $Id$
-	*/
-
-	/*
-	   This program is free software: you can redistribute it and/or modify
-	   it under the terms of the GNU Lesser General Public License as published by
-	   the Free Software Foundation, either version 3 of the License, or
-	   (at your option) any later version.
-
-	   This program is distributed in the hope that it will be useful,
-	   but WITHOUT ANY WARRANTY; without even the implied warranty of
-	   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-	   GNU General Public License for more details.
-
-	   You should have received a copy of the GNU Lesser General Public License
-	   along with this program.  If not, see <http://www.gnu.org/licenses/>.
 	 */
 
 	phpgw::import_class('phpgwapi.translation');
@@ -32,19 +15,17 @@
 	/**
 	* Setup translation - Handles multi-language support using flat files
 	*
-	* @package phpgroupware
-	* @subpackage phpgwapi
+	* @package phpgwapi
+	* @subpackage application
 	*/
 	class phpgwapi_setup_translation extends phpgwapi_translation
 	{
 		var $langarray;
 
 		/**
-		 * Constructor
+		 * constructor for the class, loads all phrases into langarray
 		 *
 		 * @param $lang	user lang variable (defaults to en)
-		 *
-		 * @return void
 		 */
 		public function __construct()
 		{
@@ -82,8 +63,6 @@
 		 *
 		 * @param $key  phrase to translate
 		 * @param $vars vars sent to lang function, passed to us
-		 *
-		 * @return string the translated string
 		 */
 		public function translate($key, $vars = array(), $only_common = false ) 
 		{
@@ -111,86 +90,77 @@
 			return $ret;
 		}
 
+		/* Following functions are called for app (un)install */
+
 		/**
-		 * Get a list of installed languages
+		 * return array of installed languages, e.g. array('de','en')
 		 *
-		 * @param bool $DEBUG enabled debugging?
-		 *
-		 * @return array list installed languages, e.g. array('de','en')
 		 */
-		public function get_langs($DEBUG=false)
+		function get_langs($DEBUG=False)
 		{
-			$langs = array();
-
-			if ( $DEBUG )
+			if($DEBUG)
 			{
 				echo '<br>get_langs(): checking db...' . "\n";
 			}
-
 			$GLOBALS['phpgw_setup']->db->query("SELECT DISTINCT(lang) FROM phpgw_lang",__LINE__,__FILE__);
+			$langs = array();
+
 			while($GLOBALS['phpgw_setup']->db->next_record())
 			{
-				if ( $DEBUG )
+				if($DEBUG)
 				{
 					echo '<br>get_langs(): found ' . $GLOBALS['phpgw_setup']->db->f(0);
 				}
-
 				$langs[] = $GLOBALS['phpgw_setup']->db->f(0);
 			}
-
 			return $langs;
 		}
 
 		/**
-		 * delete all lang entries for an application, return true if langs were found
+		 * delete all lang entries for an application, return True if langs were found
 		*
 		 * @param $appname app_name whose translations you want to delete
-		 *
-		 * @return bool was the language deleted?
 		 */
-		public function drop_langs($appname, $DEBUG = false)
+		function drop_langs($appname,$DEBUG=False)
 		{
 			if($DEBUG)
 			{
 				echo '<br>drop_langs(): Working on: ' . $appname;
 			}
-
 			$GLOBALS['phpgw_setup']->db->query("SELECT COUNT(message_id) FROM phpgw_lang WHERE app_name='$appname'",__LINE__,__FILE__);
 			$GLOBALS['phpgw_setup']->db->next_record();
-			if ( $GLOBALS['phpgw_setup']->db->f(0) )
+			if($GLOBALS['phpgw_setup']->db->f(0))
 			{
-				if ( function_exists('sem_get') )
+				if(function_exists('sem_get'))
 				{
 					$GLOBALS['phpgw_setup']->db->query("SELECT lang FROM phpgw_lang WHERE app_name='$appname'",__LINE__,__FILE__);
-					while ( $GLOBALS['phpgw_setup']->db->next_record() )
+					while ($GLOBALS['phpgw_setup']->db->next_record())
 					{
-						$GLOBALS['phpgw']->shm->delete_key('lang_' . $GLOBALS['phpgw_setup']->db->f('lang'));
+						$GLOBALS['phpgw']->cache->system_clear('phpgwapi', 'lang_' . $GLOBALS['phpgw_setup']->db->f('lang'));
 					}
 				}
 
 				$GLOBALS['phpgw_setup']->db->query("DELETE FROM phpgw_lang WHERE app_name='$appname'",__LINE__,__FILE__);
 
-				return true;
+				return True;
 			}
-			return false;
+			return False;
 		}
 
 		/**
 		 * process an application's lang files, calling get_langs() to see what langs the admin installed already
 		 *
 		 * @param $appname app_name of application to process
-		 *
-		 * @return void
 		 */
-		public function add_langs($appname, $DEBUG = false, $force_en = false)
+		function add_langs($appname,$DEBUG=False,$force_en=False)
 		{
 			$langs = $this->get_langs($DEBUG);
-			if ( $force_en && !in_array('en', $langs) )
+			if($force_en && !@in_array('en',$langs))
 			{
 				$langs[] = 'en';
 			}
 
-			if ( $DEBUG )
+			if($DEBUG)
 			{
 				echo '<br>add_langs(): chose these langs: ';
 				_debug_array($langs);
@@ -211,15 +181,13 @@
 				{
 					echo '<br>add_langs(): Working on: ' . $lang . ' for ' . $appname;
 				}
-
 				$appfile = PHPGW_SERVER_ROOT . "/{$appname}/setup/phpgw_{$lang}.lang";
-				if ( file_exists($appfile) )
+				if(file_exists($appfile))
 				{
-					if ( $DEBUG )
+					if($DEBUG)
 					{
 						echo '<br>add_langs(): Including: ' . $appfile;
 					}
-
 					$raw_file = $this->parse_lang_file($appfile, $lang);
 
 					foreach ( $raw_file as $line ) 
@@ -231,15 +199,14 @@
 
 						$GLOBALS['phpgw_setup']->db->query("SELECT COUNT(*) FROM phpgw_lang WHERE message_id='$message_id' and lang='{$lang}' ", __LINE__, __FILE__);
 						$GLOBALS['phpgw_setup']->db->next_record();
-						if ( $GLOBALS['phpgw_setup']->db->f(0) == 0 )
+						if ($GLOBALS['phpgw_setup']->db->f(0) == 0)
 						{
-							if ( $message_id && $content )
+							if($message_id && $content)
 							{
-								if ( $DEBUG )
+								if($DEBUG)
 								{
 									echo "<br>add_langs(): adding - INSERT INTO phpgw_lang VALUES ('{$message_id}','{$app_name}','{$lang}','{$content}')";
 								}
-
 								$GLOBALS['phpgw_setup']->db->query("INSERT INTO phpgw_lang VALUES ('{$message_id}','{$app_name}','{$lang}','{$content}')", __LINE__, __FILE__);
 							}
 						}

Modified: people/sigurdne/modules/phpgwapi/trunk/inc/class.shm.inc.php
===================================================================
--- people/sigurdne/modules/phpgwapi/trunk/inc/class.shm.inc.php	2009-11-20 10:27:41 UTC (rev 20844)
+++ people/sigurdne/modules/phpgwapi/trunk/inc/class.shm.inc.php	2009-11-20 10:28:10 UTC (rev 20845)
@@ -1,32 +1,4 @@
 <?php
-	/**
-	* phpGroupWare - shared memory handler
-	*
-	* @author Dave Hall <[email protected]>
-	* @author Adam Stevenson <adamstevenson@ _no_spam_  gmail.com>
-	* @author Sigurd Nes <[email protected]>
-	* @copyright Copyright (C) 2003-2008 Free Software Foundation, Inc. http://www.fsf.org/
-	* @license http://www.gnu.org/licenses/gpl.html GNU General Public License
-	* @package phpgwapi
-	* @subpackage application
- 	* @version $Id$
-	*/
-
-	/*
-	   This program is free software: you can redistribute it and/or modify
-	   it under the terms of the GNU General Public License as published by
-	   the Free Software Foundation, either version 3 of the License, or
-	   (at your option) any later version.
-
-	   This program is distributed in the hope that it will be useful,
-	   but WITHOUT ANY WARRANTY; without even the implied warranty of
-	   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-	   GNU General Public License for more details.
-
-	   You should have received a copy of the GNU General Public License
-	   along with this program.  If not, see <http://www.gnu.org/licenses/>.
-	 */
-
 /*
 			Release under the GNU public license
 			Copyright Adam Stevenson adamstevenson@ _no_spam_  gmail.com (www.adamstevenson.net)
@@ -82,6 +54,17 @@
 			For even more robust caching, check out http://www.danga.com/memcached/
 
 */
+	/**
+	* Handles shared memory
+	* @author Adam Stevenson <adamstevenson@ _no_spam_  gmail.com>
+	* @author Sigurd Nes <[email protected]>
+	* @copyright Copyright (C) 2003-2005 Free Software Foundation, Inc. http://www.fsf.org/
+	* @license http://www.gnu.org/licenses/gpl.html GNU General Public License
+	* @internal Development of this application was funded by http://www.bergen.kommune.no/bbb_/ekstern/
+	* @package phpgwapi
+	* @subpackage application
+ 	* @version $Id$
+	*/
 
 	//This makes sure there is something set for temp
 	if ( !isset($GLOBALS['phpgw_info']['server']['temp_dir'])  
@@ -475,6 +458,12 @@
 		*/
 		public static function is_enabled()
 		{
+			if ( isset($GLOBALS['phpgw_info']['server']['shm_enable'])  
+				&& $GLOBALS['phpgw_info']['server']['shm_enable'] )
+			{
 			return function_exists('sem_get') && function_exists('shmop_open');
 		}
+
+			return false;
+		}
 	}

Modified: people/sigurdne/modules/phpgwapi/trunk/inc/class.soap_client.inc.php
===================================================================
--- people/sigurdne/modules/phpgwapi/trunk/inc/class.soap_client.inc.php	2009-11-20 10:27:41 UTC (rev 20844)
+++ people/sigurdne/modules/phpgwapi/trunk/inc/class.soap_client.inc.php	2009-11-20 10:28:10 UTC (rev 20845)
@@ -1,26 +1,21 @@
 <?php
 	/**
-	 * phpGroupWare - SOAP
+	* phpGroupWare
 	 *
-	 * @link http://sourceforge.net/projects/nusoap/ This code is taken from the NuSOAP library
-	 *
-	 * @internal This file was automatically generated by the nusoap2phpgwapi.php 
-	 * script written.  Please see original header after this one and 
-	 * class.nusoap_base.inc.php for more information
-	 *
-	 * @author Caeies (conversion script) <[email protected]>
-	 * @copyright Portions Copyright (C) 2003-2008 Free Software Foundation, Inc. http://www.fsf.org/
-	 *
-	 * @package phpgwapi
+	* @author Sigurd Nes <[email protected]>
+	* @copyright Copyright (C) 2009 Free Software Foundation, Inc. http://www.fsf.org/
+	* @license http://www.gnu.org/licenses/gpl.html GNU General Public License
+	* @internal Development of this application was funded by http://www.bergen.kommune.no/bbb_/ekstern/
+	* @package phpgroupware
 	 * @subpackage communication
-	 *
-	 * @version $Id$
+	* @category core
+ 	* @version $Id$
 	 */
 
 	/*
  	   This program is free software: you can redistribute it and/or modify
-	   it under the terms of the GNU Lesser General Public License as published by
-	   the Free Software Foundation, either version 3 of the License, or
+	   it under the terms of the GNU General Public License as published by
+	   the Free Software Foundation, either version 2 of the License, or
 	   (at your option) any later version.
 
 	   This program is distributed in the hope that it will be useful,
@@ -28,115 +23,144 @@
 	   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 	   GNU General Public License for more details.
 
-	   You should have received a copy of the GNU Lesser General Public License
+	   You should have received a copy of the GNU General Public License
 	   along with this program.  If not, see <http://www.gnu.org/licenses/>.
 	 */
 
-			/*
-			 * Include dependency
-			 */
-			phpgw::import_class('phpgwapi.phpgwapi_soap_transport_http');
- /*
- * TOTALY DEPRECATED , DON'T USE
- */
 	/**
-	* SOAPx4 client
-	* @author Edd Dumbill <[email protected]>
-	* @author Victor Zou <[email protected]>
-	* @author Dietrich Ayala <[email protected]>
-	* @copyright Copyright (C) 1999-2000 Edd Dumbill
-	* @copyright Copyright (C) 2000-2001 Victor Zou
-	* @copyright Copyright (C) 2001 Dietrich Ayala
-	* @copyright Portions Copyright (C) 2003,2004 Free Software Foundation, Inc. http://www.fsf.org/
-	* @package phpgwapi
+	 * soap_client
+	 *
+	 * @package phpgroupware
 	* @subpackage communication
-	* @version $ I d: class.soap_client.inc.php,v 1.6.4.3 2004/02/10 13:51:19 ceb
-Exp $
-	* @internal This project began based on code from the 2 projects below,
-	* @internal and still contains some original code. The licenses of both must be respected.
-	* @internal XML-RPC for PHP; SOAP for PHP
+	 * @category core
 	*/
 
+	class phpgwapi_soap_client
+	{
 	/**
-	* SOAPx4 client
-	* @package phpgwapi
-	* @subpackage communication
-	* $path can be a complete endpoint url, with the other parameters left blank:
-	* $soap_client = new soap_client("http://path/to/soap/server");
-	* @deprecated : this is a wrapper to class.soap_transport_http.inc.php
+		* @var 
 	*/
+		var $phpgw_domain = 'default';
+		var	$wsdl = null;
+		var $uri = "urn://www.tempuri.testing/soap";
+		var $soap_version = SOAP_1_2;
+		var $trace	= 1;
+		var $login	= 'anonymous';
+		var $password = 'anonymous1';
+		var $encoding = 'UTF-8';
 
-class phpgwapi_soap_client extends phpgwapi_phpgwapi_soap_transport_http 
+		var $proxy_host;
+		var $proxy_port;
+		var $proxy_login;
+		var $proxy_password;
+		var $local_cert;
+		var $style; //   = SOAP_DOCUMENT;
+		var $use;   //   = SOAP_LITERAL;
+
+
+
+		/**
+		* Constructor
+		*
+		*/
+
+		function __construct($data = array(), $init = true)
 	{
-		 function phpgwapi_soap_client($path,$server=False,$port=False)
+
+			if(isset($data['phpgw_domain']) && $data['phpgw_domain'])
 		 {
-			$url = '';
-			/* We MUST Heavily test this !! */
-			/* Would be better if we "just" change class.interserver.inc.php */
-			if ( $server ) {
-				$url .= $server;
+				$this->phpgw_domain = $data['phpgw_domain'];
 			}
-			if ( $port ) {
-				$url .= ':'.$port;
+			if(isset($data['location']) && $data['location'])
+			{
+				$this->location = $data['location'];
 			}
-			$url .= $path;
-			/* Call our parent constructor */
-			$this->soap_transport_http($url);
+			else
+			{
+				$this->location = "http://{$_SERVER['HTTP_HOST']}" . parse_url($GLOBALS['phpgw_info']['server']['webserver_url'], PHP_URL_PATH) . "/soap.php?domain={$this->phpgw_domain}";
 		}
 
-		function send($msg, $action, $timeout=0, $ssl=False)
+			if(isset($data['wsdl']) && $data['wsdl'])
+			{
+				$this->wsdl = $data['wsdl'];
+			}
+			if(isset($data['uri']) && $data['uri'])
 		{
-			// where msg is an soapmsg
-			$msg->debug_flag = $this->debug_flag;
-			//$this->action = $action;
-			$this->setSOAPAction($action);
-			if($ssl)
+				$this->uri = $data['uri'];
+			}
+			if(isset($data['soap_version']) && $data['soap_version'])
 			{
-				return $this->ssl_sendPayloadHTTP10(
-					$msg,
-					$this->server,
-					$this->port,
-					$timeout,
-					$this->username,
-					$this->password
-				);
+				$this->soap_version = $data['soap_version'];
 			}
-			else
+			if(isset($data['trace']))
 			{
-				return $this->sendPayloadHTTP10(
-					$msg,
-					$this->server,
-					$this->port,
-					$timeout,
-					$this->username,
-					$this->password
-				);
+				$this->trace = $data['trace'];
 			}
+			if(isset($data['login']))
+			{
+				$this->login = $data['login'];
+			}
+			if(isset($data['password']))
+			{
+				$this->password = $data['password'];
 		}
 
-		function sendPayloadHTTP10($msg, $server, $port, $timeout=0, $username='', $password='')
+			if( $init )
 		{	
-			$this->scheme = 'http';
-			/* Add some specific headers */
-			$this->outgoing_headers['X-PHPGW-Server'] = $this->server; // ?? strange ...
-			$this->outgoing_headers['X-PHPGW-Version'] = $GLOBALS['phpgw_info']['server']['versions']['phpgwapi'] ;
-			if ( $username ) {
-				$this->setCredentials($username,$password);
+				$this->init();
 			}
-			return soap_transport_http::send($msg,$timeout);
 		}
 
-		function ssl_sendPayloadHTTP10($msg, $server, $port, $timeout=0,$username='', $password='')
+		function init()
 		{
-			$this->scheme = 'https';
-			/* Add some specific headers */
-			$this->outgoing_headers['X-PHPGW-Server'] = $this->server; // ?? strange ...
-			$this->outgoing_headers['X-PHPGW-Version'] = $GLOBALS['phpgw_info']['server']['versions']['phpgwapi'] ;
-			if ( $username ) {
-				$this->setCredentials($username,$password);
-			}
-			return soap_transport_http::send($msg,$timeout);
+			$this->client = new SoapClient($this->wsdl, array(
+				'location'			=> $this->location,
+				'uri'				=> $this->uri,
+				'soap_version'		=> $this->soap_version,
+				'trace'				=> $this->trace,
+				'login'				=> $this->login,
+				'password'			=> $this->password,
+				'encoding'			=> $this->encoding,
+				'proxy_host'		=> $this->proxy_host,
+				'proxy_port'		=> $this->proxy_port,
+				'proxy_login'		=> $this->proxy_login,
+				'proxy_password'	=> $this->proxy_password,
+				'local_cert'		=> $this->local_cert,
+				'style'				=> $this->style,
+				'use'				=> $this->use
+		 	));
 		}
 
-	} // end class soap_client
-?>
+		/**
+		* call the SOAP method, returns PHP native type
+		*
+		* Note: if the operation has multiple return values
+		* the return value of this method will be an array
+		* of those values.
+		*
+		* @param    string $function_name
+		* @param    array $arguments
+		* @return	mixed native PHP types.
+		* @access   public
+		*/
+		public function call($function_name, $arguments)
+		{
+			return $this->client->__soapCall($function_name, array($arguments));
+		}
+		public function getLastRequestHeaders()
+		{
+			return $this->client->__getLastRequestHeaders();
+		}
+		public function getLastRequest()
+		{
+			return $this->client->__getLastRequest();
+		}
+		public function getLastResponseHeaders()
+		{
+			return $this->client->__getLastResponseHeaders();
+		}
+		public function getLastResponse()
+		{
+			return $this->client->__getLastResponse();
+		}
+	}

Modified: people/sigurdne/modules/phpgwapi/trunk/inc/class.sql.inc.php
===================================================================
--- people/sigurdne/modules/phpgwapi/trunk/inc/class.sql.inc.php	2009-11-20 10:27:41 UTC (rev 20844)
+++ people/sigurdne/modules/phpgwapi/trunk/inc/class.sql.inc.php	2009-11-20 10:28:10 UTC (rev 20845)
@@ -13,21 +13,6 @@
 	* @link http://www.sogrp.com/
 	*/
 
-	/*
-	   This program is free software: you can redistribute it and/or modify
-	   it under the terms of the GNU General Public License as published by
-	   the Free Software Foundation, either version 3 of the License, or
-	   (at your option) any later version.
-
-	   This program is distributed in the hope that it will be useful,
-	   but WITHOUT ANY WARRANTY; without even the implied warranty of
-	   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-	   GNU General Public License for more details.
-
-	   You should have received a copy of the GNU General Public License
-	   along with this program.  If not, see <http://www.gnu.org/licenses/>.
-	 */
-
 	/**
 	* SQL entity name
 	*/

Modified: people/sigurdne/modules/phpgwapi/trunk/inc/class.sql_builder.inc.php
===================================================================
--- people/sigurdne/modules/phpgwapi/trunk/inc/class.sql_builder.inc.php	2009-11-20 10:27:41 UTC (rev 20844)
+++ people/sigurdne/modules/phpgwapi/trunk/inc/class.sql_builder.inc.php	2009-11-20 10:28:10 UTC (rev 20845)
@@ -13,21 +13,6 @@
 	* @link http://www.sogrp.com/
 	*/
 
-	/*
-	   This program is free software: you can redistribute it and/or modify
-	   it under the terms of the GNU General Public License as published by
-	   the Free Software Foundation, either version 3 of the License, or
-	   (at your option) any later version.
-
-	   This program is distributed in the hope that it will be useful,
-	   but WITHOUT ANY WARRANTY; without even the implied warranty of
-	   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-	   GNU General Public License for more details.
-
-	   You should have received a copy of the GNU General Public License
-	   along with this program.  If not, see <http://www.gnu.org/licenses/>.
-	 */
-
 	/**
 	* SQL Generator - helps to construct queries statements
 	*
@@ -701,7 +686,7 @@
 		* Recieve $data that is an array (operand_left, operand_right, operator)
 		* If operant_left is array I call... myself :), else try to get the field name.
 		* If right operand is array can myself to, else, nothing.
-		* Third operator IS_ a operator name that send to phpgwapi_sql::operate();
+		* Third operator IS_ a operator name that send to sql::operate();
 		* @param array $data Genertaded by calls of sql class.
 		* @param string $operation Is one of: insert, select, delete, update, if is diferent to select, then the result will not include the alias for table.
 		* @return Criteria for any sql query.
@@ -768,7 +753,7 @@
 		}
 
 		/**
-		* This is an optional criteria generator, powerfull because use phpgwapi_sql_criteria and sql_entity
+		* This is an optional criteria generator, powerfull because use sql_criteria and sql_entity
 		*/
 		function criteria_token($criteria, $operation='select')
 		{
@@ -1264,4 +1249,3 @@
 			echo $output;
 		}
 	}
-?>

Modified: people/sigurdne/modules/phpgwapi/trunk/inc/class.sql_criteria.inc.php
===================================================================
--- people/sigurdne/modules/phpgwapi/trunk/inc/class.sql_criteria.inc.php	2009-11-20 10:27:41 UTC (rev 20844)
+++ people/sigurdne/modules/phpgwapi/trunk/inc/class.sql_criteria.inc.php	2009-11-20 10:28:10 UTC (rev 20845)
@@ -13,21 +13,6 @@
 	* @link http://www.sogrp.com/
 	*/
 
-	/*
-	   This program is free software: you can redistribute it and/or modify
-	   it under the terms of the GNU General Public License as published by
-	   the Free Software Foundation, either version 3 of the License, or
-	   (at your option) any later version.
-
-	   This program is distributed in the hope that it will be useful,
-	   but WITHOUT ANY WARRANTY; without even the implied warranty of
-	   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-	   GNU General Public License for more details.
-
-	   You should have received a copy of the GNU General Public License
-	   along with this program.  If not, see <http://www.gnu.org/licenses/>.
-	 */
-
 	/**
 	* Include SQL class
 	*/
@@ -300,7 +285,7 @@
 		/**
 		* Generate a criteria stirng suitable for SQL queries, update and delete.
 		* 
-		* @param array $tokens array Multidimensional array created with calls to phpgwapi_sql_criteria class methods
+		* @param array $tokens array Multidimensional array created with calls to sql_criteria class methods
 		* @return string Return a criteria string based on tokens
 		*/
 		public static function criteria($tokens)

Modified: people/sigurdne/modules/phpgwapi/trunk/inc/class.sql_entity.inc.php
===================================================================
--- people/sigurdne/modules/phpgwapi/trunk/inc/class.sql_entity.inc.php	2009-11-20 10:27:41 UTC (rev 20844)
+++ people/sigurdne/modules/phpgwapi/trunk/inc/class.sql_entity.inc.php	2009-11-20 10:28:10 UTC (rev 20845)
@@ -13,21 +13,6 @@
 	* @link http://www.sogrp.com/
 	*/
 
-	/*
-	   This program is free software: you can redistribute it and/or modify
-	   it under the terms of the GNU General Public License as published by
-	   the Free Software Foundation, either version 3 of the License, or
-	   (at your option) any later version.
-
-	   This program is distributed in the hope that it will be useful,
-	   but WITHOUT ANY WARRANTY; without even the implied warranty of
-	   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-	   GNU General Public License for more details.
-
-	   You should have received a copy of the GNU General Public License
-	   along with this program.  If not, see <http://www.gnu.org/licenses/>.
-	 */
-
 	/**
 	* SQL entity alias substitution string EASS
 	*/
@@ -53,7 +38,6 @@
 	*/
 	define ('PHPGW_SQL_RETURN_SQL', 2);
 
-
 	/**
 	* SQL Generator ENTITY - helps to construct queries statements
 	*
@@ -85,7 +69,7 @@
 		var $ondebug;
 		var $table;
 
-		function phpgwapi_sql_entity()
+		function sql_entity()
 		{
 		}
 
@@ -399,9 +383,9 @@
 		/**
 		* Analize a criteria created by tokens and create a string that represent it, useful for any kind of operation that use criteria I guess.
 		* 
-		* @param $token_criteria array Array with all the criteria in tokens, generated with phpgwapi_sql_criteria
+		* @param $token_criteria array Array with all the criteria in tokens, generated with sql_criteria
 		* @return string Criteria string (All that goes in WHERE clause)
-		* @see phpgwapi_sql_criteria
+		* @see sql_criteria
 		*/
 
 		function entity_criteria($token_criteria)
@@ -697,8 +681,21 @@
 		*/
 		function set_update_data($element)
 		{
-			$value = ($element['value'] || $element['value'] == 0) ? $this->cast($element['value'], $element['field']) : phpgwapi_sql::null();
-			$this->values .= (($this->values)?', ':'').$element['real_field'].' = '.$value;
+			if ( $element['value'] || $element['value'] == 0 )
+			{
+				$value = $this->cast($element['value'], $element['field']);
+			}
+			else
+			{
+				phpgwapi_sql::null();
+			}
+
+			if ( $this->values )
+			{
+				$this->values .= ', ';
+			}
+
+			$this->values .= "{$element['real_field']} = {$value}";
 		}
 
 		/**
@@ -945,7 +942,7 @@
 				}
 			}
 			// this is an error :/ not $field in map
-			trigger_error("Unknown method for ${field}", E_USER_NOTICE);
+			trigger_error("Unknown method for {$field}", E_USER_NOTICE);
 			return;
 		}
 
@@ -964,7 +961,7 @@
 				}
 			}
 			// this is an error :/ not $field in map
-			trigger_error("Unknown real field for ${field}", E_USER_NOTICE);
+			trigger_error("Unknown real field for {$field}", E_USER_NOTICE);
 			return;
 		}
 
@@ -995,7 +992,7 @@
 				}
 			}
 			// this is an error :/ not $field in map
-			trigger_error("Unknown field ${field}", E_USER_NOTICE);
+			trigger_error("Unknown field {$field}", E_USER_NOTICE);
 			return;
 		}
 		
@@ -1026,6 +1023,7 @@
 									   $value));
 				$this->ldebug('add_criteria', array('Field' => $field));
 			}
+
 		}
 		function add_update($value, $field)
 		{
@@ -1062,7 +1060,7 @@
 		*/
 		function dont_exist($data)
 		{
-			trigger_error("Sorry, this data doesn't exist ${data}", E_USER_NOTICE);
+			trigger_error("Sorry, this data doesn't exist {$data}", E_USER_NOTICE);
 		}
 
 		/**
@@ -1129,4 +1127,3 @@
 			echo $output;
 		}
 	}
-?>

Added: people/sigurdne/modules/phpgwapi/trunk/inc/class.template_portico.inc.php
===================================================================
--- people/sigurdne/modules/phpgwapi/trunk/inc/class.template_portico.inc.php	                        (rev 0)
+++ people/sigurdne/modules/phpgwapi/trunk/inc/class.template_portico.inc.php	2009-11-20 10:28:10 UTC (rev 20845)
@@ -0,0 +1,126 @@
+<?php
+	/**
+	 * phpGroupWare portico template class
+	 *
+	 * @author Jan \xC5ge Johnsen <[email protected]>
+	 * @copyright Copyright (C) 2007-2008 Free Software Foundation, Inc. http://www.fsf.org/
+	 * @license http://www.fsf.org/licenses/lgpl.html GNU Lesser General Public License
+	 * @package phpgroupware
+	 * @subpackage phpgwapi
+	 * @category gui
+	 * @version $Id$
+	 */
+
+	/**
+	 * Allows you to store and retrive session variables under through php or
+	 * remote http JSON calls.
+	 *
+	 * @package phpgwapi
+	 * @subpackage gui
+	 * @category gui
+	 */
+
+	class phpgwapi_template_portico
+	{
+		public $public_functions = array
+		(
+			'store'			=> true,
+			'retrive'		=> true
+		);
+
+		/******************************************************************************
+		 * Stores JSON data through httpd request
+		 *
+		 * Returns HTTP header error code on failure or JSON data on success
+		 *
+		 * @param	location	request parameter (string) deciding where data should be stored
+		 * @param	data		request (string) JSON payload
+		 * @return	mixed		HTTP header error code on failure, JSON decoded payload on success
+		 * @access	public
+		 */
+		public function store()
+		{
+			$location = phpgw::get_var('location');
+			$data = phpgw::get_var('data', 'raw');
+
+			if( $location == '' )
+			{
+				header('HTTP/1.0 406 Not Acceptable');
+				return 'Missing location parameter';
+			}
+
+			$json = json_decode($data, true);
+
+			if( $json == null )
+			{
+				header('HTTP/1.0 406 Not Acceptable');
+				return 'Invalid JSON data parameter';
+			}
+
+			$GLOBALS['phpgw']->session->appsession("template_portico_$location", 'phpgwapi', $json);
+			return $json;
+		}
+
+		/******************************************************************************
+		 * Retrives stored data stored in session though httpd request
+		 *
+		 * Returns HTTP header error code on failure or stored data on success
+
+		 * @param	location	request parameter (string) deciding which data to return
+		 * @return	mixed		HTTP header error code on failure, stored data on success
+		 * @access	public
+		 */
+		public function retrieve()
+		{
+			$location = phpgw::get_var('location');
+
+			if( $location == '' )
+			{
+				header('HTTP/1.0 406 Not Acceptable');
+				return 'Missing location parameter';
+			}
+
+			$data = self::retrieve_local($location);
+
+			if ( $data == null )
+			{
+				header('HTTP/1.0 404 Not Found');
+				return 'No data found on that location';
+			}
+
+			return $data;
+		}
+
+		/******************************************************************************
+		 * Retrives and returns stored session variable from given location
+		 *
+		 * Returns string containing data on success, nothing on failure
+		 *
+		 * usage: retrive_local(string $location)
+		 *
+		 * @param	$location	string identifying location for data
+		 * @return	string		stored data on success, noting on failure
+		 * @access	public
+		 */
+		public static function retrieve_local($location)
+		{
+			return (array) $GLOBALS['phpgw']->session->appsession("template_portico_{$location}", 'phpgwapi');
+		}
+
+		/******************************************************************************
+		 * Stores session variable on given location
+		 *
+		 * Returns string containing data on success, nothing on failure
+ 		 *
+		 * usage: store_local(string $location, data)
+		 *
+		 * @param   $location	string identifying location for data
+		 * @param	$data		payload to store
+		 * @return	string		stored data on success, noting on failure
+		 * @access	public
+		 */
+		public static function store_local($location, $data)
+		{
+			$GLOBALS['phpgw']->session->appsession("template_portico_$location", 'phpgwapi', $data);
+		}
+	}


Property changes on: people/sigurdne/modules/phpgwapi/trunk/inc/class.template_portico.inc.php
___________________________________________________________________
Added: svn:keywords
   + Id Revision
Added: svn:eol-style
   + native

Modified: people/sigurdne/modules/phpgwapi/trunk/inc/class.translation.inc.php
===================================================================
--- people/sigurdne/modules/phpgwapi/trunk/inc/class.translation.inc.php	2009-11-20 10:27:41 UTC (rev 20844)
+++ people/sigurdne/modules/phpgwapi/trunk/inc/class.translation.inc.php	2009-11-20 10:28:10 UTC (rev 20845)
@@ -1,29 +1,15 @@
 <?php
 	/**
 	* Handles multi-language support
+	* @author Sigurd Nes <[email protected]>
 	* @author Dave Hall <[email protected]>
 	* @author Joseph Engo <[email protected]>
 	* @author Dan Kuykendall <[email protected]>
-	* @copyright Portions Copyright (C) 2000-2008 Free Software Foundation, Inc. http://www.fsf.org/
+	* @copyright Portions Copyright (C) 2000-2009 Free Software Foundation, Inc. http://www.fsf.org/
 	* @license http://www.fsf.org/licenses/lgpl.html GNU Lesser General Public License
 	* @package phpgwapi
 	* @subpackage application
 	* @version $Id$
-	*/
-
-	/*
-	   This program is free software: you can redistribute it and/or modify
-	   it under the terms of the GNU Lesser General Public License as published by
-	   the Free Software Foundation, either version 3 of the License, or
-	   (at your option) any later version.
-
-	   This program is distributed in the hope that it will be useful,
-	   but WITHOUT ANY WARRANTY; without even the implied warranty of
-	   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-	   GNU General Public License for more details.
-
-	   You should have received a copy of the GNU Lesser General Public License
-	   along with this program.  If not, see <http://www.gnu.org/licenses/>.
 	 */
 
 	/**
@@ -41,9 +27,9 @@
 		public $userlang = 'en';
 
 		/**
-		* @var bool $loaded_from_shm was the lang data loaded from shared memory?
+		* @var bool $lang_is_cached break off the function populate_cache
 		*/
-		private $loaded_from_shm;
+		public $lang_is_cached = false;
 
 		/**
 		* @var array $lang the translated strings - speeds look up
@@ -56,6 +42,11 @@
 		public $errors = array();
 
 		/**
+		* @var bool $collect_missing collects missing translations to the lang_table with app_name = ##currentapp##
+		*/
+		private $collect_missing = false;
+
+		/**
 		* Maxiumum length of a translation string
 		*/
 		const MAX_MESSAGE_ID_LENGTH = 230;
@@ -67,11 +58,19 @@
 		*/
 		public function __construct($reset = false)
 		{
-			if ( $GLOBALS['phpgw']->shm->is_enabled()
-				&& isset($GLOBALS['phpgw_info']['server']['shm_lang']) && $GLOBALS['phpgw_info']['server']['shm_lang'] )
+			$lang = 'en';
+			if ( isset($GLOBALS['phpgw_info']['user']['preferences']['common']['lang']) )
 			{
-				$this->set_userlang($GLOBALS['phpgw_info']['user']['preferences']['common']['lang']);
+				$lang = $GLOBALS['phpgw_info']['user']['preferences']['common']['lang'];
+			}
+
+			$this->set_userlang($lang);
 				$this->reset_lang($reset);
+
+			if ( isset($GLOBALS['phpgw_info']['server']['collect_missing_translations']) 
+				&& $GLOBALS['phpgw_info']['server']['collect_missing_translations'])
+			{
+				 $this->collect_missing = true;
 			}
 		}
 
@@ -80,17 +79,15 @@
 		*/
 		protected function reset_lang()
 		{
-			$this->loaded_from_shm = false;
-			if ( $GLOBALS['phpgw']->shm->is_enabled() 
-				&& $this->lang = $GLOBALS['phpgw']->shm->get_value("lang_{$this->userlang}") )
+			$lang = $GLOBALS['phpgw']->cache->system_get('phpgwapi', "lang_{$this->userlang}", true);
+			if ( is_array($lang) )
 			{
-				$this->loaded_from_shm = true;
+				$this->lang = $lang;
+				$this->lang_is_cached = true;
+				return;
 			}
-			else
-			{
 				$this->lang = array();
 			}
-		}
 
 		/**
 		* Set the user's selected language
@@ -151,13 +148,17 @@
 		/**
 		* Populate shared memory with the available translation strings
 		*/
-		public function populate_shm()
+		public function populate_cache()
 		{
-			$sql = "SELECT * from phpgw_lang ORDER BY app_name desc";
+			if($this->lang_is_cached)
+			{
+				return;
+			}
+			$sql = "SELECT * from phpgw_lang ORDER BY app_name DESC";
 			$GLOBALS['phpgw']->db->query($sql,__LINE__,__FILE__);
 			while ($GLOBALS['phpgw']->db->next_record())
 			{
-				$lang_set[$GLOBALS['phpgw']->db->f('lang')][$GLOBALS['phpgw']->db->f('message_id', true)] = $GLOBALS['phpgw']->db->f('content', true);
+				$lang_set[$GLOBALS['phpgw']->db->f('lang')][$GLOBALS['phpgw']->db->f('app_name')][$GLOBALS['phpgw']->db->f('message_id', true)] = $GLOBALS['phpgw']->db->f('content', true);
 			}
 
 			$language = array_keys($lang_set);
@@ -165,7 +166,7 @@
 			{
 				foreach($language as $lang)
 				{
-					$GLOBALS['phpgw']->shm->store_value("lang_{$lang}", $lang_set[$lang]);
+					$GLOBALS['phpgw']->cache->system_set('phpgwapi', "lang_{$lang}", $lang_set[$lang], true);
 				}
 			}
 		}
@@ -178,48 +179,71 @@
 		* @param bool $only_common only use the "common" translation, should be used when calling this from non module contexts
 		* @return string the translated string - when unable to be translated, the string is returned as "!$key"
 		*/
-		public function translate($key, $vars = array(), $only_common = false )
+		public function translate($key, $vars = array(), $only_common = false , $force_app = '')
 		{
-			$ret = $key;
 			if ( !$userlang = $this->userlang )
 			{
 				$userlang = 'en';
 			}
 
+			$app_name = $force_app ? $GLOBALS['phpgw']->db->db_addslashes($force_app) : $GLOBALS['phpgw_info']['flags']['currentapp'];
 			$lookup_key = strtolower(trim(substr($key, 0, self::MAX_MESSAGE_ID_LENGTH)));
 
 			if ( !is_array($this->lang) 
-				|| (!isset($this->lang[$lookup_key]) && !$this->loaded_from_shm) )
+				|| (!isset($this->lang[$app_name][$lookup_key])
+				&& !isset($this->lang['common'][$lookup_key])) )
 			{
-				$applist = "'common', 'all'";
-				$order = ' ORDER BY app_name ASC';
+				$applist = "'common'";
 				if ( !$only_common )
 				{
-					$applist .= ", '{$GLOBALS['phpgw_info']['flags']['currentapp']}'";
-					if ( strcasecmp($GLOBALS['phpgw_info']['flags']['currentapp'], 'common') <= 1 )
-					{
-						$order = 'ORDER BY app_name DESC';
-					}
+					$applist .= ", '{$app_name}'";
 				}
 
- 				$sql = 'SELECT message_id, content'
+ 				$sql = 'SELECT message_id, content, app_name'
 					. " FROM phpgw_lang WHERE lang = '{$userlang}' AND message_id = '" . $GLOBALS['phpgw']->db->db_addslashes($lookup_key) . '\''
-					. " AND app_name IN({$applist}) {$order}";
+					. " AND app_name IN({$applist})";
 
+//			$bt = debug_backtrace();
+//			echo "<b>translation::{$bt[1]['function']} Called from file: {$bt[1]['file']} line: {$bt[1]['line']}</b><br/>";
+//			_debug_array($sql);
+//			unset($bt);
+
+
 				$GLOBALS['phpgw']->db->query($sql,__LINE__,__FILE__);
 				while ($GLOBALS['phpgw']->db->next_record())
 				{
-					$this->lang[$lookup_key] = $GLOBALS['phpgw']->db->f('content', true);
+					$this->lang[$GLOBALS['phpgw']->db->f('app_name')][$lookup_key] = $GLOBALS['phpgw']->db->f('content', true);
 				}
+
 			}
+
 			$ret = "!{$key}";	// save key if we dont find a translation
 			$key = $lookup_key;
 
-			if ( isset($this->lang[$key]) )
+			if ( isset($this->lang[$app_name][$key]) )
 			{
-				$ret = $this->lang[$key];
+				$ret = $this->lang[$app_name][$key];
 			}
+			else if ( isset($this->lang['common'][$key]) )
+			{
+				$ret = $this->lang['common'][$key];
+			}
+			else if ($this->collect_missing)
+			{
+				$lookup_key = $GLOBALS['phpgw']->db->db_addslashes($lookup_key);
+				$sql = "SELECT message_id FROM phpgw_lang WHERE lang = '{$userlang}' AND message_id = '{$lookup_key}'"
+					. " AND app_name = '##{$app_name}##'";
+				
+				$GLOBALS['phpgw']->db->query($sql,__LINE__,__FILE__);
+
+				if( !$GLOBALS['phpgw']->db->next_record() )
+			{
+					$GLOBALS['phpgw']->db->query("INSERT INTO phpgw_lang (message_id,app_name,lang,content) VALUES('{$lookup_key}','##{$GLOBALS['phpgw_info']['flags']['currentapp']}##','$userlang','missing')",__LINE__,__FILE__);
+				}
+			}
+
 			$ndx = 1;
+
 			foreach ( $vars as $key => $val )
 			{
 				$ret = preg_replace( "/%$ndx/", $val, $ret );
@@ -246,11 +270,11 @@
 				$userlang = $GLOBALS['phpgw_info']['user']['preferences']['common']['lang'];
 			}
 
-			$sql = "SELECT message_id,content FROM phpgw_lang WHERE lang like '{$userlang}' AND app_name like '{$app}'";
+			$sql = "SELECT message_id,content FROM phpgw_lang WHERE lang = '{$userlang}' AND app_name = '{$app}'";
 			$GLOBALS['phpgw']->db->query($sql,__LINE__,__FILE__);
 			while ( $GLOBALS['phpgw']->db->next_record() )
 			{
-				$this->lang[strtolower(trim(substr($GLOBALS['phpgw']->db->f('message_id', true), 0, self::MAX_MESSAGE_ID_LENGTH)))] = $GLOBALS['phpgw']->db->f('content', true);
+				$this->lang[$app][strtolower(trim(substr($GLOBALS['phpgw']->db->f('message_id', true), 0, self::MAX_MESSAGE_ID_LENGTH)))] = $GLOBALS['phpgw']->db->f('content', true);
 			}
 		}
 
@@ -301,6 +325,10 @@
 			
 			if (count($lang_selected))
 			{
+				$GLOBALS['phpgw']->db->query("SELECT config_value FROM phpgw_config WHERE config_app='phpgwapi' AND config_name='install_id'",__LINE__,__FILE__);
+				$GLOBALS['phpgw']->db->next_record();
+				$GLOBALS['phpgw_info']['server']['install_id'] = $GLOBALS['phpgw']->db->f('config_value', true);
+
 				if ($upgrademethod == 'dumpold')
 				{
 					// dont delete the custom main- & loginscreen messages every time
@@ -319,10 +347,7 @@
 					}
 
 					//echo '<br />Working on: ' . $lang;
-					if ( $GLOBALS['phpgw']->shm->is_enabled() )
-					{
-						$GLOBALS['phpgw']->shm->delete_key('lang_' . $lang);
-					}
+					$GLOBALS['phpgw']->cache->system_clear('phpgwapi', "lang_{$lang}");
 
 					if ($upgrademethod == 'addonlynew')
 					{
@@ -366,6 +391,28 @@
 							
 							$raw[$app_name][$message_id] = $content;
 						}
+						
+						// Override with localised translations
+						
+						$ConfigDomain = phpgw::get_var('ConfigDomain');
+						$appfile_override = PHPGW_SERVER_ROOT . "/{$app}/setup/{$ConfigDomain}/phpgw_{$lang}.lang";
+
+						if ( is_file($appfile_override) )
+						{
+							$lines = $this->parse_lang_file($appfile_override, $lang);
+							if ( count($lines) )
+							{
+								foreach ( $lines as $line )
+								{
+									$message_id = $GLOBALS['phpgw']->db->db_addslashes(strtolower(trim(substr($line['message_id'], 0, self::MAX_MESSAGE_ID_LENGTH))));
+									$app_name = $GLOBALS['phpgw']->db->db_addslashes(trim($line['app_name']));
+									$content = $GLOBALS['phpgw']->db->db_addslashes(trim($line['content']));
+
+									$raw[$app_name][$message_id] = $content;
+								}
+							}
+						}
+
 						$GLOBALS['phpgw_info']['server']['lang_ctimes'][$lang][$app['name']] = filectime($appfile);
 					}
 

Modified: people/sigurdne/modules/phpgwapi/trunk/inc/class.ui_tools.inc.php
===================================================================
--- people/sigurdne/modules/phpgwapi/trunk/inc/class.ui_tools.inc.php	2009-11-20 10:27:41 UTC (rev 20844)
+++ people/sigurdne/modules/phpgwapi/trunk/inc/class.ui_tools.inc.php	2009-11-20 10:28:10 UTC (rev 20845)
@@ -190,3 +190,4 @@
 		return $elm;
 	}
 }
+?>

Modified: people/sigurdne/modules/phpgwapi/trunk/inc/class.uijsaddressbook.inc.php
===================================================================
--- people/sigurdne/modules/phpgwapi/trunk/inc/class.uijsaddressbook.inc.php	2009-11-20 10:27:41 UTC (rev 20844)
+++ people/sigurdne/modules/phpgwapi/trunk/inc/class.uijsaddressbook.inc.php	2009-11-20 10:28:10 UTC (rev 20845)
@@ -13,21 +13,6 @@
 	* @internal Inherited some code from the addressbook.php file
 	*/
 
-	/*
-	   This program is free software: you can redistribute it and/or modify
-	   it under the terms of the GNU General Public License as published by
-	   the Free Software Foundation, either version 3 of the License, or
-	   (at your option) any later version.
-
-	   This program is distributed in the hope that it will be useful,
-	   but WITHOUT ANY WARRANTY; without even the implied warranty of
-	   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-	   GNU General Public License for more details.
-
-	   You should have received a copy of the GNU General Public License
-	   along with this program.  If not, see <http://www.gnu.org/licenses/>.
-	 */
-
 	/**
 	* Addressbook Chooser
 	* 
@@ -64,7 +49,7 @@
 	* the main frame its data is here by sending a call by the onLoad event (which is
 	* called just after we finish passing our data.
 	*/
-	class uijsaddressbook
+	class phpgwapi_uijsaddressbook
 	{
 		var $public_functions=array ('show' => True,
 						 'show_mainframe' => True,

Modified: people/sigurdne/modules/phpgwapi/trunk/inc/class.utilities.inc.php
===================================================================
--- people/sigurdne/modules/phpgwapi/trunk/inc/class.utilities.inc.php	2009-11-20 10:27:41 UTC (rev 20844)
+++ people/sigurdne/modules/phpgwapi/trunk/inc/class.utilities.inc.php	2009-11-20 10:28:10 UTC (rev 20845)
@@ -9,21 +9,15 @@
 	* @version $Id$
 	*/
 
-	/*
-	   This program is free software: you can redistribute it and/or modify
-	   it under the terms of the GNU Lesser General Public License as published by
-	   the Free Software Foundation, either version 3 of the License, or
-	   (at your option) any later version.
+	$d1 = strtolower(substr(PHPGW_API_INC,0,3));
+	if($d1 == 'htt' || $d1 == 'ftp')
+	{
+		echo 'Failed attempt to break in via an old Security Hole!<br>' . "\n";
+		exit;
+	}
+	unset($d1);
 
-	   This program is distributed in the hope that it will be useful,
-	   but WITHOUT ANY WARRANTY; without even the implied warranty of
-	   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-	   GNU General Public License for more details.
 
-	   You should have received a copy of the GNU Lesser General Public License
-	   along with this program.  If not, see <http://www.gnu.org/licenses/>.
-	 */
-
 	/**
 	* This simply loads up additional utility libraries
 	* 
@@ -49,3 +43,4 @@
 			$GLOBALS['phpgw']->sbox = createObject('phpgwapi.portalbox');
 		}
 	}
+?>

Modified: people/sigurdne/modules/phpgwapi/trunk/inc/class.validator.inc.php
===================================================================
--- people/sigurdne/modules/phpgwapi/trunk/inc/class.validator.inc.php	2009-11-20 10:27:41 UTC (rev 20844)
+++ people/sigurdne/modules/phpgwapi/trunk/inc/class.validator.inc.php	2009-11-20 10:28:10 UTC (rev 20845)
@@ -9,21 +9,6 @@
 	* @package phpgwapi
 	* @subpackage utilities
 	* @version $Id$
-	*/
-
-	/*
-	   This program is free software: you can redistribute it and/or modify
-	   it under the terms of the GNU General Public License as published by
-	   the Free Software Foundation, either version 3 of the License, or
-	   (at your option) any later version.
-
-	   This program is distributed in the hope that it will be useful,
-	   but WITHOUT ANY WARRANTY; without even the implied warranty of
-	   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-	   GNU General Public License for more details.
-
-	   You should have received a copy of the GNU General Public License
-	   along with this program.  If not, see <http://www.gnu.org/licenses/>.
 	 */
 
 	/**

Modified: people/sigurdne/modules/phpgwapi/trunk/inc/class.vcard.inc.php
===================================================================
--- people/sigurdne/modules/phpgwapi/trunk/inc/class.vcard.inc.php	2009-11-20 10:27:41 UTC (rev 20844)
+++ people/sigurdne/modules/phpgwapi/trunk/inc/class.vcard.inc.php	2009-11-20 10:28:10 UTC (rev 20845)
@@ -8,21 +8,6 @@
 	* @package phpgwapi
 	* @subpackage network
 	* @version $Id$
-	*/
-
-	/*
-	   This program is free software: you can redistribute it and/or modify
-	   it under the terms of the GNU Lesser General Public License as published by
-	   the Free Software Foundation, either version 3 of the License, or
-	   (at your option) any later version.
-
-	   This program is distributed in the hope that it will be useful,
-	   but WITHOUT ANY WARRANTY; without even the implied warranty of
-	   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-	   GNU General Public License for more details.
-
-	   You should have received a copy of the GNU Lesser General Public License
-	   along with this program.  If not, see <http://www.gnu.org/licenses/>.
 	 */
 
 	/**

Modified: people/sigurdne/modules/phpgwapi/trunk/inc/class.vfs.inc.php
===================================================================
--- people/sigurdne/modules/phpgwapi/trunk/inc/class.vfs.inc.php	2009-11-20 10:27:41 UTC (rev 20844)
+++ people/sigurdne/modules/phpgwapi/trunk/inc/class.vfs.inc.php	2009-11-20 10:28:10 UTC (rev 20845)
@@ -6,21 +6,6 @@
 	* @package phpgwapi
 	* @subpackage vfs
 	* @version $Id$
-	*/
-
-	/*
-	   This program is free software: you can redistribute it and/or modify
-	   it under the terms of the GNU Lesser General Public License as published by
-	   the Free Software Foundation, either version 3 of the License, or
-	   (at your option) any later version.
-
-	   This program is distributed in the hope that it will be useful,
-	   but WITHOUT ANY WARRANTY; without even the implied warranty of
-	   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-	   GNU General Public License for more details.
-
-	   You should have received a copy of the GNU Lesser General Public License
-	   along with this program.  If not, see <http://www.gnu.org/licenses/>.
 	 */
 
 	if ( !isset($GLOBALS['phpgw_info']['server']['file_repository']) 

Modified: people/sigurdne/modules/phpgwapi/trunk/inc/class.vfs_dav.inc.php
===================================================================
--- people/sigurdne/modules/phpgwapi/trunk/inc/class.vfs_dav.inc.php	2009-11-20 10:27:41 UTC (rev 20844)
+++ people/sigurdne/modules/phpgwapi/trunk/inc/class.vfs_dav.inc.php	2009-11-20 10:28:10 UTC (rev 20845)
@@ -8,21 +8,6 @@
 	* @package phpgwapi
 	* @subpackage vfs
 	* @version $Id$
-	*/
-
-	/*
-	   This program is free software: you can redistribute it and/or modify
-	   it under the terms of the GNU Lesser General Public License as published by
-	   the Free Software Foundation, either version 3 of the License, or
-	   (at your option) any later version.
-
-	   This program is distributed in the hope that it will be useful,
-	   but WITHOUT ANY WARRANTY; without even the implied warranty of
-	   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-	   GNU General Public License for more details.
-
-	   You should have received a copy of the GNU Lesser General Public License
-	   along with this program.  If not, see <http://www.gnu.org/licenses/>.
 	 */
 
 	/**
@@ -118,10 +103,25 @@
 			{
 				$use_svn = true;
 				//so the 's' is kept
+
 				$this->basedir = preg_replace('/^svn/', 'http', $this->basedir);
+
 			}
+			
+			if(!$this->dav_user)
+			{
 			$this->dav_user = isset($GLOBALS['phpgw_info']['user']['userid']) ? (string) $GLOBALS['phpgw_info']['user']['userid'] : '';
+			}
+			//FIXME pwd has to be clear text.
+			if(!$this->dav_pwd)
+			{
 			$this->dav_pwd = isset($GLOBALS['phpgw_info']['user']['passwd']) ? (string) $GLOBALS['phpgw_info']['user']['passwd'] : '';
+			}
+			// For testing purpose:
+//			$this->dav_user = 'www-data';
+//			$this->dav_pwd = 'xxxxxx';
+
+
 			$parsed_url = parse_url($this->basedir);
 			$this->dav_host = $parsed_url['host'];
 			$this->dav_port = isset($parsed_url['port']) ? $parsed_url['port'] : '';
@@ -505,7 +505,7 @@
 				reset ($memberships);
 				while (list ($num, $group_array) = each ($memberships))
 				{
-					if ($owner_id == $group_array['account_id'])
+					if ($owner_id == $group_array->id)
 					{
 						$group_ok = 1;
 						break;
@@ -524,7 +524,7 @@
 				reset ($memberships);
 				while (list ($num, $group_array) = each ($memberships))
 				{
-					$rights |= $acl->get_rights ($group_array['account_id']);
+					$rights |= $acl->get_rights ($group_array->id);
 				}
 			}
 
@@ -816,7 +816,9 @@
 			{
 				$parsed_url['pwd'] = $this->dav_pwd;
 			}
+
 			$location = $this->glue_url($parsed_url);
+
 			header( 'Location: '.$location, true);
 			$GLOBALS['phpgw']->common->phpgw_exit();
 		}
@@ -1699,20 +1701,17 @@
 			}
 			if (isset($data['attributes']['owner_id']) && $id=$data['attributes']['owner_id'])
 			{
-				$GLOBALS['phpgw']->accounts->get_account_name($id,$lid,$fname,$lname);
-				$dav_properties['dc:publisher'] = $fname .' '. $lname;
+				$dav_properties['dc:publisher'] = (string) $GLOBALS['phpgw']->accounts->get($id);
 				$dav_properties['publisher_id'] = $id;
 			}
 			if (isset($data['attributes']['createdby_id']) && $id=$data['attributes']['createdby_id'])
 			{
-				$GLOBALS['phpgw']->accounts->get_account_name($id,$lid,$fname,$lname);
-				$dav_properties['dc:creator'] = $fname .' '. $lname;
+				$dav_properties['dc:creator'] = (string) $GLOBALS['phpgw']->accounts->get($id);
 				$dav_properties['creator_id'] = $id;
 			}
 			if (isset($data['attributes']['modifiedby_id']) && $id=$data['attributes']['modifiedby_id'])
 			{
-				$GLOBALS['phpgw']->accounts->get_account_name($id,$lid,$fname,$lname);
-				$dav_properties['dc:contributor'] = $fname .' '. $lname;
+				$dav_properties['dc:contributor'] = (string) $GLOBALS['phpgw']->accounts->get($id);
 				$dav_properties['contributor_id'] = $id;
 			}
 			if (isset($data['attributes']['app']) && $id=$data['attributes']['app'])

Modified: people/sigurdne/modules/phpgwapi/trunk/inc/class.vfs_shared.inc.php
===================================================================
--- people/sigurdne/modules/phpgwapi/trunk/inc/class.vfs_shared.inc.php	2009-11-20 10:27:41 UTC (rev 20844)
+++ people/sigurdne/modules/phpgwapi/trunk/inc/class.vfs_shared.inc.php	2009-11-20 10:28:10 UTC (rev 20845)
@@ -9,21 +9,6 @@
 	* @package phpgwapi
 	* @subpackage vfs
 	* @version $Id$
-	*/
-
-	/*
-	   This program is free software: you can redistribute it and/or modify
-	   it under the terms of the GNU Lesser General Public License as published by
-	   the Free Software Foundation, either version 3 of the License, or
-	   (at your option) any later version.
-
-	   This program is distributed in the hope that it will be useful,
-	   but WITHOUT ANY WARRANTY; without even the implied warranty of
-	   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-	   GNU General Public License for more details.
-
-	   You should have received a copy of the GNU Lesser General Public License
-	   along with this program.  If not, see <http://www.gnu.org/licenses/>.
 	 */
 
 	/**

Modified: people/sigurdne/modules/phpgwapi/trunk/inc/class.vfs_sql.inc.php
===================================================================
--- people/sigurdne/modules/phpgwapi/trunk/inc/class.vfs_sql.inc.php	2009-11-20 10:27:41 UTC (rev 20844)
+++ people/sigurdne/modules/phpgwapi/trunk/inc/class.vfs_sql.inc.php	2009-11-20 10:28:10 UTC (rev 20845)
@@ -9,21 +9,6 @@
 	* @package phpgwapi
 	* @subpackage vfs
 	* @version $Id$
-	*/
-
-	/*
-	   This program is free software: you can redistribute it and/or modify
-	   it under the terms of the GNU Lesser General Public License as published by
-	   the Free Software Foundation, either version 3 of the License, or
-	   (at your option) any later version.
-
-	   This program is distributed in the hope that it will be useful,
-	   but WITHOUT ANY WARRANTY; without even the implied warranty of
-	   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-	   GNU General Public License for more details.
-
-	   You should have received a copy of the GNU Lesser General Public License
-	   along with this program.  If not, see <http://www.gnu.org/licenses/>.
 	 */
 
 	/**
@@ -617,7 +602,7 @@
 		 */
 		function acl_check ($data)
 		{
-			//echo 'checking vfs_phpgwapi_sql_::acl_check(' . print_r($data, true) . '</pre>';
+			//echo 'checking vfs_sql::acl_check(' . print_r($data, true) . '</pre>';
 			if (!is_array ($data))
 			{
 				$data = array ();
@@ -735,7 +720,7 @@
 				reset ($memberships);
 				while (list ($num, $group_array) = each ($memberships))
 				{
-					if ($owner_id == $group_array['account_id'])
+					if ($owner_id == $group_array->id)
 					{
 						$group_ok = 1;
 						break;
@@ -744,7 +729,7 @@
 			}
 
 			$acl = CreateObject ('phpgwapi.acl', $owner_id);
-			$acl->set_account_id($owner_id);
+			$acl->set_account_id($owner_id, true);
 
 			$rights = $acl->get_rights ($user_id);
 
@@ -754,7 +739,7 @@
 				reset ($memberships);
 				while (list ($num, $group_array) = each ($memberships))
 				{
-					$rights |= $acl->get_rights ($group_array['account_id']);
+					$rights |= $acl->get_rights ($group_array->id);
 				}
 			}
 
@@ -1795,7 +1780,7 @@
 						return False;
 					}
 				}
-				elseif (!@mkdir ($p->real_full_path, 0770))
+				elseif (!mkdir ($p->real_full_path, 0770))
 				{
 					return False;
 				}
@@ -2526,4 +2511,3 @@
 			return ($rarray);
 		}
 	}
-?>

Added: people/sigurdne/modules/phpgwapi/trunk/inc/class.xml.inc.php
===================================================================
--- people/sigurdne/modules/phpgwapi/trunk/inc/class.xml.inc.php	                        (rev 0)
+++ people/sigurdne/modules/phpgwapi/trunk/inc/class.xml.inc.php	2009-11-20 10:28:10 UTC (rev 20845)
@@ -0,0 +1,3363 @@
+<?php
+	/**
+	* Class for accessing XML data through the XPath language
+	* @author Michael P. Mehl <[email protected]>
+	* @copyright Copyright (c) 2001 Michael P. Mehl
+	* @copyright Portions Copyright (C) 2004 Free Software Foundation, Inc. http://www.fsf.org/
+	* @license http://www.mozilla.org/MPL/ Mozilla Public License Version 1.1
+	* @package phpgwapi
+	* @subpackage xml
+	* @version $Id$
+	* @link http://www.phpxml.org/
+	* @link http://www.w3.org/TR/xpath
+	*/
+
+	/**
+	* Class for accessing XML data through the XPath language
+	* 
+	* This class offers methods for accessing the nodes of a XML document using 
+	* the XPath language. You can add or remove nodes, set or modify their 
+	* content and their attributes. No additional PHP extensions like DOM XML 
+	* or something similar are required to use these features.
+	* @package phpgwapi
+	* @subpackage xml
+	* @version 1.0 (2001-03-08)
+	*/
+class XML
+{
+	/**
+	* List of all document nodes.
+	*
+	* This array contains a list of all document nodes saved as an
+	* associative array.
+	*
+	* @access private
+	* @var    array
+	*/
+	var $nodes = array();
+	
+	/**
+	* List of document node IDs.
+	*
+	* This array contains a list of all IDs of all document nodes that
+	* are used for counting when adding a new node.
+	*
+	* @access private
+	* @var    array
+	*/
+	var $ids = array();
+	
+	/**
+	* Current document path.
+	*
+	* This variable saves the current path while parsing a XML file and adding
+	* the nodes being read from the file.
+	*
+	* @access private
+	* @var    string
+	*/
+	var $path = "";
+	
+	/**
+	* Current document position.
+	*
+	* This variable counts the current document position while parsing a XML
+	* file and adding the nodes being read from the file.
+	*
+	* @access private
+	* @var    int
+	*/
+	var $position = 0;
+	
+	/**
+	* Path of the document root.
+	*
+	* This string contains the full path to the node that acts as the root
+	* node of the whole document.
+	*
+	* @access private
+	* @var    string
+	*/
+	var $root = "";
+	
+	/**
+	* Current XPath expression.
+	*
+	* This string contains the full XPath expression being parsed currently.
+	*
+	* @access private
+	* @var    string
+	*/
+	var $xpath    = "";
+																				
+	/**
+	* List of entities to be converted.
+	*
+	* This array contains a list of entities to be converted when an XPath
+	* expression is evaluated.
+	*
+	* @access private
+	* @var    array
+	*/
+	var $entities = array ( "&" => "&amp;", "<" => "&lt;", ">" => "&gt;",
+		"'" => "&apos", '"' => "&quot;" );
+	
+	/**
+	* List of supported XPath axes.
+	*
+	* This array contains a list of all valid axes that can be evaluated in an
+	* XPath expression.
+	*
+	* @access private
+	* @var    array
+	*/
+	var $axes = array ( "child", "descendant", "parent", "ancestor",
+		"following-sibling", "preceding-sibling", "following", "preceding",
+		"attribute", "namespace", "self", "descendant-or-self",
+		"ancestor-or-self" );
+	
+	/**
+	* List of supported XPath functions.
+	*
+	* This array contains a list of all valid functions that can be evaluated
+	* in an XPath expression.
+	*
+	* @access private
+	* @var    array
+	*/
+	var $functions = array ( "last", "position", "count", "id", "name",
+		"string", "concat", "starts-with", "contains", "substring-before",
+		"substring-after", "substring", "string-length", "translate",
+		"boolean", "not", "true", "false", "lang", "number", "sum", "floor",
+		"ceiling", "round", "text" );
+	
+	/**
+	* List of supported XPath operators.
+	*
+	* This array contains a list of all valid operators that can be evaluated
+	* in a predicate of an XPath expression. The list is ordered by the
+	* precedence of the operators (lowest precedence first).
+	*
+	* @access private
+	* @var    array
+	*/
+	var $operators = array( " or ", " and ", "=", "!=", "<=", "<", ">=", ">",
+		"+", "-", "*", " div ", " mod " );
+
+	/**
+	* Constructor of the class.
+	*
+	* This constructor initializes the class and, when a filename is given,
+	* tries to read and parse the given file.
+	*
+	* @access    public
+	* @author    Michael P. Mehl <[email protected]>
+	* @param     string $file Path and name of the file to read and parsed.
+	* @see       load_file()
+	*/
+	function XML ( $file = "" )
+	{
+		// Check whether a file was given.
+		if ( !empty($file) )
+		{
+			// Load the XML file.
+			$this->load_file($file);
+		}
+	}
+
+	/**
+	* Reads a file and parses the XML data.
+	*
+	* This method reads the content of a XML file, tries to parse its
+	* content and upon success stores the information retrieved from
+	* the file into an array.
+	*
+	* @access    public
+	* @author    Michael P. Mehl <[email protected]>
+	* @param     string $file Path and name of the file to be read and parsed.
+	* @see       handle_start_element(), handle_end_element(),
+	*            handle_character_data()
+	*/
+	function load_file ( $file )
+	{
+		// Check whether the file exists and is readable.
+		if ( file_exists($file) && is_readable($file) )
+		{
+			// Read the content of the file.
+			$content = implode("", file($file));
+			
+			// Check whether content has been read.
+			if ( !empty($content) )
+			{
+				// Create an XML parser.
+				$parser = xml_parser_create();
+				
+				// Set the options for parsing the XML data.
+				xml_parser_set_option($parser, XML_OPTION_SKIP_WHITE, 1); 
+				xml_parser_set_option($parser, XML_OPTION_CASE_FOLDING, 0);
+				
+				// Set the object for the parser.
+				xml_set_object($parser, $this);
+				
+				// Set the element handlers for the parser.
+				xml_set_element_handler($parser, "handle_start_element",
+					"handle_end_element");
+				xml_set_character_data_handler($parser,
+					"handle_character_data");
+				
+				// Parse the XML file.
+				if ( !xml_parse($parser, $content, true) )
+				{
+					// Display an error message.
+					$this->display_error("XML error in file %s, line %d: %s",
+						$file, xml_get_current_line_number($parser),
+						xml_error_string(xml_get_error_code($parser)));
+				}
+				
+				// Free the parser.
+				xml_parser_free($parser);
+			}
+		}
+		else
+		{
+			// Display an error message.
+			$this->display_error("File %s could not be found or read.", $file);
+		}
+	}
+	
+	/**
+	* Generates a XML file with the content of the current document.
+	*
+	* This method creates a string containing the XML data being read
+	* and modified by this class before. This string can be used to save
+	* a modified document back to a file or doing other nice things with
+	* it.
+	*
+	* @access    public
+	* @author    Michael P. Mehl <[email protected]>
+	* @param     array $highlight Array containing a list of full document
+	*            paths of nodes to be highlighted by <font>...</font> tags
+	*            in the generated XML string.
+	* @param     string $root While doing a recursion with this method, this
+	*            parameter is used for internal purpose.
+	* @param     int $level While doing a recursion with this method, this
+	*            parameter is used for internal purpose.
+	* @return    string The returned string contains well-formed XML data
+	*            representing the content of this document.
+	* @see       load_file(), evaluate(), get_content()
+	*/
+	function get_file ( $highlight = array(), $root = "", $level = 0 )
+	{
+		// Create a string to save the generated XML data.
+		$xml = "";
+		
+		// Create two strings containing the tags for highlighting a node.
+		$highlight_start = "<font color=\"#FF0000\"><b>";
+		$highlight_end   = "</b></font>";
+		
+		// Generate a string to be displayed before the tags.
+		$before = "";
+		
+		// Calculate the amount of whitespaces to display.
+		for ( $i = 0; $i < ( $level * 2 ); $i++ )
+		{
+			// Add a whitespaces to the string.
+			$before .= " ";
+		}
+		
+		// Check whether a root node is given.
+		if ( empty($root) )
+		{
+			// Set it to the document root.
+			$root = $this->root;
+		}
+		
+		// Check whether the node is selected.
+		$selected = in_array($root, $highlight);
+		
+		// Now add the whitespaces to the XML data.
+		$xml .= $before;
+		
+		// Check whether the node is selected.
+		if ( $selected )
+		{
+			// Add the highlight code to the XML data.
+			$xml .= $highlight_start;
+		}
+		
+		// Now open the tag.
+		$xml .= "&lt;".$this->nodes[$root]["name"];
+		
+		// Check whether there are attributes for this node.
+		if ( count($this->nodes[$root]["attributes"]) > 0 )
+		{
+			// Run through all attributes.
+			foreach ( $this->nodes[$root]["attributes"] as $key => $value )
+			{
+				// Check whether this attribute is highlighted.
+				if ( in_array($root."/attribute::".$key, $highlight) )
+				{
+					// Add the highlight code to the XML data.
+					$xml .= $highlight_start;
+				}
+				
+				// Add the attribute to the XML data.
+				$xml .= " ".$key."=\"".trim(stripslashes($value))."\"";
+				
+				// Check whether this attribute is highlighted.
+				if ( in_array($root."/attribute::".$key, $highlight) )
+				{
+					// Add the highlight code to the XML data.
+					$xml .= $highlight_end;
+				}
+			}
+		}
+		
+		// Check whether the node contains character data or has children.
+		if ( empty($this->nodes[$root]["text"]) &&
+			!isset($this->nodes[$root]["children"]) )
+		{
+			// Add the end to the tag.
+			$xml .= "/";
+		}
+		
+		// Close the tag.
+		$xml .= "&gt;\n";
+		
+		// Check whether the node is selected.
+		if ( $selected )
+		{
+			// Add the highlight code to the XML data.
+			$xml .= $highlight_end;
+		}
+		
+		// Check whether the node contains character data.
+		if ( !empty($this->nodes[$root]["text"]) )
+		{
+			// Add the character data to the XML data.
+			$xml .= $before."  ".$this->nodes[$root]["text"]."\n";
+		}
+		
+		// Check whether the node has children.
+		if ( isset($this->nodes[$root]["children"]) )
+		{
+			// Run through all children with different names.
+			foreach ( $this->nodes[$root]["children"] as $child => $pos )
+			{
+				// Run through all children with the same name.
+				for ( $i = 1; $i <= $pos; $i++ )
+				{
+					// Generate the full path of the child.
+					$fullchild = $root."/".$child."[".$i."]";
+					
+					// Add the child's XML data to the existing data.
+					$xml .= $this->get_file($highlight, $fullchild,
+						$level + 1);
+				}
+			}
+		}
+		
+		// Check whether there are attributes for this node.
+		if ( !empty($this->nodes[$root]["text"]) ||
+			isset($this->nodes[$root]["children"]) )
+		{
+			// Add the whitespaces to the XML data.
+			$xml .= $before;
+			
+			// Check whether the node is selected.
+			if ( $selected )
+			{
+				// Add the highlight code to the XML data.
+				$xml .= $highlight_start;
+			}
+			
+			// Add the closing tag.
+			$xml .= "&lt;/".$this->nodes[$root]["name"]."&gt;";
+			
+			// Check whether the node is selected.
+			if ( $selected )
+			{
+				// Add the highlight code to the XML data.
+				$xml .= $highlight_end;
+			}
+			
+			// Add a linebreak.
+			$xml .= "\n";
+		}
+		
+		// Return the XML data.
+		return $xml;
+	}
+	
+	/**
+	* Adds a new node to the XML document.
+	*
+	* This method adds a new node to the tree of nodes of the XML document
+	* being handled by this class. The new node is created according to the
+	* parameters passed to this method.
+	*
+	* @access    public
+	* @author    Michael P. Mehl <[email protected]>
+	* @param     string $content Full path of the parent, to which the new
+	*            node should be added as a child.
+	* @param     string $name Name of the new node.
+	* @return    string The string returned by this method will contain the
+	*            full document path of the created node.
+	* @see       remove_node(), evaluate()
+	*/
+	function add_node ( $context, $name )
+	{
+		// Check whether a name for this element is already set.
+		if ( empty($this->root) )
+		{
+			// Use this tag as the root element.
+			$this->root = "/".$name."[1]";
+		}
+		
+		// Calculate the full path for this element.
+		$path = $context."/".$name;
+		
+		// Set the relative context and the position.
+		$position = ++$this->ids[$path];
+		$relative = $name."[".$position."]";
+		
+		// Calculate the full path.
+		$fullpath = $context."/".$relative;
+		
+		// Calculate the context position, which is the position of this
+		// element within elements of the same name in the parent node.
+		$this->nodes[$fullpath]["context-position"] = $position;
+		
+		// Calculate the position for the following and preceding axis
+		// detection.
+		$this->nodes[$fullpath]["document-position"] =
+			$this->nodes[$context]["document-position"] + 1;
+		
+		// Save the information about the node.
+		$this->nodes[$fullpath]["name"]   = $name;
+		$this->nodes[$fullpath]["text"]   = "";
+		$this->nodes[$fullpath]["parent"] = $context;
+		
+		// Add this element to the element count array.
+		if ( !$this->nodes[$context]["children"][$name] )
+		{
+			// Set the default name.
+			$this->nodes[$context]["children"][$name] = 1;
+		}
+		else
+		{
+			// Calculate the name.
+			$this->nodes[$context]["children"][$name] =
+				$this->nodes[$context]["children"][$name] + 1;
+		}
+		
+		// Return the path of the new node.
+		return $fullpath;
+	}
+
+	/**
+	* Removes a node from the XML document.
+	*
+	* This method removes a node from the tree of nodes of the XML document.
+	* If the node is a document node, all children of the node and its
+	* character data will be removed. If the node is an attribute node,
+	* only this attribute will be removed, the node to which the attribute
+	* belongs as well as its children will remain unmodified.
+	*
+	* @access    public
+	* @author    Michael P. Mehl <[email protected]>
+	* @param     string $node Full path of the node to be removed.
+	* @see       add_node(), evaluate()
+	*/
+	function remove_node ( $node )
+	{
+		// Check whether the node is an attribute node.
+		if ( ereg("/attribute::", $node) )
+		{
+			// Get the path to the attribute node's parent.
+			$parent = $this->prestr($node, "/attribute::");
+			
+			// Get the name of the attribute.
+			$attribute = $this->afterstr($node, "/attribute::");
+			
+			// Check whether the attribute exists.
+			if ( isset($this->nodes[$parent]["attributes"][$attribute]) )
+			{
+				// Create a new array.
+				$new = array();
+				
+				// Run through the existing attributes.
+				foreach ( $this->nodes[$parent]["attributes"]
+					as $key => $value )
+				{
+					// Check whether it's the attribute to remove.
+					if ( $key != $attribute )
+					{
+						// Add it to the new array again.
+						$new[$key] = $value;
+					}
+				}
+				
+				// Save the new attributes.
+				$this->nodes[$parent]["attributes"] = $new;
+			}
+		}
+		else
+		{
+			// Create an associative array, which contains information about
+			// all nodes that required to be renamed.
+			$rename = array();
+			
+			// Get the name, the parent and the siblings of current node.
+			$name     = $this->nodes[$node]["name"];
+			$parent   = $this->nodes[$node]["parent"];
+			$siblings = $this->nodes[$parent]["children"][$name];
+			
+			// Decrease the number of children.
+			$this->nodes[$parent]["children"][$name]--;
+			
+			// Create a counter for renumbering the siblings.
+			$counter = 1;
+			
+			// Now run through the siblings.
+			for ( $i = 1; $i <= $siblings; $i++ )
+			{
+				// Create the name of the sibling.
+				$sibling = $parent."/".$name."[".$i."]";
+				
+				// Check whether it's the name of the current node.
+				if ( $sibling != $node )
+				{
+					// Create the new name for the sibling.
+					$new = $parent."/".$name."[".$counter."]";
+					
+					// Increase the counter.
+					$counter++;
+					
+					// Add the old and the new name to the list of nodes
+					// to be renamed.
+					$rename[$sibling] = $new;
+				}
+			}
+			
+			// Create an array for saving the new node-list.
+			$nodes = array();
+			
+			// Now run through through the existing nodes.
+			foreach ( $this->nodes as $name => $values )
+			{
+				// Check the position of the path of the node to be deleted
+				// in the path of the current node.
+				$position = strpos($name, $node);
+
+				// Check whether it's not the node to be deleted.
+				if ( $position === false )
+				{
+					// Run through the array of nodes to be renamed.
+					foreach ( $rename as $old => $new )
+					{
+						// Check whether this node and it's parent requires to
+						// be renamed.
+						$name             = str_replace($old, $new, $name);
+						$values["parent"] = str_replace($old, $new,
+							$values["parent"]);
+					}
+					
+					// Add the node to the list of nodes.
+					$nodes[$name] = $values;
+				}
+			}
+			
+			// Save the new array of nodes.
+			$this->nodes = $nodes;
+		}
+	}
+
+	/**
+	* Add content to a node.
+	*
+	* This method adds content to a node. If it's an attribute node, then
+	* the value of the attribute will be set, otherwise the character data of
+	* the node will be set. The content is appended to existing content,
+	* so nothing will be overwritten.
+	*
+	* @access    public
+	* @author    Michael P. Mehl <[email protected]>
+	* @param     string $path Full document path of the node.
+	* @param     string $value String containing the content to be added.
+	* @see       get_content(), evaluate()
+	*/
+	function add_content ( $path, $value )
+	{
+		// Check whether it's an attribute node.
+		if ( ereg("/attribute::", $path) )
+		{
+			// Get the path to the attribute node's parent.
+			$parent = $this->prestr($path, "/attribute::");
+			
+			// Get the parent node.
+			$parent = $this->nodes[$parent];
+			
+			// Get the name of the attribute.
+			$attribute = $this->afterstr($path, "/attribute::");
+			
+			// Set the attribute.
+			$parent["attributes"][$attribute] .= $value;
+		}
+		else
+		{
+			// Set the character data of the node.
+			$this->nodes[$path]["text"] .= $value;
+		}
+	}
+	
+	/**
+	* Set the content of a node.
+	*
+	* This method sets the content of a node. If it's an attribute node, then
+	* the value of the attribute will be set, otherwise the character data of
+	* the node will be set. Existing content will be overwritten.
+	*
+	* @access    public
+	* @author    Michael P. Mehl <[email protected]>
+	* @param     string $path Full document path of the node.
+	* @param     string $value String containing the content to be set.
+	* @see       get_content(), evaluate()
+	*/
+	function set_content ( $path, $value )
+	{
+		// Check whether it's an attribute node.
+		if ( ereg("/attribute::", $path) )
+		{
+			// Get the path to the attribute node's parent.
+			$parent = $this->prestr($path, "/attribute::");
+			
+			// Get the parent node.
+			$parent = $this->nodes[$parent];
+			
+			// Get the name of the attribute.
+			$attribute = $this->afterstr($path, "/attribute::");
+			
+			// Set the attribute.
+			$parent["attributes"][$attribute] = $value;
+		}
+		else
+		{
+			// Set the character data of the node.
+			$this->nodes[$path]["text"] = $value;
+		}
+	}
+	
+	/**
+	* Retrieves the content of a node.
+	*
+	* This method retrieves the content of a node. If it's an attribute
+	* node, then the value of the attribute will be retrieved, otherwise
+	* it'll be the character data of the node.
+	*
+	* @access    public
+	* @author    Michael P. Mehl <[email protected]>
+	* @param     string $path Full document path of the node, from which the
+	*            content should be retrieved.
+	* @return    string The returned string contains either the value or the
+	*            character data of the node.
+	* @see       set_content(), evaluate()
+	*/
+	function get_content ( $path )
+	{
+		// Check whether it's an attribute node.
+		if ( ereg("/attribute::", $path) )
+		{
+			// Get the path to the attribute node's parent.
+			$parent = $this->prestr($path, "/attribute::");
+			
+			// Get the parent node.
+			$parent = $this->nodes[$parent];
+			
+			// Get the name of the attribute.
+			$attribute = $this->afterstr($path, "/attribute::");
+			
+			// Get the attribute.
+			$attribute = $parent["attributes"][$attribute];
+			
+			// Return the value of the attribute.
+			return $attribute;
+		}
+		else
+		{
+			// Return the cdata of the node.
+			return stripslashes($this->nodes[$path]["text"]);
+		}
+	}
+	
+	/**
+	* Add attributes to a node.
+	*
+	* This method adds attributes to a node. Existing attributes will not be
+	* overwritten.
+	*
+	* @access    public
+	* @author    Michael P. Mehl <[email protected]>
+	* @param     string $path Full document path of the node, the attributes
+	*            should be added to.
+	* @param     array $attributes Associative array containing the new
+	*            attributes for the node.
+	* @see       set_content(), get_content()
+	*/
+	function add_attributes ( $path, $attributes )
+	{
+		// Add the attributes to the node.
+		$this->nodes[$path]["attributes"] = array_merge($attributes,
+			$this->nodes[$path]["attributes"]);
+	}
+	
+	/**
+	* Sets the attributes of a node.
+	*
+	* This method sets the attributes of a node and overwrites all existing
+	* attributes by doing this.
+	*
+	* @access    public
+	* @author    Michael P. Mehl <[email protected]>
+	* @param     string $path Full document path of the node, the attributes
+	*            of which should be set.
+	* @param     array $attributes Associative array containing the new
+	*            attributes for the node.
+	* @see       set_content(), get_content()
+	*/
+	function set_attributes ( $path, $attributes )
+	{
+		// Set the attributes of the node.
+		$this->nodes[$path]["attributes"] = $attributes;
+	}
+	
+	/**
+	* Retrieves a list of all attributes of a node.
+	*
+	* This method retrieves a list of all attributes of the node specified in
+	* the argument.
+	*
+	* @access    public
+	* @author    Michael P. Mehl <[email protected]>
+	* @param     string $path Full document path of the node, from which the
+	*            list of attributes should be retrieved.
+	* @return    array The returned associative array contains the all
+	*            attributes of the specified node.
+	* @see       get_content(), $nodes, $ids
+	*/
+	function get_attributes ( $path )
+	{
+		// Return the attributes of the node.
+		return $this->nodes[$path]["attributes"];
+	}
+	
+	/**
+	* Retrieves the name of a document node.
+	*
+	* This method retrieves the name of document node specified in the
+	* argument.
+	*
+	* @access    public
+	* @author    Michael P. Mehl <[email protected]>
+	* @param     string $path Full document path of the node, from which the
+	*            name should be retrieved.
+	* @return    string The returned array contains the name of the specified
+	*            node.
+	* @see       get_content(), $nodes, $ids
+	*/
+	function get_name ( $path )
+	{
+		// Return the name of the node.
+		return $this->nodes[$path]["name"];
+	}
+	
+	/**
+	* Evaluates an XPath expression.
+	*
+	* This method tries to evaluate an XPath expression by parsing it. A
+	* XML document has to be read before this method is able to work.
+	*
+	* @access    public
+	* @author    Michael P. Mehl <[email protected]>
+	* @param     string $path XPath expression to be evaluated.
+	* @param     string $context Full path of a document node, starting
+	*            from which the XPath expression should be evaluated.
+	* @return    array The returned array contains a list of the full
+	*            document paths of all nodes that match the evaluated
+	*            XPath expression.
+	* @see       $nodes, $ids
+	*/
+	function evaluate ( $path, $context = "" )
+	{
+		// Remove slashes and quote signs.
+		$path = stripslashes($path);
+		$path = str_replace("\"", "", $path);
+		$path = str_replace("'", "", $path);
+		
+		// Split the paths into different paths.
+		$paths = $this->split_paths($path);
+		
+		// Create an empty set to save the result.
+		$result = array();
+		
+		// Run through all paths.
+		foreach ( $paths as $path )
+		{
+			// Trim the path.
+			$path = trim($path);
+			
+			// Save the current path.
+			$this->xpath = $path;
+		
+			// Convert all entities.
+			$path = strtr($path, array_flip($this->entities));
+		
+			// Split the path at every slash.
+			$steps = $this->split_steps($path);
+		
+			// Check whether the first element is empty.
+			if ( empty($steps[0]) )
+			{
+				// Remove the first and empty element.
+				array_shift($steps);
+			}
+		
+			// Start to evaluate the steps.
+			$nodes = $this->evaluate_step($context, $steps);
+		
+			// Remove duplicated nodes.
+			$nodes = array_unique($nodes);
+			
+			// Add the nodes to the result set.
+			$result = array_merge($result, $nodes);
+		}
+		
+		// Return the result.
+		return $result;
+	}
+	
+	/**
+	* Handles opening XML tags while parsing.
+	*
+	* While parsing a XML document for each opening tag this method is
+	* called. It'll add the tag found to the tree of document nodes.
+	*
+	* @access    private
+	* @author    Michael P. Mehl <[email protected]>
+	* @param     int $parser Handler for accessing the current XML parser.
+	* @param     string $name Name of the opening tag found in the document.
+	* @param     array $attributes Associative array containing a list of
+	*            all attributes of the tag found in the document.
+	* @see       handle_end_element(), handle_character_data(), $nodes, $ids
+	*/
+	function handle_start_element ( $parser, $name, $attributes )
+	{
+		// Add a node.
+		$this->path = $this->add_node($this->path, $name);
+		
+		// Set the attributes.
+		$this->set_attributes($this->path, $attributes);
+	}
+	
+	/**
+	* Handles closing XML tags while parsing.
+	*
+	* While parsing a XML document for each closing tag this method is
+	* called.
+	*
+	* @access    private
+	* @author    Michael P. Mehl <[email protected]>
+	* @param     int $parser Handler for accessing the current XML parser.
+	* @param     string $name Name of the closing tag found in the document.
+	* @see       handle_start_element(), handle_character_data(), $nodes, $ids
+	*/
+	function handle_end_element ( $parser, $name )
+	{
+		// Jump back to the parent element.
+		$this->path = substr($this->path, 0, strrpos($this->path, "/"));
+	}
+	
+	/**
+	* Handles character data while parsing.
+	*
+	* While parsing a XML document for each character data this method
+	* is called. It'll add the character data to the document tree.
+	*
+	* @access    private
+	* @author    Michael P. Mehl <[email protected]>
+	* @param     int $parser Handler for accessing the current XML parser.
+	* @param     string $text Character data found in the document.
+	* @see       handle_start_element(), handle_end_element(), $nodes, $ids
+	*/
+	function handle_character_data ( $parser, $text )
+	{
+		// Replace entities.
+		$text = strtr($text, $this->entities);
+		
+		// Save the text.
+		$this->add_content($this->path, addslashes(trim($text)));
+	}
+	
+	/**
+	* Splits an XPath expression into its different expressions.
+	*
+	* This method splits an XPath expression. Each expression can consists of
+	* list of expression being separated from each other by a | character.
+	*
+	* @access    private
+	* @author    Michael P. Mehl <[email protected]>
+	* @param     string $expression The complete expression to be splitted
+	*            into its different expressions.
+	* @return    array The array returned from this method contains a list
+	*            of all expressions found in the expression passed to this
+	*            method as a parameter.
+	* @see       evalute()
+	*/
+	function split_paths ( $expression )
+	{
+		// Create an empty array.
+		$paths = array();
+		
+		// Save the position of the slash.
+		$position = -1;
+		
+		// Run through the expression.
+		do
+		{
+			// Search for a slash.
+			$position = $this->search_string($expression, "|");
+			
+			// Check whether a | was found.
+			if ( $position >= 0 )
+			{
+				// Get the left part of the expression.
+				$left  = substr($expression, 0, $position);
+				$right = substr($expression, $position + 1);
+				
+				// Add the left value to the steps.
+				$paths[] = $left;
+				
+				// Reduce the expression to the right part.
+				$expression = $right;
+			}
+		}
+		while ( $position > -1 );
+		
+		// Add the remaing expression to the list of steps.
+		$paths[] = $expression;
+		
+		// Return the steps.
+		return $paths;
+	}
+	
+	/**
+	* Splits an XPath expression into its different steps.
+	*
+	* This method splits an XPath expression. Each expression can consists of
+	* list of steps being separated from each other by a / character.
+	*
+	* @access    private
+	* @author    Michael P. Mehl <[email protected]>
+	* @param     string $expression The complete expression to be splitted
+	*            into its different steps.
+	* @return    array The array returned from this method contains a list
+	*            of all steps found in the expression passed to this
+	*            method as a parameter.
+	* @see       evalute()
+	*/
+	function split_steps ( $expression )
+	{
+		// Create an empty array.
+		$steps = array();
+		
+		// Replace a double slashes, because they'll cause problems otherwise.
+		$expression = str_replace("//@", "/descendant::*/@", $expression);
+		$expression = str_replace("//", "/descendant::", $expression);
+		
+		// Save the position of the slash.
+		$position = -1;
+		
+		// Run through the expression.
+		do
+		{
+			// Search for a slash.
+			$position = $this->search_string($expression, "/");
+			
+			// Check whether a slash was found.
+			if ( $position >= 0 )
+			{
+				// Get the left part of the expression.
+				$left  = substr($expression, 0, $position);
+				$right = substr($expression, $position + 1);
+				
+				// Add the left value to the steps.
+				$steps[] = $left;
+				
+				// Reduce the expression to the right part.
+				$expression = $right;
+			}
+		}
+		while ( $position > -1 );
+		
+		// Add the remaing expression to the list of steps.
+		$steps[] = $expression;
+		
+		// Return the steps.
+		return $steps;
+	}
+	
+	/**
+	* Retrieves axis information from an XPath expression step.
+	*
+	* This method tries to extract the name of the axis and its node-test
+	* from a given step of an XPath expression at a given node.
+	*
+	* @access    private
+	* @author    Michael P. Mehl <[email protected]>
+	* @param     string $step String containing a step of an XPath expression.
+	* @param     string $node Full document path of the node on which the
+	*            step is executed.
+	* @return    array This method returns an array containing information
+	*            about the axis found in the step.
+	* @see       evaluate_step()
+	*/
+	function get_axis ( $step, $node )
+	{
+		// Create an array to save the axis information.
+		$axis = array(
+			"axis"      => "",
+			"node-test" => "",
+			"predicate" => array()
+		);
+		
+		// Check whether there are predicates.
+		if ( ereg("\[", $step) )
+		{
+			// Get the predicates.
+			$predicates = substr($step, strpos($step, "["));
+			
+			// Reduce the step.
+			$step = $this->prestr($step, "[");
+			
+			// Try to split the predicates.
+			$predicates = str_replace("][", "]|[", $predicates);
+			$predicates = explode("|", $predicates);
+			
+			// Run through all predicates.
+			foreach ( $predicates as $predicate )
+			{
+				// Remove the brackets.
+				$predicate = substr($predicate, 1, strlen($predicate) - 2);
+				
+				// Add the predicate to the list of predicates.
+				$axis["predicate"][] = $predicate;
+			}
+		}
+		
+		// Check whether the axis is given in plain text.
+		if ( $this->search_string($step, "::") > -1 )
+		{
+			// Split the step to extract axis and node-test.
+			$axis["axis"]      = $this->prestr($step, "::");
+			$axis["node-test"] = $this->afterstr($step, "::");
+		}
+		else
+		{
+			// Check whether the step is empty.
+			if ( empty($step) )
+			{
+				// Set it to the default value.
+				$step = ".";
+			}
+			
+			// Check whether is an abbreviated syntax.
+			if ( $step == "*" )
+			{
+				// Use the child axis and select all children.
+				$axis["axis"]      = "child";
+				$axis["node-test"] = "*";
+			}
+			elseif ( ereg("\(", $step) )
+			{
+				// Check whether it's a function.
+				if ( $this->is_function($this->prestr($step, "(")) )
+				{
+					// Get the position of the first bracket.
+					$start = strpos($step, "(");
+					$end   = strpos($step, ")", $start);
+					
+					// Get everything before, between and after the brackets.
+					$before  = substr($step, 0, $start);
+					$between = substr($step, $start + 1, $end - $start - 1);
+					$after   = substr($step, $end + 1);
+					
+					// Trim each string.
+					$before  = trim($before);
+					$between = trim($between);
+					$after   = trim($after);
+					
+					// Save the evaluated function.
+					$axis["axis"]      = "function";
+					$axis["node-test"] = $this->evaluate_function($before,
+						$between, $node);
+				}
+				else
+				{
+					// Use the child axis and a function.
+					$axis["axis"]      = "child";
+					$axis["node-test"] = $step;
+				}
+			}
+			elseif ( eregi("^@", $step) )
+			{
+				// Use the attribute axis and select the attribute.
+				$axis["axis"]      = "attribute";
+				$axis["node-test"] = substr($step, 1);
+			}
+			elseif ( eregi("\]$", $step) )
+			{
+				// Use the child axis and select a position.
+				$axis["axis"]      = "child";
+				$axis["node-test"] = substr($step, strpos($step, "["));
+			}
+			elseif ( $step == "." )
+			{
+				// Select the self axis.
+				$axis["axis"]      = "self";
+				$axis["node-test"] = "*";
+			}
+			elseif ( $step == ".." )
+			{
+				// Select the parent axis.
+				$axis["axis"]      = "parent";
+				$axis["node-test"] = "*";
+			}
+			elseif ( ereg("^[a-zA-Z0-9\-_]+$", $step) )
+			{
+				// Select the child axis and the child.
+				$axis["axis"]      = "child";
+				$axis["node-test"] = $step;
+			}
+			else
+			{
+				// Use the child axis and a name.
+				$axis["axis"]      = "child";
+				$axis["node-test"] = $step;
+			}
+		}
+
+		// Check whether it's a valid axis.
+		if ( !in_array($axis["axis"], array_merge($this->axes,
+			array("function"))) )
+		{
+			// Display an error message.
+			$this->display_error("While parsing an XPath expression, in ".
+				"the step \"%s\" the invalid axis \"%s\" was found.",
+				str_replace($step, "<b>".$step."</b>", $this->xpath),#
+				$axis["axis"]);  
+		}
+		
+		// Return the axis information.
+		return $axis;
+	}
+	
+	/**
+	* Looks for a string within another string.
+	*
+	* This method looks for a string within another string. Brackets in the
+	* string the method is looking through will be respected, which means that
+	* only if the string the method is looking for is located outside of
+	* brackets, the search will be successful.
+	*
+	* @access    private
+	* @author    Michael P. Mehl <[email protected]>
+	* @param     string $term String in which the search shall take place.
+	* @param     string $expression String that should be searched.
+	* @return    int This method returns -1 if no string was found, otherwise
+	*            the offset at which the string was found.
+	* @see       evaluate_step()
+	*/
+	function search_string ( $term, $expression )
+	{
+		// Create a new counter for the brackets.
+		$brackets = 0;
+		
+		// Run through the string.
+		for ( $i = 0; $i < strlen($term); $i++ )
+		{
+			// Get the character at the position of the string.
+			$character = substr($term, $i, 1);
+			
+			// Check whether it's a breacket.
+			if ( ( $character == "(" ) || ( $character == "[" ) )
+			{
+				// Increase the number of brackets.
+				$brackets++;
+			}
+			elseif ( ( $character == ")" ) || ( $character == "]" ) )
+			{
+				// Decrease the number of brackets.
+				$brackets--;
+			}
+			elseif ( $brackets == 0 )
+			{
+				// Check whether we can find the expression at this index.
+				if ( substr($term, $i, strlen($expression)) == $expression )
+				{
+					// Return the current index.
+					return $i;
+				}
+			}
+		}
+		
+		// Check whether we had a valid number of brackets.
+		if ( $brackets != 0 )
+		{
+			// Display an error message.
+			$this->display_error("While parsing an XPath expression, in the ".
+				"predicate \"%s\", there was an invalid number of brackets.",
+				str_replace($term, "<b>".$term."</b>", $this->xpath));
+		}
+
+		// Nothing was found.
+		return (-1);
+	}
+	
+	/**
+	* Checks for a valid function name.
+	*
+	* This method check whether an expression contains a valid name of an
+	* XPath function.
+	*
+	* @access    private
+	* @author    Michael P. Mehl <[email protected]>
+	* @param     string $expression Name of the function to be checked.
+	* @return    boolean This method returns true if the given name is a valid
+	*            XPath function name, otherwise false.
+	* @see       evaluate()
+	*/
+	function is_function ( $expression )
+	{
+		// Check whether it's in the list of supported functions.
+		if ( in_array($expression, $this->functions) )
+		{
+			// It's a function.
+			return true;
+		}
+		else
+		{
+			// It's not a function.
+			return false;
+		}
+	}
+	
+	/**
+	* Evaluates a step of an XPath expression.
+	*
+	* This method tries to evaluate a step from an XPath expression at a
+	* specific context.
+	*
+	* @access    private
+	* @author    Michael P. Mehl <[email protected]>
+	* @param     string $context Full document path of the context from
+	*            which starting the step should be evaluated.
+	* @param     array $steps Array containing the remaining steps of the
+	*            current XPath expression.
+	* @return    array This method returns an array containing all nodes
+	*            that are the result of evaluating the given XPath step.
+	* @see       evaluate()
+	*/
+	function evaluate_step ( $context, $steps )
+	{
+		// Create an empty array for saving the nodes found.
+		$nodes = array();
+
+		// Check whether the context is an array of contexts.
+		if ( is_array($context) )
+		{
+			// Run through the array.
+			foreach ( $context as $path )
+			{
+				// Call this method for this single path.
+				$nodes = array_merge($nodes,
+					$this->evaluate_step($path, $steps));
+			}
+		}
+		else
+		{
+			// Get this step.
+			$step = array_shift($steps);
+			
+			// Create an array to save the new contexts.
+			$contexts = array();
+			
+			// Get the axis of the current step.
+			$axis = $this->get_axis($step, $context);
+			
+			// Check whether it's a function.
+			if ( $axis["axis"] == "function" )
+			{
+				// Check whether an array was return by the function.
+				if ( is_array($axis["node-test"]) )
+				{
+					// Add the results to the list of contexts.
+					$contexts = array_merge($contexts, $axis["node-test"]);
+				}
+				else
+				{
+					// Add the result to the list of contexts.
+					$contexts[] = $axis["node-test"];
+				}
+			}
+			else
+			{
+				// Create the name of the method.
+				$method = "handle_axis_".str_replace("-", "_", $axis["axis"]);
+			
+				// Check whether the axis handler is defined.
+				if ( !method_exists($this, $method) )
+				{
+					// Display an error message.
+					$this->display_error("While parsing an XPath expression, ".
+						"the axis \"%s\" could not be handled, because this ".
+						"version does not support this axis.", $axis["axis"]);
+				}
+			
+				// Perform an axis action.
+				$contexts = call_user_method($method, $this, $axis, $context);
+			
+				// Check whether there are predicates.
+				if ( count($axis["predicate"]) > 0 )
+				{
+					// Check whether each node fits the predicates.
+					$contexts = $this->check_predicates($contexts,
+						$axis["predicate"]);
+				}
+			}
+			
+			// Check whether there are more steps left.
+			if ( count($steps) > 0 )
+			{
+				// Continue the evaluation of the next steps.
+				$nodes = $this->evaluate_step($contexts, $steps);
+			}
+			else
+			{
+				// Save the found contexts.
+				$nodes = $contexts;
+			}
+		}
+		
+		// Return the nodes found.
+		return $nodes;
+	}
+	
+	/**
+	* Evaluates an XPath function
+	*
+	* This method evaluates a given XPath function with its arguments on a
+	* specific node of the document.
+	*
+	* @access    private
+	* @author    Michael P. Mehl <[email protected]>
+	* @param     string $function Name of the function to be evaluated.
+	* @param     string $arguments String containing the arguments being
+	*            passed to the function.
+	* @param     string $node Full path to the document node on which the
+	*            function should be evaluated.
+	* @return    mixed This method returns the result of the evaluation of
+	*            the function. Depending on the function the type of the 
+	*            return value can be different.
+	* @see       evaluate()
+	*/
+	function evaluate_function ( $function, $arguments, $node )
+	{
+		// Remove whitespaces.
+		$function  = trim($function);
+		$arguments = trim($arguments);
+
+		// Create the name of the function handling function.
+		$method = "handle_function_".str_replace("-", "_", $function);
+		
+		// Check whether the function handling function is available.
+		if ( !method_exists($this, $method) )
+		{
+			// Display an error message.
+			$this->display_error("While parsing an XPath expression, ".
+				"the function \"%s\" could not be handled, because this ".
+				"version does not support this function.", $function);
+		}
+		
+		// Return the result of the function.
+		return call_user_method($method, $this, $node, $arguments);
+	}
+	
+	/**
+	* Evaluates a predicate on a node.
+	*
+	* This method tries to evaluate a predicate on a given node.
+	*
+	* @access    private
+	* @author    Michael P. Mehl <[email protected]>
+	* @param     string $node Full path of the node on which the predicate
+	*            should be evaluated.
+	* @param     string $predicate String containing the predicate expression
+	*            to be evaluated.
+	* @return    mixed This method is called recursively. The first call should
+	*            return a boolean value, whether the node matches the predicate
+	*            or not. Any call to the method being made during the recursion
+	*            may also return other types for further processing.
+	* @see       evaluate()
+	*/
+	function evaluate_predicate ( $node, $predicate )
+	{
+		// Set the default position and the type of the operator.
+		$position = 0;
+		$operator = "";
+		
+		// Run through all operators and try to find them.
+		foreach ( $this->operators as $expression )
+		{
+			// Check whether a position was already found.
+			if ( $position <= 0 )
+			{
+				// Try to find the operator.
+				$position = $this->search_string($predicate, $expression);
+			
+				// Check whether a operator was found.
+				if ( $position > 0 )
+				{
+					// Save the operator.
+					$operator = $expression;
+					
+					// Check whether it's the equal operator.
+					if ( $operator == "=" )
+					{
+						// Also look for other operators containing the
+						// equal sign.
+						if ( $this->search_string($predicate, "!=") ==
+							( $position - 1 ) )
+						{
+							// Get the new position.
+							$position = $this->search_string($predicate, "!=");
+							
+							// Save the new operator.
+							$operator = "!=";
+						}
+						if ( $this->search_string($predicate, "<=") ==
+							( $position - 1 ) )
+						{
+							// Get the new position.
+							$position = $this->search_string($predicate, "<=");
+							
+							// Save the new operator.
+							$operator = "<=";
+						}
+						if ( $this->search_string($predicate, ">=") ==
+							( $position - 1 ) )
+						{
+							// Get the new position.
+							$position = $this->search_string($predicate, ">=");
+							
+							// Save the new operator.
+							$operator = ">=";
+						}
+					}
+				}
+			}
+		}
+		
+		// Check whether the operator is a - sign.
+		if ( $operator == "-" )
+		{
+			// Check whether it's not a function containing a - in its name.
+			foreach ( $this->functions as $function )
+			{
+				// Check whether there's a - sign in the function name.
+				if ( ereg("-", $function) )
+				{
+					// Get the position of the - in the function name.
+					$sign = strpos($function, "-");
+					
+					// Extract a substring from the predicate.
+					$sub = substr($predicate, $position - $sign,
+						strlen($function));
+						
+					// Check whether it's the function.
+					if ( $sub == $function )
+					{
+						// Don't use the operator.
+						$operator = "";
+						$position = -1;
+					}
+				}
+			}
+		}
+		elseif ( $operator == "*" )
+		{
+			// Get some substrings.
+			$character = substr($predicate, $position - 1, 1);
+			$attribute = substr($predicate, $position - 11, 11);
+			
+			// Check whether it's an attribute selection.
+			if ( ( $character == "@" ) || ( $attribute == "attribute::" ) )
+			{
+				// Don't use the operator.
+				$operator = "";
+				$position = -1;
+			}
+		}
+		
+		// Check whether an operator was found.        
+		if ( $position > 0 )
+		{
+			// Get the left and the right part of the expression.
+			$left  = substr($predicate, 0, $position);
+			$right = substr($predicate, $position + strlen($operator));
+			
+			// Remove whitespaces.
+			$left  = trim($left);
+			$right = trim($right);
+			
+			// Evaluate the left and the right part.
+			$left  = $this->evaluate_predicate($node, $left);
+			$right = $this->evaluate_predicate($node, $right);
+			
+			// Check the kind of operator.
+			switch ( $operator )
+			{
+				case " or ":
+					// Return the two results connected by an "or".
+					return ( $left or $right );
+				
+				case " and ":
+					// Return the two results connected by an "and".
+					return ( $left and $right );
+				
+				case "=":
+					// Compare the two results.
+					return ( $left == $right );
+					
+				case "!=":
+					// Check whether the two results are not equal.
+					return ( $left != $right );
+					
+				case "<=":
+					// Compare the two results.
+					return ( $left <= $right );
+					
+				case "<":
+					// Compare the two results.
+					return ( $left < $right );
+				
+				case ">=":
+					// Compare the two results.
+					return ( $left >= $right );
+					
+				case ">":
+					// Compare the two results.
+					return ( $left > $right );
+					
+				case "+":
+					// Return the result by adding one result to the other.
+					return ( $left + $right );
+				
+				case "-":
+					// Return the result by decrease one result by the other.
+					return ( $left - $right );
+				
+				case "*":
+					// Return a multiplication of the two results.
+					return ( $left * $right );
+					
+				case " div ":
+					// Return a division of the two results.
+					if ( $right == 0 )
+					{
+						// Display an error message.
+						$this->display_error("While parsing an XPath ".
+							"predicate, a error due a division by zero ".
+							"occured.");
+					}
+					else
+					{
+						// Return the result of the division.
+						return ( $left / $right );
+					}
+					break;
+				
+				case " mod ":
+					// Return a modulo of the two results.
+					return ( $left % $right );
+			}
+		}
+		
+		// Check whether the predicate is a function.
+		if ( ereg("\(", $predicate) )
+		{
+			// Get the position of the first bracket.
+			$start = strpos($predicate, "(");
+			$end   = strpos($predicate, ")", $start);
+			
+			// Get everything before, between and after the brackets.
+			$before  = substr($predicate, 0, $start);
+			$between = substr($predicate, $start + 1, $end - $start - 1);
+			$after   = substr($predicate, $end + 1);
+			
+			// Trim each string.
+			$before  = trim($before);
+			$between = trim($between);
+			$after   = trim($after);
+			
+			// Check whether there's something after the bracket.
+			if ( !empty($after) )
+			{
+				// Display an error message.
+				$this->display_error("While parsing an XPath expression ".
+					"there was found an error in the predicate \"%s\", ".
+					"because after a closing bracket there was found ".
+					"something unknown.", str_replace($predicate,
+					"<b>".$predicate."</b>", $this->xpath));
+			}
+			
+			// Check whether it's a function.
+			if ( empty($before) && empty($after) )
+			{
+				// Evaluate the content of the brackets.
+				return $this->evaluate_predicate($node, $between);
+			}
+			elseif ( $this->is_function($before) )
+			{
+				// Return the evaluated function.
+				return $this->evaluate_function($before, $between, $node);
+			}
+			else
+			{
+				// Display an error message.
+				$this->display_error("While parsing a predicate in an XPath ".
+					"expression, a function \"%s\" was found, which is not ".
+					"yet supported by the parser.", str_replace($before,
+					"<b>".$before."</b>", $this->xpath));
+			}
+		}
+		
+		// Check whether the predicate is just a digit.
+		if ( ereg("^[0-9]+(\.[0-9]+)?$", $predicate) ||
+			ereg("^\.[0-9]+$", $predicate) )
+		{
+			// Return the value of the digit.
+			return doubleval($predicate);
+		}
+		
+		// Check whether it's an XPath expression.
+		$result = $this->evaluate($predicate, $node);
+		if ( count($result) > 0 )
+		{
+			// Convert the array.
+			$result = explode("|", implode("|", $result));
+			
+			// Get the value of the first result.
+			$value = $this->get_content($result[0]);
+			
+			// Return the value.
+			return $value;
+		}
+		
+		// Return the predicate as a string.
+		return $predicate;
+	}
+	
+	/**
+	* Checks whether a node matches predicates.
+	*
+	* This method checks whether a list of nodes passed to this method match
+	* a given list of predicates. 
+	*
+	* @access    private
+	* @author    Michael P. Mehl <[email protected]>
+	* @param     array $nodes Array of full paths of all nodes to be tested.
+	* @param     array $predicates Array of predicates to use.
+	* @return    array The array returned by this method contains a list of
+	*            all nodes matching the given predicates.
+	* @see       evaluate_step()
+	*/
+	function check_predicates ( $nodes, $predicates )
+	{
+		// Create an empty set of nodes.
+		$result = array();
+		
+		// Run through all nodes.
+		foreach ( $nodes as $node )
+		{
+			// Create a variable whether to add this node to the node-set.
+			$add = true;
+			
+			// Run through all predicates.
+			foreach ( $predicates as $predicate )
+			{
+				// Check whether the predicate is just an number.
+				if ( ereg("^[0-9]+$", $predicate) )
+				{
+					// Enhance the predicate.
+					$predicate .= "=position()";
+				}
+				
+				// Do the predicate check.
+				$check = $this->evaluate_predicate($node, $predicate);
+				
+				// Check whether it's a string.
+				if ( is_string($check) && ( ( $check == "" ) ||
+					( $check == $predicate ) ) )
+				{
+					// Set the result to false.
+					$check = false;
+				}
+				
+				// Check whether it's an integer.
+				if ( is_int($check) )
+				{
+					// Check whether it's the current position.
+					if ( $check == $this->handle_function_position($node, "") )
+					{
+						// Set it to true.
+						$check = true;
+					}
+					else
+					{
+						// Set it to false.
+						$check = false;
+					}
+				}
+				
+				// Check whether the predicate is OK for this node.
+				$add = $add && $check;
+			}
+			
+			// Check whether to add this node to the node-set.
+			if ( $add )
+			{
+				// Add the node to the node-set.
+				$result[] = $node;
+			}            
+		}
+		
+		// Return the array of nodes.
+		return $result;
+	}
+	
+	/**
+	* Checks whether a node matches a node-test.
+	*
+	* This method checks whether a node in the document matches a given
+	* node-test.
+	*
+	* @access    private
+	* @author    Michael P. Mehl <[email protected]>
+	* @param     string $context Full path of the node, which should be tested
+	*            for matching the node-test.
+	* @param     string $node_test String containing the node-test for the
+	*            node.
+	* @return    boolean This method returns true if the node matches the
+	*            node-test, otherwise false.
+	* @see       evaluate()
+	*/
+	function check_node_test ( $context, $node_test )
+	{
+		// Check whether it's a function.
+		if ( ereg("\(", $node_test) )
+		{
+			// Get the type of function to use.
+			$function = $this->prestr($node_test, "(");
+			
+			// Check whether the node fits the method.
+			switch ( $function )
+			{
+				case "node":
+					// Add this node to the list of nodes.
+					return true;
+					
+				case "text":
+					// Check whether the node has some text.
+					if ( !empty($this->nodes[$context]["text"]) )
+					{
+						// Add this node to the list of nodes.
+						return true;
+					}
+					break;
+					
+				case "comment":
+					// Check whether the node has some comment.
+					if ( !empty($this->nodes[$context]["comment"]) )
+					{
+						// Add this node to the list of nodes.
+						return true;
+					}
+					break;
+				
+				case "processing-instruction":
+					// Get the literal argument.
+					$literal = $this->afterstr($axis["node-test"], "(");
+					
+					// Cut the literal.
+					$literal = substr($literal, 0, strlen($literal) - 1);
+					
+					// Check whether a literal was given.
+					if ( !empty($literal) )
+					{
+						// Check whether the node's processing instructions
+						// are matching the literals given.
+						if ( $this->nodes[$context]
+							["processing-instructions"] == $literal )
+						{
+							// Add this node to the node-set.
+							return true;
+						}
+					}
+					else
+					{
+						// Check whether the node has processing
+						// instructions.
+						if ( !empty($this->nodes[$context]
+							["processing-instructions"]) )
+						{
+							// Add this node to the node-set.
+							return true;
+						}
+					}
+					break;
+					
+				default:
+					// Display an error message.
+					$this->display_error("While parsing an XPath ".
+						"expression there was found an undefined ".
+						"function called \"%s\".",
+						str_replace($function, "<b>".$function."</b>",
+						$this->xpath));
+			}
+		}
+		elseif ( $node_test == "*" )
+		{
+			// Add this node to the node-set.
+			return true;
+		}
+		elseif ( ereg("^[a-zA-Z0-9\-_]+", $node_test) )
+		{
+			// Check whether the node-test can be fulfilled.
+			if ( $this->nodes[$context]["name"] == $node_test )
+			{
+				// Add this node to the node-set.
+				return true;
+			}
+		}
+		else
+		{
+			// Display an error message.
+			$this->display_error("While parsing the XPath expression \"%s\" ".
+				"an empty and therefore invalid node-test has been found.",
+				$this->xpath);
+		}
+		
+		// Don't add this context.
+		return false;
+	}
+	
+	/**
+	* Handles the XPath child axis.
+	*
+	* This method handles the XPath child axis.
+	*
+	* @access    private
+	* @author    Michael P. Mehl <[email protected]>
+	* @param     array $axis Array containing information about the axis.
+	* @param     string $context Node from which starting the axis should
+	*            be processed.
+	* @return    array This method returns an array containing all nodes 
+	*            that were found during the evaluation of the given axis.
+	* @see       evaluate()
+	*/
+	function handle_axis_child ( $axis, $context )
+	{
+		// Create an empty node-set.
+		$nodes = array();
+		
+		// Get a list of all children.
+		$children = $this->nodes[$context]["children"];
+		
+		// Check whether there are children.
+		if ( !empty($children) )
+		{
+			// Run through all children.
+			foreach ( $children as $child_name => $child_position )
+			{
+				// Run through all childs with this name.
+				for ( $i = 1; $i <= $child_position; $i++ )
+				{
+					// Create the path of the child.
+					$child = $context."/".$child_name."[".$i."]";
+					
+					// Check whether 
+					if ( $this->check_node_test($child, $axis["node-test"]) )
+					{
+						// Add the child to the node-set.
+						$nodes[] = $child;
+					}
+				}
+			}
+		}
+		
+		// Return the nodeset.
+		return $nodes;
+	}
+	
+	/**
+	* Handles the XPath parent axis.
+	*
+	* This method handles the XPath parent axis.
+	*
+	* @access    private
+	* @author    Michael P. Mehl <[email protected]>
+	* @param     array $axis Array containing information about the axis.
+	* @param     string $context Node from which starting the axis should
+	*            be processed.
+	* @return    array This method returns an array containing all nodes 
+	*            that were found during the evaluation of the given axis.
+	* @see       evaluate()
+	*/
+	function handle_axis_parent ( $axis, $context )
+	{
+		// Create an empty node-set.
+		$nodes = array();
+		
+		// Check whether the parent matches the node-test.
+		if ( $this->check_node_test($this->nodes[$context]["parent"],
+			$axis["node-test"]) )
+		{
+			// Add this node to the list of nodes.
+			$nodes[] = $this->nodes[$context]["parent"];
+		}
+		
+		// Return the nodeset.
+		return $nodes;
+	}
+	
+	/**
+	* Handles the XPath attribute axis.
+	*
+	* This method handles the XPath attribute axis.
+	*
+	* @access    private
+	* @author    Michael P. Mehl <[email protected]>
+	* @param     array $axis Array containing information about the axis.
+	* @param     string $context Node from which starting the axis should
+	*            be processed.
+	* @return    array This method returns an array containing all nodes 
+	*            that were found during the evaluation of the given axis.
+	* @see       evaluate()
+	*/
+	function handle_axis_attribute ( $axis, $context )
+	{
+		// Create an empty node-set.
+		$nodes = array();
+		
+		// Check whether all nodes should be selected.
+		if ( $axis["node-test"] == "*" )
+		{
+			// Check whether there are attributes.
+			if ( count($this->nodes[$context]["attributes"]) > 0 )
+			{
+				// Run through the attributes.
+				foreach ( $this->nodes[$context]["attributes"] as
+					$key => $value )
+				{
+					// Add this node to the node-set.
+					$nodes[] = $context."/attribute::".$key;
+				}
+			}
+		}
+		elseif ( !empty($this->nodes[$context]["attributes"]
+			[$axis["node-test"]]) )
+		{
+			// Add this node to the node-set.
+			$nodes[] = $context."/attribute::".$axis["node-test"];
+		}
+			
+		// Return the nodeset.
+		return $nodes;
+	}
+
+	/**
+	* Handles the XPath self axis.
+	*
+	* This method handles the XPath self axis.
+	*
+	* @access    private
+	* @author    Michael P. Mehl <[email protected]>
+	* @param     array $axis Array containing information about the axis.
+	* @param     string $context Node from which starting the axis should
+	*            be processed.
+	* @return    array This method returns an array containing all nodes 
+	*            that were found during the evaluation of the given axis.
+	* @see       evaluate()
+	*/
+	function handle_axis_self ( $axis, $context )
+	{
+		// Create an empty node-set.
+		$nodes = array();
+		
+		// Check whether the context match the node-test.
+		if ( $this->check_node_test($context, $axis["node-test"]) )
+		{
+			// Add this node to the node-set.
+			$nodes[] = $context;
+		}
+
+		// Return the nodeset.
+		return $nodes;
+	}
+
+	/**
+	* Handles the XPath descendant axis.
+	*
+	* This method handles the XPath descendant axis.
+	*
+	* @access    private
+	* @author    Michael P. Mehl <[email protected]>
+	* @param     array $axis Array containing information about the axis.
+	* @param     string $context Node from which starting the axis should
+	*            be processed.
+	* @return    array This method returns an array containing all nodes 
+	*            that were found during the evaluation of the given axis.
+	* @see       evaluate()
+	*/
+	function handle_axis_descendant ( $axis, $context )
+	{
+		// Create an empty node-set.
+		$nodes = array();
+		
+		// Check whether the current node has children.
+		if ( count($this->nodes[$context]["children"]) > 0 )
+		{
+			// Get a list of children.
+			$children = $this->nodes[$context]["children"];
+			
+			// Run through all children.
+			foreach ( $children as $child_name => $child_position )
+			{
+				// Run through all children of this name.
+				for ( $i = 1; $i <= $child_position; $i++ )
+				{
+					// Create the full path for the children.
+					$child = $context."/".$child_name."[".$i."]";
+					
+					// Check whether the child matches the node-test.
+					if ( $this->check_node_test($child, $axis["node-test"]) )
+					{
+						// Add the child to the list of nodes.
+						$nodes[] = $child;
+					}
+					
+					// Recurse to the next level.
+					$nodes = array_merge($nodes,
+						$this->handle_axis_descendant($axis, $child));
+				}
+			}
+		}
+		
+		// Return the nodeset.
+		return $nodes;
+	}
+
+	/**
+	* Handles the XPath ancestor axis.
+	*
+	* This method handles the XPath ancestor axis.
+	*
+	* @access    private
+	* @author    Michael P. Mehl <[email protected]>
+	* @param     array $axis Array containing information about the axis.
+	* @param     string $context Node from which starting the axis should
+	*            be processed.
+	* @return    array This method returns an array containing all nodes 
+	*            that were found during the evaluation of the given axis.
+	* @see       evaluate()
+	*/
+	function handle_axis_ancestor ( $axis, $context )
+	{
+		// Create an empty node-set.
+		$nodes = array();
+		
+		// Get the parent of the current node.
+		$parent = $this->nodes[$context]["parent"];
+		
+		// Check whether the parent isn't empty.
+		if ( !empty($parent) )
+		{
+			// Check whether the parent matches the node-test.
+			if ( $this->check_node_test($parent, $axis["node-test"]) )
+			{
+				// Add the parent to the list of nodes.
+				$nodes[] = $parent;
+			}
+			
+			// Handle all other ancestors.
+			$nodes = array_merge($nodes,
+				$this->handle_axis_ancestor($axis, $parent));
+		}
+		
+		// Return the nodeset.
+		return $nodes;
+	}
+
+	/**
+	* Handles the XPath namespace axis.
+	*
+	* This method handles the XPath namespace axis.
+	*
+	* @access    private
+	* @author    Michael P. Mehl <[email protected]>
+	* @param     array $axis Array containing information about the axis.
+	* @param     string $context Node from which starting the axis should
+	*            be processed.
+	* @return    array This method returns an array containing all nodes 
+	*            that were found during the evaluation of the given axis.
+	* @see       evaluate()
+	*/
+	function handle_axis_namespace ( $axis, $context )
+	{
+		// Create an empty node-set.
+		$nodes = array();
+		
+		// Check whether all nodes should be selected.
+		if ( !empty($this->nodes[$context]["namespace"]) )
+		{
+			// Add this node to the node-set.
+			$nodes[] = $context;
+		}
+			
+		// Return the nodeset.
+		return $nodes;
+	}
+	
+	/**
+	* Handles the XPath following axis.
+	*
+	* This method handles the XPath following axis.
+	*
+	* @access    private
+	* @author    Michael P. Mehl <[email protected]>
+	* @param     array $axis Array containing information about the axis.
+	* @param     string $context Node from which starting the axis should
+	*            be processed.
+	* @return    array This method returns an array containing all nodes 
+	*            that were found during the evaluation of the given axis.
+	* @see       evaluate()
+	*/
+	function handle_axis_following ( $axis, $context )
+	{
+		// Create an empty node-set.
+		$nodes = array();
+		
+		// Get the current document position.
+		$position = $this->nodes[$context]["document-position"];
+		
+		// Create a flag, whether we already found the context node.
+		$found = false;
+		
+		// Run through all nodes of the document.
+		foreach ( $this->nodes as $node => $data )
+		{
+			// Check whether the context node has already been found.
+			if ( $found )
+			{
+				// Check whether the position is correct.
+				if ( $this->nodes[$node]["document-position"] == $position )
+				{
+					// Check whether the node fits the node-test.
+					if ( $this->check_node_test($node, $axis["node-test"]) )
+					{
+						// Add the node to the list of nodes.
+						$nodes[] = $node;
+					}
+				}
+			}
+			
+			// Check whether this is the context node.
+			if ( $node == $context )
+			{
+				// After this we'll look for more nodes.
+				$found = true;
+			}
+		}
+			
+		// Return the nodeset.
+		return $nodes;
+	}
+	
+	/**
+	* Handles the XPath preceding axis.
+	*
+	* This method handles the XPath preceding axis.
+	*
+	* @access    private
+	* @author    Michael P. Mehl <[email protected]>
+	* @param     array $axis Array containing information about the axis.
+	* @param     string $context Node from which starting the axis should
+	*            be processed.
+	* @return    array This method returns an array containing all nodes 
+	*            that were found during the evaluation of the given axis.
+	* @see       evaluate()
+	*/
+	function handle_axis_preceding ( $axis, $context )
+	{
+		// Create an empty node-set.
+		$nodes = array();
+		
+		// Get the current document position.
+		$position = $this->nodes[$context]["document-position"];
+		
+		// Create a flag, whether we already found the context node.
+		$found = true;
+		
+		// Run through all nodes of the document.
+		foreach ( $this->nodes as $node => $data )
+		{
+			// Check whether this is the context node.
+			if ( $node == $context )
+			{
+				// After this we won't look for more nodes.
+				$found = false;
+			}
+			
+			// Check whether the context node has already been found.
+			if ( $found )
+			{
+				// Check whether the position is correct.
+				if ( $this->nodes[$node]["document-position"] == $position )
+				{
+					// Check whether the node fits the node-test.
+					if ( $this->check_node_test($node, $axis["node-test"]) )
+					{
+						// Add the node to the list of nodes.
+						$nodes[] = $node;
+					}
+				}
+			}
+		}
+			
+		// Return the nodeset.
+		return $nodes;
+	}
+	
+	/**
+	* Handles the XPath following-sibling axis.
+	*
+	* This method handles the XPath following-sibling axis.
+	*
+	* @access    private
+	* @author    Michael P. Mehl <[email protected]>
+	* @param     array $axis Array containing information about the axis.
+	* @param     string $context Node from which starting the axis should
+	*            be processed.
+	* @return    array This method returns an array containing all nodes 
+	*            that were found during the evaluation of the given axis.
+	* @see       evaluate()
+	*/
+	function handle_axis_following_sibling ( $axis, $context )
+	{
+		// Create an empty node-set.
+		$nodes = array();
+		
+		// Get all children from the parent.
+		$siblings = $this->handle_axis_child($axis,
+			$this->nodes[$context]["parent"]);
+		
+		// Create a flag whether the context node was already found.
+		$found = false;
+		
+		// Run through all siblings.
+		foreach ( $siblings as $sibling )
+		{
+			// Check whether the context node was already found.
+			if ( $found )
+			{
+				// Check whether the sibling is a real sibling.
+				if ( $this->nodes[$sibling]["name"] ==
+					$this->nodes[$context]["name"] )
+				{
+					// Check whether the sibling matches the node-test.
+					if ( $this->check_node_test($sibling, $axis["node-test"]) )
+					{
+						// Add the sibling to the list of nodes.
+						$nodes[] = $sibling;
+					}
+				}
+			}
+			
+			// Check whether this is the context node.
+			if ( $sibling == $context )
+			{
+				// Continue looking for other siblings.
+				$found = true;
+			}
+		}
+			
+		// Return the nodeset.
+		return $nodes;
+	}
+	
+	/**
+	* Handles the XPath preceding-sibling axis.
+	*
+	* This method handles the XPath preceding-sibling axis.
+	*
+	* @access    private
+	* @author    Michael P. Mehl <[email protected]>
+	* @param     array $axis Array containing information about the axis.
+	* @param     string $context Node from which starting the axis should
+	*            be processed.
+	* @return    array This method returns an array containing all nodes 
+	*            that were found during the evaluation of the given axis.
+	* @see       evaluate()
+	*/
+	function handle_axis_preceding_sibling ( $axis, $context )
+	{
+		// Create an empty node-set.
+		$nodes = array();
+		
+		// Get all children from the parent.
+		$siblings = $this->handle_axis_child($axis,
+			$this->nodes[$context]["parent"]);
+		
+		// Create a flag whether the context node was already found.
+		$found = true;
+		
+		// Run through all siblings.
+		foreach ( $siblings as $sibling )
+		{
+			// Check whether this is the context node.
+			if ( $sibling == $context )
+			{
+				// Don't continue looking for other siblings.
+				$found = false;
+			}
+			
+			// Check whether the context node was already found.
+			if ( $found )
+			{
+				// Check whether the sibling is a real sibling.
+				if ( $this->nodes[$sibling]["name"] ==
+					$this->nodes[$context]["name"] )
+				{
+					// Check whether the sibling matches the node-test.
+					if ( $this->check_node_test($sibling, $axis["node-test"]) )
+					{
+						// Add the sibling to the list of nodes.
+						$nodes[] = $sibling;
+					}
+				}
+			}
+		}
+			
+		// Return the nodeset.
+		return $nodes;
+	}
+	
+	/**
+	* Handles the XPath descendant-or-self axis.
+	*
+	* This method handles the XPath descendant-or-self axis.
+	*
+	* @access    private
+	* @author    Michael P. Mehl <[email protected]>
+	* @param     array $axis Array containing information about the axis.
+	* @param     string $context Node from which starting the axis should
+	*            be processed.
+	* @return    array This method returns an array containing all nodes 
+	*            that were found during the evaluation of the given axis.
+	* @see       evaluate()
+	*/
+	function handle_axis_descendant_or_self ( $axis, $context )
+	{
+		// Create an empty node-set.
+		$nodes = array();
+		
+		// Read the nodes.
+		$nodes = array_merge(
+			$this->handle_axis_descendant($axis, $context),
+			$this->handle_axis_self($axis, $context));
+		
+		// Return the nodeset.
+		return $nodes;
+	}
+	
+	/**
+	* Handles the XPath ancestor-or-self axis.
+	*
+	* This method handles the XPath ancestor-or-self axis.
+	*
+	* @access    private
+	* @author    Michael P. Mehl <[email protected]>
+	* @param     array $axis Array containing information about the axis.
+	* @param     string $context Node from which starting the axis should
+	*            be processed.
+	* @return    array This method returns an array containing all nodes 
+	*            that were found during the evaluation of the given axis.
+	* @see       evaluate()
+	*/
+	function handle_axis_ancestor_or_self ( $axis, $context )
+	{
+		// Create an empty node-set.
+		$nodes = array();
+		
+		// Read the nodes.
+		$nodes = array_merge(
+			$this->handle_axis_ancestor($axis, $context),
+			$this->handle_axis_self($axis, $context));
+		
+		// Return the nodeset.
+		return $nodes;
+	}
+	
+	/**
+	* Handles the XPath function last.
+	*
+	* This method handles the XPath function last.
+	*
+	* @access    private
+	* @author    Michael P. Mehl <[email protected]>
+	* @param     string $node Full path of the node on which the function
+	*            should be processed.
+	* @param     string $arguments String containing the arguments that were
+	*            passed to the function.
+	* @return    mixed Depending on the type of function being processed this 
+	*            method returns different types.
+	* @see       evaluate()
+	*/
+	function handle_function_last ( $node, $arguments )
+	{
+		// Calculate the size of the context.
+		$parent   = $this->nodes[$node]["parent"];
+		$children = $this->nodes[$parent]["children"];
+		$context  = $children[$this->nodes[$node]["name"]];
+
+		// Return the size.
+		return $context;
+	}
+
+	/**
+	* Handles the XPath function position.
+	*
+	* This method handles the XPath function position.
+	*
+	* @access    private
+	* @author    Michael P. Mehl <[email protected]>
+	* @param     string $node Full path of the node on which the function
+	*            should be processed.
+	* @param     string $arguments String containing the arguments that were
+	*            passed to the function.
+	* @return    mixed Depending on the type of function being processed this 
+	*            method returns different types.
+	* @see       evaluate()
+	*/
+	function handle_function_position ( $node, $arguments )
+	{
+		// return the context-position.
+		return $this->nodes[$node]["context-position"];
+	}
+	
+	/**
+	* Handles the XPath function count.
+	*
+	* This method handles the XPath function count.
+	*
+	* @access    private
+	* @author    Michael P. Mehl <[email protected]>
+	* @param     string $node Full path of the node on which the function
+	*            should be processed.
+	* @param     string $arguments String containing the arguments that were
+	*            passed to the function.
+	* @return    mixed Depending on the type of function being processed this 
+	*            method returns different types.
+	* @see       evaluate()
+	*/
+	function handle_function_count ( $node, $arguments )
+	{
+		// Evaluate the argument of the method as an XPath and return
+		// the number of results.
+		return count($this->evaluate($arguments, $node));
+	}
+	
+	/**
+	* Handles the XPath function id.
+	*
+	* This method handles the XPath function id.
+	*
+	* @access    private
+	* @author    Michael P. Mehl <[email protected]>
+	* @param     string $node Full path of the node on which the function
+	*            should be processed.
+	* @param     string $arguments String containing the arguments that were
+	*            passed to the function.
+	* @return    mixed Depending on the type of function being processed this 
+	*            method returns different types.
+	* @see       evaluate()
+	*/
+	function handle_function_id ( $node, $arguments )
+	{
+		// Trim the arguments.
+		$arguments = trim($arguments);
+		
+		// Now split the arguments.
+		$arguments = explode(" ", $arguments);
+		
+		// Check whether 
+		
+		// Create a list of nodes.
+		$nodes = array();
+		
+		// Run through all document node.
+		foreach ( $this->nodes as $node => $position )
+		{
+			// Check whether the node has the ID we're looking for.
+			if ( in_array($this->nodes[$node]["attributes"]["id"],
+				$arguments) )
+			{
+				// Add this node to the list of nodes.
+				$nodes[] = $node;
+			}
+		}
+		
+		// Return the list of nodes.
+		return $nodes;
+	}
+	
+	/**
+	* Handles the XPath function name.
+	*
+	* This method handles the XPath function name.
+	*
+	* @access    private
+	* @author    Michael P. Mehl <[email protected]>
+	* @param     string $node Full path of the node on which the function
+	*            should be processed.
+	* @param     string $arguments String containing the arguments that were
+	*            passed to the function.
+	* @return    mixed Depending on the type of function being processed this 
+	*            method returns different types.
+	* @see       evaluate()
+	*/
+	function handle_function_name ( $node, $arguments )
+	{
+		// Return the name of the node.
+		return $this->nodes[$node]["name"];
+	}
+	
+	/**
+	* Handles the XPath function string.
+	*
+	* This method handles the XPath function string.
+	*
+	* @access    private
+	* @author    Michael P. Mehl <[email protected]>
+	* @param     string $node Full path of the node on which the function
+	*            should be processed.
+	* @param     string $arguments String containing the arguments that were
+	*            passed to the function.
+	* @return    mixed Depending on the type of function being processed this 
+	*            method returns different types.
+	* @see       evaluate()
+	*/
+	function handle_function_string ( $node, $arguments )
+	{
+		// Check what type of parameter is given
+		if ( ereg("^[0-9]+(\.[0-9]+)?$", $arguments) ||
+			ereg("^\.[0-9]+$", $arguments) )
+		{
+			// Convert the digits to a number.
+			$number = doubleval($arguments);
+				
+			// Return the number.
+			return strval($number);
+		}
+		elseif ( is_bool($arguments) )
+		{
+			// Check whether it's true.
+			if ( $arguments == true )
+			{
+				// Return true as a string.
+				return "true";
+			}
+			else
+			{
+				// Return false as a string.
+				return "false";
+			}
+		}
+		elseif ( !empty($arguments) )
+		{
+			// Use the argument as an XPath.
+			$result = $this->evaluate($arguments, $node);
+				
+			// Get the first argument.
+			$result = explode("|", implode("|", $result));
+				
+			// Return the first result as a string.
+			return $result[0];
+		}
+		elseif ( empty($arguments) )
+		{
+			// Return the current node.
+			return $node;
+		}
+		else
+		{
+			// Return an empty string.
+			return "";
+		}
+	}
+	
+	/**
+	* Handles the XPath function concat.
+	*
+	* This method handles the XPath function concat.
+	*
+	* @access    private
+	* @author    Michael P. Mehl <[email protected]>
+	* @param     string $node Full path of the node on which the function
+	*            should be processed.
+	* @param     string $arguments String containing the arguments that were
+	*            passed to the function.
+	* @return    mixed Depending on the type of function being processed this 
+	*            method returns different types.
+	* @see       evaluate()
+	*/
+	function handle_function_concat ( $node, $arguments )
+	{
+		// Split the arguments.
+		$arguments = explode(",", $arguments);
+			
+		// Run through each argument and evaluate it.
+		for ( $i = 0; $i < sizeof($arguments); $i++ )
+		{
+			// Trim each argument.
+			$arguments[$i] = trim($arguments[$i]);
+				
+			// Evaluate it.
+			$arguments[$i] = $this->evaluate_predicate($node, $arguments[$i]);
+		}
+			
+		// Put the string together.
+		$arguments = implode("", $arguments);
+			
+		// Return the string.
+		return $arguments;
+	}
+	
+	/**
+	* Handles the XPath function starts-with.
+	*
+	* This method handles the XPath function starts-with.
+	*
+	* @access    private
+	* @author    Michael P. Mehl <[email protected]>
+	* @param     string $node Full path of the node on which the function
+	*            should be processed.
+	* @param     string $arguments String containing the arguments that were
+	*            passed to the function.
+	* @return    mixed Depending on the type of function being processed this 
+	*            method returns different types.
+	* @see       evaluate()
+	*/
+	function handle_function_starts_with ( $node, $arguments )
+	{
+		// Get the arguments.
+		$first  = trim($this->prestr($arguments, ","));
+		$second = trim($this->afterstr($arguments, ","));
+			
+		// Evaluate each argument.
+		$first  = $this->evaluate_predicate($node, $first);
+		$second = $this->evaluate_predicate($node, $second);
+			
+		// Check whether the first string starts with the second one.
+		if ( ereg("^".$second, $first) )
+		{
+			// Return true.
+			return true;
+		}
+		else
+		{
+			// Return false.
+			return false;
+		}
+	}
+	
+	/**
+	* Handles the XPath function contains.
+	*
+	* This method handles the XPath function contains.
+	*
+	* @access    private
+	* @author    Michael P. Mehl <[email protected]>
+	* @param     string $node Full path of the node on which the function
+	*            should be processed.
+	* @param     string $arguments String containing the arguments that were
+	*            passed to the function.
+	* @return    mixed Depending on the type of function being processed this 
+	*            method returns different types.
+	* @see       evaluate()
+	*/
+	function handle_function_contains ( $node, $arguments )
+	{
+		// Get the arguments.
+		$first  = trim($this->prestr($arguments, ","));
+		$second = trim($this->afterstr($arguments, ","));
+			
+		// Evaluate each argument.
+		$first  = $this->evaluate_predicate($node, $first);
+		$second = $this->evaluate_predicate($node, $second);
+			
+		// Check whether the first string starts with the second one.
+		if ( ereg($second, $first) )
+		{
+			// Return true.
+			return true;
+		}
+		else
+		{
+			// Return false.
+			return false;
+		}
+	}
+	
+	/**
+	* Handles the XPath function substring-before.
+	*
+	* This method handles the XPath function substring-before.
+	*
+	* @access    private
+	* @author    Michael P. Mehl <[email protected]>
+	* @param     string $node Full path of the node on which the function
+	*            should be processed.
+	* @param     string $arguments String containing the arguments that were
+	*            passed to the function.
+	* @return    mixed Depending on the type of function being processed this 
+	*            method returns different types.
+	* @see       evaluate()
+	*/
+	function handle_function_substring_before ( $node, $arguments )
+	{
+		// Get the arguments.
+		$first  = trim($this->prestr($arguments, ","));
+		$second = trim($this->afterstr($arguments, ","));
+		  
+		// Evaluate each argument.
+		$first  = $this->evaluate_predicate($node, $first);
+		$second = $this->evaluate_predicate($node, $second);
+			
+		// Return the substring.
+		return $this->prestr(strval($first), strval($second));
+	}
+	
+	/**
+	* Handles the XPath function substring-after.
+	*
+	* This method handles the XPath function substring-after.
+	*
+	* @access    private
+	* @author    Michael P. Mehl <[email protected]>
+	* @param     string $node Full path of the node on which the function
+	*            should be processed.
+	* @param     string $arguments String containing the arguments that were
+	*            passed to the function.
+	* @return    mixed Depending on the type of function being processed this 
+	*            method returns different types.
+	* @see       evaluate()
+	*/
+	function handle_function_substring_after ( $node, $arguments )
+	{
+		// Get the arguments.
+		$first  = trim($this->prestr($arguments, ","));
+		$second = trim($this->afterstr($arguments, ","));
+			
+		// Evaluate each argument.
+		$first  = $this->evaluate_predicate($node, $first);
+		$second = $this->evaluate_predicate($node, $second);
+			
+		// Return the substring.
+		return $this->afterstr(strval($first), strval($second));
+	}
+	
+	/**
+	* Handles the XPath function substring.
+	*
+	* This method handles the XPath function substring.
+	*
+	* @access    private
+	* @author    Michael P. Mehl <[email protected]>
+	* @param     string $node Full path of the node on which the function
+	*            should be processed.
+	* @param     string $arguments String containing the arguments that were
+	*            passed to the function.
+	* @return    mixed Depending on the type of function being processed this 
+	*            method returns different types.
+	* @see       evaluate()
+	*/
+	function handle_function_substring ( $node, $arguments )
+	{
+		// Split the arguments.
+		$arguments = explode(",", $arguments);
+			
+		// Run through all arguments.
+		for ( $i = 0; $i < sizeof($arguments); $i++ )
+		{
+			// Trim the string.
+			$arguments[$i] = trim($arguments[$i]);
+				
+			// Evaluate each argument.
+			$arguments[$i] = $this->evaluate_predicate($node, $arguments[$i]);
+		}
+			
+		// Check whether a third argument was given.
+		if ( !empty($arguments[2]) )
+		{
+			// Return the substring.
+			return substr(strval($arguments[0]), $arguments[1] - 1,
+				$arguments[2]);
+		}
+		else
+		{
+			// Return the substring.
+			return substr(strval($arguments[0]), $arguments[1] - 1);
+		}
+	}
+	
+	/**
+	* Handles the XPath function string-length.
+	*
+	* This method handles the XPath function string-length.
+	*
+	* @access    private
+	* @author    Michael P. Mehl <[email protected]>
+	* @param     string $node Full path of the node on which the function
+	*            should be processed.
+	* @param     string $arguments String containing the arguments that were
+	*            passed to the function.
+	* @return    mixed Depending on the type of function being processed this 
+	*            method returns different types.
+	* @see       evaluate()
+	*/
+	function handle_function_string_length ( $node, $arguments )
+	{
+		// Trim the argument.
+		$arguments = trim($arguments);
+			
+		// Evaluate the argument.
+		$arguments = $this->evaluate_predicate($node, $arguments);
+			
+		// Return the length of the string.
+		return strlen(strval($arguments));
+	}
+	
+	/**
+	* Handles the XPath function translate.
+	*
+	* This method handles the XPath function translate.
+	*
+	* @access    private
+	* @author    Michael P. Mehl <[email protected]>
+	* @param     string $node Full path of the node on which the function
+	*            should be processed.
+	* @param     string $arguments String containing the arguments that were
+	*            passed to the function.
+	* @return    mixed Depending on the type of function being processed this 
+	*            method returns different types.
+	* @see       evaluate()
+	*/
+	function handle_function_translate ( $node, $arguments )         
+	{
+		// Split the arguments.
+		$arguments = explode(",", $arguments);
+		
+		// Run through all arguments.
+		for ( $i = 0; $i < sizeof($arguments); $i++ )
+		{
+			// Trim the argument.
+			$arguments[$i] = trim($arguments[$i]);
+			
+			// Evaluate the argument.
+			$arguments[$i] = $this->evaluate_predicate($node, $arguments[$i]);
+		}
+			
+		// Return the translated string.
+		return strtr($arguments[0], $arguments[1], $arguments[2]);
+	}
+	
+	/**
+	* Handles the XPath function boolean.
+	*
+	* This method handles the XPath function boolean.
+	*
+	* @access    private
+	* @author    Michael P. Mehl <[email protected]>
+	* @param     string $node Full path of the node on which the function
+	*            should be processed.
+	* @param     string $arguments String containing the arguments that were
+	*            passed to the function.
+	* @return    mixed Depending on the type of function being processed this 
+	*            method returns different types.
+	* @see       evaluate()
+	*/
+	function handle_function_boolean ( $node, $arguments )
+	{
+		// Trim the arguments.
+		$arguments = trim($arguments);
+		
+		// Check what type of parameter is given
+		if ( ereg("^[0-9]+(\.[0-9]+)?$", $arguments) ||
+			ereg("^\.[0-9]+$", $arguments) )
+		{
+			// Convert the digits to a number.
+			$number = doubleval($arguments);
+			
+			// Check whether the number zero.
+			if ( $number == 0 )
+			{
+				// Return false.
+				return false;
+			}
+			else
+			{
+				// Return true.
+				return true;
+			}
+		}
+		elseif ( empty($arguments) )
+		{
+			// Sorry, there were no arguments.
+			return false;
+		}
+		else
+		{
+			// Try to evaluate the argument as an XPath.
+			$result = $this->evaluate($arguments, $node);
+			
+			// Check whether we found something.
+			if ( count($result) > 0 )
+			{
+				// Return true.
+				return true;
+			}
+			else
+			{
+				// Return false.
+				return false;
+			}
+		}
+	}
+	
+	/**
+	* Handles the XPath function not.
+	*
+	* This method handles the XPath function not.
+	*
+	* @access    private
+	* @author    Michael P. Mehl <[email protected]>
+	* @param     string $node Full path of the node on which the function
+	*            should be processed.
+	* @param     string $arguments String containing the arguments that were
+	*            passed to the function.
+	* @return    mixed Depending on the type of function being processed this 
+	*            method returns different types.
+	* @see       evaluate()
+	*/
+	function handle_function_not ( $node, $arguments )
+	{
+		// Trim the arguments.
+		$arguments = trim($arguments);
+		
+		// Return the negative value of the content of the brackets.
+		return !$this->evaluate_predicate($node, $arguments);
+	}
+	
+	/**
+	* Handles the XPath function true.
+	*
+	* This method handles the XPath function true.
+	*
+	* @access    private
+	* @author    Michael P. Mehl <[email protected]>
+	* @param     string $node Full path of the node on which the function
+	*            should be processed.
+	* @param     string $arguments String containing the arguments that were
+	*            passed to the function.
+	* @return    mixed Depending on the type of function being processed this 
+	*            method returns different types.
+	* @see       evaluate()
+	*/
+	function handle_function_true ( $node, $arguments )
+	{
+		// Return true.
+		return true;
+	}
+	
+	/**
+	* Handles the XPath function false.
+	*
+	* This method handles the XPath function false.
+	*
+	* @access    private
+	* @author    Michael P. Mehl <[email protected]>
+	* @param     string $node Full path of the node on which the function
+	*            should be processed.
+	* @param     string $arguments String containing the arguments that were
+	*            passed to the function.
+	* @return    mixed Depending on the type of function being processed this 
+	*            method returns different types.
+	* @see       evaluate()
+	*/
+	function handle_function_false ( $node, $arguments )
+	{
+		// Return false.
+		return false;
+	}
+	
+	/**
+	* Handles the XPath function lang.
+	*
+	* This method handles the XPath function lang.
+	*
+	* @access    private
+	* @author    Michael P. Mehl <[email protected]>
+	* @param     string $node Full path of the node on which the function
+	*            should be processed.
+	* @param     string $arguments String containing the arguments that were
+	*            passed to the function.
+	* @return    mixed Depending on the type of function being processed this 
+	*            method returns different types.
+	* @see       evaluate()
+	*/
+	function handle_function_lang ( $node, $arguments )
+	{
+		// Trim the arguments.
+		$arguments = trim($arguments);
+		
+		// Check whether the node has an language attribute.
+		if ( empty($this->nodes[$node]["attributes"]["xml:lang"]) )
+		{
+			// Run through the ancestors.
+			while ( !empty($node) )
+			{
+				// Select the parent node.
+				$node = $this->nodes[$node]["parent"];
+				
+				// Check whether there's a language definition.
+				if ( !empty($this->nodes[$node]["attributes"]["xml:lang"]) )
+				{
+					// Check whether it's the language, the user asks for.
+					if ( eregi("^".$arguments, $this->nodes[$node]
+						["attributes"]["xml:lang"]) )
+					{
+						// Return true.
+						return true;
+					}
+					else
+					{
+						// Return false.
+						return false;
+					}
+				}
+			}
+			
+			// Return false.
+			return false;
+		}
+		else
+		{
+			// Check whether it's the language, the user asks for.
+			if ( eregi("^".$arguments, $this->nodes[$node]["attributes"]
+				["xml:lang"]) )
+			{
+				// Return true.
+				return true;
+			}
+			else
+			{
+				// Return false.
+				return false;
+			}
+		}
+	}
+	
+	/**
+	* Handles the XPath function number.
+	*
+	* This method handles the XPath function number.
+	*
+	* @access    private
+	* @author    Michael P. Mehl <[email protected]>
+	* @param     string $node Full path of the node on which the function
+	*            should be processed.
+	* @param     string $arguments String containing the arguments that were
+	*            passed to the function.
+	* @return    mixed Depending on the type of function being processed this 
+	*            method returns different types.
+	* @see       evaluate()
+	*/
+	function handle_function_number ( $node, $arguments )
+	{
+		// Check the type of argument.
+		if ( ereg("^[0-9]+(\.[0-9]+)?$", $arguments) ||
+			ereg("^\.[0-9]+$", $arguments) )
+		{
+			// Return the argument as a number.
+			return doubleval($arguments);
+		}
+		elseif ( is_bool($arguments) )
+		{
+			// Check whether it's true.
+			if ( $arguments == true )
+			{
+				// Return 1.
+				return 1;
+			}
+			else
+			{
+				// Return 0.
+				return 0;
+			}
+		}
+	}
+	
+	/**
+	* Handles the XPath function sum.
+	*
+	* This method handles the XPath function sum.
+	*
+	* @access    private
+	* @author    Michael P. Mehl <[email protected]>
+	* @param     string $node Full path of the node on which the function
+	*            should be processed.
+	* @param     string $arguments String containing the arguments that were
+	*            passed to the function.
+	* @return    mixed Depending on the type of function being processed this 
+	*            method returns different types.
+	* @see       evaluate()
+	*/
+	function handle_function_sum ( $node, $arguments )
+	{
+		// Trim the arguments.
+		$arguments = trim($arguments);
+		
+		// Evaluate the arguments as an XPath expression.
+		$results = $this->evaluate($arguments, $node);
+		
+		// Create a variable to save the sum.
+		$sum = 0;
+		
+		// Run through all results.
+		foreach ( $results as $result )
+		{
+			// Get the value of the node.
+			$result = $this->get_content($result);
+			
+			// Add it to the sum.
+			$sum += doubleval($result);
+		}
+		
+		// Return the sum.
+		return $sum;
+	}
+	
+	/**
+	* Handles the XPath function floor.
+	*
+	* This method handles the XPath function floor.
+	*
+	* @access    private
+	* @author    Michael P. Mehl <[email protected]>
+	* @param     string $node Full path of the node on which the function
+	*            should be processed.
+	* @param     string $arguments String containing the arguments that were
+	*            passed to the function.
+	* @return    mixed Depending on the type of function being processed this 
+	*            method returns different types.
+	* @see       evaluate()
+	*/
+	function handle_function_floor ( $node, $arguments )
+	{
+		// Trim the arguments.
+		$arguments = trim($arguments);
+		
+		// Convert the arguments to a number.
+		$arguments = doubleval($arguments);
+		
+		// Return the result
+		return floor($arguments);
+	}
+	
+	/**
+	* Handles the XPath function ceiling.
+	*
+	* This method handles the XPath function ceiling.
+	*
+	* @access    private
+	* @author    Michael P. Mehl <[email protected]>
+	* @param     string $node Full path of the node on which the function
+	*            should be processed.
+	* @param     string $arguments String containing the arguments that were
+	*            passed to the function.
+	* @return    mixed Depending on the type of function being processed this 
+	*            method returns different types.
+	* @see       evaluate()
+	*/
+	function handle_function_ceiling ( $node, $arguments )
+	{
+		// Trim the arguments.
+		$arguments = trim($arguments);
+		
+		// Convert the arguments to a number.
+		$arguments = doubleval($arguments);
+		
+		// Return the result
+		return ceil($arguments);
+	}
+	
+	/**
+	* Handles the XPath function round.
+	*
+	* This method handles the XPath function round.
+	*
+	* @access    private
+	* @author    Michael P. Mehl <[email protected]>
+	* @param     string $node Full path of the node on which the function
+	*            should be processed.
+	* @param     string $arguments String containing the arguments that were
+	*            passed to the function.
+	* @return    mixed Depending on the type of function being processed this 
+	*            method returns different types.
+	* @see       evaluate()
+	*/
+	function handle_function_round ( $node, $arguments )
+	{
+		// Trim the arguments.
+		$arguments = trim($arguments);
+		
+		// Convert the arguments to a number.
+		$arguments = doubleval($arguments);
+		
+		// Return the result
+		return round($arguments);
+	}
+	
+	/**
+	* Handles the XPath function text.
+	*
+	* This method handles the XPath function text.
+	*
+	* @access    private
+	* @author    Michael P. Mehl <[email protected]>
+	* @param     string $node Full path of the node on which the function
+	*            should be processed.
+	* @param     string $arguments String containing the arguments that were
+	*            passed to the function.
+	* @return    mixed Depending on the type of function being processed this 
+	*            method returns different types.
+	* @see       evaluate()
+	*/
+	function handle_function_text ( $node, $arguments )
+	{
+		// Return the character data of the node.
+		return $this->nodes[$node]["text"];
+	}
+	
+	/**
+	* Retrieves a substring before a delimiter.
+	*
+	* This method retrieves everything from a string before a given delimiter,
+	* not including the delimiter.
+	*
+	* @access    private
+	* @author    Michael P. Mehl <[email protected]>
+	* @param     string $string String, from which the substring should be
+	*            extracted.
+	* @param     string $delimiter String containing the delimiter to use.
+	* @return    string Substring from the original string before the
+	*            delimiter.
+	* @see       afterstr()
+	*/
+	function prestr ( $string, $delimiter )
+	{
+		// Return the substring.
+		return substr($string, 0, strlen($string) - strlen(strstr($string,
+			"$delimiter")));
+	}
+	
+	/**
+	* Retrieves a substring after a delimiter.
+	*
+	* This method retrieves everything from a string after a given delimiter,
+	* not including the delimiter.
+	*
+	* @access    private
+	* @author    Michael P. Mehl <[email protected]>
+	* @param     string $string String, from which the substring should be
+	*            extracted.
+	* @param     string $delimiter String containing the delimiter to use.
+	* @return    string Substring from the original string after the
+	*            delimiter.
+	* @see       prestr()
+	*/
+	function afterstr ( $string, $delimiter )
+	{
+		// Return the substring.
+		return substr($string,
+			strpos($string, $delimiter) + strlen($delimiter));
+	}
+	
+	/**
+	* Displays an error message.
+	*
+	* This method displays an error messages and stops the execution of the
+	* script. This method is called exactly in the same way as the printf
+	* function. The first argument contains the message and additional
+	* arguments of various types may be passed to this method to be inserted
+	* into the message.
+	*
+	* @access    private
+	* @author    Michael P. Mehl <[email protected]>
+	* @param     string $message Error message to be displayed.
+	*/
+	function display_error ( $message )
+	{
+		// Check whether more than one argument was given.
+		if ( func_num_args() > 1 )
+		{
+			// Read all arguments.
+			$arguments = func_get_args();
+			
+			// Create a new string for the inserting command.
+			$command = "\$message = sprintf(\$message, ";
+			
+			// Run through the array of arguments.
+			for ( $i = 1; $i < sizeof($arguments); $i++ )
+			{
+				// Add the number of the argument to the command.
+				$command .= "\$arguments[".$i."], ";
+			}
+			
+			// Replace the last separator.
+			$command = eregi_replace(", $", ");", $command);
+			
+			// Execute the command.
+			eval($command);
+		}
+		
+		// Display the error message.
+		echo "<b>phpXML error:</b> ".$message;
+		
+		// End the execution of this script.
+		exit;
+	}
+}
+
+?>
\ No newline at end of file


Property changes on: people/sigurdne/modules/phpgwapi/trunk/inc/class.xml.inc.php
___________________________________________________________________
Added: svn:keywords
   + Id Revision
Added: svn:eol-style
   + native

Modified: people/sigurdne/modules/phpgwapi/trunk/inc/class.xmlrpc_client.inc.php
===================================================================
--- people/sigurdne/modules/phpgwapi/trunk/inc/class.xmlrpc_client.inc.php	2009-11-20 10:27:41 UTC (rev 20844)
+++ people/sigurdne/modules/phpgwapi/trunk/inc/class.xmlrpc_client.inc.php	2009-11-20 10:28:10 UTC (rev 20845)
@@ -1,1120 +1,58 @@
 <?php
 	/**
-	* XMLRPC client
-	* @author Edd Dumbill <[email protected]>
-	* @copyright Copyright (C) 1999-2001 Edd Dumbill
-	* @package phpgwapi
-	* @subpackage xml
-	* @version $Id$
-	*/
-
-// Redistribution and use in source and binary forms, with or without
-// modification, are permitted provided that the following conditions
-// are met:
-//
-//    * Redistributions of source code must retain the above copyright
-//      notice, this list of conditions and the following disclaimer.
-//
-//    * Redistributions in binary form must reproduce the above
-//      copyright notice, this list of conditions and the following
-//      disclaimer in the documentation and/or other materials provided
-//      with the distribution.
-//
-//    * Neither the name of the "XML-RPC for PHP" nor the names of its
-//      contributors may be used to endorse or promote products derived
-//      from this software without specific prior written permission.
-//
-// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
-// FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
-// REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
-// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
-// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
-// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
-// HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
-// STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
-// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
-// OF THE POSSIBILITY OF SUCH DAMAGE.
-
-	require_once PHPGW_API_INC . '/xml_functions.inc.php';
-
-	/**
-	* XMLRPC client
-	* 
-	* @package phpgwapi
-	* @subpackage xml
-	*/
-	class xmlrpc_client
-	{
-		var $path;
-		var $server;
-		var $port=0;
-		var $method='http';
-		var $errno;
-		var $errstr;
-		var $debug=0;
-		var $username='';
-		var $password='';
-		var $authtype=1;
-		var $cert='';
-		var $certpass='';
-		var $cacert='';
-		var $cacertdir='';
-		var $key='';
-		var $keypass='';
-		var $verifypeer=true;
-		var $verifyhost=1;
-		var $no_multicall=false;
-		var $proxy='';
-		var $proxyport=0;
-		var $proxy_user='';
-		var $proxy_pass='';
-		var $proxy_authtype=1;
-		var $cookies=array();
-		/**
-		* List of http compression methods accepted by the client for responses.
-		* NB: PHP supports deflate, gzip compressions out of the box if compiled w. zlib
+	* phpGroupWare
 		*
-		* NNB: you can set it to any non-empty array for HTTP11 and HTTPS, since
-		* in those cases it will be up to CURL to decide the compression methods
-		* it supports. You might check for the presence of 'zlib' in the output of
-		* curl_version() to determine wheter compression is supported or not
+	* @author Sigurd Nes <[email protected]>
+	* @copyright Copyright (C) 2009 Free Software Foundation, Inc. http://www.fsf.org/
+	* @license http://www.gnu.org/licenses/gpl.html GNU General Public License
+	* @internal Development of this application was funded by http://www.bergen.kommune.no/bbb_/ekstern/
+	* @package phpgroupware
+	* @subpackage communication
+	* @category core
+ 	* @version $Id$
 		*/
-		var $accepted_compression = array();
-		/**
-		* Name of compression scheme to be used for sending requests.
-		* Either null, gzip or deflate
-		*/
-		var $request_compression = '';
-		/**
-		* CURL handle: used for keep-alive connections (PHP 4.3.8 up, see:
-		* http://curl.haxx.se/docs/faq.html#7.3)
-		*/
-		var $xmlrpc_curl_handle = null;
-		/// Wheter to use persistent connections for http 1.1 and https
-		var $keepalive = false;
-		/// Charset encodings that can be decoded without problems by the client
-		var $accepted_charset_encodings = array();
-		/// Charset encoding to be used in serializing request. NULL = use ASCII
-		var $request_charset_encoding = '';
-		/**
-		* Decides the content of xmlrpcresp objects returned by calls to send()
-		* valid strings are 'xmlrpcvals', 'phpvals' or 'xml'
-		*/
-		var $return_type = 'xmlrpcvals';
 
-		/**
-		* @param string $path either the complete server URL or the PATH part of the xmlrc server URL, e.g. /xmlrpc/server.php
-		* @param string $server the server name / ip address
-		* @param integer $port the port the server is listening on, defaults to 80 or 443 depending on protocol used
-		* @param string $method the http protocol variant: defaults to 'http', 'https' and 'http11' can be used if CURL is installed
-		*/
-		function xmlrpc_client($path, $server='', $port='', $method='')
-		{
-			// allow user to specify all params in $path
-			if($server == '' and $port == '' and $method == '')
-			{
-				$parts = parse_url($path);
-				$server = $parts['host'];
-				$path = $parts['path'];
-				if(isset($parts['query']))
-				{
-					$path .= '?'.$parts['query'];
-				}
-				if(isset($parts['fragment']))
-				{
-					$path .= '#'.$parts['fragment'];
-				}
-				if(isset($parts['port']))
-				{
-					$port = $parts['port'];
-				}
-				if(isset($parts['scheme']))
-				{
-					$method = $parts['scheme'];
-				}
-				if(isset($parts['user']))
-				{
-					$this->username = $parts['user'];
-				}
-				if(isset($parts['pass']))
-				{
-					$this->password = $parts['pass'];
-				}
-			}
-			if($path == '' || $path[0] != '/')
-			{
-				$this->path='/'.$path;
-			}
-			else
-			{
-				$this->path=$path;
-			}
-			$this->server=$server;
-			if($port != '')
-			{
-				$this->port=$port;
-			}
-			if($method != '')
-			{
-				$this->method=$method;
-			}
+	/*
+	   This program is free software: you can redistribute it and/or modify
+	   it under the terms of the GNU General Public License as published by
+	   the Free Software Foundation, either version 2 of the License, or
+	   (at your option) any later version.
 
-			// if ZLIB is enabled, let the client by default accept compressed responses
-			if(function_exists('gzinflate') || (
-				function_exists('curl_init') && (($info = curl_version()) &&
-				((is_string($info) && strpos($info, 'zlib') !== null) || isset($info['libz_version'])))
-			))
-			{
-				$this->accepted_compression = array('gzip', 'deflate');
-			}
+	   This program is distributed in the hope that it will be useful,
+	   but WITHOUT ANY WARRANTY; without even the implied warranty of
+	   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+	   GNU General Public License for more details.
 
-			// keepalives: enabled by default ONLY for PHP >= 4.3.8
-			// (see http://curl.haxx.se/docs/faq.html#7.3)
-			if(version_compare(phpversion(), '4.3.8') >= 0)
-			{
-				$this->keepalive = true;
-			}
-
-			// by default the xml parser can support these 3 charset encodings
-			$this->accepted_charset_encodings = array('UTF-8', 'ISO-8859-1', 'US-ASCII');
-		}
-
-		/**
-		* Enables/disables the echoing to screen of the xmlrpc responses received
-		* @param integer $debug values 0, 1 and 2 are supported (2 = echo sent msg too, before received response)
-		* @access public
+	   You should have received a copy of the GNU General Public License
+	   along with this program.  If not, see <http://www.gnu.org/licenses/>.
 		*/
-		function setDebug($in)
-		{
-			$this->debug=$in;
-		}
 
 		/**
-		* Add some http BASIC AUTH credentials, used by the client to authenticate
-		* @param string $u username
-		* @param string $p password
-		* @param integer $t auth type. See curl_setopt man page for supported auth types. Defaults to CURLAUTH_BASIC (basic auth)
-		* @access public
-		*/
-		function setCredentials($u, $p, $t=1)
-		{
-			$this->username=$u;
-			$this->password=$p;
-			$this->authtype=$t;
-		}
-
-		/**
-		* Add a client-side https certificate
-		* @param string $cert
-		* @param string $certpass
-		* @access public
-		*/
-		function setCertificate($cert, $certpass)
-		{
-			$this->cert = $cert;
-			$this->certpass = $certpass;
-		}
-
-		/**
-		* Add a CA certificate to verify server with (see man page about
-		* CURLOPT_CAINFO for more details
-		* @param string $cacert certificate file name (or dir holding certificates)
-		* @param bool $is_dir set to true to indicate cacert is a dir. defaults to false
-		* @access public
-		*/
-		function setCaCertificate($cacert, $is_dir=false)
-		{
-			if ($is_dir)
-			{
-				$this->cacert = $cacert;
-			}
-			else
-			{
-				$this->cacertdir = $cacert;
-			}
-		}
-
-		/**
-		* Set attributes for SSL communication: private SSL key
-		* @param string $key The name of a file containing a private SSL key
-		* @param string $keypass The secret password needed to use the private SSL key
-		* @access public
-		* NB: does not work in older php/curl installs
-		* Thanks to Daniel Convissor
-		*/
-		function setKey($key, $keypass)
-		{
-			$this->key = $key;
-			$this->keypass = $keypass;
-		}
-
-		/**
-		* Set attributes for SSL communication: verify server certificate
-		* @param bool $i enable/disable verification of peer certificate
-		* @access public
-		*/
-		function setSSLVerifyPeer($i)
-		{
-			$this->verifypeer = $i;
-		}
-
-		/**
-		* Set attributes for SSL communication: verify match of server cert w. hostname
-		* @param int $i
-		* @access public
-		*/
-		function setSSLVerifyHost($i)
-		{
-			$this->verifyhost = $i;
-		}
-
-		/**
-		* Set proxy info
-		* @param string $proxyhost
-		* @param string $proxyport Defaults to 8080 for HTTP and 443 for HTTPS
-		* @param string $proxyusername Leave blank if proxy has public access
-		* @param string $proxypassword Leave blank if proxy has public access
-		* @param int $proxyauthtype set to constant CURLAUTH_MTLM to use NTLM auth with proxy
-		* @access public
-		*/
-		function setProxy($proxyhost, $proxyport, $proxyusername = '', $proxypassword = '', $proxyauthtype = 1)
-		{
-			$this->proxy = $proxyhost;
-			$this->proxyport = $proxyport;
-			$this->proxy_user = $proxyusername;
-			$this->proxy_pass = $proxypassword;
-			$this->proxy_autthtype = $proxyauthtype;
-		}
-
-		/**
-		* Enables/disables reception of compressed xmlrpc responses.
-		* Note that enabling reception of compressed responses merely adds some standard
-		* http headers to xmlrpc requests. It is up to the xmlrpc server to return
-		* compressed responses when receiving such requests.
-		* @param string $compmethod either 'gzip', 'deflate', 'any' or ''
-		* @access public
-		*/
-		function setAcceptedCompression($compmethod)
-		{
-			if ($compmethod == 'any')
-				$this->accepted_compression = array('gzip', 'deflate');
-			else
-				$this->accepted_compression = array($compmethod);
-		}
-
-		/**
-		* Enables/disables http compression of xmlrpc request.
-		* Take care when sending compressed requests: servers might not support them
-		* (and automatic fallback to uncompressed requests is not yet implemented)
-		* @param string $compmethod either 'gzip', 'deflate' or ''
-		* @access public
-		*/
-		function setRequestCompression($compmethod)
-		{
-			$this->request_compression = $compmethod;
-		}
-
-		/**
-		* Adds a cookie to list of cookies that will be sent to server.
-		* NB: setting any param but name and value will turn the cookie into a 'version 1' cookie:
-		* do not do it unless you know what you are doing
-		* @param string $name
-		* @param string $value
-		* @param string $path
-		* @param string $domain
-		* @param int $port
-		* @access public
+	 * xmlrpc_client
 		*
-		* @todo check correctness of urlencoding cookie value (copied from php way of doing it...)
+	 * @package phpgroupware
+	 * @subpackage communication
+	 * @category core
 		*/
-		function setCookie($name, $value='', $path='', $domain='', $port=null)
-		{
-			$this->cookies[$name]['value'] = urlencode($value);
-			if ($path || $domain || $port)
-			{
-				$this->cookies[$name]['path'] = $path;
-				$this->cookies[$name]['domain'] = $domain;
-				$this->cookies[$name]['port'] = $port;
-				$this->cookies[$name]['version'] = 1;
-			}
-			else
-			{
-				$this->cookies[$name]['version'] = 0;
-			}
-		}
 
-		/**
-		* Send an xmlrpc request
-		* @param mixed $msg The message object, or an array of messages for using multicall, or the complete xml representation of a request
-		* @param integer $timeout Connection timeout, in seconds, If unspecified, a platform specific timeout will apply
-		* @param string $method if left unspecified, the http protocol chosen during creation of the object will be used
-		* @return xmlrpcresp
-		* @access public
-		*/
-		function& send($msg, $timeout=0, $method='')
-		{
-			// if user deos not specify http protocol, use native method of this client
-			// (i.e. method set during call to constructor)
-			if($method == '')
-			{
-				$method = $this->method;
-			}
+	require_once PHPGW_API_INC . '/xmlrpc/lib/xmlrpc.inc';
+	require_once PHPGW_API_INC . '/xmlrpc/lib/xmlrpcs.inc';
+	require_once PHPGW_API_INC . '/xmlrpc/lib/xmlrpc_wrappers.inc';
 
-			if(is_array($msg))
-			{
-				// $msg is an array of xmlrpcmsg's
-				$r = $this->multicall($msg, $timeout, $method);
-				return $r;
-			}
-			elseif(is_string($msg))
-			{
-				$n =& new xmlrpcmsg('');
-				$n->payload = $msg;
-				$msg = $n;
-			}
-
-			// where msg is an xmlrpcmsg
-			$msg->debug=$this->debug;
-
-			if($method == 'https')
-			{
-				$r =& $this->sendPayloadHTTPS(
-					$msg,
-					$this->server,
-					$this->port,
-					$timeout,
-					$this->username,
-					$this->password,
-					$this->authtype,
-					$this->cert,
-					$this->certpass,
-					$this->cacert,
-					$this->cacertdir,
-					$this->proxy,
-					$this->proxyport,
-					$this->proxy_user,
-					$this->proxy_pass,
-					$this->proxy_authtype,
-					$this->keepalive,
-					$this->key,
-					$this->keypass
-				);
-			}
-			elseif($method == 'http11')
-			{
-				$r =& $this->sendPayloadCURL(
-					$msg,
-					$this->server,
-					$this->port,
-					$timeout,
-					$this->username,
-					$this->password,
-					$this->authtype,
-					null,
-					null,
-					null,
-					null,
-					$this->proxy,
-					$this->proxyport,
-					$this->proxy_user,
-					$this->proxy_pass,
-					$this->proxy_authtype,
-					'http',
-					$this->keepalive
-				);
-			}
-			else
-			{
-				$r =& $this->sendPayloadHTTP10(
-					$msg,
-					$this->server,
-					$this->port,
-					$timeout,
-					$this->username,
-					$this->password,
-					$this->authtype,
-					$this->proxy,
-					$this->proxyport,
-					$this->proxy_user,
-					$this->proxy_pass,
-					$this->proxy_authtype
-				);
-			}
-
-			return $r;
-		}
-
-		/**
-		* @access private
-		*/
-		function &sendPayloadHTTP10($msg, $server, $port, $timeout=0,
-			$username='', $password='', $authtype=1, $proxyhost='',
-			$proxyport=0, $proxyusername='', $proxypassword='', $proxyauthtype=1)
+	class phpgwapi_xmlrpc_client
 		{
-			if($port==0)
-			{
-				$port=80;
-			}
-
-			// Only create the payload if it was not created previously
-			if(empty($msg->payload))
-			{
-				$msg->createPayload($this->request_charset_encoding);
-			}
-
-			$payload = $msg->payload;
-			// Deflate request body and set appropriate request headers
-			if(function_exists('gzdeflate') && ($this->request_compression == 'gzip' || $this->request_compression == 'deflate'))
-			{
-				if($this->request_compression == 'gzip')
-				{
-					$a = @gzencode($payload);
-					if($a)
-					{
-						$payload = $a;
-						$encoding_hdr = "Content-Encoding: gzip\r\n";
-					}
-				}
-				else
-				{
-					$a = @gzcompress($payload);
-					if($a)
-					{
-						$payload = $a;
-						$encoding_hdr = "Content-Encoding: deflate\r\n";
-					}
-				}
-			}
-			else
-			{
-				$encoding_hdr = '';
-			}
-
-			// thanks to Grant Rauscher <[email protected]> for this
-			$credentials='';
-			if($username!='')
-			{
-				$credentials='Authorization: Basic ' . base64_encode($username . ':' . $password) . "\r\n";
-				if ($authtype != 1)
-				{
-					error_log('XML-RPC: xmlrpc_client::send: warning. Only Basic auth is supported with HTTP 1.0');
-				}
-			}
-
-			$accepted_encoding = '';
-			if(is_array($this->accepted_compression) && count($this->accepted_compression))
-			{
-				$accepted_encoding = 'Accept-Encoding: ' . implode(', ', $this->accepted_compression) . "\r\n";
-			}
-
-			$proxy_credentials = '';
-			if($proxyhost)
-			{
-				if($proxyport == 0)
-				{
-					$proxyport = 8080;
-				}
-				$connectserver = $proxyhost;
-				$connectport = $proxyport;
-				$uri = 'http://'.$server.':'.$port.$this->path;
-				if($proxyusername != '')
-				{
-					if ($proxyauthtype != 1)
-					{
-						error_log('XML-RPC: xmlrpc_client::send: warning. Only Basic auth to proxy is supported with HTTP 1.0');
-					}
-					$proxy_credentials = 'Proxy-Authorization: Basic ' . base64_encode($proxyusername.':'.$proxypassword) . "\r\n";
-				}
-			}
-			else
-			{
-				$connectserver = $server;
-				$connectport = $port;
-				$uri = $this->path;
-			}
-
-			// Cookie generation, as per rfc2965 (version 1 cookies) or
-			// netscape's rules (version 0 cookies)
-			$cookieheader='';
-			foreach ($this->cookies as $name => $cookie)
-			{
-				if ($cookie['version'])
-				{
-					$cookieheader .= 'Cookie: $Version="' . $cookie['version'] . '"; ';
-					$cookieheader .= $name . '="' . $cookie['value'] . '";';
-					if ($cookie['path'])
-						$cookieheader .= ' $Path="' . $cookie['path'] . '";';
-					if ($cookie['domain'])
-						$cookieheader .= ' $Domain="' . $cookie['domain'] . '";';
-					if ($cookie['port'])
-						$cookieheader .= ' $Port="' . $cookie['domain'] . '";';
-					$cookieheader = substr($cookieheader, 0, -1) . "\r\n";
-				}
-				else
-				{
-					$cookieheader .= 'Cookie: ' . $name . '=' . $cookie['value'] . "\r\n";
-				}
-			}
-
-			$op= 'POST ' . $uri. " HTTP/1.0\r\n" .
-				'User-Agent: ' . $GLOBALS['xmlrpcName'] . ' ' . $GLOBALS['xmlrpcVersion'] . "\r\n" .
-				'Host: '. $server . ':' . $port . "\r\n" .
-				$credentials .
-				$proxy_credentials .
-				$accepted_encoding .
-				$encoding_hdr .
-				'Accept-Charset: ' . implode(',', $this->accepted_charset_encodings) . "\r\n" .
-				$cookieheader .
-				'Content-Type: ' . $msg->content_type . "\r\nContent-Length: " .
-				strlen($payload) . "\r\n\r\n" .
-				$payload;
-
-			if($this->debug > 1)
-			{
-				print "<PRE>\n---SENDING---\n" . htmlentities($op) . "\n---END---\n</PRE>";
-				// let the client see this now in case http times out...
-				flush();
-			}
-
-			if($timeout>0)
-			{
-				$fp=@fsockopen($connectserver, $connectport, $this->errno, $this->errstr, $timeout);
-			}
-			else
-			{
-				$fp=@fsockopen($connectserver, $connectport, $this->errno, $this->errstr);
-			}
-			if($fp)
-			{
-				if($timeout>0 && function_exists('stream_set_timeout'))
-				{
-					stream_set_timeout($fp, $timeout);
-				}
-			}
-			else
-			{
-				$this->errstr='Connect error: '.$this->errstr;
-				$r=&new xmlrpcresp(0, $GLOBALS['xmlrpcerr']['http_error'], $this->errstr . ' (' . $this->errno . ')');
-				return $r;
-			}
-
-			if(!fputs($fp, $op, strlen($op)))
-			{
-				$this->errstr='Write error';
-				$r=&new xmlrpcresp(0, $GLOBALS['xmlrpcerr']['http_error'], $this->errstr);
-				return $r;
-			}
-			else
-			{
-				// reset errno and errstr on succesful socket connection
-				$this->errstr = '';
-			}
-			// G. Giunta 2005/10/24: close socket before parsing.
-			// should yeld slightly better execution times, and make easier recursive calls (e.g. to follow http redirects)
-			$ipd='';
-			while($data=fread($fp, 32768))
-			{
-				// shall we check for $data === FALSE?
-				// as per the manual, it signals an error
-				$ipd.=$data;
-			}
-			fclose($fp);
-			$r =& $msg->parseResponse($ipd, false, $this->return_type);
-			return $r;
-
-		}
-
 		/**
-		* @access private
+		* @var 
 		*/
-		function &sendPayloadHTTPS($msg, $server, $port, $timeout=0, $username='',
-			$password='', $authtype=1, $cert='',$certpass='', $cacert='', $cacertdir='',
-			$proxyhost='', $proxyport=0, $proxyusername='', $proxypassword='', $proxyauthtype=1,
-			$keepalive=false, $key='', $keypass='')
-		{
-			$r =& $this->sendPayloadCURL($msg, $server, $port, $timeout, $username,
-				$password, $authtype, $cert, $certpass, $cacert, $cacertdir, $proxyhost, $proxyport,
-				$proxyusername, $proxypassword, $proxyauthtype, 'https', $keepalive, $key, $keypass);
-			return $r;
-		}
 
 		/**
-		* Contributed by Justin Miller <[email protected]>
-		* Requires curl to be built into PHP
-		* NB: CURL versions before 7.11.10 cannot use proxy to talk to https servers!
-		* @access private
-		*/
-		function &sendPayloadCURL($msg, $server, $port, $timeout=0, $username='',
-			$password='', $authtype=1, $cert='', $certpass='', $cacert='', $cacertdir='',
-			$proxyhost='', $proxyport=0, $proxyusername='', $proxypassword='', $proxyauthtype=1, $method='https',
-			$keepalive=false, $key='', $keypass='')
-		{
-			if(!function_exists('curl_init'))
-			{
-				$this->errstr='CURL unavailable on this install';
-				$r=&new xmlrpcresp(0, $GLOBALS['xmlrpcerr']['no_curl'], $GLOBALS['xmlrpcstr']['no_curl']);
-				return $r;
-			}
-			if($method == 'https')
-			{
-				if(($info = curl_version()) &&
-					((is_string($info) && strpos($info, 'OpenSSL') === null) || (is_array($info) && !isset($info['ssl_version']))))
-				{
-					$this->errstr='SSL unavailable on this install';
-					$r=&new xmlrpcresp(0, $GLOBALS['xmlrpcerr']['no_ssl'], $GLOBALS['xmlrpcstr']['no_ssl']);
-					return $r;
-				}
-			}
-
-			if($port == 0)
-			{
-				if($method == 'http')
-				{
-					$port = 80;
-				}
-				else
-				{
-					$port = 443;
-				}
-			}
-
-			// Only create the payload if it was not created previously
-			if(empty($msg->payload))
-			{
-				$msg->createPayload($this->request_charset_encoding);
-			}
-
-			// Deflate request body and set appropriate request headers
-			$payload = $msg->payload;
-			if(function_exists('gzdeflate') && ($this->request_compression == 'gzip' || $this->request_compression == 'deflate'))
-			{
-				if($this->request_compression == 'gzip')
-				{
-					$a = @gzencode($payload);
-					if($a)
-					{
-						$payload = $a;
-						$encoding_hdr = 'Content-Encoding: gzip';
-					}
-				}
-				else
-				{
-					$a = @gzcompress($payload);
-					if($a)
-					{
-						$payload = $a;
-						$encoding_hdr = 'Content-Encoding: deflate';
-					}
-				}
-			}
-			else
-			{
-				$encoding_hdr = '';
-			}
-
-			if($this->debug > 1)
-			{
-				print "<PRE>\n---SENDING---\n" . htmlentities($payload) . "\n---END---\n</PRE>";
-				// let the client see this now in case http times out...
-				flush();
-			}
-
-			if(!$keepalive || !$this->xmlrpc_curl_handle)
-			{
-				$curl = curl_init($method . '://' . $server . ':' . $port . $this->path);
-				if($keepalive)
-				{
-					$this->xmlrpc_curl_handle = $curl;
-				}
-			}
-			else
-			{
-				$curl = $this->xmlrpc_curl_handle;
-			}
-
-			// results into variable
-			curl_setopt($curl, CURLOPT_RETURNTRANSFER, 1);
-
-			if($this->debug)
-			{
-				curl_setopt($curl, CURLOPT_VERBOSE, 1);
-			}
-			curl_setopt($curl, CURLOPT_USERAGENT, $GLOBALS['xmlrpcName'].' '.$GLOBALS['xmlrpcVersion']);
-			// required for XMLRPC: post the data
-			curl_setopt($curl, CURLOPT_POST, 1);
-			// the data
-			curl_setopt($curl, CURLOPT_POSTFIELDS, $payload);
-
-			// return the header too
-			curl_setopt($curl, CURLOPT_HEADER, 1);
-
-			// will only work with PHP >= 5.0
-			// NB: if we set an empty string, CURL will add http header indicating
-			// ALL methods it is supporting. This is possibly a better option than
-			// letting the user tell what curl can / cannot do...
-			if(is_array($this->accepted_compression) && count($this->accepted_compression))
-			{
-				//curl_setopt($curl, CURLOPT_ENCODING, implode(',', $this->accepted_compression));
-				// empty string means 'any supported by CURL' (shall we catch errors in case CURLOPT_SSLKEY undefined ?)
-				if (count($this->accepted_compression) == 1)
-				{
-					curl_setopt($curl, CURLOPT_ENCODING, $this->accepted_compression[0]);
-				}
-				else
-					curl_setopt($curl, CURLOPT_ENCODING, '');
-			}
-			// extra headers
-			$headers = array('Content-Type: ' . $msg->content_type , 'Accept-Charset: ' . implode(',', $this->accepted_charset_encodings));
-			// if no keepalive is wanted, let the server know it in advance
-			if(!$keepalive)
-			{
-				$headers[] = 'Connection: close';
-			}
-			// request compression header
-			if($encoding_hdr)
-			{
-				$headers[] = $encoding_hdr;
-			}
-
-			curl_setopt($curl, CURLOPT_HTTPHEADER, $headers);
-			// timeout is borked
-			if($timeout)
-			{
-				curl_setopt($curl, CURLOPT_TIMEOUT, $timeout == 1 ? 1 : $timeout - 1);
-			}
-
-			if($username && $password)
-			{
-				curl_setopt($curl, CURLOPT_USERPWD, $username.':'.$password);
-				if (defined('CURLOPT_HTTPAUTH'))
-				{
-					curl_setopt($curl, CURLOPT_HTTPAUTH, $authtype);
-				}
-				else if ($authtype != 1)
-				{
-					error_log('XML-RPC: xmlrpc_client::send: warning. Only Basic auth is supported by the current PHP/curl install');
-				}
-			}
-
-			if($method == 'https')
-			{
-				// set cert file
-				if($cert)
-				{
-					curl_setopt($curl, CURLOPT_SSLCERT, $cert);
-				}
-				// set cert password
-				if($certpass)
-				{
-					curl_setopt($curl, CURLOPT_SSLCERTPASSWD, $certpass);
-				}
-				// whether to verify remote host's cert
-				curl_setopt($curl, CURLOPT_SSL_VERIFYPEER, $this->verifypeer);
-				// set ca certificates file/dir
-				if($cacert)
-				{
-					curl_setopt($curl, CURLOPT_CAINFO, $cacert);
-				}
-				if($cacertdir)
-				{
-					curl_setopt($curl, CURLOPT_CAPATH, $cacertdir);
-				}
-				// set key file (shall we catch errors in case CURLOPT_SSLKEY undefined ?)
-				if($key)
-				{
-					curl_setopt($curl, CURLOPT_SSLKEY, $key);
-				}
-				// set key password (shall we catch errors in case CURLOPT_SSLKEY undefined ?)
-				if($keypass)
-				{
-					curl_setopt($curl, CURLOPT_SSLKEYPASSWD, $keypass);
-				}
-				// whether to verify cert's common name (CN); 0 for no, 1 to verify that it exists, and 2 to verify that it matches the hostname used
-				curl_setopt($curl, CURLOPT_SSL_VERIFYHOST, $this->verifyhost);
-			}
-
-			// proxy info
-			if($proxyhost)
-			{
-				if($proxyport == 0)
-				{
-					$proxyport = 8080; // NB: even for HTTPS, local connection is on port 8080
-				}
-				curl_setopt($curl, CURLOPT_PROXY,$proxyhost.':'.$proxyport);
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.