1
0
mirror of https://github.com/owncloudarchive/contacts.git synced 2024-11-28 10:24:11 +01:00

after a painful rebase

This commit is contained in:
babelouest 2014-05-09 14:30:14 -04:00
parent f890fb5357
commit de4bb76c53
13 changed files with 708 additions and 114 deletions

17
admin.php Normal file
View File

@ -0,0 +1,17 @@
<?php
/**
* ownCloud - Contact Admin settings
*
* @author Nicolas Mora
* @copyright 2014 Nicolas Mora mail@babelouest.org
*
* This file is licensed under the Affero General Public License version 3 or
* later.
*/
namespace OCA\Contacts;
\OCP\User::checkAdminUser();
$tmpl = new \OCP\Template('contacts', 'admin');
return $tmpl->fetchPage();

View File

@ -53,18 +53,20 @@ $api->connectHook('OC_Calendar', 'getEvents', 'OCA\Contacts\Hooks', 'getBirthday
$api->connectHook('OC_Calendar', 'getSources', 'OCA\Contacts\Hooks', 'getCalenderSources');
\OCP\Util::addscript('contacts', 'loader');
\OCP\Util::addscript('contacts', 'admin');
\OC_Search::registerProvider('OCA\Contacts\SearchProvider');
//\OCP\Share::registerBackend('contact', 'OCA\Contacts\Share_Backend_Contact');
\OCP\Share::registerBackend('addressbook', 'OCA\Contacts\Share\Addressbook', 'contact');
//\OCP\App::registerPersonal('contacts','personalsettings');
\OCP\App::registerAdmin('contacts', 'admin');
if (\OCP\User::isLoggedIn()) {
$app = new App($api->getUserId());
$addressBooks = $app->getAddressBooksForUser();
foreach ($addressBooks as $addressBook) {
if ($addressBook->isActive()) {
\OCP\Contacts::registerAddressBook($addressBook->getSearchProvider());
\OCP\Contacts::registerAddressBook(new AddressbookProvider($addressBook));
}
}
}

View File

@ -40,7 +40,11 @@ $principalBackend = new OC_Connector_Sabre_Principal();
$addressbookbackends = array();
$addressbookbackends[] = new OCA\Contacts\Backend\Database(\OCP\User::getUser());
$carddavBackend = new OCA\Contacts\CardDAV\Backend(array('local', 'shared', 'ldap'));
$backends = array('local', 'shared');
if (\OCP\Config::getAppValue('contacts', 'backend_ldap', "false") === "true") {
$backends[] = 'ldap'
}
$carddavBackend = new OCA\Contacts\CardDAV\Backend($backends);
$requestBackend = new OC_Connector_Sabre_Request();
// Root nodes

View File

@ -34,6 +34,39 @@ $this->create('contacts_address_books_for_user', 'addressbooks/')
}
);
$this->create('contacts_address_book_connectors', 'connectors/{backend}')
->get()
->action(
function($params) {
\OC::$session->close();
$dispatcher = new Dispatcher($params);
$dispatcher->dispatch('BackendController', 'getConnectors');
}
)
->requirements(array('backend'));
$this->create('contacts_backend_enable', 'backend/{backend}/{enable}')
->get()
->action(
function($params) {
\OC::$session->close();
$dispatcher = new Dispatcher($params);
$dispatcher->dispatch('BackendController', 'enableBackend');
}
)
->requirements(array('backend', 'enable'));
$this->create('contacts_backend_status', 'backend/{backend}')
->get()
->action(
function($params) {
\OC::$session->close();
$dispatcher = new Dispatcher($params);
$dispatcher->dispatch('BackendController', 'backendStatus');
}
)
->requirements(array('backend'));
$this->create('contacts_address_book_add', 'addressbook/{backend}/add')
->post()
->action(
@ -428,4 +461,3 @@ $this->create('contacts_index_properties', 'indexproperties/{user}/')
)
->requirements(array('user'))
->defaults(array('user' => \OCP\User::getUser()));

73
backendcontroller.php Normal file
View File

@ -0,0 +1,73 @@
<?php
/**
* @author Nicolas Mora
* @copyright 2014 Nicolas Mora (mail@babelouest.org)
* This file is licensed under the Affero General Public License version 3 or
* later.
* See the COPYING-README file.
*/
namespace OCA\Contacts\Controller;
use OCA\Contacts\App,
OCA\Contacts\JSONResponse,
OCA\Contacts\Utils\JSONSerializer,
OCA\Contacts\Controller,
OCP\AppFramework\Http;
/**
* Controller class For Address Books
*/
class BackendController extends Controller {
/**
* @NoAdminRequired
* @NoCSRFRequired
*/
public function getConnectors() {
$response = new JSONResponse();
$prefix = "backend_ldap_";
$suffix = "_connector.xml";
$path = __DIR__ . "/../../formats/";
$files = scandir($path);
$formats = array();
foreach ($files as $file) {
if (!strncmp($file, $prefix, strlen($prefix)) && substr($file, - strlen($suffix)) === $suffix) {
if (file_exists($path.$file)) {
$format = simplexml_load_file ( $path.$file );
if ($format) {
if (isset($format['name'])) {
$formatId = substr($file, strlen($prefix), - strlen($suffix));
$formats[] = array('id' => $formatId, 'name' => (string)$format['name'], 'xml' => $format->asXML());
}
}
}
}
}
return $response->setData($formats);
}
/**
* @NoAdminRequired
* @NoCSRFRequired
*/
public function enableBackend() {
$response = new JSONResponse();
$params = $this->request->urlParams;
$backend = $params['backend'];
$enable = $params['enable'];
return $response->setData(\OCP\Config::setAppValue('contacts', 'backend_'.$backend, $enable));
}
/**
* @NoAdminRequired
* @NoCSRFRequired
*/
public function backendStatus() {
$response = new JSONResponse();
$params = $this->request->urlParams;
$backend = $params['backend'];
$enabled = \OCP\Config::getAppValue('contacts', 'backend_'.$backend, "false");
return $response->setData($enabled);
}
}

