Skip to content

Commit

Permalink
Browse files Browse the repository at this point in the history
  • Loading branch information
fmbiete committed Feb 27, 2014
1 parent 0def4ea commit 2f87f6c
Show file tree
Hide file tree
Showing 8 changed files with 220 additions and 58 deletions.
2 changes: 1 addition & 1 deletion README
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,7 @@ CardDAV server list
* Apple Addressbook Server: https://example.com/addressbooks/users/{resource|principal|username}/{collection}/
* memotoo: https://sync.memotoo.com/cardDAV/
* SabreDAV: https://example.com/addressbooks/{resource|principal|username}/{collection}/
* ownCloud: https://example.com/apps/contacts/carddav.php/addressbooks/{resource|principal|username}/{collection}/
* ownCloud: https://example.com/remote.php/carddav/addressbooks/{resource|principal|username}/{collection}/
* SOGo: https://example.com/SOGo/dav/{resource|principal|username}/Contacts/{collection}/


Expand Down
1 change: 1 addition & 0 deletions SQL/mysql.sql
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ CREATE TABLE IF NOT EXISTS `carddav_server` (
`password` varchar(128) COLLATE utf8_unicode_ci NOT NULL,
`label` varchar(128) COLLATE utf8_unicode_ci NOT NULL,
`read_only` tinyint(1) NOT NULL,
`default_server` tinyint(1) NOT NULL,
PRIMARY KEY (`carddav_server_id`),
KEY `user_id` (`user_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci AUTO_INCREMENT=1 ;
Expand Down
3 changes: 2 additions & 1 deletion SQL/mysql.update.sql
Original file line number Diff line number Diff line change
Expand Up @@ -14,4 +14,5 @@ ADD `firstname` VARCHAR( 128 ) NULL DEFAULT NULL AFTER `words` ,
ADD `surname` VARCHAR( 128 ) NULL DEFAULT NULL AFTER `firstname` ;

// updates from version 0.5
ALTER TABLE `carddav_server` ADD `read_only` tinyint(1) NOT NULL AFTER `label`;
ALTER TABLE `carddav_server` ADD `read_only` tinyint(1) NOT NULL AFTER `label`;
ALTER TABLE `carddav_server` ADD `default_server` tinyint(1) NOT NULL AFTER `read_only`;
1 change: 1 addition & 0 deletions SQL/postgresql.sql
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ CREATE TABLE IF NOT EXISTS "carddav_server" (
"password" varchar(128) NOT NULL,
"label" varchar(128) NOT NULL,
"read_only" int NOT NULL,
"default_server" int NOT NULL,
PRIMARY KEY ("carddav_server_id")
);

Expand Down
158 changes: 123 additions & 35 deletions carddav.php
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,8 @@ public function init()
$rcmail = rcmail::get_instance();
$skin_path = $this->local_skin_path();

$this->load_config();

if (!is_dir($skin_path))
{
$skin_path = 'skins/default';
Expand All @@ -64,14 +66,17 @@ public function init()
$this->add_texts('localization/', true);
$this->include_stylesheet($skin_path . '/carddav.css');

$this->resync_default_carddav_servers();

switch ($rcmail->task)
{
case 'settings':
$this->register_action('plugin.carddav-server', array($this, 'carddav_server'));
$this->register_action('plugin.carddav-server-save', array($this, 'carddav_server_save'));
$this->register_action('plugin.carddav-server-delete', array($this, 'carddav_server_delete'));
$this->register_action('plugin.carddav-server-save', array($this, 'carddav_server_save_from_settings'));
$this->register_action('plugin.carddav-server-delete', array($this, 'carddav_server_delete_from_settings'));
$this->include_script('carddav_settings.js');
$this->include_script('jquery.base64.js');
$this->add_hook('addressbooks_list', array($this, 'get_carddav_addressbook_sources'));
break;

case 'addressbook':
Expand Down Expand Up @@ -197,6 +202,11 @@ protected function get_carddav_server_list()

foreach ($servers as $server)
{
if ($server['default_server'])
{
continue;
}

// $rcmail->output->button() seems not to work within ajax requests so we build the button manually
$delete_submit = '<input
type="button"
Expand Down Expand Up @@ -374,16 +384,13 @@ protected function carddav_server_available()
/**
* Check if it's possible to connect to the CardDAV server
*
* @param array $server CardDAV server settings
* @return boolean
*/
public function carddav_server_check_connection()
public function carddav_server_check_connection($server)
{
$url = parse_input_value(base64_decode($_POST['_server_url']));
$username = parse_input_value(base64_decode($_POST['_username']));
$password = parse_input_value(base64_decode($_POST['_password']));

$carddav_backend = new carddav_backend($url);
$carddav_backend->set_auth($username, $password);
$carddav_backend = new carddav_backend($server['url']);
$carddav_backend->set_auth($server['username'], $server['password']);

return $carddav_backend->check_connection();
}
Expand Down Expand Up @@ -502,7 +509,7 @@ public function get_carddav_url_list()
$table->add(array(), 'https://example.com/addressbooks/{resource|principal|username}/{collection}/');

$table->add(array(), 'ownCloud');
$table->add(array(), 'https://example.com/apps/contacts/carddav.php/addressbooks/{resource|principal|username}/{collection}/');
$table->add(array(), 'https://example.com/remote.php/carddav/addressbooks/{resource|principal|username}/{collection}/');

$table->add(array(), 'SOGo');
$table->add(array(), 'https://example.com/SOGo/dav/{resource|principal|username}/Contacts/{collection}/');
Expand All @@ -513,37 +520,98 @@ public function get_carddav_url_list()
return $content;
}

public static function compare_servers($s1, $s2)
{
return strcasecmp($s1['url'], $s2['url']);
(strcasecmp($s1['username'], $s2['username']) << 2) +
(strcasecmp($s1['password'], $s2['password']) << 3) +
(strcasecmp($s1['label'], $s2['label']) << 4) +
(strcasecmp($s1['read_only'], $s2['read_only']) << 5);
}
/**
* Synchonize known CardDAV servers with the default set
*
* @return void
*/
public function resync_default_carddav_servers()
{
$rcmail = rcmail::get_instance();

$known_servers = $this->get_carddav_server();
$default_servers = $rcmail->config->get('carddav_default_servers', array());

$known_servers = array_filter($known_servers, create_function('$s', 'return $s["default_server"];'));

$to_remove = array_udiff($known_servers, $default_servers, array('carddav', 'compare_servers'));
$to_add = array_udiff($default_servers, $known_servers, array('carddav', 'compare_servers'));

foreach ($to_remove as $server) {
$this->write_log('removing default ' . $server['url']);
$this->delete_carddav_server($server['carddav_server_id']);
}
foreach ($to_add as $server) {
$server['default_server'] = 1;
$this->write_log('adding default ' . $server['url']);
$this->add_carddav_server($server);
}
}

/**
* Add the given CardDAV server
*
* Settings must contain the following fields: url, username, password,
* label, read_only, default_server.
*
* @settings array $server settings for the new CardDAV server
* @return boolean TRUE if the operation suceeded
*/
public function add_carddav_server($server)
{
$rcmail = rcmail::get_instance();

$query = "
INSERT INTO
".get_table_name('carddav_server')." (user_id, url, username, password, label, read_only, default_server)
VALUES
(?, ?, ?, ?, ?, ?, ?)
";

$rcmail->db->query(
$query, $rcmail->user->data['user_id'], $server['url'], $server['username'],
$server['password'] == '%p' ? '%p' : $rcmail->encrypt($server['password']),
$server['label'], $server['read_only'], $server['default_server']);

if ($rcmail->db->affected_rows())
{
$this->carddav_addressbook_sync($rcmail->db->insert_id(), false);
return TRUE;
} else {
return FALSE;
}
}

/**
* Save CardDAV server and execute first CardDAV contact sync
* Save new CardDAV server from user given parameters
*
* @return void
*/
public function carddav_server_save()
public function carddav_server_save_from_settings()
{
$rcmail = rcmail::get_instance();

if ($this->carddav_server_check_connection())
$server = array(
'url' => parse_input_value(base64_decode($_POST['_server_url'])),
'username' => parse_input_value(base64_decode($_POST['_username'])),
'password' => parse_input_value(base64_decode($_POST['_password'])),
'label' => parse_input_value(base64_decode($_POST['_label'])),
'read_only' => (int) parse_input_value(base64_decode($_POST['_read_only'])),
'default_server' => 0
);

if ($this->carddav_server_check_connection($server))
{
$user_id = $rcmail->user->data['user_id'];
$url = parse_input_value(base64_decode($_POST['_server_url']));
$username = parse_input_value(base64_decode($_POST['_username']));
$password = parse_input_value(base64_decode($_POST['_password']));
$label = parse_input_value(base64_decode($_POST['_label']));
$read_only = (int) parse_input_value(base64_decode($_POST['_read_only']));

$query = "
INSERT INTO
".get_table_name('carddav_server')." (user_id, url, username, password, label, read_only)
VALUES
(?, ?, ?, ?, ?, ?)
";

$rcmail->db->query($query, $user_id, $url, $username, $rcmail->encrypt($password), $label, $read_only);

if ($rcmail->db->affected_rows())
if ($this->add_carddav_server($server))
{
$this->carddav_addressbook_sync($rcmail->db->insert_id(), false);

$rcmail->output->command('plugin.carddav_server_message', array(
'server_list' => $this->get_carddav_server_list(),
'message' => $this->gettext('settings_saved'),
Expand All @@ -570,13 +638,13 @@ public function carddav_server_save()
/**
* Delete CardDAV server and all related local contacts
*
* @return void
* @param int $carddav_server_id CardDAV server id
* @return boolean TRUE if the operation succeeded
*/
public function carddav_server_delete()
public function delete_carddav_server($carddav_server_id)
{
$rcmail = rcmail::get_instance();
$user_id = $rcmail->user->data['user_id'];
$carddav_server_id = parse_input_value(base64_decode($_POST['_carddav_server_id']));

$query = "
DELETE FROM
Expand All @@ -590,6 +658,26 @@ public function carddav_server_delete()
$rcmail->db->query($query, $user_id, $carddav_server_id);

if ($rcmail->db->affected_rows())
{
return TRUE;
}
return FALSE;
}


/**
* Delete CardDAV server from user selection
*
* @return void
*/
public function carddav_server_delete_from_settings()
{
$rcmail = rcmail::get_instance();
$user_id = $rcmail->user->data['user_id'];
$carddav_server_id = parse_input_value(base64_decode($_POST['_carddav_server_id']));

$servers = $this->get_carddav_server($carddav_server_id);
if (!($servers[0]['default_server']) && $this->delete_carddav_server($carddav_server_id))
{
$rcmail->output->command('plugin.carddav_server_message', array(
'server_list' => $this->get_carddav_server_list(),
Expand Down
71 changes: 55 additions & 16 deletions carddav_addressbook.php
Original file line number Diff line number Diff line change
Expand Up @@ -367,15 +367,11 @@ public function reset()
*/
public function carddav_addressbook_sync($server, $carddav_contact_id = null, $vcard_id = null)
{
$rcmail = rcmail::get_instance();
$any_data_synced = false;

self::write_log('Starting CardDAV-Addressbook synchronization');

$carddav_backend = new carddav_backend($server['url']);
$carddav_backend->set_auth($server['username'], $rcmail->decrypt($server['password']));

if ($carddav_backend->check_connection())
if (false !== ($carddav_backend = $this->get_backend($server)))
{
self::write_log('Connected to the CardDAV-Server ' . $server['url']);

Expand Down Expand Up @@ -647,15 +643,16 @@ private function carddav_add($vcard)
{
$rcmail = rcmail::get_instance();
$server = current(carddav::get_carddav_server($this->carddav_server_id));
$carddav_backend = new carddav_backend($server['url']);
$carddav_backend->set_auth($server['username'], $rcmail->decrypt($server['password']));

if ($carddav_backend->check_connection())
if (false !== ($carddav_backend = $this->get_backend($server)))
{
$vcard_id = $carddav_backend->add($vcard);
$this->carddav_addressbook_sync($server, false, $vcard_id);
if($vcard_id !== false)
{
$this->carddav_addressbook_sync($server, false, $vcard_id);

return $rcmail->db->insert_id(get_table_name('carddav_contacts'));
return $rcmail->db->insert_id(get_table_name('carddav_contacts'));
}
}

return false;
Expand All @@ -673,10 +670,8 @@ private function carddav_update($carddav_contact_id, $vcard)
$rcmail = rcmail::get_instance();
$contact = $this->get_carddav_addressbook_contact($carddav_contact_id);
$server = current(carddav::get_carddav_server($this->carddav_server_id));
$carddav_backend = new carddav_backend($server['url']);
$carddav_backend->set_auth($server['username'], $rcmail->decrypt($server['password']));

if ($carddav_backend->check_connection())
if (false !== ($carddav_backend = $this->get_backend($server)))
{
$carddav_backend->update($vcard, $contact['vcard_id']);
$this->carddav_addressbook_sync($server, $carddav_contact_id, $contact['vcard_id']);
Expand All @@ -697,10 +692,8 @@ private function carddav_delete($carddav_contact_ids)
{
$rcmail = rcmail::get_instance();
$server = current(carddav::get_carddav_server($this->carddav_server_id));
$carddav_backend = new carddav_backend($server['url']);
$carddav_backend->set_auth($server['username'], $rcmail->decrypt($server['password']));

if ($carddav_backend->check_connection())
if (false !== ($carddav_backend = $this->get_backend($server)))
{
foreach ($carddav_contact_ids as $carddav_contact_id)
{
Expand All @@ -715,6 +708,52 @@ private function carddav_delete($carddav_contact_ids)
return false;
}


/**
* Get CardDAV_Backend for the given server
*
* @param array server connection parameters
* @return mixed either a CardDAV_Backend or FALSE if the connection fails
*/
private function get_backend($server) {
$rcmail = rcmail::get_instance();

$this->interpolate_settings($server);
$carddav_backend = new carddav_backend($server['url']);
$carddav_backend->set_auth($server['username'], $rcmail->decrypt($server['password']));
if ($carddav_backend->check_connection())
{
return $carddav_backend;
}
else
{
return false;
}
}

/**
* When 'default_server' is not set to 0, this will replace macros
* used in server settings.
*
* @param array $server CarDAV server array
*/
private function interpolate_settings(&$server)
{
if ($server['default_server'] == 0) {
return;
}

$rcmail = rcmail::get_instance();

$server['username'] = str_replace('%u', $_SESSION['username'], $server['username']);
$server['username'] = str_replace('%l', $rcmail->user->get_username('local'), $server['username']);
$server['username'] = str_replace('%d', $rcmail->user->get_username('domain'), $server['username']);
$server['password'] = str_replace('%p', $_SESSION['password'], $server['password']);
$server['url'] = str_replace('%u', $_SESSION['username'], $server['url']);
$server['url'] = str_replace('%l', $_SESSION['username'], $server['url']);
$server['url'] = str_replace('%d', $_SESSION['username'], $server['url']);
}

/**
* @see rcube_addressbook::list_groups()
* @param string $search
Expand Down
Loading

0 comments on commit 2f87f6c

Please sign in to comment.