From 2f784ca08157c16a993845a9375e8b7ac6e44f37 Mon Sep 17 00:00:00 2001
From: Gunnar Wrobel
Date: Fri, 3 Apr 2009 12:16:35 +0200
Subject: [PATCH] Initial import of koward.
This application should replace the kolab-webadmin in the long run. It
is primarily intended as an LDAP database manager based on the
Kolab_Server library.
---
koward/app/controllers/ApplicationController.php | 40 ++++
koward/app/controllers/CheckController.php | 59 ++++++
koward/app/controllers/IndexController.php | 21 ++
koward/app/controllers/ObjectController.php | 144 ++++++++++++++
koward/app/views/Check/run.html.php | 10 +
koward/app/views/Check/show.html.php | 9 +
koward/app/views/Index/index.html.php | 6 +
koward/app/views/Modify/add.html.php | 6 +
koward/app/views/Object/delete.html.php | 2 +
koward/app/views/Object/edit.html.php | 4 +
koward/app/views/Object/listall.html.php | 37 ++++
koward/app/views/Object/view.html.php | 3 +
koward/app/views/shared/_header.html.php | 36 ++++
koward/app/views/shared/_menu.html.php | 5 +
koward/bin/bootstrap.php | 15 ++
koward/config/attributes.php | 26 +++
koward/config/conf.php | 3 +
koward/config/objects.php | 44 +++++
koward/config/routes.php | 12 ++
koward/doc/QUESTIONS.txt | 5 +
koward/lib/Exception.php | 30 +++
koward/lib/Form/Object.php | 118 ++++++++++++
koward/lib/Koward.php | 87 +++++++++
koward/lib/Test.php | 173 +++++++++++++++++
koward/lib/Test/AllTests.php | 78 ++++++++
koward/lib/Test/Renderer.php | 44 +++++
koward/lib/Test/Server/UserTest.php | 43 +++++
koward/lib/Test/Template/scenario.html.dist | 13 ++
koward/lib/Test/Template/scenario_header.html.dist | 6 +
koward/lib/Test/Template/scenarios.html.dist | 54 ++++++
koward/lib/Test/Template/step.html.dist | 6 +
koward/test/AllTests.php | 83 ++++++++
koward/test/KowardTest.php | 95 +++++++++
koward/test/TestInit.php | 25 +++
koward/themes/graphics/favicon.ico | Bin 0 -> 1406 bytes
koward/themes/graphics/query.png | Bin 0 -> 223 bytes
koward/themes/kolab/screen.css | 212 +++++++++++++++++++++
37 files changed, 1554 insertions(+)
create mode 100644 koward/app/controllers/ApplicationController.php
create mode 100644 koward/app/controllers/CheckController.php
create mode 100644 koward/app/controllers/IndexController.php
create mode 100644 koward/app/controllers/ObjectController.php
create mode 100644 koward/app/views/Check/run.html.php
create mode 100644 koward/app/views/Check/show.html.php
create mode 100644 koward/app/views/Index/index.html.php
create mode 100644 koward/app/views/Modify/add.html.php
create mode 100644 koward/app/views/Object/delete.html.php
create mode 100644 koward/app/views/Object/edit.html.php
create mode 100644 koward/app/views/Object/listall.html.php
create mode 100644 koward/app/views/Object/view.html.php
create mode 100644 koward/app/views/shared/_header.html.php
create mode 100644 koward/app/views/shared/_menu.html.php
create mode 100644 koward/bin/bootstrap.php
create mode 100644 koward/config/attributes.php
create mode 100644 koward/config/conf.php
create mode 100644 koward/config/objects.php
create mode 100644 koward/config/routes.php
create mode 100644 koward/doc/QUESTIONS.txt
create mode 100644 koward/lib/Exception.php
create mode 100644 koward/lib/Form/Object.php
create mode 100644 koward/lib/Koward.php
create mode 100644 koward/lib/Test.php
create mode 100644 koward/lib/Test/AllTests.php
create mode 100644 koward/lib/Test/Renderer.php
create mode 100644 koward/lib/Test/Server/UserTest.php
create mode 100644 koward/lib/Test/Template/scenario.html.dist
create mode 100644 koward/lib/Test/Template/scenario_header.html.dist
create mode 100644 koward/lib/Test/Template/scenarios.html.dist
create mode 100644 koward/lib/Test/Template/step.html.dist
create mode 100644 koward/test/AllTests.php
create mode 100644 koward/test/KowardTest.php
create mode 100644 koward/test/TestInit.php
create mode 100644 koward/themes/graphics/favicon.ico
create mode 100644 koward/themes/graphics/query.png
create mode 100644 koward/themes/kolab/screen.css
diff --git a/koward/app/controllers/ApplicationController.php b/koward/app/controllers/ApplicationController.php
new file mode 100644
index 000000000..55cfd478e
--- /dev/null
+++ b/koward/app/controllers/ApplicationController.php
@@ -0,0 +1,40 @@
+koward = Koward_Koward::singleton();
+
+ $this->types = array_keys($this->koward->objects);
+ if (empty($this->types)) {
+ throw new KowardException('No object types have been configured!');
+ }
+
+ $this->menu = $this->getMenu();
+
+ $this->theme = isset($this->koward->conf['koward']['theme']) ? $this->koward->conf['koward']['theme'] : 'koward';
+ }
+
+ /**
+ * Builds Koward's list of menu items.
+ */
+ public function getMenu()
+ {
+ global $registry;
+
+ require_once 'Horde/Menu.php';
+ $menu = new Menu();
+
+ $menu->add($this->urlFor(array('controller' => 'object', 'action' => 'listall')),
+ _("_Objects"), 'user.png', $registry->getImageDir('horde'));
+ $menu->add($this->urlFor(array('controller' => 'object', 'action' => 'edit')),
+ _("_Add"), 'plus.png', $registry->getImageDir('horde'));
+ $menu->add(Horde::applicationUrl('search'), _("_Search"), 'search.png', $registry->getImageDir('horde'));
+ $menu->add(Horde::applicationUrl('Queries'), _("_Queries"), 'query.png', $registry->getImageDir('koward'));
+ $menu->add($this->urlFor(array('controller' => 'check', 'action' => 'show')),
+ _("_Test"), 'problem.png', $registry->getImageDir('horde'));
+
+ return $menu;
+ }
+}
diff --git a/koward/app/controllers/CheckController.php b/koward/app/controllers/CheckController.php
new file mode 100644
index 000000000..39bf83e5b
--- /dev/null
+++ b/koward/app/controllers/CheckController.php
@@ -0,0 +1,59 @@
+suite = Koward_Test_AllTests::suite();
+ }
+
+ public function show()
+ {
+ $this->list = array();
+
+ $this->list[0] = Horde::link(
+ $this->urlFor(array('controller' => 'check',
+ 'action' => 'run',
+ 'id' => 'all')),
+ _("All tests")) . _("All tests") . '';
+
+ $this->list[1] = '';
+
+ for ($i = 0; $i < $this->suite->count(); $i++) {
+ $class_name = $this->suite->testAt($i)->getName();
+ $this->list[$i + 2] = Horde::link(
+ $this->urlFor(array('controller' => 'check',
+ 'action' => 'run',
+ 'id' => $i + 1)),
+ $class_name) . $class_name . '';
+ }
+ }
+
+ public function run()
+ {
+
+ if ($this->params['id'] == 'all') {
+ $this->test = $this->suite;
+ } else {
+ $id = (int) $this->params['id'];
+ if (!empty($id)) {
+ $this->test = $this->suite->testAt($id - 1);
+ } else {
+ $this->test = null;
+ $this->koward->notification->push(_("You selected no test!"));
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/koward/app/controllers/IndexController.php b/koward/app/controllers/IndexController.php
new file mode 100644
index 000000000..40e2c7702
--- /dev/null
+++ b/koward/app/controllers/IndexController.php
@@ -0,0 +1,21 @@
+title = _("Index");
+ $this->welcome = _("Welcome to the Koward administration interface");
+ }
+}
\ No newline at end of file
diff --git a/koward/app/controllers/ObjectController.php b/koward/app/controllers/ObjectController.php
new file mode 100644
index 000000000..f76f32dac
--- /dev/null
+++ b/koward/app/controllers/ObjectController.php
@@ -0,0 +1,144 @@
+object_type = $this->params->get('id', $this->types[0]);
+
+ if (isset($this->koward->objects[$this->object_type])) {
+ $this->attributes = $this->koward->objects[$this->object_type]['attributes'];
+ $params = array('attributes' => array_keys($this->attributes));
+ $this->objectlist = $this->koward->server->listHash($this->object_type,
+ $params);
+ foreach ($this->objectlist as $uid => $info) {
+ $this->objectlist[$uid]['edit_url'] = Horde::link(
+ $this->urlFor(array('controller' => 'object',
+ 'action' => 'edit',
+ 'id' => $uid)),
+ _("Edit")) . Horde::img('edit.png', _("Edit"), '',
+ $GLOBALS['registry']->getImageDir('horde'))
+ . '';
+ $this->objectlist[$uid]['delete_url'] = Horde::link(
+ $this->urlFor(array('controller' => 'object',
+ 'action' => 'delete',
+ 'id' => $uid)),
+ _("Delete")) . Horde::img('delete.png', _("Delete"), '',
+ $GLOBALS['registry']->getImageDir('horde'))
+ . '';
+ $this->objectlist[$uid]['view_url'] = Horde::link(
+ $this->urlFor(array('controller' => 'object',
+ 'action' => 'view',
+ 'id' => $uid)), _("View"));
+ }
+ } else {
+ $this->objectlist = 'Unkown object type.';
+ }
+ $this->tabs = new Horde_UI_Tabs(null, Variables::getDefaultVariables());
+ foreach ($this->koward->objects as $key => $configuration) {
+ $this->tabs->addTab($configuration['list_label'],
+ $this->urlFor(array('controller' => 'object',
+ 'action' => 'listall',
+ 'id' => $key)),
+ $key);
+ }
+
+ $this->render();
+ }
+
+ public function delete()
+ {
+ try {
+ if (empty($this->params->id)) {
+ $this->koward->notification->push(_("The object that should be deleted has not been specified."),
+ 'horde.error');
+ } else {
+ $this->object = $this->koward->getObject($this->params->id);
+ if (empty($this->params->submit)) {
+ $this->token = $this->koward->getRequestToken('object.delete');
+ } else {
+ $this->koward->checkRequestToken('object.delete', $this->params->token);
+ $this->object->delete();
+ $this->koward->notification->push(sprintf(_("Successfully deleted the object \"%s\""),
+ $this->params->id),
+ 'horde.message');
+ header('Location: ' . $this->urlFor(array('controller' => 'object',
+ 'action' => 'listall',
+ 'id' => get_class($this->object))));
+ exit;
+ }
+ }
+ } catch (Exception $e) {
+ $this->koward->notification->push($e->getMessage(), 'horde.error');
+ }
+
+ $this->render();
+ }
+
+ public function view()
+ {
+ try {
+ if (empty($this->params->id)) {
+ $this->koward->notification->push(_("The object that should be viewed has not been specified."),
+ 'horde.error');
+ } else {
+ $this->object = $this->koward->getObject($this->params->id);
+
+ require_once 'Horde/Variables.php';
+ $this->vars = Variables::getDefaultVariables();
+ $this->form = new Koward_Form_Object($this->vars, $this->object,
+ array('title' => _("View object")));
+ }
+ } catch (Exception $e) {
+ $this->koward->notification->push($e->getMessage(), 'horde.error');
+ }
+
+ $this->render();
+ }
+
+ public function edit()
+ {
+ try {
+ if (empty($this->params->id)) {
+ $this->object = null;
+ } else {
+ $this->object = $this->koward->getObject($this->params->id);
+ }
+
+ require_once 'Horde/Variables.php';
+ $this->vars = Variables::getDefaultVariables();
+ $this->form = new Koward_Form_Object($this->vars, $this->object);
+
+ if ($this->form->validate()) {
+ $object = $this->form->execute();
+
+ header('Location: ' . $this->urlFor(array('controller' => 'object',
+ 'action' => 'view',
+ 'id' => $object->get(Horde_Koward_Server_Object::ATTRIBUTE_UID))));
+ exit;
+ }
+ } catch (Exception $e) {
+ $this->koward->notification->push($e->getMessage(), 'horde.error');
+ }
+
+ $this->post = $this->urlFor(array('controller' => 'object',
+ 'action' => 'edit',
+ 'id' => $this->params->id));
+
+ $this->render();
+ }
+}
\ No newline at end of file
diff --git a/koward/app/views/Check/run.html.php b/koward/app/views/Check/run.html.php
new file mode 100644
index 000000000..ea945e832
--- /dev/null
+++ b/koward/app/views/Check/run.html.php
@@ -0,0 +1,10 @@
+= $this->renderPartial('header'); ?>
+= $this->renderPartial('menu'); ?>
+
+test)) {
+ ob_start();
+ $listener = new Koward_Test_Renderer();
+ PHPUnit_TextUI_TestRunner::run($this->test, array('listeners' => array($listener)));
+ echo ob_get_clean();
+}
\ No newline at end of file
diff --git a/koward/app/views/Check/show.html.php b/koward/app/views/Check/show.html.php
new file mode 100644
index 000000000..f58908fef
--- /dev/null
+++ b/koward/app/views/Check/show.html.php
@@ -0,0 +1,9 @@
+= $this->renderPartial('header'); ?>
+= $this->renderPartial('menu'); ?>
+
+list as $test) {
+ echo $test;
+ echo '
';
+}
\ No newline at end of file
diff --git a/koward/app/views/Index/index.html.php b/koward/app/views/Index/index.html.php
new file mode 100644
index 000000000..0696b72ec
--- /dev/null
+++ b/koward/app/views/Index/index.html.php
@@ -0,0 +1,6 @@
+= $this->renderPartial('header'); ?>
+= $this->renderPartial('menu'); ?>
+
+
+
= $this->welcome ?>
+
diff --git a/koward/app/views/Modify/add.html.php b/koward/app/views/Modify/add.html.php
new file mode 100644
index 000000000..fb15bbee4
--- /dev/null
+++ b/koward/app/views/Modify/add.html.php
@@ -0,0 +1,6 @@
+= $this->renderPartial('header'); ?>
+= $this->renderPartial('menu'); ?>
+
+form->renderActive(new Horde_Form_Renderer(), $vars, 'modify', 'post');
+
diff --git a/koward/app/views/Object/delete.html.php b/koward/app/views/Object/delete.html.php
new file mode 100644
index 000000000..055e78c2a
--- /dev/null
+++ b/koward/app/views/Object/delete.html.php
@@ -0,0 +1,2 @@
+= $this->renderPartial('header'); ?>
+= $this->renderPartial('menu'); ?>
diff --git a/koward/app/views/Object/edit.html.php b/koward/app/views/Object/edit.html.php
new file mode 100644
index 000000000..5185924e7
--- /dev/null
+++ b/koward/app/views/Object/edit.html.php
@@ -0,0 +1,4 @@
+= $this->renderPartial('header'); ?>
+= $this->renderPartial('menu'); ?>
+= $this->form->renderActive(new Horde_Form_Renderer(), $this->vars,
+ $this->post, 'post'); ?>
\ No newline at end of file
diff --git a/koward/app/views/Object/listall.html.php b/koward/app/views/Object/listall.html.php
new file mode 100644
index 000000000..d53aa87c2
--- /dev/null
+++ b/koward/app/views/Object/listall.html.php
@@ -0,0 +1,37 @@
+= $this->renderPartial('header'); ?>
+= $this->renderPartial('menu'); ?>
+
+= $this->tabs->render($this->object_type); ?>
+
+
+
+
+ | getImageDir('horde')) ?> |
+ getImageDir('horde')) ?> |
+ attributes as $attribute => $info): ?>
+ = $info['title'] ?> |
+
+
+
+
+ objectlist as $dn => $info): ?>
+
+ |
+ = $info['edit_url'] ?>
+ |
+
+ = $info['delete_url'] ?>
+ |
+ attributes as $attribute => $ainfo): ?>
+
+
+ = $info['view_url'] . $this->escape($info[$attribute]) . ''; ?>
+
+ = $this->escape($info[$attribute]) ?>
+
+ |
+
+
+
+
+
diff --git a/koward/app/views/Object/view.html.php b/koward/app/views/Object/view.html.php
new file mode 100644
index 000000000..f26176458
--- /dev/null
+++ b/koward/app/views/Object/view.html.php
@@ -0,0 +1,3 @@
+= $this->renderPartial('header'); ?>
+= $this->renderPartial('menu'); ?>
+= $this->form->renderInactive(new Horde_Form_Renderer(), $this->vars); ?>
\ No newline at end of file
diff --git a/koward/app/views/shared/_header.html.php b/koward/app/views/shared/_header.html.php
new file mode 100644
index 000000000..dc72ba84e
--- /dev/null
+++ b/koward/app/views/shared/_header.html.php
@@ -0,0 +1,36 @@
+
+
+
+
+' : '' ?>
+
+get('name');
+$page_title .= !empty($this->title) ? ' :: ' . $this->title : '';
+
+Horde::includeScriptFiles();
+?>
+
+
+
+print_view) ? $this->theme : 'print') ?>
+
+
+
+
diff --git a/koward/app/views/shared/_menu.html.php b/koward/app/views/shared/_menu.html.php
new file mode 100644
index 000000000..3be3269c7
--- /dev/null
+++ b/koward/app/views/shared/_menu.html.php
@@ -0,0 +1,5 @@
+
+koward->notification->notify(array('listeners' => 'status')) ?>
+
diff --git a/koward/bin/bootstrap.php b/koward/bin/bootstrap.php
new file mode 100644
index 000000000..8003cabb8
--- /dev/null
+++ b/koward/bin/bootstrap.php
@@ -0,0 +1,15 @@
+ 'int')),
+);
+$parser = new Horde_Argv_Parser(array('optionList' => $options));
+list($opts, $tags) = $parser->parseArgs();
+
+if (!$opts->not_defined) {
+ throw new InvalidArgumentException('');
+}
+
+exit(0);
diff --git a/koward/config/attributes.php b/koward/config/attributes.php
new file mode 100644
index 000000000..3a4908610
--- /dev/null
+++ b/koward/config/attributes.php
@@ -0,0 +1,26 @@
+ _("First Name"),
+ 'type' => 'text',
+ 'required' => true,
+ 'params' => array('regex' => '', 'size' => 40, 'maxlength' => 255)
+);
+$attributes['sn'] = array(
+ 'label' => _("Last Name"),
+ 'type' => 'text',
+ 'required' => true,
+ 'params' => array('regex' => '', 'size' => 40, 'maxlength' => 255)
+);
+$attributes['mail'] = array(
+ 'label' => _("Mail address"),
+ 'type' => 'text',
+ 'required' => true,
+ 'params' => array('regex' => '', 'size' => 40, 'maxlength' => 255)
+);
+$attributes['uid'] = array(
+ 'label' => _("User ID"),
+ 'type' => 'text',
+ 'required' => true,
+ 'params' => array('regex' => '', 'size' => 40, 'maxlength' => 255)
+);
diff --git a/koward/config/conf.php b/koward/config/conf.php
new file mode 100644
index 000000000..656621cbe
--- /dev/null
+++ b/koward/config/conf.php
@@ -0,0 +1,3 @@
+ _("Object"),
+ 'list_label' => _("Objects"),
+ 'attributes' => array(
+ 'id' => array(
+ 'title' => _("Object id"),
+ 'width' => 80,
+ 'link_view'=> true,
+ ),
+ ),
+);
+
+$objects['Horde_Kolab_Server_Object_user'] = array(
+ 'label' => _("User"),
+ 'list_label' => _("Users"),
+ 'attributes' => array(
+ 'sn' => array(
+ 'title' => _("Last name"),
+ 'width' => 20,
+ ),
+ 'givenName' => array(
+ 'title' => _("First name"),
+ 'width' => 20,
+ ),
+ 'mail' => array(
+ 'title' => _("E-mail"),
+ 'width' => 20,
+ 'link_view'=> true,
+ ),
+ 'uid' => array(
+ 'title' => _("User ID"),
+ 'width' => 20,
+ ),
+ ),
+);
+
+$objects['Horde_Kolab_Server_Object_administrator'] = array(
+ 'label' => _("Administrator"),
+ 'list_label' => _("Administrators"),
+ 'attributes' => array(
+ ),
+);
diff --git a/koward/config/routes.php b/koward/config/routes.php
new file mode 100644
index 000000000..10434784f
--- /dev/null
+++ b/koward/config/routes.php
@@ -0,0 +1,12 @@
+connect('index', array('controller' => 'index'));
+$mapper->connect('index.php', array('controller' => 'index'));
+
+$mapper->connect('check/:action/:id', array('controller' => 'check', 'action' => 'show'));
+$mapper->connect(':controller/:action/:id', array('controller' => 'object'));
+
+// Local route overrides
+if (file_exists(dirname(__FILE__) . '/routes.local.php')) {
+ include dirname(__FILE__) . '/routes.local.php';
+}
diff --git a/koward/doc/QUESTIONS.txt b/koward/doc/QUESTIONS.txt
new file mode 100644
index 000000000..0955803d4
--- /dev/null
+++ b/koward/doc/QUESTIONS.txt
@@ -0,0 +1,5 @@
+Can we have mixed CLI and html views? If we can, will these be in a library install location?
+
+How to add translations?
+
+How to install via PEAR?
diff --git a/koward/lib/Exception.php b/koward/lib/Exception.php
new file mode 100644
index 000000000..3498db45e
--- /dev/null
+++ b/koward/lib/Exception.php
@@ -0,0 +1,30 @@
+
+ * @license http://www.fsf.org/copyleft/lgpl.html LGPL
+ * @link http://pear.horde.org/index.php?package=Koward_Server
+ */
+
+/**
+ * This class provides the standard error class for the Koward application.
+ *
+ * Copyright 2009 The Horde Project (http://www.horde.org/)
+ *
+ * See the enclosed file COPYING for license information (LGPL). If you
+ * did not receive this file, see http://www.fsf.org/copyleft/lgpl.html.
+ *
+ * @category Kolab
+ * @package Koward_Server
+ * @author Gunnar Wrobel
+ * @license http://www.fsf.org/copyleft/lgpl.html LGPL
+ * @link http://pear.horde.org/index.php?package=Koward_Server
+ */
+class Koward_Exception extends Exception
+{
+}
diff --git a/koward/lib/Form/Object.php b/koward/lib/Form/Object.php
new file mode 100644
index 000000000..5a4a35208
--- /dev/null
+++ b/koward/lib/Form/Object.php
@@ -0,0 +1,118 @@
+koward = &Koward_Koward::singleton();
+
+ $this->object = &$object;
+
+ parent::Horde_Form($vars);
+
+ if (empty($this->object)) {
+ $title = _("Add Object");
+ $this->setButtons(_("Add"));
+
+ foreach ($this->koward->objects as $key => $config) {
+ $options[$key] = $config['label'];
+ }
+
+ $v = &$this->addVariable(_("Choose an object type"), 'type', 'enum', true, false, null, array($options, true));
+ $action = Horde_Form_Action::factory('submit');
+ $v->setAction($action);
+ $v->setOption('trackchange', true);
+ if (is_null($vars->get('formname')) &&
+ $vars->get($v->getVarName()) != $vars->get('__old_' . $v->getVarName())) {
+ $this->koward->notification->push(sprintf(_("Selected object type \"%s\"."), $object_conf[$vars->get('type')]['label']), 'horde.message');
+ }
+ } else {
+ $title = _("Edit Object");
+ $type = get_class($this->object);
+ if (!$this->isSubmitted()) {
+ $vars->set('type', $type);
+ $keys = array_keys($this->koward->objects[$type]['attributes']);
+ $vars->set('object', $this->object->toHash($keys));
+ $this->setButtons(_("Edit"));
+ }
+ }
+
+ if (isset($params['title'])) {
+ $title = $params['title'];
+ }
+
+ $this->setTitle($title);
+
+ $type = $vars->get('type');
+ if (isset($type)) {
+ $this->_addFields($this->koward->objects[$type]);
+ }
+ }
+
+ /**
+ * Set up the Horde_Form fields for the attributes of this object type.
+ */
+ function _addFields($config)
+ {
+ // Now run through and add the form variables.
+ $fields = isset($config['attributes']) ? $config['attributes'] : array();
+ $tabs = isset($config['tabs']) ? $config['tabs'] : array('' => $fields);
+
+ foreach ($tabs as $tab => $tab_fields) {
+ if (!empty($tab)) {
+ $this->setSection($tab, $tab);
+ }
+ foreach ($tab_fields as $key => $field) {
+ if (!in_array($key, array_keys($fields)) ||
+ !isset($this->koward->attributes[$key])) {
+ continue;
+ }
+
+ $attribute = $this->koward->attributes[$key];
+ $params = isset($attribute['params']) ? $attribute['params'] : array();
+ $desc = isset($attribute['desc']) ? $attribute['desc'] : null;
+
+ $readonly = isset($attribute['readonly']) ? $attribute['readonly'] : null;
+ $v = &$this->addVariable($attribute['label'], 'object[' . $key . ']', $attribute['type'], $attribute['required'], $readonly, $desc, $params);
+ }
+
+ if (isset($attribute['default'])) {
+ $v->setDefault($attribute['default']);
+ }
+ }
+ }
+
+ function &execute()
+ {
+ $this->getInfo($this->_vars, $info);
+ if (isset($info['object'])) {
+ if (empty($this->object)) {
+ if (isset($info['type'])) {
+ $object = $this->koward->server->add(array_merge(array('type' => $info['type']),
+ $info['object']));
+ $this->koward->notification->push(_("Successfully added the object."),
+ 'horde.message');
+ return $object;
+ }
+ } else {
+ $this->object->save($info['object']);
+ $this->koward->notification->push(_("Successfully updated the object."),
+ 'horde.message');
+ return $this->object;
+ }
+ }
+ }
+}
diff --git a/koward/lib/Koward.php b/koward/lib/Koward.php
new file mode 100644
index 000000000..744eea6fa
--- /dev/null
+++ b/koward/lib/Koward.php
@@ -0,0 +1,87 @@
+
+ * @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html
+ * @category Kolab
+ * @package Koward
+ */
+
+class Koward_Koward {
+
+ /**
+ * The singleton instance.
+ *
+ * @var Koward_Koward
+ */
+ static protected $instance = null;
+
+ public $objectconf;
+
+ public function __construct()
+ {
+ require_once 'Horde/Notification.php';
+ require_once 'Horde/Registry.php';
+
+ $this->notification = Notification::singleton();
+ $this->registry = Registry::singleton();
+
+ $result = $this->registry->pushApp('koward', false);
+ if ($result instanceOf PEAR_Error) {
+ $this->notification->push($result);
+ }
+
+ $this->conf = Horde::loadConfiguration('conf.php', 'conf');
+ $this->objects = Horde::loadConfiguration('objects.php', 'objects');
+ $this->attributes = Horde::loadConfiguration('attributes.php', 'attributes');
+ $this->server = Horde_Kolab_Server::singleton();
+ }
+
+ /**
+ * Get a token for protecting a form.
+ *
+ * @param string $seed TODO
+ *
+ * @return TODO
+ */
+ static public function getRequestToken($seed)
+ {
+ $token = Horde_Token::generateId($seed);
+ $_SESSION['horde_form_secrets'][$token] = time();
+ return $token;
+ }
+
+ /**
+ * Check if a token for a form is valid.
+ *
+ * @param string $seed TODO
+ * @param string $token TODO
+ *
+ * @throws Horde_Exception
+ */
+ static public function checkRequestToken($seed, $token)
+ {
+ if (empty($_SESSION['horde_form_secrets'][$token])) {
+ throw new Horde_Exception(_("We cannot verify that this request was really sent by you. It could be a malicious request. If you intended to perform this action, you can retry it now."));
+ }
+
+ if ($_SESSION['horde_form_secrets'][$token] + $GLOBALS['conf']['server']['token_lifetime'] < time()) {
+ throw new Horde_Exception(sprintf(_("This request cannot be completed because the link you followed or the form you submitted was only valid for %d minutes. Please try again now."), round($GLOBALS['conf']['server']['token_lifetime'] / 60)));
+ }
+ }
+
+ public function getObject($uid)
+ {
+ return $this->server->fetch($uid);
+ }
+
+ static public function singleton()
+ {
+ if (!isset(self::$instance)) {
+ self::$instance = new Koward_Koward();
+ }
+
+ return self::$instance;
+ }
+}
\ No newline at end of file
diff --git a/koward/lib/Test.php b/koward/lib/Test.php
new file mode 100644
index 000000000..62b937973
--- /dev/null
+++ b/koward/lib/Test.php
@@ -0,0 +1,173 @@
+
+ * @license http://www.fsf.org/copyleft/lgpl.html LGPL
+ * @link http://pear.horde.org/index.php?package=Koward
+ */
+
+/**
+ * Base for PHPUnit scenarios.
+ *
+ * Copyright 2009 The Horde Project (http://www.horde.org/)
+ *
+ * See the enclosed file COPYING for license information (LGPL). If you
+ * did not receive this file, see http://www.fsf.org/copyleft/lgpl.html.
+ *
+ * @category Kolab
+ * @package Koward
+ * @author Gunnar Wrobel
+ * @license http://www.fsf.org/copyleft/lgpl.html LGPL
+ * @link http://pear.horde.org/index.php?package=Koward
+ */
+class Koward_Test extends Horde_Kolab_Test_Storage
+{
+ /**
+ * Prepare the configuration.
+ *
+ * @return NULL
+ */
+ public function prepareConfiguration()
+ {
+ $fh = fopen(HORDE_BASE . '/config/conf.php', 'w');
+ $data = <<applications['horde'] = array(
+ 'fileroot' => dirname(__FILE__) . '/..',
+ 'webroot' => '/',
+ 'initial_page' => 'login.php',
+ 'name' => _("Horde"),
+ 'status' => 'active',
+ 'templates' => dirname(__FILE__) . '/../templates',
+ 'provides' => 'horde',
+);
+
+\$this->applications['koward'] = array(
+ 'fileroot' => KOWARD_BASE,
+ 'webroot' => \$this->applications['horde']['webroot'] . '/koward',
+ 'name' => _("Koward"),
+ 'status' => 'active',
+ 'initial_page' => 'index.php',
+);
+EOD;
+ fwrite($fh, "
+ * @license http://www.fsf.org/copyleft/lgpl.html LGPL
+ * @link http://pear.horde.org/index.php?package=Kolab_Server
+ */
+
+/**
+ * The Autoloader allows us to omit "require/include" statements.
+ */
+require_once 'Horde/Autoloader.php';
+
+/**
+ * Combine the tests for this package.
+ *
+ * Copyright 2007-2009 The Horde Project (http://www.horde.org/)
+ *
+ * See the enclosed file COPYING for license information (LGPL). If you
+ * did not receive this file, see http://www.fsf.org/copyleft/lgpl.html.
+ *
+ * @category Kolab
+ * @package Kolab_Server
+ * @author Gunnar Wrobel
+ * @license http://www.fsf.org/copyleft/lgpl.html LGPL
+ * @link http://pear.horde.org/index.php?package=Kolab_Server
+ */
+class Koward_Test_AllTests
+{
+
+ /**
+ * Main entry point for running the suite.
+ *
+ * @return NULL
+ */
+ public static function main()
+ {
+ PHPUnit_TextUI_TestRunner::run(self::suite());
+ }
+
+ /**
+ * Collect the unit tests of this directory into a new suite.
+ *
+ * @return PHPUnit_Framework_TestSuite The test suite.
+ */
+ public static function suite()
+ {
+ // Catch strict standards
+ // FIXME: This does not work yet, as we still have a number of
+ // static methods in basic Horde libraries that are not
+ // declared as such.
+ //error_reporting(E_ALL | E_STRICT);
+
+ $suite = new PHPUnit_Framework_TestSuite('Kolab server test suite');
+
+ $basedir = dirname(__FILE__);
+ $baseregexp = preg_quote($basedir . DIRECTORY_SEPARATOR, '/');
+
+ foreach (new RecursiveIteratorIterator(new RecursiveDirectoryIterator($basedir)) as $file) {
+ if ($file->isFile() && preg_match('/Test.php$/', $file->getFilename())) {
+ $pathname = $file->getPathname();
+ require $pathname;
+
+ $class = str_replace(DIRECTORY_SEPARATOR, '_',
+ preg_replace("/^$baseregexp(.*)\.php/", '\\1', $pathname));
+ $suite->addTestSuite('Koward_Test_' . $class);
+ }
+ }
+
+ return $suite;
+ }
+
+}
diff --git a/koward/lib/Test/Renderer.php b/koward/lib/Test/Renderer.php
new file mode 100644
index 000000000..e8308aa1f
--- /dev/null
+++ b/koward/lib/Test/Renderer.php
@@ -0,0 +1,44 @@
+templatePath = sprintf(
+ '%s%sTemplate%s',
+
+ dirname(__FILE__),
+ DIRECTORY_SEPARATOR,
+ DIRECTORY_SEPARATOR
+ );
+ }
+
+ /**
+ * @param string $buffer
+ */
+ public function write($buffer)
+ {
+ if ($this->out !== NULL) {
+ fwrite($this->out, $buffer);
+
+ if ($this->autoFlush) {
+ $this->incrementalFlush();
+ }
+ } else {
+
+ print $buffer;
+
+ if ($this->autoFlush) {
+ $this->incrementalFlush();
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/koward/lib/Test/Server/UserTest.php b/koward/lib/Test/Server/UserTest.php
new file mode 100644
index 000000000..d2f055924
--- /dev/null
+++ b/koward/lib/Test/Server/UserTest.php
@@ -0,0 +1,43 @@
+
+ * @license http://www.fsf.org/copyleft/lgpl.html LGPL
+ * @link http://pear.horde.org/index.php?package=Koward
+ */
+
+/**
+ * Test the user object.
+ *
+ * Copyright 2009 The Horde Project (http://www.horde.org/)
+ *
+ * See the enclosed file COPYING for license information (LGPL). If you
+ * did not receive this file, see http://www.fsf.org/copyleft/lgpl.html.
+ *
+ * @category Kolab
+ * @package Koward
+ * @author Gunnar Wrobel
+ * @license http://www.fsf.org/copyleft/lgpl.html LGPL
+ * @link http://pear.horde.org/index.php?package=Koward
+ */
+class Koward_Test_Server_UserTest extends Horde_Kolab_Test_Server {
+
+ /**
+ * Test listing users if there are no users.
+ *
+ * @scenario
+ *
+ * @return NULL
+ */
+ public function listingUsersOnEmptyServer()
+ {
+ $this->given('the current Kolab server')
+ ->when('listing all users')
+ ->then('the list is an empty array');
+ }
+}
diff --git a/koward/lib/Test/Template/scenario.html.dist b/koward/lib/Test/Template/scenario.html.dist
new file mode 100644
index 000000000..caa149aab
--- /dev/null
+++ b/koward/lib/Test/Template/scenario.html.dist
@@ -0,0 +1,13 @@
+
+ |
+ [+] {name}
+ |
+
+
+ |
+
+ |
+
+
diff --git a/koward/lib/Test/Template/scenario_header.html.dist b/koward/lib/Test/Template/scenario_header.html.dist
new file mode 100644
index 000000000..7b205d1cd
--- /dev/null
+++ b/koward/lib/Test/Template/scenario_header.html.dist
@@ -0,0 +1,6 @@
+
+ |
+
+ |
+
+
diff --git a/koward/lib/Test/Template/scenarios.html.dist b/koward/lib/Test/Template/scenarios.html.dist
new file mode 100644
index 000000000..1037cfb70
--- /dev/null
+++ b/koward/lib/Test/Template/scenarios.html.dist
@@ -0,0 +1,54 @@
+
+
+
+
+
+{scenarios}
+
+ |
+ [+] Summary:
+
+
+
+ | Successful scenarios: |
+ {successfulScenarios} |
+
+
+ | Failed scenarios: |
+ {failedScenarios} |
+
+
+ | Skipped scenarios: |
+ {skippedScenarios} |
+
+
+ | Incomplete scenarios: |
+ {incompleteScenarios} |
+
+
+
+ |
+
+
diff --git a/koward/lib/Test/Template/step.html.dist b/koward/lib/Test/Template/step.html.dist
new file mode 100644
index 000000000..bcdce3f40
--- /dev/null
+++ b/koward/lib/Test/Template/step.html.dist
@@ -0,0 +1,6 @@
+
+ | {text} |
+ {action} |
+ |
+
+
diff --git a/koward/test/AllTests.php b/koward/test/AllTests.php
new file mode 100644
index 000000000..3d1f3a70c
--- /dev/null
+++ b/koward/test/AllTests.php
@@ -0,0 +1,83 @@
+
+ * @license http://www.fsf.org/copyleft/lgpl.html LGPL
+ * @link http://pear.horde.org/index.php?package=Koward
+ */
+
+if (!defined('PHPUnit_MAIN_METHOD')) {
+ define('PHPUnit_MAIN_METHOD', 'Koward_AllTests::main');
+}
+
+/**
+ * Initialize testing for this application.
+ */
+require_once 'TestInit.php';
+
+/**
+ * Combine the tests for this package.
+ *
+ * Copyright 2007-2009 The Horde Project (http://www.horde.org/)
+ *
+ * See the enclosed file COPYING for license information (LGPL). If you
+ * did not receive this file, see http://www.fsf.org/copyleft/lgpl.html.
+ *
+ * @category Kolab
+ * @package Koward
+ * @author Gunnar Wrobel
+ * @license http://www.fsf.org/copyleft/lgpl.html LGPL
+ * @link http://pear.horde.org/index.php?package=Koward
+ */
+class Koward_AllTests
+{
+ /**
+ * Main entry point for running the suite.
+ *
+ * @return NULL
+ */
+ public static function main()
+ {
+ PHPUnit_TextUI_TestRunner::run(self::suite());
+ }
+
+ /**
+ * Collect the unit tests of this directory into a new suite.
+ *
+ * @return PHPUnit_Framework_TestSuite The test suite.
+ */
+ public static function suite()
+ {
+ // Catch strict standards
+ error_reporting(E_ALL | E_STRICT);
+
+ // Build the suite
+ $suite = new PHPUnit_Framework_TestSuite('Koward');
+
+ $basedir = dirname(__FILE__);
+ $baseregexp = preg_quote($basedir . DIRECTORY_SEPARATOR, '/');
+
+ foreach (new RecursiveIteratorIterator(new RecursiveDirectoryIterator($basedir)) as $file) {
+ if ($file->isFile() && preg_match('/Test.php$/', $file->getFilename())) {
+ $pathname = $file->getPathname();
+ require $pathname;
+
+ $class = str_replace(DIRECTORY_SEPARATOR, '_',
+ preg_replace("/^$baseregexp(.*)\.php/", '\\1', $pathname));
+ $suite->addTestSuite('Koward_' . $class);
+ }
+ }
+
+ return $suite;
+ }
+
+}
+
+if (PHPUnit_MAIN_METHOD == 'Koward_AllTests::main') {
+ Koward_AllTests::main();
+}
diff --git a/koward/test/KowardTest.php b/koward/test/KowardTest.php
new file mode 100644
index 000000000..4b4abf5bb
--- /dev/null
+++ b/koward/test/KowardTest.php
@@ -0,0 +1,95 @@
+
+ * @license http://www.fsf.org/copyleft/lgpl.html LGPL
+ * @link http://pear.horde.org/index.php?package=Koward
+ */
+
+/**
+ * Initialize testing for this application.
+ */
+require_once 'TestInit.php';
+
+/**
+ * Test the user object.
+ *
+ * Copyright 2009 The Horde Project (http://www.horde.org/)
+ *
+ * See the enclosed file COPYING for license information (LGPL). If you
+ * did not receive this file, see http://www.fsf.org/copyleft/lgpl.html.
+ *
+ * @category Kolab
+ * @package Koward
+ * @author Gunnar Wrobel
+ * @license http://www.fsf.org/copyleft/lgpl.html LGPL
+ * @link http://pear.horde.org/index.php?package=Koward
+ */
+class Koward_KowardTest extends Koward_Test
+{
+ /**
+ * Set up testing.
+ *
+ * @return NULL
+ */
+ protected function setUp()
+ {
+ $world = $this->prepareBasicSetup();
+
+ $this->koward = Koward_Koward::singleton();
+ }
+
+ /**
+ * Verify that the Koward object ist initialized correctly.
+ *
+ * @return NULL
+ */
+ public function testSetup()
+ {
+ $this->assertType('Horde_Kolab_Server', $this->koward->server);
+ }
+
+ /**
+ * Verify that we can fetch objects from the Kolab server.
+ *
+ * @return NULL
+ */
+ public function testFetching()
+ {
+ $this->assertType('Horde_Kolab_Server_Object', $this->koward->getObject('cn=Gunnar Wrobel,dc=example,dc=org'));
+ }
+
+ /**
+ * Verify token processing mechanisms.
+ *
+ * @return NULL
+ */
+ public function testToken()
+ {
+ // Get the token.
+ $token = $this->koward->getRequestToken('test');
+ // Checking it should be fine.
+ $this->koward->checkRequestToken('test', $token);
+ // Now we set the token to a value that will be considered a timeout.
+ $_SESSION['horde_form_secrets'][$token] = time() - 100000;
+ try {
+ $this->koward->checkRequestToken('test', $token);
+ $this->fail('The rquest token is still valid which was not expected.');
+ } catch (Horde_Exception $e) {
+ $this->assertContains(_("This request cannot be completed because the link you followed or the form you submitted was only valid for"), $e->getMessage());
+ }
+ // Now we remove the token
+ unset($_SESSION['horde_form_secrets'][$token]);
+ try {
+ $this->koward->checkRequestToken('test', $token);
+ $this->fail('The rquest token is still valid which was not expected.');
+ } catch (Horde_Exception $e) {
+ $this->assertEquals(_("We cannot verify that this request was really sent by you. It could be a malicious request. If you intended to perform this action, you can retry it now."), $e->getMessage());
+ }
+ }
+}
diff --git a/koward/test/TestInit.php b/koward/test/TestInit.php
new file mode 100644
index 000000000..8091e44c9
--- /dev/null
+++ b/koward/test/TestInit.php
@@ -0,0 +1,25 @@
+
+ * @license http://www.fsf.org/copyleft/lgpl.html LGPL
+ * @link http://pear.horde.org/index.php?package=Koward
+ */
+
+/**
+ * The Autoloader allows us to omit "require/include" statements.
+ */
+require_once 'Horde/Autoloader.php';
+
+if (!defined('KOWARD_BASE')) {
+ define('KOWARD_BASE', dirname(__FILE__) . '/../');
+}
+
+/* Set up the application class and controller loading */
+Horde_Autoloader::addClassPattern('/^Koward_/', KOWARD_BASE . '/lib/');
+Horde_Autoloader::addClassPattern('/^Koward_/', KOWARD_BASE . '/app/controllers/');
diff --git a/koward/themes/graphics/favicon.ico b/koward/themes/graphics/favicon.ico
new file mode 100644
index 0000000000000000000000000000000000000000..0f8fa0816309acfe30380bea80a1a40cd3859906
GIT binary patch
literal 1406
zcmeH_=~vWc6vsbL%3@kllxZ7=RBlm8i(5*RUCkbSa&0fyx`fgsGUAJa>F;UCcVp1VBv-gEBqTo5u@Sz*FDGZ-gZ
zlVu)uO_W(+DNAq^CUu99B#Bnf(d0%&5ikNyELn(DACIJTpeDeXo^*d|u3hDl1B6bo
zC3)vYnllrqk61^shaERNn#u5XK`Qq{>dQp!Hj4iIXsTjED9z2J^UNwr_IT2+RuSVg
zgHY?S7&S#m*=vzb*-@%IOWpcOG{^5EbJ<)@*jm$R=tp0zrn#|^!Rky}Rbl+P!-xqbzs@QtEn?Uhdq|>nU@F3gt-}(~r{E
zRDm|yo0^;)(gFf#Kj%l+#SpYr*O0Dkq5GF3NEfzI6dg+MfJCgjD+a|HDhu-Hsw?1X
z++n&p+Np{OMAv;2#hjV+wbY_1E5lHdNR!7H>Iw^~^O{J+gt16HDx~T(T8b_pDW=ns
zbs9}>5}FJJ+UwV;%FCkpk1|SrI!}-GFLdRZDlu`}(Mj^XJFi+sTUzr>!7`
zq1yvAEVZCJBaolxThOM{(RTg-rP(U_5>KuN^6quqo
z`o0iep_7ut!A$ykoI(7!&=)H;)Rxm%dy$
z!8+B(#%9@KF>{vq_PO!m%opoU%y{VC*Tj2vLIk_qE56=*`mr~BMeO6R%dLI1VwI^u
z@x$(??;EzZey|`a=a_5b_J
zMV_tb%+z-k5oD;F?)ciacU9BPgAB#Na|OQCHT+AEF;G9-@g~h}TTtG{*OLudcLcXx
z&Zy+c)qQf}nMVVAPL6%f8kVacd;;=q&V23P%&NLD?#6jGu3gIYJ3!9xboFyt=akR{
E0DOE