138
js/admin.js Normal file
View File

@ -0,0 +1,138 @@
console.log($('#contacts-ldap-enabled'));
$(document).ready(function() {
$.when(
backendStatus(
'ldap'
))
.then(function(response) {
if(!response.error) {
console.log('response', response.data);
if (response.data === "true") {
$('#contacts-ldap-enabled').prop('checked', true);
}
} else {
console.warn('Error', response.message);
}
}).fail(function(response) {
console.log(response.message);
});
$('#contacts-ldap-enabled').change(function() {
var enabled=$(this).prop('checked')?"true":"false";
$.when(
enableBackend(
'ldap',
enabled
))
.then(function(response) {
if(!response.error) {
console.log('response', response.data);
} else {
console.warn('Error', response.message);
}
}).fail(function(response) {
console.log(response.message);
});
});
});
function requestRoute(route, type, routeParams, params, additionalHeaders) {
var isJSON = (typeof params === 'string');
var contentType = isJSON
? (type === 'PATCH' ? 'application/json-merge-patch' : 'application/json')
: 'application/x-www-form-urlencoded';
var processData = !isJSON;
contentType += '; charset=UTF-8';
var url = OC.generateUrl('apps/contacts/' + route, routeParams);
var headers = {
Accept : 'application/json; charset=utf-8'
};
if(typeof additionalHeaders === 'object') {
headers = $.extend(headers, additionalHeaders);
}
var ajaxParams = {
type: type,
url: url,
dataType: 'json',
headers: headers,
contentType: contentType,
processData: processData,
data: params
};
var defer = $.Deferred();
$.ajax(ajaxParams)
.done(function(response, textStatus, jqXHR) {
console.log(jqXHR);
defer.resolve(new JSONResponse(jqXHR));
})
.fail(function(jqXHR/*, textStatus, error*/) {
console.log(jqXHR);
var response = jqXHR.responseText ? $.parseJSON(jqXHR.responseText) : null;
console.log('response', response);
defer.reject(new JSONResponse(jqXHR));
});
return defer.promise();
}
function enableBackend(backend, enable, params) {
return this.requestRoute(
'backend/{backend}/{enable}',
'GET',
{backend: backend, enable: enable},
JSON.stringify(params)
);
}
function backendStatus(backend, params) {
return this.requestRoute(
'backend/{backend}',
'GET',
{backend: backend},
JSON.stringify(params)
);
}
var JSONResponse = function(jqXHR) {
this.getAllResponseHeaders = jqXHR.getAllResponseHeaders;
this.getResponseHeader = jqXHR.getResponseHeader;
this.statusCode = jqXHR.status;
var response = jqXHR.responseJSON;
this.error = false;
console.log('jqXHR', jqXHR);
if (!response) {
// 204 == No content
// 304 == Not modified
if ([204, 304].indexOf(this.statusCode) === -1) {
this.error = true;
}
this.message = jqXHR.statusText;
} else {
// We need to allow for both the 'old' success/error status property
// with the body in the data property, and the newer where we rely
// on the status code, and the entire body is used.
if (response.status === 'error'|| this.statusCode >= 400) {
this.error = true;
if (!response.data || !response.data.message) {
this.message = t('contacts', 'Server error! Please inform system administator');
} else {
console.log('JSONResponse', response);
this.message = (response.data && response.data.message)
? response.data.message
: response;
}
} else {
this.data = response.data || response;
// Kind of a hack
if (response.metadata) {
this.metadata = response.metadata;
}
}
}
};

View File

