diff --git a/abook_class.php b/abook_class.php
index d5edea3..d06b511 100755
--- a/abook_class.php
+++ b/abook_class.php
@@ -34,22 +34,18 @@ class abook_carddav extends addressbook_backend {
/* Constructor */
function abook_carddav($param) {
- $this->sname = _("carddav address book");
+ // defaults
+ $this->sname = _("CardDAV Address Book");
if (is_array($param)) {
- if (!empty($param['name'])) {
- $this->sname = $param['name'];
- }
-
- if (isset($param['writeable'])) {
- $this->writeable = $param['writeable'];
- }
-
- if (isset($param['listing'])) {
- $this->listing = $param['listing'];
- }
-
- return $this->open(true);
+ if (!empty($param['name'])) { $this->sname = $param['name']; }
+ if (!empty($param['abook_uri'])) { $this->abook_uri = $param['abook_uri']; }
+ if (!empty($param['base_uri'])) { $this->base_uri = $param['base_uri']; }
+ if (!empty($param['username'])) { $this->username = $param['username']; }
+ if (!empty($param['password'])) { $this->password = $param['password']; }
+ if (isset($param['writeable'])) { $this->writeable = $param['writeable']; }
+ if (isset($param['listing'])) { $this->listing = $param['listing']; }
+ return $this->open();
}
else {
return $this->set_error('Invalid argument to constructor');
@@ -60,15 +56,13 @@ class abook_carddav extends addressbook_backend {
*
*/
function open() {
- // backend open function
- $this->account = new Account(DISCOVERY_URI, USERNAME, PASSWORD);
- // Use stored addressbook uri if it exists
- if(defined('abook_uri')){
- $this->abook = new AddressbookCollection(abook_uri, $this->account);
- // TODO: check that it's valid
- return true;
- }
+ // backend open function
+ $this->account = new Account($this->base_uri, $this->username, $this->password, $this->base_uri);
+ $this->abook = new AddressbookCollection($this->abook_uri, $this->account);
+ // TODO: check that it's valid
+ return true;
+ /* TODO: move this to discover page
// Discover the addressbooks for that account
try {
$discover = new Discovery();
@@ -83,37 +77,26 @@ class abook_carddav extends addressbook_backend {
// HINT: use this line to get your discovered addressbook URI
// echo "discovered: " . $this->abook->getUri();
return true;
+ */
}
/**
- *
+ * Run query against addressbook and return squurrelmail-type address(es)
+ * Params are same as in https://mstilkerich.github.io/carddavclient/classes/MStilkerich-CardDavClient-AddressbookCollection.html#method_query
+ * except the lack of 2nd parameter:
+ * @param array $query
+ * The query filter conditions, for format see https://mstilkerich.github.io/carddavclient/classes/MStilkerich-CardDavClient-XmlElements-Filter.html#method___construct
+ * @param bool $matchAll
+ * Whether all or any of the conditions needs to match.
+ * @param int $limit
+ * Tell the server to return at most $limit results. 0 means no limit.
+ * @return either:
+ * * a single address (array) - if $limit==1
+ * * or array of addresses (arrays)
*/
- function close() {
- // ADDME: backend close function
-
- }
-
-
- /* ========================== Public ======================== */
-
- /**
- * Search addressesbook for entries where any field matches expr.
- * It's expected to support * and ? wildcards, and search all fields in any position.
- * Note that currently, it does not.
- * @param expr string search expression.
- * @return array of addresses (arrays)
- */
- function search($expr) {
- $ret = array();
-
- /* To be replaced by advanded search expression parsing */
- if(is_array($expr)) { return; }
-
- // list all addresses where any of these fields contains $expr.
- // wildcards not supported.
- // Also note that we don't check for presence of email here,
- // this will be filtered out later
- $all=$this->abook->query(['FN' => "/$expr/", 'EMAIL' => "/$expr/", 'ORG' => "/$expr/", 'NOTE' => "/$expr/"],["FN", "N", "EMAIL", "ORG"]);
+ function run_query($query, $match_all=false, $limit=0) {
+ // TODO: add nickname to list of fields if $this->writeable
+ $all=$this->abook->query($query,["FN", "N", "EMAIL", "ORG"],$match_all,$limit);
/*
Returns an array of matched VCards:
The keys of the array are the URIs of the vcards
@@ -126,7 +109,10 @@ class abook_carddav extends addressbook_backend {
if(!isset($vcard->EMAIL)) { continue; }
$names = $vcard->N->getParts();
// last,first,additional,prefix,suffix
- array_push($ret,array(
+ // TODO: if !$this->writeable then we want to add one row per each email this vcard has
+ // foreach($vcard->EMAIL as $email) { ... }
+ $value = array(
+ // TODO: nickname depends on $this->writeable
'nickname' => substr($uri, $abook_uri_len),
'name' => (string)$vcard->FN,
'firstname' => (string)$names[1],
@@ -134,11 +120,34 @@ class abook_carddav extends addressbook_backend {
'email' => (string)$vcard->EMAIL,
'label' => (string)$vcard->ORG,
'backend' => $this->bnum,
- 'source' => $this->sname));
+ 'source' => $this->sname);
+ if($limit == 1) { return $value; }
+ array_push($ret,$value);
}
+ return $ret;
+ }
+
+ /* ========================== Public ======================== */
+ /**
+ * Search addressesbook for entries where any field matches expr.
+ * It's expected to support * and ? wildcards, and search all fields in any position.
+ * Note that currently, it does not.
+ * @param expr string search expression.
+ * @return array of addresses (arrays)
+ */
+ function search($expr) {
- return $ret;
+ /* To be replaced by advanded search expression parsing */
+ if(is_array($expr)) { return; }
+
+ if ($expr=='*') { return $this->list_addr(); }
+
+ // list all addresses where any of these fields contains $expr.
+ // wildcards are not supported.
+ // Also note that we don't check for presence of email in the filter,
+ // this will be filtered out inside run_query
+ return $this->run_query(['FN' => "/$expr/", 'EMAIL' => "/$expr/", 'ORG' => "/$expr/", 'NOTE' => "/$expr/"]);
}
/**
@@ -174,6 +183,7 @@ class abook_carddav extends addressbook_backend {
$vcard = $one['vcard'];
$names = $vcard->N->getParts();
return array(
+ // TODO: nickname depends on $this->writeable
'nickname' => substr($uri, $abook_uri_len),
'name' => (string)$vcard->FN,
'firstname' => (string)$names[1],
@@ -193,31 +203,11 @@ class abook_carddav extends addressbook_backend {
$filter=['EMAIL' => "/$value/="];
}
if($field == SM_ABOOK_FIELD_LABEL) {
- $filter=['ORG' => "/$value/="];
+ $filter=['ORG' => "/$value/=", 'EMAIL' => "//"];
}
if(!isset($filter)) { return array(); }
- $all=$this->abook->query($filter,["FN", "N", "EMAIL", "ORG"],true,1);
- /*
- Returns an array of matched VCards:
- The keys of the array are the URIs of the vcards
- The values are associative arrays with keys etag (type: string) and vcard (type: VCard)
- */
- foreach($all as $uri => $one) {
- $vcard = $one['vcard'];
- if(!isset($vcard->EMAIL)) { continue; }
- $names = $vcard->N->getParts();
- // last,first,additional,prefix,suffix
- return array(
- 'nickname' => substr($uri, $abook_uri_len),
- 'name' => (string)$vcard->FN,
- 'firstname' => (string)$names[1],
- 'lastname' => (string)$names[0],
- 'email' => (string)$vcard->EMAIL,
- 'label' => (string)$vcard->ORG,
- 'backend' => $this->bnum,
- 'source' => $this->sname);
- }
+ return $this->run_query($filter,true,1);
}
/**
@@ -225,34 +215,8 @@ class abook_carddav extends addressbook_backend {
* @return array of addresses (arrays)
*/
function list_addr() {
- $ret = array();
-
// list all addresses having an email
- $all=$this->abook->query(['EMAIL' => "//"],["FN", "N", "EMAIL", "ORG"]);
- /*
- Returns an array of matched VCards:
- The keys of the array are the URIs of the vcards
- The values are associative arrays with keys etag (type: string) and vcard (type: VCard)
- */
-
- $abook_uri_len=strlen($this->abook->getUriPath());
- foreach($all as $uri => $one) {
- $vcard = $one['vcard'];
- // if(!isset($vcard->EMAIL)) { continue; }
- $names = $vcard->N->getParts();
- // last,first,additional,prefix,suffix
- array_push($ret,array(
- 'nickname' => substr($uri, $abook_uri_len),
- 'name' => (string)$vcard->FN,
- 'firstname' => (string)$names[1],
- 'lastname' => (string)$names[0],
- 'email' => (string)$vcard->EMAIL,
- 'label' => (string)$vcard->ORG,
- 'backend' => $this->bnum,
- 'source' => $this->sname));
- }
-
- return $ret;
+ return $this->run_query(['EMAIL' => "//"]);
}
/**
diff --git a/setup.php b/setup.php
index 55abdc2..d3a0dcb 100755
--- a/setup.php
+++ b/setup.php
@@ -24,6 +24,8 @@ function squirrelmail_plugin_init_abook_carddav() {
$squirrelmail_plugin_hooks['abook_init']['abook_carddav'] = 'abook_carddav_init';
$squirrelmail_plugin_hooks['abook_add_class']['abook_carddav'] = 'abook_carddav_class';
+ $squirrelmail_plugin_hooks['optpage_loadhook_display']['abook_carddav'] = 'abook_carddav_optpage';
+
}
/**
@@ -38,7 +40,24 @@ function abook_carddav_init(&$argv) {
bindtextdomain ('abook_carddav', SM_PATH . 'locale');
textdomain ('abook_carddav');
- $r=$abook->add_backend('carddav',array('name'=>_("CardDAV Address Book")));
+ // TODO: consider multiple uris
+ $abook_uri = getPref($data_dir, $username, 'plugin_abook_carddav_abook_uri');
+ $abook_base_uri = getPref($data_dir, $username, 'plugin_abook_carddav_base_uri');
+ $abook_username = getPref($data_dir, $username, 'plugin_abook_carddav_username');
+ $abook_password = getPref($data_dir, $username, 'plugin_abook_carddav_password');
+ $abook_writeable = getPref($data_dir, $username, 'plugin_abook_carddav_writeable');
+ $abook_listing = getPref($data_dir, $username, 'plugin_abook_carddav_listing');
+ if(substr_compare($abook_uri, 'http', 0)) {
+ $r=$abook->add_backend('carddav',array(
+ 'name'=>_("CardDAV Address Book"),
+ 'abook_uri'=>$abook_uri,
+ 'base_uri'=>$abook_base_uri,
+ 'username'=>$abook_username,
+ 'password'=>$abook_password,
+ 'writeable'=>$abook_writeable,
+ 'listing'=>$abook_listing,
+ ));
+ }
bindtextdomain ('squirrelmail', SM_PATH . 'locale');
textdomain ('squirrelmail');
@@ -48,12 +67,59 @@ function abook_carddav_class() {
bindtextdomain ('abook_carddav', SM_PATH . 'locale');
textdomain ('abook_carddav');
- require_once(SM_PATH . 'plugins/abook_carddav/abook_class.php');
+ // load file only if $abook_uri is set
+ $abook_uri = getPref($data_dir, $username, 'plugin_abook_carddav_abook_uri');
+ if(substr_compare($abook_uri, 'http', 0)) {
+ require_once(SM_PATH . 'plugins/abook_carddav/abook_class.php');
+ }
bindtextdomain ('squirrelmail', SM_PATH . 'locale');
textdomain ('squirrelmail');
}
+function abook_carddav_optpage() {
+ global $optpage_data;
+ global $username, $data_dir;
+
+ sq_change_text_domain('abook_carddav');
+ $optpage_data['grps']['abook_carddav'] = _("CardDAV Address Book");
+ $optpage_data['vals']['abook_carddav'][] = array(
+ 'name' => 'plugin_abook_carddav_abook_uri',
+ 'caption' => _("URI of addressbook - MUST start with 'http' (both 'http://' and 'https://' are ok)"),
+ 'trailing_text' => _("use discovery page to get one"),
+ 'type' => SMOPT_TYPE_STRING,
+ // 'initial_value' => $abook_uri,
+ );
+ $optpage_data['vals']['abook_carddav'][] = array(
+ 'name' => 'plugin_abook_carddav_base_uri',
+ 'caption' => _("base URI - usually a server name with protocol and port"),
+ 'trailing_text' => _("use discovery page to get one"),
+ 'type' => SMOPT_TYPE_STRING,
+ // 'initial_value' => $abook_uri,
+ );
+ $optpage_data['vals']['abook_carddav'][] = array(
+ 'name' => 'plugin_abook_carddav_username',
+ 'caption' => _("Username"),
+ 'type' => SMOPT_TYPE_STRING,
+ );
+ $optpage_data['vals']['abook_carddav'][] = array(
+ 'name' => 'plugin_abook_carddav_password',
+ 'caption' => _("Password"),
+ 'type' => SMOPT_TYPE_STRING,
+ );
+ $optpage_data['vals']['abook_carddav'][] = array(
+ 'name' => 'plugin_abook_carddav_writeable',
+ 'caption' => _("Writeable (nickname field shows part of vcard URI)"),
+ 'type' => SMOPT_TYPE_BOOLEAN,
+ );
+ $optpage_data['vals']['abook_carddav'][] = array(
+ 'name' => 'plugin_abook_carddav_listing',
+ 'caption' => _("Listing allowed (otherwise, only addressbook search is useful)"),
+ 'type' => SMOPT_TYPE_BOOLEAN,
+ );
+}
+
+
/**
* shows plugin's version
* @return string