@ -13,6 +13,7 @@ namespace OCA\Contacts;
use Sabre\VObject,
OCP\AppFramework,
OCA\Contacts\Controller\AddressBookController,
OCA\Contacts\Controller\BackendController,
OCA\Contacts\Controller\GroupController,
OCA\Contacts\Controller\ContactController,
OCA\Contacts\Controller\ContactPhotoController,
@ -53,7 +54,6 @@ class App {
* @var array
*/
public static $backendClasses = array(
'ldap' => 'OCA\Contacts\Backend\Ldap',
'local' => 'OCA\Contacts\Backend\Database',
'shared' => 'OCA\Contacts\Backend\Shared',
'localusers' => 'OCA\Contacts\Backend\LocalUsers',
@ -71,6 +71,9 @@ class App {
$this->dbBackend = $dbBackend
? $dbBackend
: new Backend\Database($user);
if (\OCP\Config::getAppValue('contacts', 'backend_ldap', "false") === "true") {
self::$backendClasses['ldap'] = 'OCA\Contacts\Backend\Ldap';
}
}
/**

View File

@ -38,10 +38,15 @@ class Ldap extends AbstractBackend {
* @var string
*/
public $name='ldap';
static private $preparedQueries = array();
private $ldapConnection = null;
private $connector = null;
/**
* The cached address books.
* @var array[]
*/
public $addressbooks;
/**
* @brief validates and sets the ldap parameters
* @param $ldapParams array containing the parameters
@ -50,7 +55,7 @@ class Ldap extends AbstractBackend {
public function setLdapParams($aid) {
$tmp = $this->getPreferences($aid);
if ($tmp != false) {
$this->ldapParams = $tmp;
$this->ldapParams = (array)$tmp;
$this->connector = new LdapConnector($this->ldapParams['ldap_vcard_connector']);
return true;
} else {
@ -213,12 +218,7 @@ class Ldap extends AbstractBackend {
*/
public function ldapUpdate($ldapDN, $ldapValues) {
if (self::ldapIsConnected()) {
$result = @ldap_modify($this->ldapConnection, $ldapDN, $ldapValues);
if (!$result) {
self::ldapDelete($ldapDN);
return self::ldapAdd($ldapDN, $ldapValues);
}
return true;
return @ldap_modify($this->ldapConnection, $ldapDN, $ldapValues);
}
return false;
}
@ -257,12 +257,10 @@ class Ldap extends AbstractBackend {
*/
public function getAddressBooksForUser(array $options = array()) {
$addressbookidList = $this->getAddressbookList();
$this->addressbooks = array();
foreach($addressbookidList as $addressbookid) {
$this->addressbooks[] = self::getAddressBook($addressbookid);
}
return $this->addressbooks;
}
/**
@ -286,16 +284,19 @@ class Ldap extends AbstractBackend {
}
// Hmm, not found. Lets query the db.
$preferences = self::getPreferences($addressbookid);
if ($preferences != false) {
$current = array();
$current['id'] = (string)$addressbookid;
$current['displayname'] = (string)$preferences['displayname'];
$current['description'] = (string)$preferences['description'];
$current['owner'] = $this->userid;
$current['uri'] = (string)$preferences['uri'];
$current['permissions'] = \OCP\PERMISSION_ALL;
$current['lastmodified'] = self::lastModifiedAddressBook($addressbookid);
return $current;
if (count($preferences) > 0) {
$preferences['id'] = (string)$addressbookid;
$preferences['backend'] = $this->name;
$preferences['owner'] = $this->userid;
$preferences['permissions'] = \OCP\PERMISSION_ALL;
$preferences['lastmodified'] = self::lastModifiedAddressBook($addressbookid);
// remove the ldappassword from the return value if exists
if (isset($preferences['ldappass']) && (isset($options['getpwd']) && !$options['getpwd'])) {
unset($preferences['ldappass']);
}
return $preferences;
} else {
return array();
}
@ -322,14 +323,22 @@ class Ldap extends AbstractBackend {
*
* @param string $addressbookid
* @param array $properties
* @return bool
* @return string|false The ID if the modified AddressBook or false on error.
*/
public function updateAddressBook($addressbookid, array $properties, array $options = array()) {
// TODO: use backend settings
return true;
if ($this->hasAddressBook($addressbookid)) {
// Addressbook exists, modify it through the create function
if (isset($properties['ldappassmodified']) && $properties['ldappassmodified'] != 'true') {
// If password hasn't changed, get it from the preferences
$addrbook = $this->getAddressBook($addressbookid, array('getpwd' => true));
$properties['ldappass'] = base64_decode($addrbook['ldappass']);
}
return $this->setAddressBook($properties, $options);
} else {
return false;
}
}
/**
* Creates a new address book
*
@ -341,7 +350,80 @@ class Ldap extends AbstractBackend {
* @return string|false The ID if the newly created AddressBook or false on error.
*/
public function createAddressBook(array $properties, array $options = array()) {
// TODO: use backend settings
if (!isset($properties['uri']) || $this->hasAddressBook($properties['uri'])) {
return false;
} else {
return $this->setAddressBook($properties, $options);
}
}
/*
* Sets the parameters for a new or existing addressbook
*
* @param array $properties
* @return string|false The ID if the newly created AddressBook or false on error.
*/
public function setAddressBook(array $properties, array $options = array()) {
if (count($properties) === 0) {
return false;
}
if (isset($properties['displayname']) && $properties['displayname'] != '' &&
isset($properties['uri']) && $properties['uri'] != '' &&
isset($properties['ldapurl']) && $properties['ldapurl'] != '' &&
isset($properties['ldappagesize']) && $properties['ldappagesize'] != '' &&
isset($properties['ldapbasednsearch']) && $properties['ldapbasednsearch'] != '' &&
isset($properties['ldapfilter']) && $properties['ldapfilter'] != '' &&
isset($properties['ldapvcardconnector']) &&
isset($properties['ldapanonymous']) &&
($properties['ldapanonymous']=='true'
|| ($properties['ldapanonymous']=='false'
&& isset($properties['ldapuser']) && $properties['ldapuser'] != ''
&& isset($properties['ldappass']) && $properties['ldappass'] != ''
)
) &&
isset($properties['ldapreadonly']) &&
($properties['ldapreadonly']=='true'
|| ($properties['ldapreadonly']=='false'
&& isset($properties['ldapbasednmodify']) && $properties['ldapbasednmodify'] != ''
)
)
) {
$addressbookSettings = array();
$addressbookSettings['uri'] = $properties['uri'];
$addressbookSettings['displayname'] = $properties['displayname'];
$addressbookSettings['description'] = $properties['description'];
$addressbookSettings['ldapurl'] = $properties['ldapurl'];
$addressbookSettings['ldapanonymous'] = ($properties['ldapanonymous']=='true');
$addressbookSettings['ldapreadonly'] = ($properties['ldapreadonly']=='true');
$addressbookSettings['ldapuser'] = ($properties['ldapanonymous']=='false')?$properties['ldapuser']:"";
$addressbookSettings['ldappass'] = ($properties['ldapanonymous']=='false')?base64_encode($properties['ldappass']):"";
$addressbookSettings['ldappagesize'] = $properties['ldappagesize'];
$addressbookSettings['ldapbasednsearch'] = $properties['ldapbasednsearch'];
$addressbookSettings['ldapfilter'] = $properties['ldapfilter'];
$addressbookSettings['ldapbasednmodify'] = ($properties['ldapanonymous']=='false')?$properties['ldapbasednmodify']:"";
$addressbookSettings['ldapconnectorid'] = $properties['ldapvcardconnector'];
if ($properties['ldapvcardconnector'] != '') {
$prefix = "backend_ldap_";
$suffix = "_connector.xml";
$path = __DIR__ . "/../../formats/";
if (file_exists( $path.$prefix.$properties['ldapvcardconnector'].$suffix )) {
$addressbookSettings['ldap_vcard_connector'] = file_get_contents ( $path.$prefix.$properties['ldapvcardconnector'].$suffix );
}
} else {
$addressbookSettings['ldap_vcard_connector'] = $properties['ldapvcardconnectorvalue'];
}
$addressbookList = $this->getAddressbookList();
if (!in_array($properties['uri'], $addressbookList)) {
$addressbookList[] = $properties['uri'];
$this->setAddressbookList($addressbookList);
}
$this->setPreferences($properties['uri'], $addressbookSettings);
$this->setActive(1, $properties['uri']);
return $properties['uri'];
}
return false;
}
/**
@ -351,27 +433,21 @@ class Ldap extends AbstractBackend {
* @return bool
*/
public function deleteAddressBook($addressbookid, array $options = array()) {
$addressbook = self::getAddressBook($addressbookid);
//$addressbook = self::getAddressBook($addressbookid);
$addressbookList = $this->getAddressbookList();
$toRemove = array_search($addressbookid, $addressbookList);
if (is_int($toRemove)) {
unset($addressbookList[$toRemove]);
$addressbookList = array_values($addressbookList);
$this->setAddressbookList($addressbookList);
}
self::removePreferences($addressbookid);
// TODO: use backend settings
return true;
}
/**
* @brief Get the last modification time for an address book.
*
* Must return a UNIX time stamp or null if the backend
* doesn't support it.
*
* TODO: Implement default methods get/set for backends that
* don't support.
* @param string $addressbookid
* @returns int | null
*/
public function lastModifiedAddressBook($addressbookid, array $options = array()) {
return null;
}
/**
* Returns all contacts for a specific addressbook id.
*
@ -399,6 +475,16 @@ class Ldap extends AbstractBackend {
* @return array
*/
public function getContacts($addressbookid, array $options = array()) {
$backtrace = debug_backtrace();
$trace=array();
foreach ($backtrace as $elt) {
foreach ($elt as $key => $line) {
if ($key == "file" || $key == "line") {
$trace[] = $line;
}
}
}
$cards = array();
$vcards = array();
if(is_array($addressbookid) && count($addressbookid)) {
@ -448,7 +534,6 @@ class Ldap extends AbstractBackend {
$cards = array();
$toReturn = false;
self::setLdapParams($addressbookid);
if (self::setLdapParams($addressbookid)) {
foreach ($a_ids as $id) {
$cid = str_replace(".vcf", "", $id);
@ -465,7 +550,7 @@ class Ldap extends AbstractBackend {
$this->connector->getLdapEntries());
} else {
$card = self::ldapFindOne(base64_decode($cid),
'objectClass=*',
$this->ldapParams['ldapfilter'],
$this->connector->getLdapEntries());
}
}
@ -501,7 +586,7 @@ class Ldap extends AbstractBackend {
$URI = (string)$vcard->{'X-LDAP-DN'};
}
return array('id' => $UID,
'permissions' => \OCP\PERMISSION_READ,
'permissions' => \OCP\PERMISSION_ALL,
'displayname' => $FN,
'carddata' => $vcard->serialize(),
'uri' => $URI,
@ -516,25 +601,16 @@ class Ldap extends AbstractBackend {
* @return string|bool The identifier for the new contact or false on error.
*/
public function createContact($addressbookid, $contact, array $options = array()) {
$backtrace = debug_backtrace();
$trace=array();
foreach ($backtrace as $elt) {
foreach ($elt as $key => $line) {
if ($key == "file" || $key == "line") {
$trace[] = $line;
}
}
}
//error_log("stay added ".print_r($trace,1));
$uri = isset($options['uri']) ? $options['uri'] : null;
$contact->REV = (new \DateTime)->format(\DateTime::W3C);
// 2014/02/13 Sometimes, a card is created without a name (I don't like that)...
if (!isset($contact->N)) {
$generated = "gruik".rand(0, 65535);
$generated = "nocn-".rand(0, 65535);
$contact->N = $generated;
$contact->FN = $generated;
error_log("Generated name: $generated");
}
if(!$contact instanceof VCard) {
@ -545,7 +621,6 @@ class Ldap extends AbstractBackend {
return false;
}
}
error_log("adding ".$contact->serialize());
try {
$contact->validate(VCard::REPAIR|VCard::UPGRADE);
@ -588,16 +663,6 @@ class Ldap extends AbstractBackend {
* @return bool
*/
public function updateContact($addressbookid, $id, $carddata, array $options = array()) {
$backtrace = debug_backtrace();
$trace=array();
foreach ($backtrace as $elt) {
foreach ($elt as $key => $line) {
if ($key == "file" || $key == "line") {
$trace[] = $line;
}
}
}
//error_log("stay modified ".print_r($trace,1));
if(!$carddata instanceof VCard) {
try {
$vcard = \Sabre\VObject\Reader::read($carddata);
@ -609,7 +674,14 @@ class Ldap extends AbstractBackend {
$vcard = $carddata;
}
//error_log("updating ".$vcard->serialize());
try {
$vcard->validate(VCard::REPAIR|VCard::UPGRADE);
} catch (\Exception $e) {
OCP\Util::writeLog('contacts', __METHOD__ . ' ' .
'Error validating vcard: ' . $e->getMessage(), \OCP\Util::ERROR);
return false;
}
//$vcard->REV = (new \DateTime)->format(\DateTime::W3C);
if (!is_array($id)) {
$a_ids = array($id);
@ -631,6 +703,8 @@ class Ldap extends AbstractBackend {
$dn = base64_decode($tmpVCard->{'X-LDAP-DN'});
}
// Updates the existing card
$ldifSource = self::ldapFindOne($dn, $this->ldapParams['ldapfilter'], $this->connector->getLdapEntries());
$this->connector->insertEmptyEntries($ldifSource, $ldifEntries);
$result = self::ldapUpdate($dn, $ldifEntries);
}
self::ldapCloseConnection();
@ -645,19 +719,8 @@ class Ldap extends AbstractBackend {
* @return bool
*/
public function deleteContact($addressbookid, $id, array $options = array()) {
$backtrace = debug_backtrace();
$trace=array();
foreach ($backtrace as $elt) {
foreach ($elt as $key => $line) {
if ($key == "file" || $key == "line") {
$trace[] = $line;
}
}
}
//error_log("stay dead ".print_r($trace, 1));
self::setLdapParams($addressbookid);
self::ldapCreateAndBindConnection();
$card=null;
if (is_array($id)) {
$card = self::getContact($addressbookid, $id);
} else {
@ -694,20 +757,33 @@ class Ldap extends AbstractBackend {
}
}
// Please remove this
public function debug_string_backtrace() {
ob_start();
debug_print_backtrace();
$trace = ob_get_contents();
ob_end_clean();
/**
* @brief sets the list of ldap addressbooks in the preferences
* with the list given in parameter
* @param the new list
* @returns result|false
*/
protected function setAddressbookList(array $addressbookList) {
$key = $this->name . "_list";
$data = json_encode($addressbookList);
return $data
? \OCP\Config::setUserValue($this->userid, 'contacts', $key, $data)
: false;
}
/**
* @brief gets the list of ldap addressbooks in the preferences
* returns array()
*/
protected function getAddressbookList() {
$key = $this->name . "_list";
$data = \OCP\Config::getUserValue($this->userid, 'contacts', $key, false);
return $data ? json_decode($data) : array();
}
// Remove first item from backtrace as it's this function which
// is redundant.
$trace = preg_replace ('/^#0\s+' . __FUNCTION__ . "[^\n]*\n/", '', $trace, 1);
// Renumber backtrace items.
$trace = preg_replace ('/^#(\d+)/me', '\'#\' . ($1 - 1)', $trace);
return $trace;
}
public function getSearchProvider($addressbook) {
return new \OCA\Contacts\AddressbookProvider($addressbook);
}
}

View File

@ -33,7 +33,14 @@ class LdapConnector {
\OCP\Util::writeLog('ldap_vcard_connector', __METHOD__.', error in setting xml config', \OCP\Util::DEBUG);
}
}
private function convertDate ($ldapDate) {
$tstamp = strtotime($ldapDate);
$theDate = new \DateTime;
$theDate->setTimestamp($tstamp);
return $theDate;
}
/**
* @brief transform a ldap entry into an VCard object
* for each ldap entry which is like "property: value"
@ -43,26 +50,27 @@ class LdapConnector {
*/
public function ldapToVCard($ldapEntry) {
$vcard = \Sabre\VObject\Component::create('VCARD');
$vcard->REV = $ldapEntry['modifytimestamp'][0];
$vcard->REV = $this->convertDate($ldapEntry['modifytimestamp'][0])->format(\DateTime::W3C);
//error_log("modifytimestamp: ".$vcard->REV);
$vcard->{'X-LDAP-DN'} = base64_encode($ldapEntry['dn']);
// OCP\Util::writeLog('ldap_vcard_connector', __METHOD__.' vcard is '.$vcard->serialize(), \OCP\Util::DEBUG);
for ($i=0; $i<$ldapEntry["count"]; $i++) {
// ldap property name : $ldap_entry[$i]
$l_property = $ldapEntry[$i];
for ($j=0;$j<$ldapEntry[$l_property]["count"];$j++){
$lProperty = $ldapEntry[$i];
for ($j=0;$j<$ldapEntry[$lProperty]["count"];$j++){
// What to do :
// convert the ldap property into vcard property, type and position (if needed)
// $v_params format: array('property' => property, 'type' => array(types), 'position' => position)
$v_params = $this->getVCardProperty($l_property);
$v_params = $this->getVCardProperty($lProperty);
foreach ($v_params as $v_param) {
if (isset($v_param['unassigned'])) {
// if the value comes from the unassigned entry, it's a vcard property dumped
try {
$property = \Sabre\VObject\Reader::read($ldapEntry[$l_property][$j]);
$property = \Sabre\VObject\Reader::read($ldapEntry[$lProperty][$j]);
$vcard->add($property);
} catch (exception $e) {
}
@ -74,9 +82,9 @@ class LdapConnector {
// modify the property with the new data
if (strcasecmp($v_param['image'], 'true') == 0) {
$this->updateVCardImageProperty($v_property, $ldapEntry[$l_property][$j], $vcard->VERSION);
$this->updateVCardImageProperty($v_property, $ldapEntry[$lProperty][$j], $vcard->VERSION);
} else {
$this->updateVCardProperty($v_property, $ldapEntry[$l_property][$j], $v_param['position']);
$this->updateVCardProperty($v_property, $ldapEntry[$lProperty][$j], $v_param['position']);
}
}
}
@ -86,7 +94,6 @@ class LdapConnector {
if (!isset($vcard->UID)) {
$vcard->UID = base64_encode($ldapEntry['dn']);
}
$vcard->validate(\Sabre\VObject\Component\VCard::REPAIR);
return $vcard;
}
@ -179,16 +186,16 @@ class LdapConnector {
/**
* @brief gets the vcard property values from an ldif entry name
* @param $l_property the ldif property name
* @param $lProperty the ldif property name
* @return array('property' => property, 'type' => type, 'position' => position)
*/
public function getVCardProperty($l_property) {
public function getVCardProperty($lProperty) {
$properties = array();
if (strcmp($l_property, $this->getUnassignedVCardProperty()) == 0) {
if (strcmp($lProperty, $this->getUnassignedVCardProperty()) == 0) {
$properties[] = array('unassigned' => true);
} else {
foreach ($this->config_content->ldap_entries->ldif_entry as $ldif_entry) {
if ($l_property == $ldif_entry['name']) {
if ($lProperty == $ldif_entry['name']) {
// $ldif_entry['name'] is the right config xml
foreach ($ldif_entry->vcard_entry as $vcard_entry) {
$type=isset($vcard_entry['type'])?$vcard_entry['type']:"";
@ -421,6 +428,22 @@ class LdapConnector {
return false;
}
}
/**
* @brief adds empty entries in $dest if $dest doesn't have those entries and if $source has
* otherwise, I couldn't find how to remove attributes
* @param $source the source ldap entry as model
* @param $dest the destination entry to add empty params if we have to
*/
public function insertEmptyEntries($source, &$dest) {
for ($i=0; $i<$source["count"]; $i++) {
$lProperty = $source[$i];
if (!isset($dest[$lProperty]) && $lProperty != 'modifytimestamp') {
$dest[$lProperty] = array();
}
}
}
}
?>

View File

@ -0,0 +1,73 @@
<?php
/**
* @author Nicolas Mora
* @copyright 2014 Nicolas Mora (mail@babelouest.org)
* This file is licensed under the Affero General Public License version 3 or
* later.
* See the COPYING-README file.
*/
namespace OCA\Contacts\Controller;
use OCA\Contacts\App,
OCA\Contacts\JSONResponse,
OCA\Contacts\Utils\JSONSerializer,
OCA\Contacts\Controller,
OCP\AppFramework\Http;
/**
* Controller class For Address Books
*/
class BackendController extends Controller {
/**
* @NoAdminRequired
* @NoCSRFRequired
*/
public function getConnectors() {
$response = new JSONResponse();
$prefix = "backend_ldap_";
$suffix = "_connector.xml";
$path = __DIR__ . "/../../formats/";
$files = scandir($path);
$formats = array();
foreach ($files as $file) {
if (!strncmp($file, $prefix, strlen($prefix)) && substr($file, - strlen($suffix)) === $suffix) {
if (file_exists($path.$file)) {
$format = simplexml_load_file ( $path.$file );
if ($format) {
if (isset($format['name'])) {
$formatId = substr($file, strlen($prefix), - strlen($suffix));
$formats[] = array('id' => $formatId, 'name' => (string)$format['name'], 'xml' => $format->asXML());
}
}
}
}
}
return $response->setData($formats);
}
/**
* @NoAdminRequired
* @NoCSRFRequired
*/
public function enableBackend() {
$response = new JSONResponse();
$params = $this->request->urlParams;
$backend = $params['backend'];
$enable = $params['enable'];
return $response->setData(\OCP\Config::setAppValue('contacts', 'backend_'.$backend, $enable));
}
/**
* @NoAdminRequired
* @NoCSRFRequired
*/
public function backendStatus() {
$response = new JSONResponse();
$params = $this->request->urlParams;
$backend = $params['backend'];
$enabled = \OCP\Config::getAppValue('contacts', 'backend_'.$backend, "false");
return $response->setData($enabled);
}
}

View File

@ -21,7 +21,8 @@ use OCP\AppFramework\App as MainApp,
OCA\Contacts\Controller\ContactPhotoController,
OCA\Contacts\Controller\SettingsController,
OCA\Contacts\Controller\ImportController,
OCA\Contacts\Controller\ExportController;
OCA\Contacts\Controller\ExportController,
OCA\Contacts\Controller\BackendController;
/**
* This class manages our app actions
@ -105,6 +106,10 @@ class Dispatcher extends MainApp {
$request = $container->query('Request');
return new ExportController($appName, $request, $app);
});
$this->container->registerService('BackendController', function(IAppContainer $container) use($appName, $app) {
$request = $container->query('Request');
return new BackendController($appName, $request, $app);
});
}
}

21
templates/admin.php Normal file
View File

@ -0,0 +1,21 @@
<?php
/**
* ownCloud - Contacts
*
* @author Nicolas Mora
* @copyright 2014 Nicolas Mora mail@babelouest.org
*
* This file is licensed under the Affero General Public License version 3 or
* later.
*/
?>
<div class="section">
<h2>Contacts</h2>
<input type="checkbox" name="contacts-ldap-enabled" id="contacts-ldap-enabled" value="checked"/>
<label for="contacts-ldap-enabled"><?php p($l->t('Enable LDAP Backend')) ?></label><br>
<em><?php p($l->t('Enable LDAP backend for the contacts application')) ?></em>
<br/><em><?php p($l->t('Warning: LDAP Backend is in beta mode, use with precautions')) ?></em>
</div>

View File

@ -1,3 +1,6 @@
<?php
use OCA\Contacts\ImportManager;
?>
<div id="app">
<div id="app-navigation" class="loading">
<ul id="grouplist" class="hidden-on-load">
@ -20,6 +23,15 @@
<ul class="addressbooklist">
</ul>
<input type="text" tabindex="0" autofocus id="add-address-book" placeholder="<?php p($l->t('Display name')); ?>" title="<?php p($l->t('Add Address Book')); ?>" />
<?php
if (\OCP\Config::getAppValue('contacts', 'backend_ldap', "false") === "true") {
?>
<ul class="oc-addnew">
<li id="add-ldap-address-book-element"><a class="oc-addnew-init"><?php p($l->t('Add LDAP Address Book')); ?></a></li>
</ul>
<?php
}
?>
</div>
<div id="import">
<h2 data-id="import" tabindex="0" role="button"><?php p($l->t('Import')); ?></h2>
@ -31,7 +43,8 @@
<select id="import_format">
<option value="automatic"><?php p($l->t('Automatic format')); ?></option>
<?php
$types = $_['importManager']->getTypes();
$importManager = new ImportManager();
$types = $importManager->getTypes();
foreach ($types as $id => $label) {
echo "<option value=\"$id\">$label</option>";
}
@ -503,3 +516,117 @@
</span>
</li>
</script>
<script id="addressBookConfigTemplate" class="hidden" type="text/template">
<div id="addressbooks-ui-div" class="addressbooks-ui-class">
<input type="hidden" id="addressbooks-ui-addressbookid" />
<input type="hidden" id="addressbooks-ui-backend" value="{backend}" />
<p id="addressbooks-ui-name-p">
<label for="addressbooks-ui-name">
<?php p($l->t('Name')); ?>:
</label>
<input type="text" class="nonempty value" id="addressbooks-ui-name" value=""
placeholder="<?php p($l->t('Name')); ?>" required />
</p>
<p id="addressbooks-ui-uri-p">
<label for="addressbooks-ui-uri">
<?php p($l->t('Addressbook URI')); ?>:
</label>
<input type="text" class="nonempty value" id="addressbooks-ui-uri" value=""
placeholder="<?php p($l->t('URI')); ?>" required />
</p>
<p id="addressbooks-ui-description-p">
<label for="addressbooks-ui-description">
<?php p($l->t('Description')); ?>:
</label>
<input type="text" class="nonempty value" id="addressbooks-ui-description" value=""
placeholder="<?php p($l->t('Description')); ?>" />
</p>
<p id="addressbooks-ui-ldapurl-p">
<label for="addressbooks-ui-ldapurl">
<?php p($l->t('LDAP URL')); ?>:
</label>
<input type="text" class="nonempty value" id="addressbooks-ui-ldapurl" value=""
placeholder="<?php p($l->t('LDAP URL')); ?>" required />
</p>
<p id="addressbooks-ui-ldapanonymous-p">
<label for="addressbooks-ui-ldapanonymous">
<?php p($l->t('Anonymous')); ?>:
</label>
<input type="checkbox" id="addressbooks-ui-ldapanonymous" title="<?php p($l->t('Anonymous')); ?>" />
</p>
<p id="addressbooks-ui-ldapreadonly-p">
<label for="addressbooks-ui-ldapreadonly">
<?php p($l->t('Read-only')); ?>:
</label>
<input type="checkbox" id="addressbooks-ui-ldapreadonly" title="<?php p($l->t('Read-Only')); ?>" />
</p>
<p id="addressbooks-ui-ldapuser-p">
<label for="addressbooks-ui-ldapuser">
<?php p($l->t('User')); ?>:
</label>
<input type="text" class="nonempty value" id="addressbooks-ui-ldapuser" value=""
placeholder="<?php p($l->t('User')); ?>" required />
</p>
<p id="addressbooks-ui-ldappass-p">
<input type="hidden" id="addressbooks-ui-ldappass-modified" />
<label for="addressbooks-ui-ldappass">
<?php p($l->t('Password')); ?>:
</label>
<input type="password" class="nonempty value" id="addressbooks-ui-ldappass" value=""
placeholder="<?php p($l->t('Password')); ?>" required />
</p>
<p id="addressbooks-ui-ldappagesize-p">
<label for="addressbooks-ui-ldappagesize">
<?php p($l->t('Page size')); ?>:
</label>
<input type="text" class="nonempty value" id="addressbooks-ui-ldappagesize" value="20"
placeholder="<?php p($l->t('Page size')); ?>" required />
</p>
<p id="addressbooks-ui-ldapbasednsearch-p">
<label for="addressbooks-ui-ldapbasednsearch">
<?php p($l->t('Base DN for search')); ?>:
</label>
<input type="text" class="nonempty value" id="addressbooks-ui-ldapbasednsearch" value=""
placeholder="<?php p($l->t('Base DN')); ?>" required />
</p>
<p id="addressbooks-ui-ldapfilter-p">
<label for="addressbooks-ui-ldapfilter">
<?php p($l->t('Search filter')); ?>:
</label>
<input type="text" class="nonempty value" id="addressbooks-ui-ldapfilter" value=""
placeholder="<?php p($l->t('Filter')); ?>" required />
</p>
<p id="addressbooks-ui-ldapbasednmodify-p">
<label for="addressbooks-ui-ldapbasednmodify">
<?php p($l->t('Base DN for modification')); ?>:
</label>
<input type="text" class="nonempty value" id="addressbooks-ui-ldapbasednmodify" value=""
placeholder="<?php p($l->t('Base DN modification')); ?>" required />
</p>
<p id="addressbooks-ui-ldapvcardconnector-p">
<label for="addressbooks-ui-ldapvcardconnector">
<?php p($l->t('Connector')); ?>:
</label>
<select id="addressbooks-ui-ldapvcardconnector">
</select>
</p>
<p id="addressbooks-ui-ldapvcardconnector-value-p">
<label for="addressbooks-ui-ldapvcardconnector-value">
<?php p($l->t('Connector value (Better use external editor and copy/paste)')); ?>:
</label>
<textarea id="addressbooks-ui-ldapvcardconnector-value"></textarea>
</p>
<p id="addressbooks-ui-ldapvcardconnector-copyfrom-p">
<label for="addressbooks-ui-ldapvcardconnector-copyfrom">
<?php p($l->t('Copy from (Warning, replaces current custom value)')); ?>:
</label>
<select id="addressbooks-ui-ldapvcardconnector-copyfrom">
</select>
</p>
<p id="addressbooks-ui-errortitle-p">&nbsp;
</p>
<p id="addressbooks-ui-errormessage-p">&nbsp;
</p>
</div>
</script>