From 59b316d9a23fd31598100536680c04a5dcb8026f Mon Sep 17 00:00:00 2001 From: Markus Neubauer Date: Tue, 8 Dec 2015 08:42:57 +0100 Subject: [PATCH 01/87] Create upgrade-pb-3.2-3.3.sql --- misc/scripts/upgrade-pb-3.2-3.3.sql | 42 +++++++++++++++++++++++++++++ 1 file changed, 42 insertions(+) create mode 100644 misc/scripts/upgrade-pb-3.2-3.3.sql diff --git a/misc/scripts/upgrade-pb-3.2-3.3.sql b/misc/scripts/upgrade-pb-3.2-3.3.sql new file mode 100644 index 000000000..bd18c3879 --- /dev/null +++ b/misc/scripts/upgrade-pb-3.2-3.3.sql @@ -0,0 +1,42 @@ +CREATE TABLE IF NOT EXISTS `pb_prv` ( + `id` int(10) unsigned NOT NULL AUTO_INCREMENT, + `user_id` int(10) unsigned NOT NULL DEFAULT '0', + `firstname` varchar(40) COLLATE utf8_unicode_ci NOT NULL DEFAULT '', + `lastname` varchar(40) COLLATE utf8_unicode_ci NOT NULL DEFAULT '', + `number` varchar(25) CHARACTER SET ascii NOT NULL DEFAULT '', + `ptype` varchar(16) COLLATE utf8_unicode_ci NOT NULL COMMENT 'cell,work,home', + `vcard_id` int(11) NOT NULL, + `cat_id` int(11) NOT NULL, + `modified` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, + PRIMARY KEY (`id`), + KEY `uid_lastname_firstname` (`user_id`,`lastname`(15),`firstname`(10)), + KEY `uid_firstname_lastname` (`user_id`,`firstname`(10),`lastname`(10)), + KEY `uid_number` (`user_id`,`number`(10)), + KEY `uid_vcard` (`user_id`,`vcard_id`), + KEY `uid_cat_lastname_firstname` (`user_id`,`cat_id`,`lastname`,`firstname`), + KEY `uid_cat_firstname_lastname` (`user_id`,`cat_id`,`firstname`,`lastname`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci; + +CREATE TABLE IF NOT EXISTS `pb_cloud` ( + `id` int(11) NOT NULL AUTO_INCREMENT, + `user_id` int(11) NOT NULL, + `url` varchar(256) COLLATE utf8_unicode_ci NOT NULL, + `login` varchar(64) COLLATE utf8_unicode_ci NOT NULL, + `pass` varbinary(64) NOT NULL, + `frequency` varchar(3) COLLATE utf8_unicode_ci NOT NULL DEFAULT '1d', + `next_poll` datetime NOT NULL, + `modified` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, + PRIMARY KEY (`id`), + KEY `user_id` (`user_id`), + KEY `next_poll` (`next_poll`), + KEY `url` (`user_id`,`url`(255)), + KEY `login` (`user_id`,`login`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci; + +ALTER TABLE `pb_prv` ADD `ptype` VARCHAR(16) NOT NULL COMMENT 'cell,work,home'; +ALTER TABLE `pb_prv` ADD `vcard_id` int(11) NOT NULL; +ALTER TABLE `pb_prv` ADD `cat_id` int(11) NOT NULL; +ALTER TABLE `pb_prv` ADD `modified` TIMESTAMP on update CURRENT_TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP; +ALTER TABLE `pb_prv` ADD INDEX `uid_vcard` (`user_id`,`vcard_id`); +ALTER TABLE `pb_prv` ADD INDEX `uid_cat_lastname_firstname` (`user_id`,`cat_id`,`lastname`,`firstname`); +ALTER TABLE `pb_prv` ADD INDEX `uid_cat_firstname_lastname` (`user_id`,`cat_id`,`firstname`,`lastname`); From 03faefe78ae7af053ad411cfd0e07b96e728fe9e Mon Sep 17 00:00:00 2001 From: Markus Neubauer Date: Tue, 8 Dec 2015 15:01:12 +0100 Subject: [PATCH 02/87] added categories --- misc/scripts/upgrade-pb-3.2-3.3.sql | 27 ++++++++++++++++++++------- 1 file changed, 20 insertions(+), 7 deletions(-) diff --git a/misc/scripts/upgrade-pb-3.2-3.3.sql b/misc/scripts/upgrade-pb-3.2-3.3.sql index bd18c3879..bd2d7c8a1 100644 --- a/misc/scripts/upgrade-pb-3.2-3.3.sql +++ b/misc/scripts/upgrade-pb-3.2-3.3.sql @@ -1,3 +1,4 @@ +// gs 3.3 private phonebook CREATE TABLE IF NOT EXISTS `pb_prv` ( `id` int(10) unsigned NOT NULL AUTO_INCREMENT, `user_id` int(10) unsigned NOT NULL DEFAULT '0', @@ -17,6 +18,17 @@ CREATE TABLE IF NOT EXISTS `pb_prv` ( KEY `uid_cat_firstname_lastname` (`user_id`,`cat_id`,`firstname`,`lastname`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci; +// alter existing 3.2 private phonebook +ALTER TABLE `pb_prv` ADD `ptype` VARCHAR(16) NOT NULL COMMENT 'cell,work,home'; +ALTER TABLE `pb_prv` ADD `vcard_id` int(11) NOT NULL; +ALTER TABLE `pb_prv` ADD `cat_id` int(11) NOT NULL; +ALTER TABLE `pb_prv` ADD `modified` TIMESTAMP on update CURRENT_TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP; +ALTER TABLE `pb_prv` ADD INDEX `uid_vcard` (`user_id`,`vcard_id`); +ALTER TABLE `pb_prv` ADD INDEX `uid_cat_lastname_firstname` (`user_id`,`cat_id`,`lastname`,`firstname`); +ALTER TABLE `pb_prv` ADD INDEX `uid_cat_firstname_lastname` (`user_id`,`cat_id`,`firstname`,`lastname`); + + +// import voip phone book from cloud for preparing the xml to phone functionality CREATE TABLE IF NOT EXISTS `pb_cloud` ( `id` int(11) NOT NULL AUTO_INCREMENT, `user_id` int(11) NOT NULL, @@ -33,10 +45,11 @@ CREATE TABLE IF NOT EXISTS `pb_cloud` ( KEY `login` (`user_id`,`login`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci; -ALTER TABLE `pb_prv` ADD `ptype` VARCHAR(16) NOT NULL COMMENT 'cell,work,home'; -ALTER TABLE `pb_prv` ADD `vcard_id` int(11) NOT NULL; -ALTER TABLE `pb_prv` ADD `cat_id` int(11) NOT NULL; -ALTER TABLE `pb_prv` ADD `modified` TIMESTAMP on update CURRENT_TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP; -ALTER TABLE `pb_prv` ADD INDEX `uid_vcard` (`user_id`,`vcard_id`); -ALTER TABLE `pb_prv` ADD INDEX `uid_cat_lastname_firstname` (`user_id`,`cat_id`,`lastname`,`firstname`); -ALTER TABLE `pb_prv` ADD INDEX `uid_cat_firstname_lastname` (`user_id`,`cat_id`,`firstname`,`lastname`); +// add categories like family etc. to phone book +CREATE TABLE IF NOT EXISTS `pb_category` ( + `id` int(11) NOT NULL AUTO_INCREMENT, + `user_id` int(11) NOT NULL, + `category` varchar(24) COLLATE utf8_unicode_ci NOT NULL, + `modified` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, + PRIMARY KEY (`id`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci; From 0cf62efa79f51b1b7206b5cb4a6b5fec34ec5a03 Mon Sep 17 00:00:00 2001 From: Markus Neubauer Date: Tue, 8 Dec 2015 15:27:27 +0100 Subject: [PATCH 03/87] Update pb_private.php --- .../htdocs/gui/mod/pb_private.php | 58 ++++++++++++++++--- 1 file changed, 51 insertions(+), 7 deletions(-) diff --git a/opt/gemeinschaft/htdocs/gui/mod/pb_private.php b/opt/gemeinschaft/htdocs/gui/mod/pb_private.php index de3984d11..da4c7d730 100644 --- a/opt/gemeinschaft/htdocs/gui/mod/pb_private.php +++ b/opt/gemeinschaft/htdocs/gui/mod/pb_private.php @@ -10,6 +10,10 @@ * Philipp Kempgen * Peter Kozak * Soeren Sprenger +* Markus Neubauer - 2015 +* - extending db and preparing for vcards +* you need to alter the db for this version to work: +* * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License @@ -52,9 +56,11 @@ function confirm_delete() { $name = trim(@$_REQUEST['name' ]); $number = trim(@$_REQUEST['number' ]); +$ptype = trim(@$_REQUEST['ptype' ]); $save_lname = trim(@$_REQUEST['slname' ]); $save_fname = trim(@$_REQUEST['sfname' ]); $save_number = trim(@$_REQUEST['snumber']); +$save_ptype = trim(@$_REQUEST['sptype']); $page = (int) (@$_REQUEST['page' ]); $delete_entry = (int)trim(@$_REQUEST['delete' ]); $edit_entry = (int)trim(@$_REQUEST['edit' ]); @@ -78,18 +84,19 @@ function confirm_delete() { if ($save_entry < 1) { $rs = $DB->execute( -'INSERT INTO `pb_prv` (`id`, `user_id`, `lastname`, `firstname`, `number`) VALUES -(NULL, '. $user_id .', \''. $DB->escape($save_lname) .'\', \''. $DB->escape($save_fname) .'\', \''. $DB->escape($save_number) .'\')' +'INSERT INTO `pb_prv` (`id`, `user_id`, `lastname`, `firstname`, `number`, `ptype`) VALUES +(NULL, '. $user_id .', \''. $DB->escape($save_lname) .'\', \''. $DB->escape($save_fname) .'\', \''. $DB->escape($save_number) .'\', \''. $DB->escape($save_ptype) .'\')' ); } else { $rs = $DB->execute( -'UPDATE `pb_prv` SET `lastname`=\''. $DB->escape($save_lname) .'\', `firstname`=\''. $DB->escape($save_fname) .'\', `number`=\''. $DB->escape($save_number) .'\' +'UPDATE `pb_prv` SET `lastname`=\''. $DB->escape($save_lname) .'\', `firstname`=\''. $DB->escape($save_fname) .'\', `number`=\''. $DB->escape($save_number) .'\', `ptype`=\''. $DB->escape($save_ptype) .'\' WHERE `id`='. $save_entry .' AND `user_id`='. $user_id ); $save_number = ''; $save_name = ''; + $save_ptype = ''; } } @@ -112,7 +119,7 @@ function confirm_delete() { $rs = $DB->execute( 'SELECT SQL_CALC_FOUND_ROWS '. - '`id`, `lastname`, `firstname`, `number` '. + '`id`, `lastname`, `firstname`, `number` , `ptype` '. 'FROM '. '`pb_prv` '. 'WHERE '. @@ -140,7 +147,7 @@ function confirm_delete() { $rs = $DB->execute( 'SELECT SQL_CALC_FOUND_ROWS '. - '`id`, `lastname`, `firstname`, `number` '. + '`id`, `lastname`, `firstname`, `number`, `ptype` '. 'FROM '. '`pb_prv` '. 'WHERE '. @@ -164,7 +171,7 @@ function confirm_delete() { - + @@ -214,7 +221,7 @@ function confirm_delete() { - + ', "\n"; echo '', "\n"; +echo '', "\n"; ?> @@ -248,6 +256,9 @@ function confirm_delete() { + @@ -270,6 +281,10 @@ function confirm_delete() { echo ''; echo '', "\n"; + echo '', "\n"; + echo '', "\n"; echo '', "\n"; + + echo '', "\n"; echo ' +
> > + [1] +  
'; + echo ''; + echo ''; echo ''; echo ''; @@ -291,6 +306,8 @@ function confirm_delete() { echo '', htmlEnt($r['number']), '', htmlEnt($r['ptype']), ''; $sudo_url = @@ -320,6 +337,9 @@ function confirm_delete() { + +
+
+

[1] Type of phone number: cell/work/home etc.

+execute('SHOW COLUMNS FROM pb_prv LIKE "ptype"')->fetchRow() ) ) { + $rs = $DB->execute('ALTER TABLE `pb_prv` ADD `ptype` varchar(16) NOT NULL COMMENT "cell,work,home"'); + } + if (empty( $DB->execute('SHOW COLUMNS FROM pb_prv LIKE "vcard_id"')->fetchRow() )) { + $rs = $DB->execute('ALTER TABLE `pb_prv` ADD `vcard_id` int(11) NOT NULL'); + $rs = $DB->execute('ALTER TABLE `pb_prv` ADD INDEX `uid_vcard` (`user_id`,`vcard_id`)'); + } + if (empty( $DB->execute('SHOW COLUMNS FROM pb_prv LIKE "cat_id"')->fetchRow() )) { + $rs = $DB->execute('ALTER TABLE `pb_prv` ADD `cat_id` int(11) NOT NULL'); + $rs = $DB->execute('ALTER TABLE `pb_prv` ADD INDEX `uid_cat_lastname_firstname` (`user_id`,`cat_id`,`lastname`,`firstname`)'); + $rs = $DB->execute('ALTER TABLE `pb_prv` ADD INDEX `uid_cat_firstname_lastname` (`user_id`,`cat_id`,`firstname`,`lastname`)'); + } + if (empty( $DB->execute('SHOW COLUMNS FROM pb_prv LIKE "modified"')->fetchRow() )) { + $rs = $DB->execute('ALTER TABLE `pb_prv` ADD `modified` TIMESTAMP on update CURRENT_TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP'); + } +} +*/ +?> From eefe71bbfaf255ee6c30ab32b8523576e9b02407 Mon Sep 17 00:00:00 2001 From: Markus Neubauer Date: Tue, 8 Dec 2015 15:28:24 +0100 Subject: [PATCH 04/87] Create pb_cloud.php --- opt/gemeinschaft/htdocs/gui/mod/pb_cloud.php | 384 +++++++++++++++++++ 1 file changed, 384 insertions(+) create mode 100644 opt/gemeinschaft/htdocs/gui/mod/pb_cloud.php diff --git a/opt/gemeinschaft/htdocs/gui/mod/pb_cloud.php b/opt/gemeinschaft/htdocs/gui/mod/pb_cloud.php new file mode 100644 index 000000000..da66d2581 --- /dev/null +++ b/opt/gemeinschaft/htdocs/gui/mod/pb_cloud.php @@ -0,0 +1,384 @@ + +* +* This program is free software; you can redistribute it and/or +* modify it under the terms of the GNU General Public License +* as published by the Free Software Foundation; either version 2 +* of the License, or (at your option) any later version. +* +* This program is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +* GNU General Public License for more details. +* +* You should have received a copy of the GNU General Public License +* along with this program; if not, write to the Free Software +* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, +* MA 02110-1301, USA. +\*******************************************************************/ + +defined('GS_VALID') or die('No direct access.'); +include_once( GS_DIR .'lib/utf8-normalize/gs_utf_normal.php' ); + +echo '

'; +if (@$MODULES[$SECTION]['icon']) + echo ' '; +if (count( $MODULES[$SECTION]['sub'] ) > 1 ) + echo $MODULES[$SECTION]['title'], ' - '; +echo $MODULES[$SECTION]['sub'][$MODULE]['title']; +echo '

', "\n"; + + +echo '', "\n"; +echo '' ,"\n"; + +$per_page = (int)GS_GUI_NUM_RESULTS; + +$name = trim(@$_REQUEST['name' ]); +$url = trim(@$_REQUEST['url' ]); +$login = trim(@$_REQUEST['login' ]); +$pass = trim(@$_REQUEST['pass' ]); +$frequency = trim(@$_REQUEST['frequency' ]); +$save_url = trim(@$_REQUEST['surl']); +$save_login = trim(@$_REQUEST['slogin' ]); +$save_pass = trim(@$_REQUEST['spass' ]); +$save_frequency = trim(@$_REQUEST['sfrequency' ]); +$page = (int) (@$_REQUEST['page' ]); +$delete_entry = (int)trim(@$_REQUEST['delete' ]); +$edit_entry = (int)trim(@$_REQUEST['edit' ]); +$save_entry = (int)trim(@$_REQUEST['save' ]); + +$user_id = (int)@$_SESSION['sudo_user']['info']['id']; + +if ($delete_entry > 0) { + # delete entry + + $rs = $DB->execute( +'DELETE FROM `pb_cloud` +WHERE `id`='. $delete_entry .' AND `user_id`='. $user_id + ); + +} + +if (($save_url != '' || $save_login != '') && ($save_pass != '')) { + # save entry + + // check or correct frequency + if ( empty($save_frequency) ) { + $save_frequency='1d'; + } else { + $p = substr($save_frequency, -1); + if ( ! ('h' == $p || 'd' == $p || 'm' == $p) ) { + $save_frequency='1d'; + } + } + + if ($save_entry < 1) { + + $rs = $DB->execute( +'INSERT INTO `pb_cloud` (`id`, `user_id`, `url`, `login`, `pass`, `frequency`, `next_poll`) VALUES +(NULL, '. $user_id .', \''. $DB->escape($save_url) .'\', \''. $DB->escape($save_login) .'\', des_encrypt(\''. $save_pass .'\',\'' . $save_login. '\'), \''. $DB->escape($save_frequency) .'\', NOW())' + ); + + } else { + + $rs = $DB->execute( +'UPDATE `pb_cloud` SET `url`=\''. $DB->escape($save_url) .'\', `login`=\''. $DB->escape($save_login) .'\', `pass`=des_encrypt(\''. $save_pass .'\',\'' . $save_login .'\'), `frequency`=\'' . $save_frequency . '\', `next_poll`=NOW() + WHERE `id`='. $save_entry .' AND `user_id`='. $user_id + ); + $save_url = ''; + $save_login = ''; + $save_pass = ''; + $save_frequency = ''; + + } +} + + + + + +if ($url != '') { + + # search by url + + $search_url = 'url='. urlEncode($url); + + $url_sql = '%' . str_replace( + array( '*', '?' ), + array( '%', '_' ), + $url + ) .'%'; + + $rs = $DB->execute( + 'SELECT SQL_CALC_FOUND_ROWS '. + '`id`, `url`, `login`, cast(des_decrypt(`pass`,`login`) as char(16)) as pass, `frequency` '. + 'FROM '. + '`pb_cloud` '. + 'WHERE '. + '`url` LIKE \''. $DB->escape($url_sql) .'\' '. + 'AND '. + '`user_id`='. $user_id .' '. + 'ORDER BY `url`, `login` '. + 'LIMIT '. ($page*(int)$per_page) .','. (int)$per_page + ); + $num_total = @$DB->numFoundRows(); + $num_pages = ceil($num_total / $per_page); + +} else { + + # search by login + + $search_url = 'login='. urlEncode($login); + + $login_sql = str_replace( + array( '*', '?' ), + array( '%', '_' ), + $login + ) .'%'; + + $rs = $DB->execute( + 'SELECT SQL_CALC_FOUND_ROWS '. + '`id`, `url`, `login`, cast(des_decrypt(`pass`,`login`) as char(16)) as pass, `frequency` '. + 'FROM '. + '`pb_cloud` '. + 'WHERE '. + '`login` LIKE \''. $DB->escape($login_sql) .'\' '. + 'AND '. + '`user_id`='. $DB->escape($user_id).' '. + 'ORDER BY `login`, `url` '. + 'LIMIT '. ($page*(int)$per_page) .','. (int)$per_page + ); + $num_total = @$DB->numFoundRows(); + $num_pages = ceil($num_total / $per_page); + +} + + +?> + + + + + + + + + + + + + + + + + + + +
+
+ + + + +
+
+
+ + + +
+
+ 0) { + echo + '', + '', __('zurück'), '', + '', "\n"; +} else { + echo + '', __('zurück'), '', "\n"; +} +if ($page < $num_pages-1) { + echo + '', + '', __('weiter'), '', + '', "\n"; +} else { + echo + '', __('weiter'), '', "\n"; +} + +?> +
+ $cs) { + echo '', htmlEnt($cd), '', "\n"; +} + +?> +
+ + + +', "\n"; +echo gs_form_hidden($SECTION, $MODULE), "\n"; +echo '', "\n"; +echo '', "\n"; +?> + + + + + + + + + + + + + +fetchRow()) { + echo '', "\n"; + + if ($r['id']==$edit_entry) { + + echo '', "\n"; + + echo '', "\n"; + + echo '', "\n"; + + echo '', "\n"; + + echo ''; + + } else { + + echo '', "\n"; + + echo '', "\n"; + + echo '', "\n"; + + echo '', "\n"; + + echo ''; + + } + + echo '', "\n"; + } +} + +?> + + + + + + + + + + + + + +
> + [1] + > + + + + + [2] +  
'; + echo ''; + echo ''; + echo ''; + echo ''; + echo ''; + echo ''; + echo ''; + echo ''; + echo ''; + echo ''; + echo ''; + echo ''; + echo '', __('abbrechen'), ''; + + echo '', htmlEnt($r['url']); + echo '', htmlEnt($r['login']), '', str_repeat('•', strLen($r['pass'])), '', htmlEnt($r['frequency']), ''; + $sudo_url = + (@$_SESSION['sudo_user']['name'] == @$_SESSION['real_user']['name']) + ? '' : ('&sudo='. @$_SESSION['sudo_user']['name']); + echo '', __('bearbeiten'), '   '; + echo '', __('entfernen'), ''; + echo '
+ + + + + + + + + + abbrechen';*/ ?> +
+ + +
+

Hint: vCards automatically will be fetched on new entry or record changes, besides schedule.

+

[1] URL: Enter the full vCard URL including scheme from your provider. Naiv examples:

+
+
+
ownCloud
https://example.com/remote.php/carddav/addressbooks/{resource|principal|username}/{collection}/
+
memotoo
https://sync.memotoo.com/cardDAV/
+
SabreDAV
https://example.com/addressbooks/{resource|principal|username}/{collection}/
+
radicale
https://example.com/radicale/{resource|principal|username}/{collection}/
+
SOGo
https://example.com/SOGo/dav/{resource|principal|username}/Contacts/{collection}/
+
DAViCal
https://example.com/{resource|principal|username}/{collection}/
+
Apple Addressbook Server
https://example.com/addressbooks/users/{resource|principal|username}/{collection}/
+
+
+

[2] Schedule: Refresh in h=hour, d=day, m=month etc., two digits followed by one char allowed
      Example: Where '4h' is every 4 hours (~ also during night). Defaults to '1d'

From 1b395ecfe2b5fd55e3e63dc6ab95bd133f7174e1 Mon Sep 17 00:00:00 2001 From: Markus Neubauer Date: Tue, 8 Dec 2015 15:29:07 +0100 Subject: [PATCH 05/87] Create pb_category.php --- .../htdocs/gui/mod/pb_category.php | 268 ++++++++++++++++++ 1 file changed, 268 insertions(+) create mode 100644 opt/gemeinschaft/htdocs/gui/mod/pb_category.php diff --git a/opt/gemeinschaft/htdocs/gui/mod/pb_category.php b/opt/gemeinschaft/htdocs/gui/mod/pb_category.php new file mode 100644 index 000000000..43d0033aa --- /dev/null +++ b/opt/gemeinschaft/htdocs/gui/mod/pb_category.php @@ -0,0 +1,268 @@ + +* +* This program is free software; you can redistribute it and/or +* modify it under the terms of the GNU General Public License +* as published by the Free Software Foundation; either version 2 +* of the License, or (at your option) any later version. +* +* This program is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +* GNU General Public License for more details. +* +* You should have received a copy of the GNU General Public License +* along with this program; if not, write to the Free Software +* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, +* MA 02110-1301, USA. +\*******************************************************************/ + +defined('GS_VALID') or die('No direct access.'); +include_once( GS_DIR .'lib/utf8-normalize/gs_utf_normal.php' ); + +echo '

'; +if (@$MODULES[$SECTION]['icon']) + echo ' '; +if (count( $MODULES[$SECTION]['sub'] ) > 1 ) + echo $MODULES[$SECTION]['title'], ' - '; +echo $MODULES[$SECTION]['sub'][$MODULE]['title']; +echo '

', "\n"; + + +echo '', "\n"; +echo '' ,"\n"; + +$per_page = (int)GS_GUI_NUM_RESULTS; + +$name = trim(@$_REQUEST['name' ]); +$category = trim(@$_REQUEST['category' ]); +$save_category = trim(@$_REQUEST['scategory']); +$page = (int) (@$_REQUEST['page' ]); +$delete_entry = (int)trim(@$_REQUEST['delete' ]); +$edit_entry = (int)trim(@$_REQUEST['edit' ]); +$save_entry = (int)trim(@$_REQUEST['save' ]); + +$user_id = (int)@$_SESSION['sudo_user']['info']['id']; + +if ($delete_entry > 0) { + # delete entry + + $rs = $DB->execute( +'DELETE FROM `pb_category` +WHERE `id`='. $delete_entry .' AND `user_id`='. $user_id + ); + +} + +if ( $save_category != '' ) { + # save entry + + if ($save_entry < 1) { + + $rs = $DB->execute( +'INSERT INTO `pb_category` (`id`, `user_id`, `category`) VALUES +(NULL, '. $user_id .', \''. $DB->escape($save_category) .'\')' + ); + + } else { + + $rs = $DB->execute( +'UPDATE `pb_category` SET `category`=\''. $DB->escape($save_category) .'\' + WHERE `id`='. $save_entry .' AND `user_id`='. $user_id + ); + $save_category = ''; + + } +} + + +# search by category + +$search_url = 'category='. urlEncode($category); + +$category_sql = '%' . str_replace( + array( '*', '?' ), + array( '%', '_' ), + $category +) .'%'; + +$rs = $DB->execute( + 'SELECT SQL_CALC_FOUND_ROWS '. + '`id`, `category` '. + 'FROM '. + '`pb_category` '. + 'WHERE '. + '`category` LIKE \''. $DB->escape($category_sql) .'\' '. + 'AND '. + '`user_id`='. $user_id .' '. + 'ORDER BY `category` ' . + 'LIMIT '. ($page*(int)$per_page) .','. (int)$per_page + ); +$num_total = @$DB->numFoundRows(); +$num_pages = ceil($num_total / $per_page); + + +?> + + + + + + + + + + + + + + + + + +
+
+ + + + +
+
+ 0) { + echo + '', + '', __('zurück'), '', + '', "\n"; +} else { + echo + '', __('zurück'), '', "\n"; +} +if ($page < $num_pages-1) { + echo + '', + '', __('weiter'), '', + '', "\n"; +} else { + echo + '', __('weiter'), '', "\n"; +} + +?> +
+ $cs) { + echo '', htmlEnt($cd), '', "\n"; +} + +?> +
+ + + +', "\n"; +echo gs_form_hidden($SECTION, $MODULE), "\n"; +echo '', "\n"; +?> + + + + + + + + + +fetchRow()) { + echo '', "\n"; + + if ($r['id']==$edit_entry) { + + echo '', "\n"; + + echo ''; + + } else { + + echo '', "\n"; + + echo ''; + + } + + echo '', "\n"; + } +} + +?> + + + + + + + + + + +
> + +
'; + echo ''; + echo ''; + echo ''; + echo ''; + echo ''; + echo ''; + echo '', __('abbrechen'), ''; + + echo '', htmlEnt($r['category']); + echo ''; + $sudo_url = + (@$_SESSION['sudo_user']['name'] == @$_SESSION['real_user']['name']) + ? '' : ('&sudo='. @$_SESSION['sudo_user']['name']); + echo '', __('bearbeiten'), '   '; + echo '', __('entfernen'), ''; + echo '
+ + + + abbrechen';*/ ?> +
+ + From fc489e21d176dc0d9a759beeeed65c4602542fe4 Mon Sep 17 00:00:00 2001 From: Markus Neubauer Date: Tue, 8 Dec 2015 15:29:47 +0100 Subject: [PATCH 06/87] Update modules.php --- opt/gemeinschaft/htdocs/gui/inc/modules.php | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/opt/gemeinschaft/htdocs/gui/inc/modules.php b/opt/gemeinschaft/htdocs/gui/inc/modules.php index 3c1003123..f2ba6e429 100644 --- a/opt/gemeinschaft/htdocs/gui/inc/modules.php +++ b/opt/gemeinschaft/htdocs/gui/inc/modules.php @@ -71,7 +71,13 @@ 's' => array('title' => __('Intern' ), 'id' => 3001) ), 25=>array( 'k' => 'private', - 's' => array('title' => __('Persönlich' ), 'id' => 3002) ) + 's' => array('title' => __('Persönlich' ), 'id' => 3002) ), + 35=>array( + 'k' => 'category' , + 's' => array('title' => __('Kategorien' ), 'id' => 3006) ), + 45=>array( + 'k' => 'cloud' , + 's' => array('title' => __('Cloud' ), 'id' => 3005) ) ); if (gs_get_conf('GS_PB_IMPORTED_ENABLED')) { $pos = (int)gs_get_conf('GS_PB_IMPORTED_ORDER', 9) * 10; From f5974711034bb637053cdfa630745d5cf2fdbb91 Mon Sep 17 00:00:00 2001 From: Markus Neubauer Date: Tue, 8 Dec 2015 15:31:28 +0100 Subject: [PATCH 07/87] Update upgrade-pb-3.2-3.3.sql --- misc/scripts/upgrade-pb-3.2-3.3.sql | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/misc/scripts/upgrade-pb-3.2-3.3.sql b/misc/scripts/upgrade-pb-3.2-3.3.sql index bd2d7c8a1..2cd588c89 100644 --- a/misc/scripts/upgrade-pb-3.2-3.3.sql +++ b/misc/scripts/upgrade-pb-3.2-3.3.sql @@ -53,3 +53,7 @@ CREATE TABLE IF NOT EXISTS `pb_category` ( `modified` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, PRIMARY KEY (`id`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci; + +// set new modules active +INSERT INTO `group_members` (`group`, `member`) VALUES (6, 3005) ON DUPLICATE KEY UPDATE `member` = 3005; +INSERT INTO `group_members` (`group`, `member`) VALUES (6, 3006) ON DUPLICATE KEY UPDATE `member` = 3006; From 3bd8c0a295c317ca02e6c0936671de07f99ee41a Mon Sep 17 00:00:00 2001 From: Markus Neubauer Date: Thu, 10 Dec 2015 17:45:15 +0100 Subject: [PATCH 08/87] Update upgrade-pb-3.2-3.3.sql --- misc/scripts/upgrade-pb-3.2-3.3.sql | 66 ++++++++++++++++++++--------- 1 file changed, 46 insertions(+), 20 deletions(-) diff --git a/misc/scripts/upgrade-pb-3.2-3.3.sql b/misc/scripts/upgrade-pb-3.2-3.3.sql index 2cd588c89..d6046e8f8 100644 --- a/misc/scripts/upgrade-pb-3.2-3.3.sql +++ b/misc/scripts/upgrade-pb-3.2-3.3.sql @@ -6,52 +6,78 @@ CREATE TABLE IF NOT EXISTS `pb_prv` ( `lastname` varchar(40) COLLATE utf8_unicode_ci NOT NULL DEFAULT '', `number` varchar(25) CHARACTER SET ascii NOT NULL DEFAULT '', `ptype` varchar(16) COLLATE utf8_unicode_ci NOT NULL COMMENT 'cell,work,home', - `vcard_id` int(11) NOT NULL, - `cat_id` int(11) NOT NULL, + `card_id` int(10) unsigned NOT NULL, `modified` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, PRIMARY KEY (`id`), KEY `uid_lastname_firstname` (`user_id`,`lastname`(15),`firstname`(10)), KEY `uid_firstname_lastname` (`user_id`,`firstname`(10),`lastname`(10)), KEY `uid_number` (`user_id`,`number`(10)), - KEY `uid_vcard` (`user_id`,`vcard_id`), - KEY `uid_cat_lastname_firstname` (`user_id`,`cat_id`,`lastname`,`firstname`), - KEY `uid_cat_firstname_lastname` (`user_id`,`cat_id`,`firstname`,`lastname`) + KEY `uid_cardid` (`user_id`,`card_id`), + KEY `cloud_card_id` (`card_id`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci; // alter existing 3.2 private phonebook ALTER TABLE `pb_prv` ADD `ptype` VARCHAR(16) NOT NULL COMMENT 'cell,work,home'; -ALTER TABLE `pb_prv` ADD `vcard_id` int(11) NOT NULL; -ALTER TABLE `pb_prv` ADD `cat_id` int(11) NOT NULL; +ALTER TABLE `pb_prv` ADD `vcard_id` int(10) NOT NULL; ALTER TABLE `pb_prv` ADD `modified` TIMESTAMP on update CURRENT_TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP; -ALTER TABLE `pb_prv` ADD INDEX `uid_vcard` (`user_id`,`vcard_id`); -ALTER TABLE `pb_prv` ADD INDEX `uid_cat_lastname_firstname` (`user_id`,`cat_id`,`lastname`,`firstname`); -ALTER TABLE `pb_prv` ADD INDEX `uid_cat_firstname_lastname` (`user_id`,`cat_id`,`firstname`,`lastname`); +ALTER TABLE `pb_prv` ADD INDEX `uid_cardid` (`user_id`,`card_id`); +ALTER TABLE `pb_prv` ADD INDEX `cloud_card_id` (`card_id`); // import voip phone book from cloud for preparing the xml to phone functionality CREATE TABLE IF NOT EXISTS `pb_cloud` ( - `id` int(11) NOT NULL AUTO_INCREMENT, - `user_id` int(11) NOT NULL, + `id` int(10) unsigned NOT NULL AUTO_INCREMENT, + `user_id` int(10) unsigned NOT NULL, `url` varchar(256) COLLATE utf8_unicode_ci NOT NULL, - `login` varchar(64) COLLATE utf8_unicode_ci NOT NULL, + `login` varchar(32) COLLATE utf8_unicode_ci NOT NULL, `pass` varbinary(64) NOT NULL, `frequency` varchar(3) COLLATE utf8_unicode_ci NOT NULL DEFAULT '1d', + `ctag` varchar(32) COLLATE utf8_unicode_ci NOT NULL, + `last_remote_modified` datetime NOT NULL, `next_poll` datetime NOT NULL, `modified` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, PRIMARY KEY (`id`), - KEY `user_id` (`user_id`), + UNIQUE KEY `uid_url_login` (`user_id`,`url`(255),`login`), KEY `next_poll` (`next_poll`), - KEY `url` (`user_id`,`url`(255)), - KEY `login` (`user_id`,`login`) + KEY `uid_login` (`user_id`,`login`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci; + +// holds the vcards +CREATE TABLE IF NOT EXISTS `pb_cloud_card` ( + `id` int(10) unsigned NOT NULL AUTO_INCREMENT, + `cloud_id` int(10) unsigned NOT NULL, + `vcard_id` varchar(36) COLLATE utf8_unicode_ci NOT NULL, + `etag` varchar(32) COLLATE utf8_unicode_ci NOT NULL, + `vcard` text COLLATE utf8_unicode_ci NOT NULL, + `last_modified` datetime NOT NULL, + PRIMARY KEY (`id`), + KEY `cloud_id_vcard_id` (`cloud_id`,`vcard_id`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci; -// add categories like family etc. to phone book +// add categories (i.e like family, company etc.) CREATE TABLE IF NOT EXISTS `pb_category` ( - `id` int(11) NOT NULL AUTO_INCREMENT, - `user_id` int(11) NOT NULL, + `id` int(10) unsigned NOT NULL AUTO_INCREMENT, + `user_id` int(10) unsigned NOT NULL, `category` varchar(24) COLLATE utf8_unicode_ci NOT NULL, `modified` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, - PRIMARY KEY (`id`) + PRIMARY KEY (`id`), + UNIQUE KEY `uid_catid` (`user_id`,`category`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci; + +// connect a phone book entry to a category +CREATE TABLE IF NOT EXISTS `pb_prv_category` ( + `id` int(10) unsigned NOT NULL AUTO_INCREMENT, + `user_id` int(10) unsigned NOT NULL, + `cat_id` int(10) unsigned NOT NULL, + `card_id` int(10) unsigned NOT NULL, + `prv_id` int(10) unsigned NOT NULL, + PRIMARY KEY (`id`), + KEY `uid_catid_cardid` (`user_id`,`cat_id`,`card_id`), + KEY `uid_prvid` (`user_id`,`prv_id`), + KEY `uid_cardid` (`user_id`,`card_id`), + KEY `card_id` (`card_id`), + KEY `prv_id` (`prv_id`), + KEY `cat_id` (`cat_id`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci; // set new modules active From 0600261e4e1427ee714a621e42dfb432f64dffd5 Mon Sep 17 00:00:00 2001 From: Markus Neubauer Date: Thu, 10 Dec 2015 17:50:01 +0100 Subject: [PATCH 09/87] Update modules.php --- opt/gemeinschaft/htdocs/gui/inc/modules.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/opt/gemeinschaft/htdocs/gui/inc/modules.php b/opt/gemeinschaft/htdocs/gui/inc/modules.php index f2ba6e429..06fbaa2e1 100644 --- a/opt/gemeinschaft/htdocs/gui/inc/modules.php +++ b/opt/gemeinschaft/htdocs/gui/inc/modules.php @@ -77,7 +77,7 @@ 's' => array('title' => __('Kategorien' ), 'id' => 3006) ), 45=>array( 'k' => 'cloud' , - 's' => array('title' => __('Cloud' ), 'id' => 3005) ) + 's' => array('title' => __('Cloud Import' ), 'id' => 3005) ) ); if (gs_get_conf('GS_PB_IMPORTED_ENABLED')) { $pos = (int)gs_get_conf('GS_PB_IMPORTED_ORDER', 9) * 10; From ea7cbe2fbe26a9aecf94cae67f8a9659b04ac8f6 Mon Sep 17 00:00:00 2001 From: Markus Neubauer Date: Thu, 10 Dec 2015 17:51:22 +0100 Subject: [PATCH 10/87] Update pb_private.php --- opt/gemeinschaft/htdocs/gui/mod/pb_private.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/opt/gemeinschaft/htdocs/gui/mod/pb_private.php b/opt/gemeinschaft/htdocs/gui/mod/pb_private.php index da4c7d730..ae8d4dd59 100644 --- a/opt/gemeinschaft/htdocs/gui/mod/pb_private.php +++ b/opt/gemeinschaft/htdocs/gui/mod/pb_private.php @@ -94,11 +94,11 @@ function confirm_delete() { 'UPDATE `pb_prv` SET `lastname`=\''. $DB->escape($save_lname) .'\', `firstname`=\''. $DB->escape($save_fname) .'\', `number`=\''. $DB->escape($save_number) .'\', `ptype`=\''. $DB->escape($save_ptype) .'\' WHERE `id`='. $save_entry .' AND `user_id`='. $user_id ); + + } $save_number = ''; $save_name = ''; $save_ptype = ''; - - } } From 598eed265f84c2b49d4efe943c73897a83bd4df6 Mon Sep 17 00:00:00 2001 From: Markus Neubauer Date: Thu, 10 Dec 2015 17:51:59 +0100 Subject: [PATCH 11/87] Update pb_cloud.php --- opt/gemeinschaft/htdocs/gui/mod/pb_cloud.php | 21 +++++++++++--------- 1 file changed, 12 insertions(+), 9 deletions(-) diff --git a/opt/gemeinschaft/htdocs/gui/mod/pb_cloud.php b/opt/gemeinschaft/htdocs/gui/mod/pb_cloud.php index da66d2581..b5e735da5 100644 --- a/opt/gemeinschaft/htdocs/gui/mod/pb_cloud.php +++ b/opt/gemeinschaft/htdocs/gui/mod/pb_cloud.php @@ -73,17 +73,19 @@ function confirm_delete() { } -if (($save_url != '' || $save_login != '') && ($save_pass != '')) { +if ($save_url != '' && $save_login != '' && $save_pass != '') { # save entry // check or correct frequency - if ( empty($save_frequency) ) { - $save_frequency='1d'; + if ( strlen($save_frequency) < 2 ) { + $save_frequency = '1d'; } else { + $save_frequency = str_replace(' ', '', $save_frequency); $p = substr($save_frequency, -1); - if ( ! ('h' == $p || 'd' == $p || 'm' == $p) ) { - $save_frequency='1d'; - } + if ( ! ('h' == $p || 'd' == $p || 'm' == $p) ) + $save_frequency = substr($save_frequency, 0, -1) . 'd'; + if ( ! is_numeric(substr($save_frequency, 0, -1)) || substr($save_frequency, 0, -1) == '0' ) + $save_frequency = '1' . substr($save_frequency, -1); } if ($save_entry < 1) { @@ -99,12 +101,12 @@ function confirm_delete() { 'UPDATE `pb_cloud` SET `url`=\''. $DB->escape($save_url) .'\', `login`=\''. $DB->escape($save_login) .'\', `pass`=des_encrypt(\''. $save_pass .'\',\'' . $save_login .'\'), `frequency`=\'' . $save_frequency . '\', `next_poll`=NOW() WHERE `id`='. $save_entry .' AND `user_id`='. $user_id ); + + } $save_url = ''; $save_login = ''; $save_pass = ''; $save_frequency = ''; - - } } @@ -381,4 +383,5 @@ function confirm_delete() {
Apple Addressbook Server
https://example.com/addressbooks/users/{resource|principal|username}/{collection}/
-

[2] Schedule: Refresh in h=hour, d=day, m=month etc., two digits followed by one char allowed
      Example: Where '4h' is every 4 hours (~ also during night). Defaults to '1d'

+

[2] Schedule: h=hour, d=day, m=month (Max. 2 digits + 1 char, no minutes allowed).
+       Example: '4h' = refresh every 4 hours (~ also during night). Defaults to '1d'.

From 92082c15dca860ef3beaca74efdda46c52149067 Mon Sep 17 00:00:00 2001 From: Markus Neubauer Date: Thu, 10 Dec 2015 17:52:36 +0100 Subject: [PATCH 12/87] Update pb_category.php --- opt/gemeinschaft/htdocs/gui/mod/pb_category.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/opt/gemeinschaft/htdocs/gui/mod/pb_category.php b/opt/gemeinschaft/htdocs/gui/mod/pb_category.php index 43d0033aa..b8e1cc8ba 100644 --- a/opt/gemeinschaft/htdocs/gui/mod/pb_category.php +++ b/opt/gemeinschaft/htdocs/gui/mod/pb_category.php @@ -83,9 +83,9 @@ function confirm_delete() { 'UPDATE `pb_category` SET `category`=\''. $DB->escape($save_category) .'\' WHERE `id`='. $save_entry .' AND `user_id`='. $user_id ); - $save_category = ''; } + $save_category = ''; } From 015c8236b7ed8e01c4d40d1f188b480efd150360 Mon Sep 17 00:00:00 2001 From: Markus Neubauer Date: Thu, 10 Dec 2015 17:54:12 +0100 Subject: [PATCH 13/87] Create CardDAV.php --- opt/gemeinschaft/lib/carddav/CardDAV.php | 679 +++++++++++++++++++++++ 1 file changed, 679 insertions(+) create mode 100644 opt/gemeinschaft/lib/carddav/CardDAV.php diff --git a/opt/gemeinschaft/lib/carddav/CardDAV.php b/opt/gemeinschaft/lib/carddav/CardDAV.php new file mode 100644 index 000000000..aae5fd23b --- /dev/null +++ b/opt/gemeinschaft/lib/carddav/CardDAV.php @@ -0,0 +1,679 @@ +set_auth('username', 'password'); + * echo $carddav->get(); + * + * + * Simple vCard query + * ------------------ + * $carddav = new carddav_backend('https://davical.example.com/user/contacts/'); + * $carddav->set_auth('username', 'password'); + * echo $carddav->get_vcard('0126FFB4-2EB74D0A-302EA17F'); + * + * + * XML vCard query + * ------------------ + * $carddav = new carddav_backend('https://davical.example.com/user/contacts/'); + * $carddav->set_auth('username', 'password'); + * echo $carddav->get_xml_vcard('0126FFB4-2EB74D0A-302EA17F'); + * + * + * Check CardDAV server connection + * ------------------------------- + * $carddav = new carddav_backend('https://davical.example.com/user/contacts/'); + * $carddav->set_auth('username', 'password'); + * var_dump($carddav->check_connection()); + * + * + * CardDAV delete query + * -------------------- + * $carddav = new carddav_backend('https://davical.example.com/user/contacts/'); + * $carddav->set_auth('username', 'password'); + * $carddav->delete('0126FFB4-2EB74D0A-302EA17F'); + * + * + * CardDAV add query + * -------------------- + * $vcard = 'BEGIN:VCARD + * VERSION:3.0 + * UID:1f5ea45f-b28a-4b96-25as-ed4f10edf57b + * FN:Christian Putzke + * N:Christian;Putzke;;; + * EMAIL;TYPE=OTHER:christian.putzke@graviox.de + * END:VCARD'; + * + * $carddav = new carddav_backend('https://davical.example.com/user/contacts/'); + * $carddav->set_auth('username', 'password'); + * $vcard_id = $carddav->add($vcard); + * + * + * CardDAV update query + * -------------------- + * $vcard = 'BEGIN:VCARD + * VERSION:3.0 + * UID:1f5ea45f-b28a-4b96-25as-ed4f10edf57b + * FN:Christian Putzke + * N:Christian;Putzke;;; + * EMAIL;TYPE=OTHER:christian.putzke@graviox.de + * END:VCARD'; + * + * $carddav = new carddav_backend('https://davical.example.com/user/contacts/'); + * $carddav->set_auth('username', 'password'); + * $carddav->update($vcard, '0126FFB4-2EB74D0A-302EA17F'); + * + * + * CardDAV debug + * ------------- + * $carddav = new carddav_backend('https://davical.example.com/user/contacts/'); + * $carddav->enable_debug(); + * $carddav->set_auth('username', 'password'); + * $carddav->get(); + * var_dump($carddav->get_debug()); + * + * + * CardDAV server list + * ------------------- + * DAViCal: https://example.com/{resource|principal|username}/{collection}/ + * 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}/ + * SOGo: https://example.com/SOGo/dav/{resource|principal|username}/Contacts/{collection}/ + * + * + * @author Christian Putzke + * @copyright Christian Putzke + * @link http://www.graviox.de/ + * @link https://twitter.com/cputzke/ + * @since 20.07.2011 + * @version 0.6 + * @license http://www.gnu.org/licenses/agpl.html GNU AGPL v3 or later + * + */ + +class carddav_backend +{ + /** + * CardDAV PHP Version + * + * @constant string + */ + const VERSION = '0.6'; + + /** + * User agent displayed in http requests + * + * @constant string + */ + const USERAGENT = 'CardDAV PHP/'; + + /** + * CardDAV server url + * + * @var string + */ + private $url = null; + + /** + * CardDAV server url_parts + * + * @var array + */ + private $url_parts = null; + + /** + * Authentication string + * + * @var string + */ + private $auth = null; + + /** + * Authentication: username + * + * @var string + */ + private $username = null; + + /** + * Authentication: password + * + * @var string + */ + private $password = null; + + /** + * Characters used for vCard id generation + * + * @var array + */ + private $vcard_id_chars = array(0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 'A', 'B', 'C', 'D', 'E', 'F'); + + /** + * CardDAV server connection (curl handle) + * + * @var resource + */ + private $curl; + + /** + * Debug on or off + * + * @var boolean + */ + private $debug = false; + + /** + * All available debug information + * + * @var array + */ + private $debug_information = array(); + + /** + * Exception codes + */ + const EXCEPTION_WRONG_HTTP_STATUS_CODE_GET = 1000; + const EXCEPTION_WRONG_HTTP_STATUS_CODE_GET_VCARD = 1001; + const EXCEPTION_WRONG_HTTP_STATUS_CODE_GET_XML_VCARD = 1002; + const EXCEPTION_WRONG_HTTP_STATUS_CODE_DELETE = 1003; + const EXCEPTION_WRONG_HTTP_STATUS_CODE_ADD = 1004; + const EXCEPTION_WRONG_HTTP_STATUS_CODE_UPDATE = 1005; + const EXCEPTION_MALFORMED_XML_RESPONSE = 1006; + const EXCEPTION_COULD_NOT_GENERATE_NEW_VCARD_ID = 1007; + + + /** + * Constructor + * Sets the CardDAV server url + * + * @param string $url CardDAV server url + */ + public function __construct($url = null) + { + if ($url !== null) + { + $this->set_url($url); + } + } + + /** + * Sets debug information + * + * @param array $debug_information Debug information + * @return void + */ + public function set_debug(array $debug_information) + { + $this->debug_information[] = $debug_information; + } + + /** + * Sets the CardDAV server url + * + * @param string $url CardDAV server url + * @return void + */ + public function set_url($url) + { + $this->url = $url; + + if (substr($this->url, -1, 1) !== '/') + { + $this->url = $this->url . '/'; + } + + $this->url_parts = parse_url($this->url); + } + + /** + * Sets authentication information + * + * @param string $username CardDAV server username + * @param string $password CardDAV server password + * @return void + */ + public function set_auth($username, $password) + { + $this->username = $username; + $this->password = $password; + $this->auth = $username . ':' . $password; + } + + /** + * Gets all available debug information + * + * @return array $this->debug_information All available debug information + */ + public function get_debug() + { + return $this->debug_information; + } + + /** + * Gets all vCards including additional information from the CardDAV server + * + * @param boolean $include_vcards Include vCards within the response (simplified only) + * @param boolean $raw Get response raw or simplified + * @return string Raw or simplified XML response + */ + public function get($include_vcards = true, $raw = false) + { + $result = $this->query($this->url, 'PROPFIND'); + + switch ($result['http_code']) + { + case 200: + case 207: + if ($raw === true) + { + return $result['response']; + } + else + { + return $this->simplify($result['response'], $include_vcards); + } + break; + + default: + throw new Exception('Woops, something\'s gone wrong! The CardDAV server returned the http status code ' . $result['http_code'] . '.', self::EXCEPTION_WRONG_HTTP_STATUS_CODE_GET); + break; + } + } + + /** + * Gets a clean vCard from the CardDAV server + * + * @param string $vcard_id vCard id on the CardDAV server + * @return string vCard (text/vcard) + */ + public function get_vcard($vcard_id) + { + $vcard_id = str_replace('.vcf', null, $vcard_id); + $result = $this->query($this->url . $vcard_id . '.vcf', 'GET'); + + switch ($result['http_code']) + { + case 200: + case 207: + return $result['response']; + break; + + default: + throw new Exception('Woops, something\'s gone wrong! The CardDAV server returned the http status code ' . $result['http_code'] . '.', self::EXCEPTION_WRONG_HTTP_STATUS_CODE_GET_VCARD); + break; + } + } + + /** + * Gets a vCard + XML from the CardDAV Server + * + * @param string $vcard_id vCard id on the CardDAV Server + * @return string Raw or simplified vCard (text/xml) + */ + public function get_xml_vcard($vcard_id) + { + $vcard_id = str_replace('.vcf', null, $vcard_id); + + $xml = new XMLWriter(); + $xml->openMemory(); + $xml->setIndent(4); + $xml->startDocument('1.0', 'utf-8'); + $xml->startElement('C:addressbook-multiget'); + $xml->writeAttribute('xmlns:D', 'DAV:'); + $xml->writeAttribute('xmlns:C', 'urn:ietf:params:xml:ns:carddav'); + $xml->startElement('D:prop'); + $xml->writeElement('D:getetag'); + $xml->writeElement('D:getlastmodified'); + $xml->endElement(); + $xml->writeElement('D:href', $this->url_parts['path'] . $vcard_id . '.vcf'); + $xml->endElement(); + $xml->endDocument(); + + $result = $this->query($this->url, 'REPORT', $xml->outputMemory(), 'text/xml'); + + switch ($result['http_code']) + { + case 200: + case 207: + return $this->simplify($result['response'], true); + break; + + default: + throw new Exception('Woops, something\'s gone wrong! The CardDAV server returned the http status code ' . $result['http_code'] . '.', self::EXCEPTION_WRONG_HTTP_STATUS_CODE_GET_XML_VCARD); + break; + } + } + + /** + * Enables the debug mode + * + * @return void + */ + public function enable_debug() + { + $this->debug = true; + } + + /** + * Checks if the CardDAV server is reachable + * + * @return boolean + */ + public function check_connection() + { + $result = $this->query($this->url, 'OPTIONS'); + + if ($result['http_code'] === 200) + { + return true; + } + else + { + return false; + } + } + + /** + * Cleans the vCard + * + * @param string $vcard vCard + * @return string $vcard vCard + */ + private function clean_vcard($vcard) + { + $vcard = str_replace("\t", null, $vcard); + + return $vcard; + } + + /** + * Deletes an entry from the CardDAV server + * + * @param string $vcard_id vCard id on the CardDAV server + * @return boolean + */ + public function delete($vcard_id) + { + $result = $this->query($this->url . $vcard_id . '.vcf', 'DELETE'); + + switch ($result['http_code']) + { + case 204: + return true; + break; + + default: + throw new Exception('Woops, something\'s gone wrong! The CardDAV server returned the http status code ' . $result['http_code'] . '.', self::EXCEPTION_WRONG_HTTP_STATUS_CODE_DELETE); + break; + } + } + + /** + * Adds an entry to the CardDAV server + * + * @param string $vcard vCard + * @param string $vcard_id vCard id on the CardDAV server + * @return string The new vCard id + */ + public function add($vcard, $vcard_id = null) + { + if ($vcard_id === null) + { + $vcard_id = $this->generate_vcard_id(); + } + $vcard = $this->clean_vcard($vcard); + $result = $this->query($this->url . $vcard_id . '.vcf', 'PUT', $vcard, 'text/vcard'); + + switch($result['http_code']) + { + case 201: + return $vcard_id; + break; + + default: + throw new Exception('Woops, something\'s gone wrong! The CardDAV server returned the http status code ' . $result['http_code'] . '.', self::EXCEPTION_WRONG_HTTP_STATUS_CODE_ADD); + break; + } + } + + /** + * Updates an entry to the CardDAV server + * + * @param string $vcard vCard + * @param string $vcard_id vCard id on the CardDAV server + * @return boolean + */ + public function update($vcard, $vcard_id) + { + try + { + return $this->add($vcard, $vcard_id); + } + catch (Exception $e) + { + throw new Exception($e->getMessage(), self::EXCEPTION_WRONG_HTTP_STATUS_CODE_UPDATE); + } + } + + /** + * Simplify CardDAV XML response + * + * @param string $response CardDAV XML response + * @param boolean $include_vcards Include vCards or not + * @return string Simplified CardDAV XML response + */ + private function simplify($response, $include_vcards = true) + { + $response = $this->clean_response($response); + + try + { + $xml = new SimpleXMLElement($response); + } + catch(Exception $e) + { + throw new Exception('The XML response seems to be malformed and can\'t be simplified!', self::EXCEPTION_MALFORMED_XML_RESPONSE, $e); + } + + $simplified_xml = new XMLWriter(); + $simplified_xml->openMemory(); + $simplified_xml->setIndent(4); + + $simplified_xml->startDocument('1.0', 'utf-8'); + $simplified_xml->startElement('response'); + + if (!empty($xml->response)) + { + foreach ($xml->response as $response) + { + if (preg_match('/vcard/', $response->propstat->prop->getcontenttype) || preg_match('/vcf/', $response->href)) + { + $id = basename($response->href); + $id = str_replace('.vcf', null, $id); + + if (!empty($id)) + { + $simplified_xml->startElement('element'); + $simplified_xml->writeElement('id', $id); + $simplified_xml->writeElement('etag', str_replace('"', null, $response->propstat->prop->getetag)); + $simplified_xml->writeElement('last_modified', $response->propstat->prop->getlastmodified); + + if ($include_vcards === true) + { + $simplified_xml->writeElement('vcard', $this->get_vcard($id)); + } + $simplified_xml->endElement(); + } + } + else if (preg_match('/unix-directory/', $response->propstat->prop->getcontenttype)) + { + if (isset($response->propstat->prop->href)) + { + $href = $response->propstat->prop->href; + } + else if (isset($response->href)) + { + $href = $response->href; + } + else + { + $href = null; + } + + $url = str_replace($this->url_parts['path'], null, $this->url) . $href; + $simplified_xml->startElement('addressbook_element'); + $simplified_xml->writeElement('display_name', $response->propstat->prop->displayname); + $simplified_xml->writeElement('url', $url); + $simplified_xml->writeElement('last_modified', $response->propstat->prop->getlastmodified); + $simplified_xml->endElement(); + } + } + } + + $simplified_xml->endElement(); + $simplified_xml->endDocument(); + + return $simplified_xml->outputMemory(); + } + + /** + * Cleans CardDAV XML response + * + * @param string $response CardDAV XML response + * @return string $response Cleaned CardDAV XML response + */ + private function clean_response($response) + { + $response = utf8_encode($response); + $response = str_replace('D:', null, $response); + $response = str_replace('d:', null, $response); + $response = str_replace('C:', null, $response); + $response = str_replace('c:', null, $response); + + return $response; + } + + /** + * Curl initialization + * + * @return void + */ + public function curl_init() + { + if (empty($this->curl)) + { + $this->curl = curl_init(); + curl_setopt($this->curl, CURLOPT_HEADER, true); + curl_setopt($this->curl, CURLOPT_SSL_VERIFYHOST, false); + curl_setopt($this->curl, CURLOPT_SSL_VERIFYPEER, false); + curl_setopt($this->curl, CURLOPT_RETURNTRANSFER, true); + curl_setopt($this->curl, CURLOPT_USERAGENT, self::USERAGENT.self::VERSION); + + if ($this->auth !== null) + { + curl_setopt($this->curl, CURLOPT_HTTPAUTH, CURLAUTH_ANY); + curl_setopt($this->curl, CURLOPT_USERPWD, $this->auth); + } + } + } + + /** + * Query the CardDAV server via curl and returns the response + * + * @param string $url CardDAV server URL + * @param string $method HTTP method like (OPTIONS, GET, HEAD, POST, PUT, DELETE, TRACE, COPY, MOVE) + * @param string $content Content for CardDAV queries + * @param string $content_type Set content type + * @return array Raw CardDAV Response and http status code + */ + private function query($url, $method, $content = null, $content_type = null) + { + $this->curl_init(); + + curl_setopt($this->curl, CURLOPT_URL, $url); + curl_setopt($this->curl, CURLOPT_CUSTOMREQUEST, $method); + + if ($content !== null) + { + curl_setopt($this->curl, CURLOPT_POST, true); + curl_setopt($this->curl, CURLOPT_POSTFIELDS, $content); + } + else + { + curl_setopt($this->curl, CURLOPT_POST, false); + curl_setopt($this->curl, CURLOPT_POSTFIELDS, null); + } + + if ($content_type !== null) + { + curl_setopt($this->curl, CURLOPT_HTTPHEADER, array('Content-type: '.$content_type)); + } + else + { + curl_setopt($this->curl, CURLOPT_HTTPHEADER, array()); + } + + $complete_response = curl_exec($this->curl); + $header_size = curl_getinfo($this->curl, CURLINFO_HEADER_SIZE); + $http_code = curl_getinfo($this->curl, CURLINFO_HTTP_CODE); + $header = trim(substr($complete_response, 0, $header_size)); + $response = substr($complete_response, $header_size); + + $return = array( + 'response' => $response, + 'http_code' => $http_code + ); + + if ($this->debug === true) + { + $debug = $return; + $debug['url'] = $url; + $debug['method'] = $method; + $debug['content'] = $content; + $debug['content_type'] = $content_type; + $debug['header'] = $header; + $this->set_debug($debug); + } + + return $return; + } + + /** + * Returns a valid and unused vCard id + * + * @return$carddav->query($this->url . $vcard_id . '.vcf', 'GET'); + + if ($result['http_code'] !== 404) + { + $vcard_id = $this->generate_vcard_id(); + } + + return $vcard_id; + } + catch (Exception $e) + { + throw new Exception($e->getMessage(), self::EXCEPTION_COULD_NOT_GENERATE_NEW_VCARD_ID); + } + } + + /** + * Destructor + * Close curl connection if it's open + * + * @return void + */ + public function __destruct() + { + if (!empty($this->curl)) + { + curl_close($this->curl); + } + } +} From 42943235dedda7f3ba0714ff557bacc8ad0cf8df Mon Sep 17 00:00:00 2001 From: Markus Neubauer Date: Thu, 10 Dec 2015 17:55:04 +0100 Subject: [PATCH 14/87] Create xml2array.php --- opt/gemeinschaft/lib/xml/xml2array.php | 142 +++++++++++++++++++++++++ 1 file changed, 142 insertions(+) create mode 100644 opt/gemeinschaft/lib/xml/xml2array.php diff --git a/opt/gemeinschaft/lib/xml/xml2array.php b/opt/gemeinschaft/lib/xml/xml2array.php new file mode 100644 index 000000000..165405134 --- /dev/null +++ b/opt/gemeinschaft/lib/xml/xml2array.php @@ -0,0 +1,142 @@ +rawXML = $xml; + } + + function parse($xml = NULL) + { + if (!is_null($xml)) + { + $this->rawXML = $xml; + } + + $this->isError = false; + + if (!$this->parse_init()) + { + return false; + } + + $this->index = 0; + $this->parsed = $this->parse_recurse(); + $this->status = 'parsing complete'; + + return $this->parsed; + } + + function parse_recurse() + { + $found = array(); + $tagCount = array(); + + while (isset($this->valueArray[$this->index])) + { + $tag = $this->valueArray[$this->index]; + $this->index++; + + if ($tag['type'] == 'close') + { + return $found; + } + + if ($tag['type'] == 'cdata') + { + $tag['tag'] = $this->cdataKey; + $tag['type'] = 'complete'; + } + + $tagName = $tag['tag']; + + if (isset($tagCount[$tagName])) + { + if ($tagCount[$tagName] == 1) + { + $found[$tagName] = array($found[$tagName]); + } + + $tagRef =& $found[$tagName][$tagCount[$tagName]]; + $tagCount[$tagName]++; + } + else + { + $tagCount[$tagName] = 1; + $tagRef =& $found[$tagName]; + } + + switch ($tag['type']) + { + case 'open': + $tagRef = $this->parse_recurse(); + + if (isset($tag['attributes'])) + { + $tagRef[$this->attribKey] = $tag['attributes']; + } + + if (isset($tag['value'])) + { + if (isset($tagRef[$this->cdataKey])) + { + $tagRef[$this->cdataKey] = (array)$tagRef[$this->cdataKey]; + array_unshift($tagRef[$this->cdataKey], $tag['value']); + } + else + { + $tagRef[$this->cdataKey] = $tag['value']; + } + } + break; + + case 'complete': + if (isset($tag['attributes'])) + { + $tagRef[$this->attribKey] = $tag['attributes']; + $tagRef =& $tagRef[$this->valueKey]; + } + + if (isset($tag['value'])) + { + $tagRef = $tag['value']; + } + break; + } + } + + return $found; + } + + function parse_init() + { + $this->parser = xml_parser_create(); + + $parser = $this->parser; + xml_parser_set_option($parser, XML_OPTION_CASE_FOLDING, 0); + xml_parser_set_option($parser, XML_OPTION_SKIP_WHITE, 1); + if (!$res = (bool)xml_parse_into_struct($parser, $this->rawXML, $this->valueArray, $this->keyArray)) + { + $this->isError = true; + $this->error = 'error: '.xml_error_string(xml_get_error_code($parser)).' at line '.xml_get_current_line_number($parser); + } + xml_parser_free($parser); + + return $res; + } +} + +?> From 02fff4c71edb2df6290a7f8b597b9581f7f5d6a1 Mon Sep 17 00:00:00 2001 From: Markus Neubauer Date: Thu, 10 Dec 2015 17:56:12 +0100 Subject: [PATCH 15/87] Create gs-carddav-reader.php --- .../scripts/gs-carddav-reader.php | 315 ++++++++++++++++++ 1 file changed, 315 insertions(+) create mode 100644 opt/gemeinschaft/scripts/gs-carddav-reader.php diff --git a/opt/gemeinschaft/scripts/gs-carddav-reader.php b/opt/gemeinschaft/scripts/gs-carddav-reader.php new file mode 100644 index 000000000..9d999452b --- /dev/null +++ b/opt/gemeinschaft/scripts/gs-carddav-reader.php @@ -0,0 +1,315 @@ +#!/usr/bin/php -q + +* +* +* This program is free software; you can redistribute it and/or +* modify it under the terms of the GNU General Public License +* as published by the Free Software Foundation; either version 2 +* of the License, or (at your option) any later version. +* +* This program is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +* GNU General Public License for more details. +* +* You should have received a copy of the GNU General Public License +* along with this program; if not, write to the Free Software +* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, +* MA 02110-1301, USA. +\*******************************************************************/ + +define('GS_VALID', true); // arriving nativ here + +require_once( dirName(__FILE__) .'/../inc/conf.php' ); +$CARDDAV_LOG = 'cloud_connector.log'; +$FIFO = ''; +$process_name = 'vcard-checker'; +include_once( GS_DIR .'inc/log.php' ); + +if (defined('STDIN' )) @fClose(STDIN ); +if (defined('STDOUT')) @fClose(STDOUT); +if (defined('STDERR')) @fClose(STDERR); + +include_once( GS_DIR .'lib/yadb/yadb.php' ); +include_once( GS_DIR .'inc/gs-lib.php' ); +require_once( GS_DIR .'lib/carddav/CardDAV.php' ); +require_once( GS_DIR .'lib/XML/xml2array.php' ); +require_once( GS_DIR .'inc/db_connect.php' ); + + +// vCard DAV connect +function gs_vcards_connect( $url=null, $login=null, $pass=null ) { + global $CARDDAV_LOG, $FIFO; + + if (! class_exists('carddav_backend')) { + gs_log( GS_LOG_FATAL, getmypid() .': This PHP does not support carddav (lib CardDav.php missing)!', $CARDDAV_LOG, $FIFO ); + exit(1); + } + + $carddav_conn = new carddav_backend($url); + $carddav_conn->set_auth($login, $pass); + + if ( $carddav_conn->check_connection() ) { + gs_log(GS_LOG_DEBUG, getmypid() .': connected to CardDAV '. $url .' for user ' . $login, $CARDDAV_LOG, $FIFO ); + return $carddav_conn; + } else { + gs_log(GS_LOG_FATAL, getmypid() .': Could not connect to CardDAV '. $url .' for user ' . $login, $CARDDAV_LOG, $FIFO ); + return false; + } +} + +// update gs records +function gs_vcard_update( $vcr, $head, $vcard, $lvc=array() ) { + global $CARDDAV_LOG, $FIFO, $DB, $CANONIZE_INTL_PREFIX, $CANONIZE_COUNTRY_CODE, $CANONIZE_NATL_PREFIX; + + $last_modified = date("Y-m-d H:i:s", strtotime( $head['d:propstat']['d:prop']['d:getlastmodified'] )); + $etag = str_replace('"', '', $head['d:propstat']['d:prop']['d:getetag']); + + // remove phone numbers on existing vcards -> update is difficult due to aligment with name/phone number + if ( ! empty($lvc) ) { + $DB->execute('DELETE FROM `pb_prv` WHERE `user_id`=' . $vcr['user_id'] . ' and `card_id`=' . $lvc['id']); + $DB->execute('DELETE FROM `pb_prv_category` WHERE `user_id`=' . $vcr['user_id'] . ' and `card_id`=' . $lvc['id']); + } + else { + $DB->execute('INSERT INTO `pb_cloud_card` ' . + ' (`cloud_id`,`vcard_id`,`etag`,`vcard`,`last_modified`) ' . + ' VALUES(' . $vcr['id'] . ',\'' . $head['vcard_id'] . '\',\'' . $etag . '\',\'' . mysql_real_escape_string($vcard) . '\',\'' . $last_modified . '\')'); + $lvc = $DB->execute( 'SELECT `id`,`cloud_id`,`vcard_id`,`etag`,`last_modified`' . + ' FROM `pb_cloud_card` ' . + ' WHERE `cloud_id`=' . $vcr['id'] . + ' and `vcard_id`=\'' . $head['vcard_id'] . '\'' + )->fetchRow(); + } + + $tmp_vcard = explode("\n", $vcard); + + $n = array(); + $acat = array(); + $fn = ''; + $ln = ''; + foreach ( $tmp_vcard as $value ) { + if ( empty( $value ) ) continue; + + $elem = substr($value, strpos($value, ':') + 1 ); + $key = substr($value, 0, strpos($value, ':') ); + if ( 'N' == $key ) { + $elem = trim($elem); + $aname = explode(';', $elem); + $ln = array_shift ( $aname ); + for ($i = count($aname); $i >= 0; $i--) { + if ( empty($aname[$i]) ) continue; + $fn .= ' ' . $aname[$i]; + } + $fn = ltrim( $fn ); + } + if ( empty( $ln) ) { + $ln = $fn; + $fn=''; + } + + elseif ( 'TEL' == substr($key, 0, 3) ) { + $elem = trim($elem); + $ptype = strtolower( substr($key, strpos($key, '=') + 1) ); + + if ( '+' == substr($elem, 0, 1) ) + $elem = GS_CANONIZE_INTL_PREFIX . substr($elem, 1); + + $number = preg_replace('/\D/', '', $elem); + + if ( GS_CANONIZE_INTL_PREFIX . GS_CANONIZE_COUNTRY_CODE == substr($number, 0, strlen(GS_CANONIZE_INTL_PREFIX . GS_CANONIZE_COUNTRY_CODE) ) ) + $number = GS_CANONIZE_NATL_PREFIX . substr($number, strlen(GS_CANONIZE_INTL_PREFIX . GS_CANONIZE_COUNTRY_CODE)); + + // insert number + $n[$number] = $ptype; + } + + elseif ( 'CATEGORIES' == $key ) { + $elem = trim($elem); + $acat = explode( ',', $elem ); + } + } + + // loop over phone numbers + foreach ( $n as $number => $ptype ) { + + // check_duplicates from within a vcard + if ( $prc = $DB->execute('SELECT `id` FROM `pb_prv` WHERE `user_id`=' . $vcr['user_id'] . ' and `firstname`=\'' . $fn . '\' and `lastname`=\'' . $ln . '\' and `number`=\'' . $number . '\' and `card_id`=0')->fetchRow() ) + $DB->execute('DELETE FROM `pb_prv` WHERE `id`=' . $prc['id']); + + // add a phone record + $DB->execute('INSERT INTO `pb_prv` ' . + ' (`user_id`,`firstname`,`lastname`,`number`,`ptype`,`card_id`) ' . + ' VALUES(' . $vcr['user_id'] .',\'' . $fn .'\',\'' . $ln .'\',\'' . $number .'\',\'' . $ptype .'\',' . $lvc['id'] . ')'); + + // loop over categories + if ( ! empty( $acat) ) { + $prc = $DB->execute( 'SELECT `id` FROM `pb_prv` WHERE `user_id`=' . $vcr['user_id'] . ' and `firstname`=\'' . $fn . '\' and `lastname`=\'' . $ln . '\' and `number`=\'' . $number . '\' and `ptype`=\'' . $ptype . '\' and `card_id`=' . $lvc['id'])->fetchRow(); + foreach ( $acat as $cat ) { + if ( empty($cat) ) continue; + if ( ! $crc = $DB->execute( 'SELECT `id` FROM `pb_category` WHERE `user_id`=' . $vcr['user_id'] . ' and `category`=\'' . $cat . '\'')->fetchRow() ) { + // insert rec + $DB->execute('INSERT INTO `pb_category` ' . + ' (`user_id`,`category`) ' . + ' VALUES(' . $vcr['user_id'] .',\'' . $cat .'\')'); + $crc = $DB->execute( 'SELECT `id` FROM `pb_category` WHERE `user_id`=' . $vcr['user_id'] . ' and `category`=\'' . $cat . '\'')->fetchRow(); + } + // correct xref + $DB->execute('INSERT INTO `pb_prv_category` ' . + ' (`user_id`,`cat_id`,`card_id`,`prv_id`) ' . + ' VALUES(' . $vcr['user_id'] .',' . $crc['id'] .',' . $lvc['id'] .',' . $prc['id'] . ')'); + } + } + } + +} + + +// fetch vcards for a cloud entry +function gs_vcards_update( $vcr ) { + global $CARDDAV_LOG, $FIFO, $DB; + + $carddav_conn = gs_vcards_connect( $vcr['url'], $vcr['login'], $vcr['pass'] ); + if ( ! is_object( $carddav_conn ) || $carddav_conn === false ) { + return false; + } + + $a = new XMLThing(); + $vchead = $a->parse($carddav_conn->get(false,true)); + $vchead = $vchead['d:multistatus']['d:response']; + $head = array_shift ( $vchead ); + + // skip rest if not modified between, depending on header etag or lastmodified + if ( isset( $head['d:propstat']['d:prop']['cs:getctag'] ) ) { + // ref etag: https://tools.ietf.org/html/rfc6352 + $last_ctag = str_replace('"', '', $head['d:propstat']['d:prop']['cs:getctag']); + if ( $last_ctag == $vcr['last_ctag'] ) { + gs_log(GS_LOG_DEBUG, getmypid() .': no update, ctag='. $last_ctag, $CARDDAV_LOG, $FIFO ); + return true; + } + } else $last_ctag = ''; + + if ( isset($head['d:propstat']['d:prop']['d:getlastmodified']) ) { + $last_modified = date("Y-m-d H:i:s", strtotime( $head['d:propstat']['d:prop']['d:getlastmodified'] )); + if ( $last_modified <= $vcr['last_remote_modified'] ) { + gs_log(GS_LOG_DEBUG, getmypid() .': no update, last modified='. $last_modified, $CARDDAV_LOG, $FIFO ); + return true; + } + } else $last_modified = $vcr['modified']; + + gs_log(GS_LOG_DEBUG, getmypid() .': updating..., last modified='. $last_modified, $CARDDAV_LOG, $FIFO ); + // update ctag and last_modified immed + $DB->execute('UPDATE `pb_cloud` SET `ctag`=\'' . $last_ctag . '\', `last_remote_modified`=\'' . $last_modified . '\' WHERE `id`=' . $vcr['id']); + + // get unseen records + gs_log(GS_LOG_DEBUG, getmypid() .': fetch unseen', $CARDDAV_LOG, $FIFO ); + $unseen=array(); + $unrc = $DB->execute('SELECT `id`, `vcard_id`,`etag`, `last_modified` FROM `pb_cloud_card` WHERE `cloud_id`=' . $vcr['id']); + while ( $urc = $unrc->fetchRow() ) { + $unseen[$urc['vcard_id']] = array( + 'id' => $urc['id'], + 'etag' => $urc['etag'], + 'last_modified' => $urc['last_modified'] + ); + } + if ( empty($unseen) ) gs_log(GS_LOG_DEBUG, getmypid() .': no unseen, adding ...', $CARDDAV_LOG, $FIFO ); + + gs_log(GS_LOG_DEBUG, getmypid() .': updating vcards...', $CARDDAV_LOG, $FIFO ); + + // iterate through all of them + for ($i = 0; $i < count($vchead); $i++) { + + $vcard_id=str_replace('.vcf', null, substr($vchead[$i]['d:href'], strrpos($vchead[$i]['d:href'], '/') + 1) ); + + $vchead[$i]['vcard_id'] = $vcard_id; + + // check for existing vcard + if ( isset($unseen[$vcard_id]) ) { + $lvc = $unseen[$vcard_id]; + // avoid deleting + unset($unseen["$vcard_id"]); + + // skip if not modified + $last_modified = date("Y-m-d H:i:s", strtotime( $vchead[$i]['d:propstat']['d:prop']['d:getlastmodified'] )); + $last_etag = str_replace('"', '', $vchead[$i]['d:propstat']['d:prop']['d:getetag']); + if ( $last_etag == $lvc['etag'] && $last_modified == $lvc['last_modified'] ) continue; + + gs_log(GS_LOG_DEBUG, getmypid() .': updating '. $vcard_id, $CARDDAV_LOG, $FIFO ); + + $vchead[$i]['d:propstat']['d:prop']['d:getlastmodified'] = $last_modified; + + // modified remote get the new vcard + $vcard = $carddav_conn->get_vcard($vcard_id . '.vcf'); + gs_vcard_update( $vcr, $vchead[$i], $vcard, $lvc ); + + } else { + + gs_log(GS_LOG_DEBUG, getmypid() .': adding '. $vcard_id, $CARDDAV_LOG, $FIFO ); + // missing local add new vcard + $vcard = $carddav_conn->get_vcard($vcard_id . '.vcf'); + gs_vcard_update( $vcr, $vchead[$i], $vcard ); + } + } + + // delete no more existing recs + foreach ($unseen as $vcard_id => $value) { + gs_log(GS_LOG_DEBUG, getmypid() .': deleting '. $vcard_id, $CARDDAV_LOG, $FIFO ); + $DB->execute('DELETE FROM `pb_prv_category` WHERE `user_id`=' . $vcr['user_id'] . ' and `card_id`=' . $value['id']); + $DB->execute('DELETE FROM `pb_prv` WHERE `user_id`=' . $vcr['user_id'] . ' and `card_id`=' . $value['id']); + $DB->execute('DELETE FROM `pb_cloud_card` WHERE `id`=' . $value['id']); + } + + return true; +} + +$DB = gs_db_master_connect(); + + +// remain in loop, doing a record time by time (avoid race cond in dup exec) +while ( true ) { + $vcrc = @ $DB->execute( + 'SELECT + `id`, `user_id`, `url`, `login`, cast(des_decrypt(`pass`,`login`) as char(16)) as pass, `frequency`, `ctag`, `last_remote_modified`, `modified` + FROM `pb_cloud` + WHERE `next_poll` < NOW() ORDER BY `next_poll` + LIMIT 1' + ); + if ( $vcr = $vcrc->fetchRow() ) { + gs_log(GS_LOG_NOTICE, getmypid() .': Check vCards: '. $vcr['login'] . ': ' . $vcr['url'], $CARDDAV_LOG, $FIFO ); + } else { + break; //the loop + } + + // update next check immediately to avoid concurrent execs in timeout situations + $hdm2text = array( + 'h' => 'hour', + 'd' => 'day', + 'm' => 'month' + ); + $period = substr($vcr['frequency'], -1); + $freq = substr($vcr['frequency'], 0, -1); + if ( $freq > 1 ) $more = 's'; + else $more = ''; + + $next_poll = date_format(date_add( date_create(), DateInterval::createFromDateString("$freq $hdm2text[$period]" . "$more") ), "Y-m-d H:i:s"); + + $DB->execute('UPDATE `pb_cloud` SET `next_poll`=\'' . $next_poll . '\' WHERE `id`=' . $vcr['id']); + + if ( gs_vcards_update( $vcr ) === true ) { + // all went ok + gs_log(GS_LOG_NOTICE, getmypid() .': Check vCards completed normal.', $CARDDAV_LOG, $FIFO ); + + } else { + // any failure + gs_log(GS_LOG_WARNING, getmypid() .': Check vCards failed for '. $vcr['login'] . ': ' . $vcr['url'], $CARDDAV_LOG, $FIFO ); + } +} + +?> From fcb2533fab47f055d83ccb288b7c3281117d4673 Mon Sep 17 00:00:00 2001 From: Markus Neubauer Date: Thu, 10 Dec 2015 18:03:37 +0100 Subject: [PATCH 16/87] Create gs-carddav-reader-to-db --- etc/cron.d/gs-carddav-reader-to-db | 6 ++++++ 1 file changed, 6 insertions(+) create mode 100644 etc/cron.d/gs-carddav-reader-to-db diff --git a/etc/cron.d/gs-carddav-reader-to-db b/etc/cron.d/gs-carddav-reader-to-db new file mode 100644 index 000000000..5e12a1755 --- /dev/null +++ b/etc/cron.d/gs-carddav-reader-to-db @@ -0,0 +1,6 @@ +# Gemeinschaft +# $Revision$ + +# refresh cloud card phone books into the database + +*/11 * * * * root sleep 23; /opt/gemeinschaft/sbin/gs-carddav-reader.php 1>>/dev/null 2>>/dev/null From 35dd61208a13fdbb0500c3507c4d1d4d5662d058 Mon Sep 17 00:00:00 2001 From: Markus Neubauer Date: Thu, 10 Dec 2015 18:05:25 +0100 Subject: [PATCH 17/87] Update gs-carddav-reader-to-db --- etc/cron.d/gs-carddav-reader-to-db | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/etc/cron.d/gs-carddav-reader-to-db b/etc/cron.d/gs-carddav-reader-to-db index 5e12a1755..dd63e7d4e 100644 --- a/etc/cron.d/gs-carddav-reader-to-db +++ b/etc/cron.d/gs-carddav-reader-to-db @@ -3,4 +3,4 @@ # refresh cloud card phone books into the database -*/11 * * * * root sleep 23; /opt/gemeinschaft/sbin/gs-carddav-reader.php 1>>/dev/null 2>>/dev/null +*/17 * * * * root sleep 23; /opt/gemeinschaft/sbin/gs-carddav-reader.php 1>>/dev/null 2>>/dev/null From 08f4d627b89cbc899716bf171f316b9da63fd78e Mon Sep 17 00:00:00 2001 From: Markus Neubauer Date: Thu, 10 Dec 2015 18:05:46 +0100 Subject: [PATCH 18/87] Update gs-carddav-reader-to-db --- etc/cron.d/gs-carddav-reader-to-db | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/etc/cron.d/gs-carddav-reader-to-db b/etc/cron.d/gs-carddav-reader-to-db index dd63e7d4e..4ade8a3a6 100644 --- a/etc/cron.d/gs-carddav-reader-to-db +++ b/etc/cron.d/gs-carddav-reader-to-db @@ -3,4 +3,4 @@ # refresh cloud card phone books into the database -*/17 * * * * root sleep 23; /opt/gemeinschaft/sbin/gs-carddav-reader.php 1>>/dev/null 2>>/dev/null +*/17 * * * * root sleep 23; nice -n 15 /opt/gemeinschaft/sbin/gs-carddav-reader.php 1>>/dev/null 2>>/dev/null From 49bdca951f439650064ee856a1230d98d04bf94f Mon Sep 17 00:00:00 2001 From: Markus Neubauer Date: Thu, 10 Dec 2015 18:30:37 +0100 Subject: [PATCH 19/87] Update asterisk.sql --- usr/share/doc/gemeinschaft/asterisk.sql | 76 +++++++++++++++++++++++-- 1 file changed, 72 insertions(+), 4 deletions(-) diff --git a/usr/share/doc/gemeinschaft/asterisk.sql b/usr/share/doc/gemeinschaft/asterisk.sql index f647c5ab0..9102dbeb2 100644 --- a/usr/share/doc/gemeinschaft/asterisk.sql +++ b/usr/share/doc/gemeinschaft/asterisk.sql @@ -6180,6 +6180,8 @@ INSERT INTO `group_members` VALUES (6,3001); INSERT INTO `group_members` VALUES (6,3002); INSERT INTO `group_members` VALUES (6,3003); INSERT INTO `group_members` VALUES (6,3004); +INSERT INTO `group_members` VALUES (6,3005); +INSERT INTO `group_members` VALUES (6,3006); INSERT INTO `group_members` VALUES (6,4000); INSERT INTO `group_members` VALUES (6,4001); INSERT INTO `group_members` VALUES (6,4002); @@ -6672,6 +6674,68 @@ INSERT INTO `pb_ldap` VALUES ('012345','TEST','HANS','123','2007-05-24 07:28:28' /*!40000 ALTER TABLE `pb_ldap` ENABLE KEYS */; UNLOCK TABLES; +-- +-- Tabellenstruktur für Tabelle `pb_category` +-- + +CREATE TABLE IF NOT EXISTS `pb_category` ( + `id` int(10) unsigned NOT NULL AUTO_INCREMENT, + `user_id` int(10) unsigned NOT NULL, + `category` varchar(24) COLLATE utf8_unicode_ci NOT NULL, + `modified` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, + PRIMARY KEY (`id`), + UNIQUE KEY `uid_catid` (`user_id`,`category`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci; + +-- +-- Tabellenstruktur für Tabelle `pb_cloud` +-- + +CREATE TABLE IF NOT EXISTS `pb_cloud` ( + `id` int(10) unsigned NOT NULL AUTO_INCREMENT, + `user_id` int(10) unsigned NOT NULL, + `url` varchar(256) COLLATE utf8_unicode_ci NOT NULL, + `login` varchar(32) COLLATE utf8_unicode_ci NOT NULL, + `pass` varbinary(64) NOT NULL, + `frequency` varchar(3) COLLATE utf8_unicode_ci NOT NULL DEFAULT '1d', + `ctag` varchar(32) COLLATE utf8_unicode_ci NOT NULL, + `last_remote_modified` datetime NOT NULL, + `next_poll` datetime NOT NULL, + `modified` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, + PRIMARY KEY (`id`), + UNIQUE KEY `uid_url_login` (`user_id`,`url`(255),`login`), + KEY `next_poll` (`next_poll`), + KEY `uid_login` (`user_id`,`login`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci; + +-- +-- Tabellenstruktur für Tabelle `pb_cloud_card` +-- + +CREATE TABLE IF NOT EXISTS `pb_cloud_card` ( + `id` int(10) unsigned NOT NULL AUTO_INCREMENT, + `cloud_id` int(10) unsigned NOT NULL, + `vcard_id` varchar(36) COLLATE utf8_unicode_ci NOT NULL, + `etag` varchar(32) COLLATE utf8_unicode_ci NOT NULL, + `vcard` text COLLATE utf8_unicode_ci NOT NULL, + `last_modified` datetime NOT NULL, + PRIMARY KEY (`id`), + KEY `cloud_id_vcard_id` (`cloud_id`,`vcard_id`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci; + +-- +-- Tabellenstruktur für Tabelle `pb_category` +-- + +CREATE TABLE IF NOT EXISTS `pb_category` ( + `id` int(10) unsigned NOT NULL AUTO_INCREMENT, + `user_id` int(10) unsigned NOT NULL, + `category` varchar(24) COLLATE utf8_unicode_ci NOT NULL, + `modified` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, + PRIMARY KEY (`id`), + UNIQUE KEY `uid_catid` (`user_id`,`category`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci; + -- -- Table structure for table `pb_prv` -- @@ -6679,18 +6743,23 @@ UNLOCK TABLES; DROP TABLE IF EXISTS `pb_prv`; /*!40101 SET @saved_cs_client = @@character_set_client */; /*!40101 SET character_set_client = utf8 */; -CREATE TABLE `pb_prv` ( +DROP TABLE IF EXISTS `pb_prv`; +CREATE TABLE IF NOT EXISTS `pb_prv` ( `id` int(10) unsigned NOT NULL AUTO_INCREMENT, `user_id` int(10) unsigned NOT NULL DEFAULT '0', `firstname` varchar(40) COLLATE utf8_unicode_ci NOT NULL DEFAULT '', `lastname` varchar(40) COLLATE utf8_unicode_ci NOT NULL DEFAULT '', `number` varchar(25) CHARACTER SET ascii NOT NULL DEFAULT '', + `ptype` varchar(16) COLLATE utf8_unicode_ci NOT NULL COMMENT 'cell,work,home', + `card_id` int(10) unsigned NOT NULL, + `modified` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, PRIMARY KEY (`id`), KEY `uid_lastname_firstname` (`user_id`,`lastname`(15),`firstname`(10)), KEY `uid_firstname_lastname` (`user_id`,`firstname`(10),`lastname`(10)), KEY `uid_number` (`user_id`,`number`(10)), - CONSTRAINT `pb_prv_ibfk_1` FOREIGN KEY (`user_id`) REFERENCES `users` (`id`) -) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci; + KEY `uid_vcard` (`user_id`,`card_id`), + KEY `cloud_card_id` (`card_id`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci; /*!40101 SET character_set_client = @saved_cs_client */; -- @@ -7655,4 +7724,3 @@ USE `asterisk`; /*!40111 SET SQL_NOTES=@OLD_SQL_NOTES */; -- Dump completed on 2010-10-19 19:30:00 - From ce99a391c92f76d1528e40227ff06a695f3d796d Mon Sep 17 00:00:00 2001 From: Markus Neubauer Date: Fri, 11 Dec 2015 08:18:32 +0100 Subject: [PATCH 20/87] small fix (from c&p) --- opt/gemeinschaft/htdocs/gui/mod/pb_category.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/opt/gemeinschaft/htdocs/gui/mod/pb_category.php b/opt/gemeinschaft/htdocs/gui/mod/pb_category.php index b8e1cc8ba..703f85f7b 100644 --- a/opt/gemeinschaft/htdocs/gui/mod/pb_category.php +++ b/opt/gemeinschaft/htdocs/gui/mod/pb_category.php @@ -231,7 +231,7 @@ function confirm_delete() { $sudo_url = (@$_SESSION['sudo_user']['name'] == @$_SESSION['real_user']['name']) ? '' : ('&sudo='. @$_SESSION['sudo_user']['name']); - echo '', __('bearbeiten'), '   '; + echo '', __('bearbeiten'), '   '; echo '', __('entfernen'), ''; echo ''; From 52e0c47ee5860bd470d6cf602a673a42a76090be Mon Sep 17 00:00:00 2001 From: Markus Neubauer Date: Fri, 11 Dec 2015 08:19:07 +0100 Subject: [PATCH 21/87] small fix (from c&p) --- opt/gemeinschaft/htdocs/gui/mod/pb_cloud.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/opt/gemeinschaft/htdocs/gui/mod/pb_cloud.php b/opt/gemeinschaft/htdocs/gui/mod/pb_cloud.php index b5e735da5..eed61634f 100644 --- a/opt/gemeinschaft/htdocs/gui/mod/pb_cloud.php +++ b/opt/gemeinschaft/htdocs/gui/mod/pb_cloud.php @@ -325,7 +325,7 @@ function confirm_delete() { $sudo_url = (@$_SESSION['sudo_user']['name'] == @$_SESSION['real_user']['name']) ? '' : ('&sudo='. @$_SESSION['sudo_user']['name']); - echo '', __('bearbeiten'), '   '; + echo '', __('bearbeiten'), '   '; echo '', __('entfernen'), ''; echo ''; From eaa018bcbd30fbd0e613cac1db1c0004eb631ab4 Mon Sep 17 00:00:00 2001 From: Markus Neubauer Date: Fri, 11 Dec 2015 08:40:26 +0100 Subject: [PATCH 22/87] moved from scripts to sbin as it is a cron job --- opt/gemeinschaft/sbin/gs-carddav-reader | 315 ++++++++++++++++++++++++ 1 file changed, 315 insertions(+) create mode 100644 opt/gemeinschaft/sbin/gs-carddav-reader diff --git a/opt/gemeinschaft/sbin/gs-carddav-reader b/opt/gemeinschaft/sbin/gs-carddav-reader new file mode 100644 index 000000000..9d999452b --- /dev/null +++ b/opt/gemeinschaft/sbin/gs-carddav-reader @@ -0,0 +1,315 @@ +#!/usr/bin/php -q + +* +* +* This program is free software; you can redistribute it and/or +* modify it under the terms of the GNU General Public License +* as published by the Free Software Foundation; either version 2 +* of the License, or (at your option) any later version. +* +* This program is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +* GNU General Public License for more details. +* +* You should have received a copy of the GNU General Public License +* along with this program; if not, write to the Free Software +* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, +* MA 02110-1301, USA. +\*******************************************************************/ + +define('GS_VALID', true); // arriving nativ here + +require_once( dirName(__FILE__) .'/../inc/conf.php' ); +$CARDDAV_LOG = 'cloud_connector.log'; +$FIFO = ''; +$process_name = 'vcard-checker'; +include_once( GS_DIR .'inc/log.php' ); + +if (defined('STDIN' )) @fClose(STDIN ); +if (defined('STDOUT')) @fClose(STDOUT); +if (defined('STDERR')) @fClose(STDERR); + +include_once( GS_DIR .'lib/yadb/yadb.php' ); +include_once( GS_DIR .'inc/gs-lib.php' ); +require_once( GS_DIR .'lib/carddav/CardDAV.php' ); +require_once( GS_DIR .'lib/XML/xml2array.php' ); +require_once( GS_DIR .'inc/db_connect.php' ); + + +// vCard DAV connect +function gs_vcards_connect( $url=null, $login=null, $pass=null ) { + global $CARDDAV_LOG, $FIFO; + + if (! class_exists('carddav_backend')) { + gs_log( GS_LOG_FATAL, getmypid() .': This PHP does not support carddav (lib CardDav.php missing)!', $CARDDAV_LOG, $FIFO ); + exit(1); + } + + $carddav_conn = new carddav_backend($url); + $carddav_conn->set_auth($login, $pass); + + if ( $carddav_conn->check_connection() ) { + gs_log(GS_LOG_DEBUG, getmypid() .': connected to CardDAV '. $url .' for user ' . $login, $CARDDAV_LOG, $FIFO ); + return $carddav_conn; + } else { + gs_log(GS_LOG_FATAL, getmypid() .': Could not connect to CardDAV '. $url .' for user ' . $login, $CARDDAV_LOG, $FIFO ); + return false; + } +} + +// update gs records +function gs_vcard_update( $vcr, $head, $vcard, $lvc=array() ) { + global $CARDDAV_LOG, $FIFO, $DB, $CANONIZE_INTL_PREFIX, $CANONIZE_COUNTRY_CODE, $CANONIZE_NATL_PREFIX; + + $last_modified = date("Y-m-d H:i:s", strtotime( $head['d:propstat']['d:prop']['d:getlastmodified'] )); + $etag = str_replace('"', '', $head['d:propstat']['d:prop']['d:getetag']); + + // remove phone numbers on existing vcards -> update is difficult due to aligment with name/phone number + if ( ! empty($lvc) ) { + $DB->execute('DELETE FROM `pb_prv` WHERE `user_id`=' . $vcr['user_id'] . ' and `card_id`=' . $lvc['id']); + $DB->execute('DELETE FROM `pb_prv_category` WHERE `user_id`=' . $vcr['user_id'] . ' and `card_id`=' . $lvc['id']); + } + else { + $DB->execute('INSERT INTO `pb_cloud_card` ' . + ' (`cloud_id`,`vcard_id`,`etag`,`vcard`,`last_modified`) ' . + ' VALUES(' . $vcr['id'] . ',\'' . $head['vcard_id'] . '\',\'' . $etag . '\',\'' . mysql_real_escape_string($vcard) . '\',\'' . $last_modified . '\')'); + $lvc = $DB->execute( 'SELECT `id`,`cloud_id`,`vcard_id`,`etag`,`last_modified`' . + ' FROM `pb_cloud_card` ' . + ' WHERE `cloud_id`=' . $vcr['id'] . + ' and `vcard_id`=\'' . $head['vcard_id'] . '\'' + )->fetchRow(); + } + + $tmp_vcard = explode("\n", $vcard); + + $n = array(); + $acat = array(); + $fn = ''; + $ln = ''; + foreach ( $tmp_vcard as $value ) { + if ( empty( $value ) ) continue; + + $elem = substr($value, strpos($value, ':') + 1 ); + $key = substr($value, 0, strpos($value, ':') ); + if ( 'N' == $key ) { + $elem = trim($elem); + $aname = explode(';', $elem); + $ln = array_shift ( $aname ); + for ($i = count($aname); $i >= 0; $i--) { + if ( empty($aname[$i]) ) continue; + $fn .= ' ' . $aname[$i]; + } + $fn = ltrim( $fn ); + } + if ( empty( $ln) ) { + $ln = $fn; + $fn=''; + } + + elseif ( 'TEL' == substr($key, 0, 3) ) { + $elem = trim($elem); + $ptype = strtolower( substr($key, strpos($key, '=') + 1) ); + + if ( '+' == substr($elem, 0, 1) ) + $elem = GS_CANONIZE_INTL_PREFIX . substr($elem, 1); + + $number = preg_replace('/\D/', '', $elem); + + if ( GS_CANONIZE_INTL_PREFIX . GS_CANONIZE_COUNTRY_CODE == substr($number, 0, strlen(GS_CANONIZE_INTL_PREFIX . GS_CANONIZE_COUNTRY_CODE) ) ) + $number = GS_CANONIZE_NATL_PREFIX . substr($number, strlen(GS_CANONIZE_INTL_PREFIX . GS_CANONIZE_COUNTRY_CODE)); + + // insert number + $n[$number] = $ptype; + } + + elseif ( 'CATEGORIES' == $key ) { + $elem = trim($elem); + $acat = explode( ',', $elem ); + } + } + + // loop over phone numbers + foreach ( $n as $number => $ptype ) { + + // check_duplicates from within a vcard + if ( $prc = $DB->execute('SELECT `id` FROM `pb_prv` WHERE `user_id`=' . $vcr['user_id'] . ' and `firstname`=\'' . $fn . '\' and `lastname`=\'' . $ln . '\' and `number`=\'' . $number . '\' and `card_id`=0')->fetchRow() ) + $DB->execute('DELETE FROM `pb_prv` WHERE `id`=' . $prc['id']); + + // add a phone record + $DB->execute('INSERT INTO `pb_prv` ' . + ' (`user_id`,`firstname`,`lastname`,`number`,`ptype`,`card_id`) ' . + ' VALUES(' . $vcr['user_id'] .',\'' . $fn .'\',\'' . $ln .'\',\'' . $number .'\',\'' . $ptype .'\',' . $lvc['id'] . ')'); + + // loop over categories + if ( ! empty( $acat) ) { + $prc = $DB->execute( 'SELECT `id` FROM `pb_prv` WHERE `user_id`=' . $vcr['user_id'] . ' and `firstname`=\'' . $fn . '\' and `lastname`=\'' . $ln . '\' and `number`=\'' . $number . '\' and `ptype`=\'' . $ptype . '\' and `card_id`=' . $lvc['id'])->fetchRow(); + foreach ( $acat as $cat ) { + if ( empty($cat) ) continue; + if ( ! $crc = $DB->execute( 'SELECT `id` FROM `pb_category` WHERE `user_id`=' . $vcr['user_id'] . ' and `category`=\'' . $cat . '\'')->fetchRow() ) { + // insert rec + $DB->execute('INSERT INTO `pb_category` ' . + ' (`user_id`,`category`) ' . + ' VALUES(' . $vcr['user_id'] .',\'' . $cat .'\')'); + $crc = $DB->execute( 'SELECT `id` FROM `pb_category` WHERE `user_id`=' . $vcr['user_id'] . ' and `category`=\'' . $cat . '\'')->fetchRow(); + } + // correct xref + $DB->execute('INSERT INTO `pb_prv_category` ' . + ' (`user_id`,`cat_id`,`card_id`,`prv_id`) ' . + ' VALUES(' . $vcr['user_id'] .',' . $crc['id'] .',' . $lvc['id'] .',' . $prc['id'] . ')'); + } + } + } + +} + + +// fetch vcards for a cloud entry +function gs_vcards_update( $vcr ) { + global $CARDDAV_LOG, $FIFO, $DB; + + $carddav_conn = gs_vcards_connect( $vcr['url'], $vcr['login'], $vcr['pass'] ); + if ( ! is_object( $carddav_conn ) || $carddav_conn === false ) { + return false; + } + + $a = new XMLThing(); + $vchead = $a->parse($carddav_conn->get(false,true)); + $vchead = $vchead['d:multistatus']['d:response']; + $head = array_shift ( $vchead ); + + // skip rest if not modified between, depending on header etag or lastmodified + if ( isset( $head['d:propstat']['d:prop']['cs:getctag'] ) ) { + // ref etag: https://tools.ietf.org/html/rfc6352 + $last_ctag = str_replace('"', '', $head['d:propstat']['d:prop']['cs:getctag']); + if ( $last_ctag == $vcr['last_ctag'] ) { + gs_log(GS_LOG_DEBUG, getmypid() .': no update, ctag='. $last_ctag, $CARDDAV_LOG, $FIFO ); + return true; + } + } else $last_ctag = ''; + + if ( isset($head['d:propstat']['d:prop']['d:getlastmodified']) ) { + $last_modified = date("Y-m-d H:i:s", strtotime( $head['d:propstat']['d:prop']['d:getlastmodified'] )); + if ( $last_modified <= $vcr['last_remote_modified'] ) { + gs_log(GS_LOG_DEBUG, getmypid() .': no update, last modified='. $last_modified, $CARDDAV_LOG, $FIFO ); + return true; + } + } else $last_modified = $vcr['modified']; + + gs_log(GS_LOG_DEBUG, getmypid() .': updating..., last modified='. $last_modified, $CARDDAV_LOG, $FIFO ); + // update ctag and last_modified immed + $DB->execute('UPDATE `pb_cloud` SET `ctag`=\'' . $last_ctag . '\', `last_remote_modified`=\'' . $last_modified . '\' WHERE `id`=' . $vcr['id']); + + // get unseen records + gs_log(GS_LOG_DEBUG, getmypid() .': fetch unseen', $CARDDAV_LOG, $FIFO ); + $unseen=array(); + $unrc = $DB->execute('SELECT `id`, `vcard_id`,`etag`, `last_modified` FROM `pb_cloud_card` WHERE `cloud_id`=' . $vcr['id']); + while ( $urc = $unrc->fetchRow() ) { + $unseen[$urc['vcard_id']] = array( + 'id' => $urc['id'], + 'etag' => $urc['etag'], + 'last_modified' => $urc['last_modified'] + ); + } + if ( empty($unseen) ) gs_log(GS_LOG_DEBUG, getmypid() .': no unseen, adding ...', $CARDDAV_LOG, $FIFO ); + + gs_log(GS_LOG_DEBUG, getmypid() .': updating vcards...', $CARDDAV_LOG, $FIFO ); + + // iterate through all of them + for ($i = 0; $i < count($vchead); $i++) { + + $vcard_id=str_replace('.vcf', null, substr($vchead[$i]['d:href'], strrpos($vchead[$i]['d:href'], '/') + 1) ); + + $vchead[$i]['vcard_id'] = $vcard_id; + + // check for existing vcard + if ( isset($unseen[$vcard_id]) ) { + $lvc = $unseen[$vcard_id]; + // avoid deleting + unset($unseen["$vcard_id"]); + + // skip if not modified + $last_modified = date("Y-m-d H:i:s", strtotime( $vchead[$i]['d:propstat']['d:prop']['d:getlastmodified'] )); + $last_etag = str_replace('"', '', $vchead[$i]['d:propstat']['d:prop']['d:getetag']); + if ( $last_etag == $lvc['etag'] && $last_modified == $lvc['last_modified'] ) continue; + + gs_log(GS_LOG_DEBUG, getmypid() .': updating '. $vcard_id, $CARDDAV_LOG, $FIFO ); + + $vchead[$i]['d:propstat']['d:prop']['d:getlastmodified'] = $last_modified; + + // modified remote get the new vcard + $vcard = $carddav_conn->get_vcard($vcard_id . '.vcf'); + gs_vcard_update( $vcr, $vchead[$i], $vcard, $lvc ); + + } else { + + gs_log(GS_LOG_DEBUG, getmypid() .': adding '. $vcard_id, $CARDDAV_LOG, $FIFO ); + // missing local add new vcard + $vcard = $carddav_conn->get_vcard($vcard_id . '.vcf'); + gs_vcard_update( $vcr, $vchead[$i], $vcard ); + } + } + + // delete no more existing recs + foreach ($unseen as $vcard_id => $value) { + gs_log(GS_LOG_DEBUG, getmypid() .': deleting '. $vcard_id, $CARDDAV_LOG, $FIFO ); + $DB->execute('DELETE FROM `pb_prv_category` WHERE `user_id`=' . $vcr['user_id'] . ' and `card_id`=' . $value['id']); + $DB->execute('DELETE FROM `pb_prv` WHERE `user_id`=' . $vcr['user_id'] . ' and `card_id`=' . $value['id']); + $DB->execute('DELETE FROM `pb_cloud_card` WHERE `id`=' . $value['id']); + } + + return true; +} + +$DB = gs_db_master_connect(); + + +// remain in loop, doing a record time by time (avoid race cond in dup exec) +while ( true ) { + $vcrc = @ $DB->execute( + 'SELECT + `id`, `user_id`, `url`, `login`, cast(des_decrypt(`pass`,`login`) as char(16)) as pass, `frequency`, `ctag`, `last_remote_modified`, `modified` + FROM `pb_cloud` + WHERE `next_poll` < NOW() ORDER BY `next_poll` + LIMIT 1' + ); + if ( $vcr = $vcrc->fetchRow() ) { + gs_log(GS_LOG_NOTICE, getmypid() .': Check vCards: '. $vcr['login'] . ': ' . $vcr['url'], $CARDDAV_LOG, $FIFO ); + } else { + break; //the loop + } + + // update next check immediately to avoid concurrent execs in timeout situations + $hdm2text = array( + 'h' => 'hour', + 'd' => 'day', + 'm' => 'month' + ); + $period = substr($vcr['frequency'], -1); + $freq = substr($vcr['frequency'], 0, -1); + if ( $freq > 1 ) $more = 's'; + else $more = ''; + + $next_poll = date_format(date_add( date_create(), DateInterval::createFromDateString("$freq $hdm2text[$period]" . "$more") ), "Y-m-d H:i:s"); + + $DB->execute('UPDATE `pb_cloud` SET `next_poll`=\'' . $next_poll . '\' WHERE `id`=' . $vcr['id']); + + if ( gs_vcards_update( $vcr ) === true ) { + // all went ok + gs_log(GS_LOG_NOTICE, getmypid() .': Check vCards completed normal.', $CARDDAV_LOG, $FIFO ); + + } else { + // any failure + gs_log(GS_LOG_WARNING, getmypid() .': Check vCards failed for '. $vcr['login'] . ': ' . $vcr['url'], $CARDDAV_LOG, $FIFO ); + } +} + +?> From 17f65eabab59146e6d0f16c420daffd948afeab0 Mon Sep 17 00:00:00 2001 From: Markus Neubauer Date: Fri, 11 Dec 2015 08:41:14 +0100 Subject: [PATCH 23/87] moved to sbin --- .../scripts/gs-carddav-reader.php | 315 ------------------ 1 file changed, 315 deletions(-) delete mode 100644 opt/gemeinschaft/scripts/gs-carddav-reader.php diff --git a/opt/gemeinschaft/scripts/gs-carddav-reader.php b/opt/gemeinschaft/scripts/gs-carddav-reader.php deleted file mode 100644 index 9d999452b..000000000 --- a/opt/gemeinschaft/scripts/gs-carddav-reader.php +++ /dev/null @@ -1,315 +0,0 @@ -#!/usr/bin/php -q - -* -* -* This program is free software; you can redistribute it and/or -* modify it under the terms of the GNU General Public License -* as published by the Free Software Foundation; either version 2 -* of the License, or (at your option) any later version. -* -* This program is distributed in the hope that it will be useful, -* but WITHOUT ANY WARRANTY; without even the implied warranty of -* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -* GNU General Public License for more details. -* -* You should have received a copy of the GNU General Public License -* along with this program; if not, write to the Free Software -* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, -* MA 02110-1301, USA. -\*******************************************************************/ - -define('GS_VALID', true); // arriving nativ here - -require_once( dirName(__FILE__) .'/../inc/conf.php' ); -$CARDDAV_LOG = 'cloud_connector.log'; -$FIFO = ''; -$process_name = 'vcard-checker'; -include_once( GS_DIR .'inc/log.php' ); - -if (defined('STDIN' )) @fClose(STDIN ); -if (defined('STDOUT')) @fClose(STDOUT); -if (defined('STDERR')) @fClose(STDERR); - -include_once( GS_DIR .'lib/yadb/yadb.php' ); -include_once( GS_DIR .'inc/gs-lib.php' ); -require_once( GS_DIR .'lib/carddav/CardDAV.php' ); -require_once( GS_DIR .'lib/XML/xml2array.php' ); -require_once( GS_DIR .'inc/db_connect.php' ); - - -// vCard DAV connect -function gs_vcards_connect( $url=null, $login=null, $pass=null ) { - global $CARDDAV_LOG, $FIFO; - - if (! class_exists('carddav_backend')) { - gs_log( GS_LOG_FATAL, getmypid() .': This PHP does not support carddav (lib CardDav.php missing)!', $CARDDAV_LOG, $FIFO ); - exit(1); - } - - $carddav_conn = new carddav_backend($url); - $carddav_conn->set_auth($login, $pass); - - if ( $carddav_conn->check_connection() ) { - gs_log(GS_LOG_DEBUG, getmypid() .': connected to CardDAV '. $url .' for user ' . $login, $CARDDAV_LOG, $FIFO ); - return $carddav_conn; - } else { - gs_log(GS_LOG_FATAL, getmypid() .': Could not connect to CardDAV '. $url .' for user ' . $login, $CARDDAV_LOG, $FIFO ); - return false; - } -} - -// update gs records -function gs_vcard_update( $vcr, $head, $vcard, $lvc=array() ) { - global $CARDDAV_LOG, $FIFO, $DB, $CANONIZE_INTL_PREFIX, $CANONIZE_COUNTRY_CODE, $CANONIZE_NATL_PREFIX; - - $last_modified = date("Y-m-d H:i:s", strtotime( $head['d:propstat']['d:prop']['d:getlastmodified'] )); - $etag = str_replace('"', '', $head['d:propstat']['d:prop']['d:getetag']); - - // remove phone numbers on existing vcards -> update is difficult due to aligment with name/phone number - if ( ! empty($lvc) ) { - $DB->execute('DELETE FROM `pb_prv` WHERE `user_id`=' . $vcr['user_id'] . ' and `card_id`=' . $lvc['id']); - $DB->execute('DELETE FROM `pb_prv_category` WHERE `user_id`=' . $vcr['user_id'] . ' and `card_id`=' . $lvc['id']); - } - else { - $DB->execute('INSERT INTO `pb_cloud_card` ' . - ' (`cloud_id`,`vcard_id`,`etag`,`vcard`,`last_modified`) ' . - ' VALUES(' . $vcr['id'] . ',\'' . $head['vcard_id'] . '\',\'' . $etag . '\',\'' . mysql_real_escape_string($vcard) . '\',\'' . $last_modified . '\')'); - $lvc = $DB->execute( 'SELECT `id`,`cloud_id`,`vcard_id`,`etag`,`last_modified`' . - ' FROM `pb_cloud_card` ' . - ' WHERE `cloud_id`=' . $vcr['id'] . - ' and `vcard_id`=\'' . $head['vcard_id'] . '\'' - )->fetchRow(); - } - - $tmp_vcard = explode("\n", $vcard); - - $n = array(); - $acat = array(); - $fn = ''; - $ln = ''; - foreach ( $tmp_vcard as $value ) { - if ( empty( $value ) ) continue; - - $elem = substr($value, strpos($value, ':') + 1 ); - $key = substr($value, 0, strpos($value, ':') ); - if ( 'N' == $key ) { - $elem = trim($elem); - $aname = explode(';', $elem); - $ln = array_shift ( $aname ); - for ($i = count($aname); $i >= 0; $i--) { - if ( empty($aname[$i]) ) continue; - $fn .= ' ' . $aname[$i]; - } - $fn = ltrim( $fn ); - } - if ( empty( $ln) ) { - $ln = $fn; - $fn=''; - } - - elseif ( 'TEL' == substr($key, 0, 3) ) { - $elem = trim($elem); - $ptype = strtolower( substr($key, strpos($key, '=') + 1) ); - - if ( '+' == substr($elem, 0, 1) ) - $elem = GS_CANONIZE_INTL_PREFIX . substr($elem, 1); - - $number = preg_replace('/\D/', '', $elem); - - if ( GS_CANONIZE_INTL_PREFIX . GS_CANONIZE_COUNTRY_CODE == substr($number, 0, strlen(GS_CANONIZE_INTL_PREFIX . GS_CANONIZE_COUNTRY_CODE) ) ) - $number = GS_CANONIZE_NATL_PREFIX . substr($number, strlen(GS_CANONIZE_INTL_PREFIX . GS_CANONIZE_COUNTRY_CODE)); - - // insert number - $n[$number] = $ptype; - } - - elseif ( 'CATEGORIES' == $key ) { - $elem = trim($elem); - $acat = explode( ',', $elem ); - } - } - - // loop over phone numbers - foreach ( $n as $number => $ptype ) { - - // check_duplicates from within a vcard - if ( $prc = $DB->execute('SELECT `id` FROM `pb_prv` WHERE `user_id`=' . $vcr['user_id'] . ' and `firstname`=\'' . $fn . '\' and `lastname`=\'' . $ln . '\' and `number`=\'' . $number . '\' and `card_id`=0')->fetchRow() ) - $DB->execute('DELETE FROM `pb_prv` WHERE `id`=' . $prc['id']); - - // add a phone record - $DB->execute('INSERT INTO `pb_prv` ' . - ' (`user_id`,`firstname`,`lastname`,`number`,`ptype`,`card_id`) ' . - ' VALUES(' . $vcr['user_id'] .',\'' . $fn .'\',\'' . $ln .'\',\'' . $number .'\',\'' . $ptype .'\',' . $lvc['id'] . ')'); - - // loop over categories - if ( ! empty( $acat) ) { - $prc = $DB->execute( 'SELECT `id` FROM `pb_prv` WHERE `user_id`=' . $vcr['user_id'] . ' and `firstname`=\'' . $fn . '\' and `lastname`=\'' . $ln . '\' and `number`=\'' . $number . '\' and `ptype`=\'' . $ptype . '\' and `card_id`=' . $lvc['id'])->fetchRow(); - foreach ( $acat as $cat ) { - if ( empty($cat) ) continue; - if ( ! $crc = $DB->execute( 'SELECT `id` FROM `pb_category` WHERE `user_id`=' . $vcr['user_id'] . ' and `category`=\'' . $cat . '\'')->fetchRow() ) { - // insert rec - $DB->execute('INSERT INTO `pb_category` ' . - ' (`user_id`,`category`) ' . - ' VALUES(' . $vcr['user_id'] .',\'' . $cat .'\')'); - $crc = $DB->execute( 'SELECT `id` FROM `pb_category` WHERE `user_id`=' . $vcr['user_id'] . ' and `category`=\'' . $cat . '\'')->fetchRow(); - } - // correct xref - $DB->execute('INSERT INTO `pb_prv_category` ' . - ' (`user_id`,`cat_id`,`card_id`,`prv_id`) ' . - ' VALUES(' . $vcr['user_id'] .',' . $crc['id'] .',' . $lvc['id'] .',' . $prc['id'] . ')'); - } - } - } - -} - - -// fetch vcards for a cloud entry -function gs_vcards_update( $vcr ) { - global $CARDDAV_LOG, $FIFO, $DB; - - $carddav_conn = gs_vcards_connect( $vcr['url'], $vcr['login'], $vcr['pass'] ); - if ( ! is_object( $carddav_conn ) || $carddav_conn === false ) { - return false; - } - - $a = new XMLThing(); - $vchead = $a->parse($carddav_conn->get(false,true)); - $vchead = $vchead['d:multistatus']['d:response']; - $head = array_shift ( $vchead ); - - // skip rest if not modified between, depending on header etag or lastmodified - if ( isset( $head['d:propstat']['d:prop']['cs:getctag'] ) ) { - // ref etag: https://tools.ietf.org/html/rfc6352 - $last_ctag = str_replace('"', '', $head['d:propstat']['d:prop']['cs:getctag']); - if ( $last_ctag == $vcr['last_ctag'] ) { - gs_log(GS_LOG_DEBUG, getmypid() .': no update, ctag='. $last_ctag, $CARDDAV_LOG, $FIFO ); - return true; - } - } else $last_ctag = ''; - - if ( isset($head['d:propstat']['d:prop']['d:getlastmodified']) ) { - $last_modified = date("Y-m-d H:i:s", strtotime( $head['d:propstat']['d:prop']['d:getlastmodified'] )); - if ( $last_modified <= $vcr['last_remote_modified'] ) { - gs_log(GS_LOG_DEBUG, getmypid() .': no update, last modified='. $last_modified, $CARDDAV_LOG, $FIFO ); - return true; - } - } else $last_modified = $vcr['modified']; - - gs_log(GS_LOG_DEBUG, getmypid() .': updating..., last modified='. $last_modified, $CARDDAV_LOG, $FIFO ); - // update ctag and last_modified immed - $DB->execute('UPDATE `pb_cloud` SET `ctag`=\'' . $last_ctag . '\', `last_remote_modified`=\'' . $last_modified . '\' WHERE `id`=' . $vcr['id']); - - // get unseen records - gs_log(GS_LOG_DEBUG, getmypid() .': fetch unseen', $CARDDAV_LOG, $FIFO ); - $unseen=array(); - $unrc = $DB->execute('SELECT `id`, `vcard_id`,`etag`, `last_modified` FROM `pb_cloud_card` WHERE `cloud_id`=' . $vcr['id']); - while ( $urc = $unrc->fetchRow() ) { - $unseen[$urc['vcard_id']] = array( - 'id' => $urc['id'], - 'etag' => $urc['etag'], - 'last_modified' => $urc['last_modified'] - ); - } - if ( empty($unseen) ) gs_log(GS_LOG_DEBUG, getmypid() .': no unseen, adding ...', $CARDDAV_LOG, $FIFO ); - - gs_log(GS_LOG_DEBUG, getmypid() .': updating vcards...', $CARDDAV_LOG, $FIFO ); - - // iterate through all of them - for ($i = 0; $i < count($vchead); $i++) { - - $vcard_id=str_replace('.vcf', null, substr($vchead[$i]['d:href'], strrpos($vchead[$i]['d:href'], '/') + 1) ); - - $vchead[$i]['vcard_id'] = $vcard_id; - - // check for existing vcard - if ( isset($unseen[$vcard_id]) ) { - $lvc = $unseen[$vcard_id]; - // avoid deleting - unset($unseen["$vcard_id"]); - - // skip if not modified - $last_modified = date("Y-m-d H:i:s", strtotime( $vchead[$i]['d:propstat']['d:prop']['d:getlastmodified'] )); - $last_etag = str_replace('"', '', $vchead[$i]['d:propstat']['d:prop']['d:getetag']); - if ( $last_etag == $lvc['etag'] && $last_modified == $lvc['last_modified'] ) continue; - - gs_log(GS_LOG_DEBUG, getmypid() .': updating '. $vcard_id, $CARDDAV_LOG, $FIFO ); - - $vchead[$i]['d:propstat']['d:prop']['d:getlastmodified'] = $last_modified; - - // modified remote get the new vcard - $vcard = $carddav_conn->get_vcard($vcard_id . '.vcf'); - gs_vcard_update( $vcr, $vchead[$i], $vcard, $lvc ); - - } else { - - gs_log(GS_LOG_DEBUG, getmypid() .': adding '. $vcard_id, $CARDDAV_LOG, $FIFO ); - // missing local add new vcard - $vcard = $carddav_conn->get_vcard($vcard_id . '.vcf'); - gs_vcard_update( $vcr, $vchead[$i], $vcard ); - } - } - - // delete no more existing recs - foreach ($unseen as $vcard_id => $value) { - gs_log(GS_LOG_DEBUG, getmypid() .': deleting '. $vcard_id, $CARDDAV_LOG, $FIFO ); - $DB->execute('DELETE FROM `pb_prv_category` WHERE `user_id`=' . $vcr['user_id'] . ' and `card_id`=' . $value['id']); - $DB->execute('DELETE FROM `pb_prv` WHERE `user_id`=' . $vcr['user_id'] . ' and `card_id`=' . $value['id']); - $DB->execute('DELETE FROM `pb_cloud_card` WHERE `id`=' . $value['id']); - } - - return true; -} - -$DB = gs_db_master_connect(); - - -// remain in loop, doing a record time by time (avoid race cond in dup exec) -while ( true ) { - $vcrc = @ $DB->execute( - 'SELECT - `id`, `user_id`, `url`, `login`, cast(des_decrypt(`pass`,`login`) as char(16)) as pass, `frequency`, `ctag`, `last_remote_modified`, `modified` - FROM `pb_cloud` - WHERE `next_poll` < NOW() ORDER BY `next_poll` - LIMIT 1' - ); - if ( $vcr = $vcrc->fetchRow() ) { - gs_log(GS_LOG_NOTICE, getmypid() .': Check vCards: '. $vcr['login'] . ': ' . $vcr['url'], $CARDDAV_LOG, $FIFO ); - } else { - break; //the loop - } - - // update next check immediately to avoid concurrent execs in timeout situations - $hdm2text = array( - 'h' => 'hour', - 'd' => 'day', - 'm' => 'month' - ); - $period = substr($vcr['frequency'], -1); - $freq = substr($vcr['frequency'], 0, -1); - if ( $freq > 1 ) $more = 's'; - else $more = ''; - - $next_poll = date_format(date_add( date_create(), DateInterval::createFromDateString("$freq $hdm2text[$period]" . "$more") ), "Y-m-d H:i:s"); - - $DB->execute('UPDATE `pb_cloud` SET `next_poll`=\'' . $next_poll . '\' WHERE `id`=' . $vcr['id']); - - if ( gs_vcards_update( $vcr ) === true ) { - // all went ok - gs_log(GS_LOG_NOTICE, getmypid() .': Check vCards completed normal.', $CARDDAV_LOG, $FIFO ); - - } else { - // any failure - gs_log(GS_LOG_WARNING, getmypid() .': Check vCards failed for '. $vcr['login'] . ': ' . $vcr['url'], $CARDDAV_LOG, $FIFO ); - } -} - -?> From 7281cc2929df5c5de2bd450c5eba10388df6b238 Mon Sep 17 00:00:00 2001 From: Markus Neubauer Date: Fri, 11 Dec 2015 08:48:49 +0100 Subject: [PATCH 24/87] Rename gs-carddav-reader to gs-carddav-reader-to-db --- .../sbin/{gs-carddav-reader => gs-carddav-reader-to-db} | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename opt/gemeinschaft/sbin/{gs-carddav-reader => gs-carddav-reader-to-db} (100%) diff --git a/opt/gemeinschaft/sbin/gs-carddav-reader b/opt/gemeinschaft/sbin/gs-carddav-reader-to-db similarity index 100% rename from opt/gemeinschaft/sbin/gs-carddav-reader rename to opt/gemeinschaft/sbin/gs-carddav-reader-to-db From f9fd55ec9a212ee4919824ee97c85eeb75b0a488 Mon Sep 17 00:00:00 2001 From: Markus Neubauer Date: Fri, 11 Dec 2015 09:33:29 +0100 Subject: [PATCH 25/87] prohibit changes on cloud records Prohibit changes on cloud records, as the cloud server always needs to win. This is mandatory as phone addressbooks of smartphones and web should not diverge. --- opt/gemeinschaft/htdocs/gui/mod/pb_private.php | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/opt/gemeinschaft/htdocs/gui/mod/pb_private.php b/opt/gemeinschaft/htdocs/gui/mod/pb_private.php index ae8d4dd59..571c361a6 100644 --- a/opt/gemeinschaft/htdocs/gui/mod/pb_private.php +++ b/opt/gemeinschaft/htdocs/gui/mod/pb_private.php @@ -119,7 +119,7 @@ function confirm_delete() { $rs = $DB->execute( 'SELECT SQL_CALC_FOUND_ROWS '. - '`id`, `lastname`, `firstname`, `number` , `ptype` '. + '`id`, `lastname`, `firstname`, `number` , `ptype`, `card_id` '. 'FROM '. '`pb_prv` '. 'WHERE '. @@ -147,7 +147,7 @@ function confirm_delete() { $rs = $DB->execute( 'SELECT SQL_CALC_FOUND_ROWS '. - '`id`, `lastname`, `firstname`, `number`, `ptype` '. + '`id`, `lastname`, `firstname`, `number`, `ptype`, `card_id` '. 'FROM '. '`pb_prv` '. 'WHERE '. @@ -314,8 +314,10 @@ function confirm_delete() { (@$_SESSION['sudo_user']['name'] == @$_SESSION['real_user']['name']) ? '' : ('&sudo='. @$_SESSION['sudo_user']['name']); echo '', __('wählen'), '   '; - echo '', __('bearbeiten'), '   '; - echo '', __('entfernen'), ''; + if ( ! $r['card_id'] ) { + echo '', __('bearbeiten'), '   '; + echo '', __('entfernen'), ''; + } echo ''; } From beffedc52f57997e77e92c8e376420231237c29d Mon Sep 17 00:00:00 2001 From: Markus Neubauer Date: Sat, 12 Dec 2015 00:12:57 +0100 Subject: [PATCH 26/87] Update upgrade-pb-3.2-3.3.sql --- misc/scripts/upgrade-pb-3.2-3.3.sql | 20 ++++++++++++++------ 1 file changed, 14 insertions(+), 6 deletions(-) diff --git a/misc/scripts/upgrade-pb-3.2-3.3.sql b/misc/scripts/upgrade-pb-3.2-3.3.sql index d6046e8f8..89978e15b 100644 --- a/misc/scripts/upgrade-pb-3.2-3.3.sql +++ b/misc/scripts/upgrade-pb-3.2-3.3.sql @@ -6,20 +6,28 @@ CREATE TABLE IF NOT EXISTS `pb_prv` ( `lastname` varchar(40) COLLATE utf8_unicode_ci NOT NULL DEFAULT '', `number` varchar(25) CHARACTER SET ascii NOT NULL DEFAULT '', `ptype` varchar(16) COLLATE utf8_unicode_ci NOT NULL COMMENT 'cell,work,home', + `pref` int(2) unsigned NOT NULL DEFAULT '9', `card_id` int(10) unsigned NOT NULL, `modified` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, PRIMARY KEY (`id`), - KEY `uid_lastname_firstname` (`user_id`,`lastname`(15),`firstname`(10)), - KEY `uid_firstname_lastname` (`user_id`,`firstname`(10),`lastname`(10)), - KEY `uid_number` (`user_id`,`number`(10)), - KEY `uid_cardid` (`user_id`,`card_id`), - KEY `cloud_card_id` (`card_id`) + KEY `uid_vcard` (`user_id`,`card_id`), + KEY `cloud_card_id` (`card_id`), + KEY `uid_lastname_firstname_pref` (`user_id`,`lastname`(15),`firstname`(10),`pref`,`ptype`), + KEY `uid_number_pref` (`user_id`,`number`(10),`pref`,`ptype`), + KEY `uid_firstname_lastname_pref` (`user_id`,`firstname`(10),`lastname`(10),`pref`,`ptype`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci; // alter existing 3.2 private phonebook -ALTER TABLE `pb_prv` ADD `ptype` VARCHAR(16) NOT NULL COMMENT 'cell,work,home'; +ALTER TABLE `pb_prv` ADD `ptype` VARCHAR(16) NOT NULL COMMENT 'cell,work,home'; +ALTER TABLE `pb_prv` ADD `pref` int(2) unsigned NOT NULL DEFAULT '9'; ALTER TABLE `pb_prv` ADD `vcard_id` int(10) NOT NULL; ALTER TABLE `pb_prv` ADD `modified` TIMESTAMP on update CURRENT_TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP; +ALTER TABLE `asterisk`.`pb_prv` DROP INDEX `uid_firstname_lastname_pref` , + ADD INDEX `uid_firstname_lastname_pref` ( `user_id` , `firstname` ( 10 ) , `lastname` ( 10 ) , `pref` , `ptype` ); +ALTER TABLE `asterisk`.`pb_prv` DROP INDEX `uid_lastname_firstname_pref` , + ADD INDEX `uid_lastname_firstname_pref` ( `user_id` , `lastname` ( 15 ) , `firstname` ( 10 ) , `pref` , `ptype` ); +ALTER TABLE `asterisk`.`pb_prv` DROP INDEX `uid_number_pref` , + ADD INDEX `uid_number_pref` ( `user_id` , `number` ( 10 ) , `pref` , `ptype` ); ALTER TABLE `pb_prv` ADD INDEX `uid_cardid` (`user_id`,`card_id`); ALTER TABLE `pb_prv` ADD INDEX `cloud_card_id` (`card_id`); From 77e3a8ad44f8cad627ed7d39e732c88075dd97ca Mon Sep 17 00:00:00 2001 From: Markus Neubauer Date: Sat, 12 Dec 2015 00:14:45 +0100 Subject: [PATCH 27/87] Update gs-carddav-reader-to-db --- opt/gemeinschaft/sbin/gs-carddav-reader-to-db | 50 +++++++++++-------- 1 file changed, 28 insertions(+), 22 deletions(-) diff --git a/opt/gemeinschaft/sbin/gs-carddav-reader-to-db b/opt/gemeinschaft/sbin/gs-carddav-reader-to-db index 9d999452b..4f8b2d72d 100644 --- a/opt/gemeinschaft/sbin/gs-carddav-reader-to-db +++ b/opt/gemeinschaft/sbin/gs-carddav-reader-to-db @@ -93,32 +93,29 @@ function gs_vcard_update( $vcr, $head, $vcard, $lvc=array() ) { $n = array(); $acat = array(); + $aparam = array(); $fn = ''; $ln = ''; foreach ( $tmp_vcard as $value ) { if ( empty( $value ) ) continue; - $elem = substr($value, strpos($value, ':') + 1 ); - $key = substr($value, 0, strpos($value, ':') ); + $pos = strpos($value, ':'); + $elem = trim(substr($value, $pos + 1 )); + $aparam = explode(';', substr($value, 0, $pos)); + $key = strtoupper( array_shift( $aparam ) ); + if ( 'N' == $key ) { - $elem = trim($elem); $aname = explode(';', $elem); - $ln = array_shift ( $aname ); + $ln = array_shift( $aname ); for ($i = count($aname); $i >= 0; $i--) { if ( empty($aname[$i]) ) continue; $fn .= ' ' . $aname[$i]; } $fn = ltrim( $fn ); } - if ( empty( $ln) ) { - $ln = $fn; - $fn=''; - } + if ( empty( $ln) ) { $ln = $fn; $fn=''; } - elseif ( 'TEL' == substr($key, 0, 3) ) { - $elem = trim($elem); - $ptype = strtolower( substr($key, strpos($key, '=') + 1) ); - + elseif ( 'TEL' == $key ) { if ( '+' == substr($elem, 0, 1) ) $elem = GS_CANONIZE_INTL_PREFIX . substr($elem, 1); @@ -127,18 +124,27 @@ function gs_vcard_update( $vcr, $head, $vcard, $lvc=array() ) { if ( GS_CANONIZE_INTL_PREFIX . GS_CANONIZE_COUNTRY_CODE == substr($number, 0, strlen(GS_CANONIZE_INTL_PREFIX . GS_CANONIZE_COUNTRY_CODE) ) ) $number = GS_CANONIZE_NATL_PREFIX . substr($number, strlen(GS_CANONIZE_INTL_PREFIX . GS_CANONIZE_COUNTRY_CODE)); - // insert number - $n[$number] = $ptype; - } + // add number to array, making it singular + $n[$number] = array( 'type' => '', 'pref' => 99 ); - elseif ( 'CATEGORIES' == $key ) { - $elem = trim($elem); - $acat = explode( ',', $elem ); + // add attributes to the number + foreach ( $aparam as $param ) { + if ( empty($param) ) continue; + $k2 = explode('=', strtoupper( $param )); + if ( 'TYPE' == $k2[0] ) { + if ( $k2[1] == 'PREF' ) $n[$number]['pref'] = 0; + else $n[$number]['type'] .= strtolower( $k2[1] ) . ','; + } + elseif ( 'PREF' == $key2 ) $n[$number]['pref'] = $value2; + } + $n[$number]['type'] = rtrim($n[$number]['type'], ','); } + + elseif ( 'CATEGORIES' == $key ) $acat = explode( ',', $elem ); } // loop over phone numbers - foreach ( $n as $number => $ptype ) { + foreach ( $n as $number => $param ) { // check_duplicates from within a vcard if ( $prc = $DB->execute('SELECT `id` FROM `pb_prv` WHERE `user_id`=' . $vcr['user_id'] . ' and `firstname`=\'' . $fn . '\' and `lastname`=\'' . $ln . '\' and `number`=\'' . $number . '\' and `card_id`=0')->fetchRow() ) @@ -146,12 +152,12 @@ function gs_vcard_update( $vcr, $head, $vcard, $lvc=array() ) { // add a phone record $DB->execute('INSERT INTO `pb_prv` ' . - ' (`user_id`,`firstname`,`lastname`,`number`,`ptype`,`card_id`) ' . - ' VALUES(' . $vcr['user_id'] .',\'' . $fn .'\',\'' . $ln .'\',\'' . $number .'\',\'' . $ptype .'\',' . $lvc['id'] . ')'); + ' (`user_id`,`firstname`,`lastname`,`number`,`ptype`,`pref`,`card_id`) ' . + ' VALUES(' . $vcr['user_id'] .',\'' . $fn .'\',\'' . $ln .'\',\'' . $number .'\',\'' . $param['type'] .'\',' . $param['pref'] . ',' . $lvc['id'] . ')'); // loop over categories if ( ! empty( $acat) ) { - $prc = $DB->execute( 'SELECT `id` FROM `pb_prv` WHERE `user_id`=' . $vcr['user_id'] . ' and `firstname`=\'' . $fn . '\' and `lastname`=\'' . $ln . '\' and `number`=\'' . $number . '\' and `ptype`=\'' . $ptype . '\' and `card_id`=' . $lvc['id'])->fetchRow(); + $prc = $DB->execute( 'SELECT `id` FROM `pb_prv` WHERE `user_id`=' . $vcr['user_id'] . ' and `firstname`=\'' . $fn . '\' and `lastname`=\'' . $ln . '\' and `number`=\'' . $number . '\' and `ptype`=\'' . $param['type'] . '\' and `card_id`=' . $lvc['id'])->fetchRow(); foreach ( $acat as $cat ) { if ( empty($cat) ) continue; if ( ! $crc = $DB->execute( 'SELECT `id` FROM `pb_category` WHERE `user_id`=' . $vcr['user_id'] . ' and `category`=\'' . $cat . '\'')->fetchRow() ) { From 98d2a65eb0be713dbe16254dc9e4f0fd8c36439d Mon Sep 17 00:00:00 2001 From: Markus Neubauer Date: Sat, 12 Dec 2015 00:17:29 +0100 Subject: [PATCH 28/87] Update pb_cloud.php --- opt/gemeinschaft/htdocs/gui/mod/pb_cloud.php | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/opt/gemeinschaft/htdocs/gui/mod/pb_cloud.php b/opt/gemeinschaft/htdocs/gui/mod/pb_cloud.php index eed61634f..3a399bf5b 100644 --- a/opt/gemeinschaft/htdocs/gui/mod/pb_cloud.php +++ b/opt/gemeinschaft/htdocs/gui/mod/pb_cloud.php @@ -383,5 +383,7 @@ function confirm_delete() {
Apple Addressbook Server
https://example.com/addressbooks/users/{resource|principal|username}/{collection}/
-

[2] Schedule: h=hour, d=day, m=month (Max. 2 digits + 1 char, no minutes allowed).
-       Example: '4h' = refresh every 4 hours (~ also during night). Defaults to '1d'.

+

[2] Schedule: Defaults to '1d', the first/next update will happen within half an hour.
+       Where h=hour, d=day, m=month (Max. 2 digits plus 1 char, no blank/minutes allowed).
+       Example: 12h =~ refresh every 12 hours (~ also during night), starting with now (save time).
+       You can trigger a refresh using edit and save with no other changes.

From 41c668a7483ffa4f993903c012c0f8d8fbc8f4f7 Mon Sep 17 00:00:00 2001 From: Markus Neubauer Date: Sat, 12 Dec 2015 00:18:16 +0100 Subject: [PATCH 29/87] Update pb_private.php --- .../htdocs/gui/mod/pb_private.php | 368 ++++++++++++++++++ 1 file changed, 368 insertions(+) diff --git a/opt/gemeinschaft/htdocs/gui/mod/pb_private.php b/opt/gemeinschaft/htdocs/gui/mod/pb_private.php index 571c361a6..5c1f33dcc 100644 --- a/opt/gemeinschaft/htdocs/gui/mod/pb_private.php +++ b/opt/gemeinschaft/htdocs/gui/mod/pb_private.php @@ -7,6 +7,15 @@ * Copyright 2007, amooma GmbH, Bachstr. 126, 56566 Neuwied, Germany, * http://www.amooma.de/ * Stefan Wintermeyer +* Philipp Kempgen * Philipp Kempgen * Peter Kozak * Soeren Sprenger @@ -105,6 +114,365 @@ function confirm_delete() { +if ($number != '') { + + # search by number + + $search_url = 'number='. urlEncode($number); + + $number_sql = str_replace( + array( '*', '?' ), + array( '%', '_' ), + $number + ) .'%'; + + $rs = $DB->execute( + 'SELECT SQL_CALC_FOUND_ROWS '. + '`id`, `lastname`, `firstname`, `number` , `ptype`, `card_id` '. + 'FROM '. + '`pb_prv` '. + 'WHERE '. + '`number` LIKE \''. $DB->escape($number_sql) .'\' '. + 'AND '. + '`user_id`='. $user_id .' '. + 'ORDER BY `lastname`, `firstname`, `pref`, `ptype` '. + 'LIMIT '. ($page*(int)$per_page) .','. (int)$per_page + ); + $num_total = @$DB->numFoundRows(); + $num_pages = ceil($num_total / $per_page); + +} else { + + # search by name + + $number = ''; + $search_url = 'name='. urlEncode($name); + + $name_sql = str_replace( + array( '*', '?' ), + array( '%', '_' ), + $name + ) .'%'; + + $rs = $DB->execute( + 'SELECT SQL_CALC_FOUND_ROWS '. + '`id`, `lastname`, `firstname`, `number`, `ptype`, `card_id` '. + 'FROM '. + '`pb_prv` '. + 'WHERE '. + '( `lastname` LIKE _utf8\''. $DB->escape($name_sql) .'\' COLLATE utf8_unicode_ci OR '. + ' `firstname` LIKE _utf8\''. $DB->escape($name_sql) .'\' COLLATE utf8_unicode_ci ) '. + 'AND '. + '`user_id`='. $DB->escape($user_id).' '. + 'ORDER BY `lastname`, `firstname`, `pref`, `ptype` '. + 'LIMIT '. ($page*(int)$per_page) .','. (int)$per_page + ); + $num_total = @$DB->numFoundRows(); + $num_pages = ceil($num_total / $per_page); + +} + + +?> + + + + + + + + + + + + + + + + + + + +
+
+ + + + +
+
+
+ + + +
+
+ 0) { + echo + '', + '', __('zurück'), '', + '', "\n"; +} else { + echo + '', __('zurück'), '', "\n"; +} +if ($page < $num_pages-1) { + echo + '', + '', __('weiter'), '', + '', "\n"; +} else { + echo + '', __('weiter'), '', "\n"; +} + +?> +
+ $cs) { + echo '', htmlEnt($cd), '', "\n"; +} + +?> +
+ + + +', "\n"; +echo gs_form_hidden($SECTION, $MODULE), "\n"; +echo '', "\n"; +echo '', "\n"; +echo '', "\n"; +?> + + + + + + + + + + + + +fetchRow()) { + echo '', "\n"; + + if ($r['id']==$edit_entry) { + + echo '', "\n"; + + echo '', "\n"; + + echo '', "\n"; + + echo ''; + + } else { + + $show_name = trim( $r['lastname'] . ', ' . $r['firstname'], " ," ); + if ( $last_seen != $show_name ) { + echo '', "\n"; + + echo '', "\n"; + + echo '', "\n"; + + echo ''; + + } + + echo '', "\n"; + } +} + +?> + + + + + + + + + + + + +
> + + > + + > + [1] + + +
'; + echo ''; + echo ''; + echo ''; + echo ''; + echo ''; + echo ''; + echo ''; + echo ''; + echo ''; + echo ''; + echo '', __('abbrechen'), ''; + + echo ''; + $last_seen = htmlEnt($show_name); + } + else echo ''; + echo $last_seen; + echo '', htmlEnt($r['number']), '', htmlEnt($r['ptype']), ''; + $sudo_url = + (@$_SESSION['sudo_user']['name'] == @$_SESSION['real_user']['name']) + ? '' : ('&sudo='. @$_SESSION['sudo_user']['name']); + echo '', __('wählen'), '   '; + echo '', __('bearbeiten'), '   '; + echo '', __('entfernen'), ''; + if ( $r['card_id'] ) echo ' [2]'; + echo '
+ + + + + + + + abbrechen';*/ ?> +
+ + +
+

[1] Type of phone number: cell/work/home etc.

+

[2] You can loose local changes on a refresh, rather modify/delete this entry within your cloud!

+empgen@amooma.de> +* Peter Kozak +* Soeren Sprenger +* Markus Neubauer - 2015 +* - extending db and preparing for vcards +* you need to alter the db for this version to work: +* +* +* This program is free software; you can redistribute it and/or +* modify it under the terms of the GNU General Public License +* as published by the Free Software Foundation; either version 2 +* of the License, or (at your option) any later version. +* +* This program is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +* GNU General Public License for more details. +* +* You should have received a copy of the GNU General Public License +* along with this program; if not, write to the Free Software +* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, +* MA 02110-1301, USA. +\*******************************************************************/ + +defined('GS_VALID') or die('No direct access.'); +include_once( GS_DIR .'lib/utf8-normalize/gs_utf_normal.php' ); + +echo '

'; +if (@$MODULES[$SECTION]['icon']) + echo ' '; +if (count( $MODULES[$SECTION]['sub'] ) > 1 ) + echo $MODULES[$SECTION]['title'], ' - '; +echo $MODULES[$SECTION]['sub'][$MODULE]['title']; +echo '

', "\n"; + + +echo '', "\n"; +echo '' ,"\n"; + +$per_page = (int)GS_GUI_NUM_RESULTS; + +$name = trim(@$_REQUEST['name' ]); +$number = trim(@$_REQUEST['number' ]); +$ptype = trim(@$_REQUEST['ptype' ]); +$save_lname = trim(@$_REQUEST['slname' ]); +$save_fname = trim(@$_REQUEST['sfname' ]); +$save_number = trim(@$_REQUEST['snumber']); +$save_ptype = trim(@$_REQUEST['sptype']); +$page = (int) (@$_REQUEST['page' ]); +$delete_entry = (int)trim(@$_REQUEST['delete' ]); +$edit_entry = (int)trim(@$_REQUEST['edit' ]); +$save_entry = (int)trim(@$_REQUEST['save' ]); + +$user_id = (int)@$_SESSION['sudo_user']['info']['id']; + +if ($delete_entry > 0) { + # delete entry + + $rs = $DB->execute( +'DELETE FROM `pb_prv` +WHERE `id`='. $delete_entry .' AND `user_id`='. $user_id + ); + +} + +if (($save_lname != '' || $save_fname != '') && ($save_number != '')) { + # save entry + + if ($save_entry < 1) { + + $rs = $DB->execute( +'INSERT INTO `pb_prv` (`id`, `user_id`, `lastname`, `firstname`, `number`, `ptype`) VALUES +(NULL, '. $user_id .', \''. $DB->escape($save_lname) .'\', \''. $DB->escape($save_fname) .'\', \''. $DB->escape($save_number) .'\', \''. $DB->escape($save_ptype) .'\')' + ); + + } else { + + $rs = $DB->execute( +'UPDATE `pb_prv` SET `lastname`=\''. $DB->escape($save_lname) .'\', `firstname`=\''. $DB->escape($save_fname) .'\', `number`=\''. $DB->escape($save_number) .'\', `ptype`=\''. $DB->escape($save_ptype) .'\' +WHERE `id`='. $save_entry .' AND `user_id`='. $user_id + ); + + } + $save_number = ''; + $save_name = ''; + $save_ptype = ''; +} + + + + + if ($number != '') { # search by number From 073f14310df4454fa89675b315b3ad4ee0e374ac Mon Sep 17 00:00:00 2001 From: Markus Neubauer Date: Sat, 12 Dec 2015 00:20:14 +0100 Subject: [PATCH 30/87] Update pb_private.php --- .../htdocs/gui/mod/pb_private.php | 383 ------------------ 1 file changed, 383 deletions(-) diff --git a/opt/gemeinschaft/htdocs/gui/mod/pb_private.php b/opt/gemeinschaft/htdocs/gui/mod/pb_private.php index 5c1f33dcc..1ebf54435 100644 --- a/opt/gemeinschaft/htdocs/gui/mod/pb_private.php +++ b/opt/gemeinschaft/htdocs/gui/mod/pb_private.php @@ -7,15 +7,6 @@ * Copyright 2007, amooma GmbH, Bachstr. 126, 56566 Neuwied, Germany, * http://www.amooma.de/ * Stefan Wintermeyer -* Philipp Kempgen * Philipp Kempgen * Peter Kozak * Soeren Sprenger @@ -375,377 +366,3 @@ function confirm_delete() {

[1] Type of phone number: cell/work/home etc.

[2] You can loose local changes on a refresh, rather modify/delete this entry within your cloud!

-empgen@amooma.de> -* Peter Kozak -* Soeren Sprenger -* Markus Neubauer - 2015 -* - extending db and preparing for vcards -* you need to alter the db for this version to work: -* -* -* This program is free software; you can redistribute it and/or -* modify it under the terms of the GNU General Public License -* as published by the Free Software Foundation; either version 2 -* of the License, or (at your option) any later version. -* -* This program is distributed in the hope that it will be useful, -* but WITHOUT ANY WARRANTY; without even the implied warranty of -* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -* GNU General Public License for more details. -* -* You should have received a copy of the GNU General Public License -* along with this program; if not, write to the Free Software -* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, -* MA 02110-1301, USA. -\*******************************************************************/ - -defined('GS_VALID') or die('No direct access.'); -include_once( GS_DIR .'lib/utf8-normalize/gs_utf_normal.php' ); - -echo '

'; -if (@$MODULES[$SECTION]['icon']) - echo ' '; -if (count( $MODULES[$SECTION]['sub'] ) > 1 ) - echo $MODULES[$SECTION]['title'], ' - '; -echo $MODULES[$SECTION]['sub'][$MODULE]['title']; -echo '

', "\n"; - - -echo '', "\n"; -echo '' ,"\n"; - -$per_page = (int)GS_GUI_NUM_RESULTS; - -$name = trim(@$_REQUEST['name' ]); -$number = trim(@$_REQUEST['number' ]); -$ptype = trim(@$_REQUEST['ptype' ]); -$save_lname = trim(@$_REQUEST['slname' ]); -$save_fname = trim(@$_REQUEST['sfname' ]); -$save_number = trim(@$_REQUEST['snumber']); -$save_ptype = trim(@$_REQUEST['sptype']); -$page = (int) (@$_REQUEST['page' ]); -$delete_entry = (int)trim(@$_REQUEST['delete' ]); -$edit_entry = (int)trim(@$_REQUEST['edit' ]); -$save_entry = (int)trim(@$_REQUEST['save' ]); - -$user_id = (int)@$_SESSION['sudo_user']['info']['id']; - -if ($delete_entry > 0) { - # delete entry - - $rs = $DB->execute( -'DELETE FROM `pb_prv` -WHERE `id`='. $delete_entry .' AND `user_id`='. $user_id - ); - -} - -if (($save_lname != '' || $save_fname != '') && ($save_number != '')) { - # save entry - - if ($save_entry < 1) { - - $rs = $DB->execute( -'INSERT INTO `pb_prv` (`id`, `user_id`, `lastname`, `firstname`, `number`, `ptype`) VALUES -(NULL, '. $user_id .', \''. $DB->escape($save_lname) .'\', \''. $DB->escape($save_fname) .'\', \''. $DB->escape($save_number) .'\', \''. $DB->escape($save_ptype) .'\')' - ); - - } else { - - $rs = $DB->execute( -'UPDATE `pb_prv` SET `lastname`=\''. $DB->escape($save_lname) .'\', `firstname`=\''. $DB->escape($save_fname) .'\', `number`=\''. $DB->escape($save_number) .'\', `ptype`=\''. $DB->escape($save_ptype) .'\' -WHERE `id`='. $save_entry .' AND `user_id`='. $user_id - ); - - } - $save_number = ''; - $save_name = ''; - $save_ptype = ''; -} - - - - - -if ($number != '') { - - # search by number - - $search_url = 'number='. urlEncode($number); - - $number_sql = str_replace( - array( '*', '?' ), - array( '%', '_' ), - $number - ) .'%'; - - $rs = $DB->execute( - 'SELECT SQL_CALC_FOUND_ROWS '. - '`id`, `lastname`, `firstname`, `number` , `ptype`, `card_id` '. - 'FROM '. - '`pb_prv` '. - 'WHERE '. - '`number` LIKE \''. $DB->escape($number_sql) .'\' '. - 'AND '. - '`user_id`='. $user_id .' '. - 'ORDER BY `lastname`, `firstname` '. - 'LIMIT '. ($page*(int)$per_page) .','. (int)$per_page - ); - $num_total = @$DB->numFoundRows(); - $num_pages = ceil($num_total / $per_page); - -} else { - - # search by name - - $number = ''; - $search_url = 'name='. urlEncode($name); - - $name_sql = str_replace( - array( '*', '?' ), - array( '%', '_' ), - $name - ) .'%'; - - $rs = $DB->execute( - 'SELECT SQL_CALC_FOUND_ROWS '. - '`id`, `lastname`, `firstname`, `number`, `ptype`, `card_id` '. - 'FROM '. - '`pb_prv` '. - 'WHERE '. - '( `lastname` LIKE _utf8\''. $DB->escape($name_sql) .'\' COLLATE utf8_unicode_ci OR '. - ' `firstname` LIKE _utf8\''. $DB->escape($name_sql) .'\' COLLATE utf8_unicode_ci ) '. - 'AND '. - '`user_id`='. $DB->escape($user_id).' '. - 'ORDER BY `lastname`, `firstname` '. - 'LIMIT '. ($page*(int)$per_page) .','. (int)$per_page - ); - $num_total = @$DB->numFoundRows(); - $num_pages = ceil($num_total / $per_page); - -} - - -?> - - - - - - - - - - - - - - - - - - - -
-
- - - - -
-
-
- - - -
-
- 0) { - echo - '', - '', __('zurück'), '', - '', "\n"; -} else { - echo - '', __('zurück'), '', "\n"; -} -if ($page < $num_pages-1) { - echo - '', - '', __('weiter'), '', - '', "\n"; -} else { - echo - '', __('weiter'), '', "\n"; -} - -?> -
- $cs) { - echo '', htmlEnt($cd), '', "\n"; -} - -?> -
- - - -', "\n"; -echo gs_form_hidden($SECTION, $MODULE), "\n"; -echo '', "\n"; -echo '', "\n"; -echo '', "\n"; -?> - - - - - - - - - - - - -fetchRow()) { - echo '', "\n"; - - if ($r['id']==$edit_entry) { - - echo '', "\n"; - - echo '', "\n"; - - echo '', "\n"; - - echo ''; - - } else { - - echo '', "\n"; - - echo '', "\n"; - - echo '', "\n"; - - echo ''; - - } - - echo '', "\n"; - } -} - -?> - - - - - - - - - - - - -
> - - > - - > - [1] -  
'; - echo ''; - echo ''; - echo ''; - echo ''; - echo ''; - echo ''; - echo ''; - echo ''; - echo ''; - echo ''; - echo '', __('abbrechen'), ''; - - echo '', htmlEnt($r['lastname']); - if ($r['firstname'] != '') - echo ', ', htmlEnt($r['firstname']); - echo '', htmlEnt($r['number']), '', htmlEnt($r['ptype']), ''; - $sudo_url = - (@$_SESSION['sudo_user']['name'] == @$_SESSION['real_user']['name']) - ? '' : ('&sudo='. @$_SESSION['sudo_user']['name']); - echo '', __('wählen'), '   '; - if ( ! $r['card_id'] ) { - echo '', __('bearbeiten'), '   '; - echo '', __('entfernen'), ''; - } - echo '
- - - - - - - - abbrechen';*/ ?> -
- - -
-

[1] Type of phone number: cell/work/home etc.

-execute('SHOW COLUMNS FROM pb_prv LIKE "ptype"')->fetchRow() ) ) { - $rs = $DB->execute('ALTER TABLE `pb_prv` ADD `ptype` varchar(16) NOT NULL COMMENT "cell,work,home"'); - } - if (empty( $DB->execute('SHOW COLUMNS FROM pb_prv LIKE "vcard_id"')->fetchRow() )) { - $rs = $DB->execute('ALTER TABLE `pb_prv` ADD `vcard_id` int(11) NOT NULL'); - $rs = $DB->execute('ALTER TABLE `pb_prv` ADD INDEX `uid_vcard` (`user_id`,`vcard_id`)'); - } - if (empty( $DB->execute('SHOW COLUMNS FROM pb_prv LIKE "cat_id"')->fetchRow() )) { - $rs = $DB->execute('ALTER TABLE `pb_prv` ADD `cat_id` int(11) NOT NULL'); - $rs = $DB->execute('ALTER TABLE `pb_prv` ADD INDEX `uid_cat_lastname_firstname` (`user_id`,`cat_id`,`lastname`,`firstname`)'); - $rs = $DB->execute('ALTER TABLE `pb_prv` ADD INDEX `uid_cat_firstname_lastname` (`user_id`,`cat_id`,`firstname`,`lastname`)'); - } - if (empty( $DB->execute('SHOW COLUMNS FROM pb_prv LIKE "modified"')->fetchRow() )) { - $rs = $DB->execute('ALTER TABLE `pb_prv` ADD `modified` TIMESTAMP on update CURRENT_TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP'); - } -} -*/ -?> From 4e7cd12d35d80f00a263da080fd16c1586a86397 Mon Sep 17 00:00:00 2001 From: Markus Neubauer Date: Sat, 12 Dec 2015 00:40:45 +0100 Subject: [PATCH 31/87] Update asterisk.sql --- usr/share/doc/gemeinschaft/asterisk.sql | 39 +++++++++++++------------ 1 file changed, 21 insertions(+), 18 deletions(-) diff --git a/usr/share/doc/gemeinschaft/asterisk.sql b/usr/share/doc/gemeinschaft/asterisk.sql index 9102dbeb2..4a4b1b56d 100644 --- a/usr/share/doc/gemeinschaft/asterisk.sql +++ b/usr/share/doc/gemeinschaft/asterisk.sql @@ -6723,19 +6723,6 @@ CREATE TABLE IF NOT EXISTS `pb_cloud_card` ( KEY `cloud_id_vcard_id` (`cloud_id`,`vcard_id`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci; --- --- Tabellenstruktur für Tabelle `pb_category` --- - -CREATE TABLE IF NOT EXISTS `pb_category` ( - `id` int(10) unsigned NOT NULL AUTO_INCREMENT, - `user_id` int(10) unsigned NOT NULL, - `category` varchar(24) COLLATE utf8_unicode_ci NOT NULL, - `modified` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, - PRIMARY KEY (`id`), - UNIQUE KEY `uid_catid` (`user_id`,`category`) -) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci; - -- -- Table structure for table `pb_prv` -- @@ -6743,7 +6730,6 @@ CREATE TABLE IF NOT EXISTS `pb_category` ( DROP TABLE IF EXISTS `pb_prv`; /*!40101 SET @saved_cs_client = @@character_set_client */; /*!40101 SET character_set_client = utf8 */; -DROP TABLE IF EXISTS `pb_prv`; CREATE TABLE IF NOT EXISTS `pb_prv` ( `id` int(10) unsigned NOT NULL AUTO_INCREMENT, `user_id` int(10) unsigned NOT NULL DEFAULT '0', @@ -6751,14 +6737,15 @@ CREATE TABLE IF NOT EXISTS `pb_prv` ( `lastname` varchar(40) COLLATE utf8_unicode_ci NOT NULL DEFAULT '', `number` varchar(25) CHARACTER SET ascii NOT NULL DEFAULT '', `ptype` varchar(16) COLLATE utf8_unicode_ci NOT NULL COMMENT 'cell,work,home', + `pref` int(2) unsigned NOT NULL DEFAULT '9', `card_id` int(10) unsigned NOT NULL, `modified` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, PRIMARY KEY (`id`), - KEY `uid_lastname_firstname` (`user_id`,`lastname`(15),`firstname`(10)), - KEY `uid_firstname_lastname` (`user_id`,`firstname`(10),`lastname`(10)), - KEY `uid_number` (`user_id`,`number`(10)), KEY `uid_vcard` (`user_id`,`card_id`), - KEY `cloud_card_id` (`card_id`) + KEY `cloud_card_id` (`card_id`), + KEY `uid_lastname_firstname_pref` (`user_id`,`lastname`(15),`firstname`(10),`pref`,`ptype`), + KEY `uid_number_pref` (`user_id`,`number`(10),`pref`,`ptype`), + KEY `uid_firstname_lastname_pref` (`user_id`,`firstname`(10),`lastname`(10),`pref`,`ptype`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci; /*!40101 SET character_set_client = @saved_cs_client */; @@ -6771,6 +6758,22 @@ LOCK TABLES `pb_prv` WRITE; /*!40000 ALTER TABLE `pb_prv` ENABLE KEYS */; UNLOCK TABLES; +-- connect a phone book entry to a category +CREATE TABLE IF NOT EXISTS `pb_prv_category` ( + `id` int(10) unsigned NOT NULL AUTO_INCREMENT, + `user_id` int(10) unsigned NOT NULL, + `cat_id` int(10) unsigned NOT NULL, + `card_id` int(10) unsigned NOT NULL, + `prv_id` int(10) unsigned NOT NULL, + PRIMARY KEY (`id`), + KEY `uid_catid_cardid` (`user_id`,`cat_id`,`card_id`), + KEY `uid_prvid` (`user_id`,`prv_id`), + KEY `uid_cardid` (`user_id`,`card_id`), + KEY `card_id` (`card_id`), + KEY `prv_id` (`prv_id`), + KEY `cat_id` (`cat_id`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci; + -- -- Table structure for table `penalties` -- From 5555ad59dce1da9904ba3352b47a20000f9bfa75 Mon Sep 17 00:00:00 2001 From: Markus Neubauer Date: Mon, 14 Dec 2015 15:52:34 +0100 Subject: [PATCH 32/87] Update gs-carddav-reader-to-db --- opt/gemeinschaft/sbin/gs-carddav-reader-to-db | 96 ++++++++++++++----- 1 file changed, 70 insertions(+), 26 deletions(-) diff --git a/opt/gemeinschaft/sbin/gs-carddav-reader-to-db b/opt/gemeinschaft/sbin/gs-carddav-reader-to-db index 4f8b2d72d..49a12fd67 100644 --- a/opt/gemeinschaft/sbin/gs-carddav-reader-to-db +++ b/opt/gemeinschaft/sbin/gs-carddav-reader-to-db @@ -44,24 +44,28 @@ require_once( GS_DIR .'lib/carddav/CardDAV.php' ); require_once( GS_DIR .'lib/XML/xml2array.php' ); require_once( GS_DIR .'inc/db_connect.php' ); +$CLOUD_MSG = ''; // vCard DAV connect function gs_vcards_connect( $url=null, $login=null, $pass=null ) { - global $CARDDAV_LOG, $FIFO; + global $CARDDAV_LOG, $FIFO, $CLOUD_MSG; if (! class_exists('carddav_backend')) { - gs_log( GS_LOG_FATAL, getmypid() .': This PHP does not support carddav (lib CardDav.php missing)!', $CARDDAV_LOG, $FIFO ); - exit(1); + $CLOUD_MSG = 'This system does not support carddav (lib CardDav.php missing)!'; + gs_log( GS_LOG_FATAL, getmypid() . $CLOUD_MSG, $CARDDAV_LOG, $FIFO ); + return false; } $carddav_conn = new carddav_backend($url); $carddav_conn->set_auth($login, $pass); - + if ( $carddav_conn->check_connection() ) { - gs_log(GS_LOG_DEBUG, getmypid() .': connected to CardDAV '. $url .' for user ' . $login, $CARDDAV_LOG, $FIFO ); + $CLOUD_MSG = 'connected CardDAV '. $url .' for user ' . $login; + gs_log(GS_LOG_DEBUG, getmypid() . $CLOUD_MSG, $CARDDAV_LOG, $FIFO ); return $carddav_conn; } else { - gs_log(GS_LOG_FATAL, getmypid() .': Could not connect to CardDAV '. $url .' for user ' . $login, $CARDDAV_LOG, $FIFO ); + $CLOUD_MSG = 'can not connect to cloud, check url, and login/password.'; + gs_log(GS_LOG_FATAL, getmypid() . $CLOUD_MSG, $CARDDAV_LOG, $FIFO ); return false; } } @@ -90,7 +94,7 @@ function gs_vcard_update( $vcr, $head, $vcard, $lvc=array() ) { } $tmp_vcard = explode("\n", $vcard); - + $n = array(); $acat = array(); $aparam = array(); @@ -118,7 +122,7 @@ function gs_vcard_update( $vcr, $head, $vcard, $lvc=array() ) { elseif ( 'TEL' == $key ) { if ( '+' == substr($elem, 0, 1) ) $elem = GS_CANONIZE_INTL_PREFIX . substr($elem, 1); - + $number = preg_replace('/\D/', '', $elem); if ( GS_CANONIZE_INTL_PREFIX . GS_CANONIZE_COUNTRY_CODE == substr($number, 0, strlen(GS_CANONIZE_INTL_PREFIX . GS_CANONIZE_COUNTRY_CODE) ) ) @@ -142,13 +146,13 @@ function gs_vcard_update( $vcr, $head, $vcard, $lvc=array() ) { elseif ( 'CATEGORIES' == $key ) $acat = explode( ',', $elem ); } - + // loop over phone numbers foreach ( $n as $number => $param ) { // check_duplicates from within a vcard if ( $prc = $DB->execute('SELECT `id` FROM `pb_prv` WHERE `user_id`=' . $vcr['user_id'] . ' and `firstname`=\'' . $fn . '\' and `lastname`=\'' . $ln . '\' and `number`=\'' . $number . '\' and `card_id`=0')->fetchRow() ) - $DB->execute('DELETE FROM `pb_prv` WHERE `id`=' . $prc['id']); + $DB->execute('DELETE FROM `pb_prv` WHERE `id`=' . $prc['id']); // add a phone record $DB->execute('INSERT INTO `pb_prv` ' . @@ -180,7 +184,11 @@ function gs_vcard_update( $vcr, $head, $vcard, $lvc=array() ) { // fetch vcards for a cloud entry function gs_vcards_update( $vcr ) { - global $CARDDAV_LOG, $FIFO, $DB; + global $CARDDAV_LOG, $FIFO, $DB, $CLOUD_MSG; + $vc_add = 0; + $vc_mod = 0; + $vc_del = 0; + $vc_seen = 0; $carddav_conn = gs_vcards_connect( $vcr['url'], $vcr['login'], $vcr['pass'] ); if ( ! is_object( $carddav_conn ) || $carddav_conn === false ) { @@ -191,13 +199,15 @@ function gs_vcards_update( $vcr ) { $vchead = $a->parse($carddav_conn->get(false,true)); $vchead = $vchead['d:multistatus']['d:response']; $head = array_shift ( $vchead ); - + $CLOUD_MSG = ''; + // skip rest if not modified between, depending on header etag or lastmodified if ( isset( $head['d:propstat']['d:prop']['cs:getctag'] ) ) { // ref etag: https://tools.ietf.org/html/rfc6352 $last_ctag = str_replace('"', '', $head['d:propstat']['d:prop']['cs:getctag']); if ( $last_ctag == $vcr['last_ctag'] ) { - gs_log(GS_LOG_DEBUG, getmypid() .': no update, ctag='. $last_ctag, $CARDDAV_LOG, $FIFO ); + $CLOUD_MSG = 'no update, cloud last ctag: '. $last_ctag; + gs_log(GS_LOG_DEBUG, getmypid() . $CLOUD_MSG, $CARDDAV_LOG, $FIFO ); return true; } } else $last_ctag = ''; @@ -205,7 +215,8 @@ function gs_vcards_update( $vcr ) { if ( isset($head['d:propstat']['d:prop']['d:getlastmodified']) ) { $last_modified = date("Y-m-d H:i:s", strtotime( $head['d:propstat']['d:prop']['d:getlastmodified'] )); if ( $last_modified <= $vcr['last_remote_modified'] ) { - gs_log(GS_LOG_DEBUG, getmypid() .': no update, last modified='. $last_modified, $CARDDAV_LOG, $FIFO ); + $CLOUD_MSG = 'no update, cloud last modified: '. $last_modified; + gs_log(GS_LOG_DEBUG, getmypid() . $CLOUD_MSG, $CARDDAV_LOG, $FIFO ); return true; } } else $last_modified = $vcr['modified']; @@ -213,7 +224,7 @@ function gs_vcards_update( $vcr ) { gs_log(GS_LOG_DEBUG, getmypid() .': updating..., last modified='. $last_modified, $CARDDAV_LOG, $FIFO ); // update ctag and last_modified immed $DB->execute('UPDATE `pb_cloud` SET `ctag`=\'' . $last_ctag . '\', `last_remote_modified`=\'' . $last_modified . '\' WHERE `id`=' . $vcr['id']); - + // get unseen records gs_log(GS_LOG_DEBUG, getmypid() .': fetch unseen', $CARDDAV_LOG, $FIFO ); $unseen=array(); @@ -228,14 +239,15 @@ function gs_vcards_update( $vcr ) { if ( empty($unseen) ) gs_log(GS_LOG_DEBUG, getmypid() .': no unseen, adding ...', $CARDDAV_LOG, $FIFO ); gs_log(GS_LOG_DEBUG, getmypid() .': updating vcards...', $CARDDAV_LOG, $FIFO ); - + // iterate through all of them for ($i = 0; $i < count($vchead); $i++) { $vcard_id=str_replace('.vcf', null, substr($vchead[$i]['d:href'], strrpos($vchead[$i]['d:href'], '/') + 1) ); - + $vchead[$i]['vcard_id'] = $vcard_id; - + + $vc_seen += 1; // check for existing vcard if ( isset($unseen[$vcard_id]) ) { $lvc = $unseen[$vcard_id]; @@ -247,6 +259,7 @@ function gs_vcards_update( $vcr ) { $last_etag = str_replace('"', '', $vchead[$i]['d:propstat']['d:prop']['d:getetag']); if ( $last_etag == $lvc['etag'] && $last_modified == $lvc['last_modified'] ) continue; + $vc_mod += 1; gs_log(GS_LOG_DEBUG, getmypid() .': updating '. $vcard_id, $CARDDAV_LOG, $FIFO ); $vchead[$i]['d:propstat']['d:prop']['d:getlastmodified'] = $last_modified; @@ -256,22 +269,34 @@ function gs_vcards_update( $vcr ) { gs_vcard_update( $vcr, $vchead[$i], $vcard, $lvc ); } else { - - gs_log(GS_LOG_DEBUG, getmypid() .': adding '. $vcard_id, $CARDDAV_LOG, $FIFO ); // missing local add new vcard - $vcard = $carddav_conn->get_vcard($vcard_id . '.vcf'); + $vc_add += 1; + gs_log(GS_LOG_DEBUG, getmypid() .': adding '. $vcard_id, $CARDDAV_LOG, $FIFO ); + $vcard = $carddav_conn->get_vcard($vcard_id . '.vcf'); gs_vcard_update( $vcr, $vchead[$i], $vcard ); } } // delete no more existing recs foreach ($unseen as $vcard_id => $value) { + $vc_del += 1; gs_log(GS_LOG_DEBUG, getmypid() .': deleting '. $vcard_id, $CARDDAV_LOG, $FIFO ); $DB->execute('DELETE FROM `pb_prv_category` WHERE `user_id`=' . $vcr['user_id'] . ' and `card_id`=' . $value['id']); $DB->execute('DELETE FROM `pb_prv` WHERE `user_id`=' . $vcr['user_id'] . ' and `card_id`=' . $value['id']); $DB->execute('DELETE FROM `pb_cloud_card` WHERE `id`=' . $value['id']); } + // clean up categories + $rs2 = $DB->execute( 'DELETE c FROM `pb_category` AS c ' . + ' LEFT JOIN `pb_prv_category` AS p ' . + ' ON c.id = p.cat_id ' . + ' WHERE c.user_id = ' . $vcr['user_id'] . + ' AND p.id IS NULL' + ); + + $CLOUD_MSG = $vc_seen . ' seen, ' . $vc_mod . ' modified, ' . $vc_add . ' added, ' . $vc_del . ' deleted'; + gs_log(GS_LOG_DEBUG, getmypid() . $CLOUD_MSG, $CARDDAV_LOG, $FIFO ); + return true; } @@ -280,11 +305,13 @@ $DB = gs_db_master_connect(); // remain in loop, doing a record time by time (avoid race cond in dup exec) while ( true ) { + $CLOUD_MSG = ''; $vcrc = @ $DB->execute( 'SELECT - `id`, `user_id`, `url`, `login`, cast(des_decrypt(`pass`,`login`) as char(16)) as pass, `frequency`, `ctag`, `last_remote_modified`, `modified` + `id`, `user_id`, `url`, `login`, cast(des_decrypt(`pass`,`login`) as char(16)) as pass, `frequency`, `ctag`, + `last_remote_modified`, `modified`, `error_count` FROM `pb_cloud` - WHERE `next_poll` < NOW() ORDER BY `next_poll` + WHERE `next_poll` < NOW() AND `active`=1 ORDER BY `next_poll` LIMIT 1' ); if ( $vcr = $vcrc->fetchRow() ) { @@ -292,7 +319,7 @@ while ( true ) { } else { break; //the loop } - + // update next check immediately to avoid concurrent execs in timeout situations $hdm2text = array( 'h' => 'hour', @@ -306,16 +333,33 @@ while ( true ) { $next_poll = date_format(date_add( date_create(), DateInterval::createFromDateString("$freq $hdm2text[$period]" . "$more") ), "Y-m-d H:i:s"); - $DB->execute('UPDATE `pb_cloud` SET `next_poll`=\'' . $next_poll . '\' WHERE `id`=' . $vcr['id']); + $DB->execute('UPDATE `pb_cloud` SET `next_poll`=\'' . $next_poll . '\', `message`=\'Update in progress...\' WHERE `id`=' . $vcr['id']); + $unset_active=''; if ( gs_vcards_update( $vcr ) === true ) { // all went ok gs_log(GS_LOG_NOTICE, getmypid() .': Check vCards completed normal.', $CARDDAV_LOG, $FIFO ); + $CLOUD_MSG = 'OK - ' . $CLOUD_MSG; + $error_counter = ', `error_count`=0 '; } else { // any failure - gs_log(GS_LOG_WARNING, getmypid() .': Check vCards failed for '. $vcr['login'] . ': ' . $vcr['url'], $CARDDAV_LOG, $FIFO ); + $error_counter=', `error_count`=`error_count`+1 '; + $CLOUD_MSG = getmypid() . ': '; + if ( $vcr['error_count'] = 4 ) { + // deactivate record + $unset_active = ', `active`=0 '; + $CLOUD_MSG .= 'Set inactive. '; + }; + $CLOUD_MSG .= 'Check vCards failed for ' . $vcr['login'] . ': ' . $vcr['url'] . ', ' . $CLOUD_MSG; + gs_log(GS_LOG_WARNING, $CLOUD_MSG, $CARDDAV_LOG, $FIFO ); + // increment error counter } + // inform on user display + $DB->execute('UPDATE `pb_cloud` SET `message` = CONCAT_WS(\' \', ' . + '\'' . $CLOUD_MSG . '\',\', last check: \', `modified` ) ' . + $error_counter . $unset_active . + ' WHERE `id` = ' . $vcr['id']); } ?> From bef04fffb8db8ac993c843d82f17efcdf10e61de Mon Sep 17 00:00:00 2001 From: Markus Neubauer Date: Mon, 14 Dec 2015 15:53:31 +0100 Subject: [PATCH 33/87] Update pb_category.php --- opt/gemeinschaft/htdocs/gui/mod/pb_category.php | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/opt/gemeinschaft/htdocs/gui/mod/pb_category.php b/opt/gemeinschaft/htdocs/gui/mod/pb_category.php index 703f85f7b..9bd28e9de 100644 --- a/opt/gemeinschaft/htdocs/gui/mod/pb_category.php +++ b/opt/gemeinschaft/htdocs/gui/mod/pb_category.php @@ -189,7 +189,7 @@ function confirm_delete() { - @@ -206,7 +206,7 @@ function confirm_delete() { if ($r['id']==$edit_entry) { echo '', "\n"; echo '
> + >
'; - echo ''; + echo ''; echo ''; @@ -249,7 +249,7 @@ function confirm_delete() { if ($edit_entry < 1) { ?> - +
+

Hint: Categories are coming from the cloud and
+           must be changed within the cloud to really become active here.

From 0e347e04bcb1e36e55fc610e7976a26b725f84a1 Mon Sep 17 00:00:00 2001 From: Markus Neubauer Date: Mon, 14 Dec 2015 15:54:10 +0100 Subject: [PATCH 34/87] Update home_home.php --- opt/gemeinschaft/htdocs/gui/mod/home_home.php | 56 +++++++++++++++++++ 1 file changed, 56 insertions(+) diff --git a/opt/gemeinschaft/htdocs/gui/mod/home_home.php b/opt/gemeinschaft/htdocs/gui/mod/home_home.php index db74df080..75e0088f5 100644 --- a/opt/gemeinschaft/htdocs/gui/mod/home_home.php +++ b/opt/gemeinschaft/htdocs/gui/mod/home_home.php @@ -9,6 +9,8 @@ * Stefan Wintermeyer * Philipp Kempgen * Peter Kozak +* STD Markus Neubauer +* - added view for cloud books * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License @@ -297,6 +299,7 @@ ?> +
@@ -317,6 +320,59 @@
+ + + +
+ +
+ +
+ + execute( +'SELECT `url`, `login`, `message`, `active`, `error_count` +FROM + `pb_cloud` +WHERE + `user_id`='. (int)@$_SESSION['sudo_user']['info']['id'] . ' +ORDER BY `active`, `error_count` DESC +LIMIT 5' + ); + ?> + +
+    + +
+
+ ' ,"\n"; + echo '' ,"\n"; + $i=0; + while ($r = $rs->fetchRow()) { + echo '' ,"\n"; + echo '', htmlEnt($r['url']) ,', Status: '; + echo htmlEnt($r['message']) ,'' ,"\n"; + echo '' ,"\n"; + ++$i; + } + if ($i===0) { + echo '' ,"\n"; + echo '', __('keine') ,'' ,"\n"; + echo '' ,"\n"; + } + echo '' ,"\n"; + echo '' ,"\n"; + + ?> +
+ +
+
   From 8f955fc7affff0438cb2449fd8c83008465b0dd4 Mon Sep 17 00:00:00 2001 From: Markus Neubauer Date: Mon, 14 Dec 2015 15:54:47 +0100 Subject: [PATCH 35/87] Update pb_cloud.php --- opt/gemeinschaft/htdocs/gui/mod/pb_cloud.php | 98 +++++++++++++++----- 1 file changed, 74 insertions(+), 24 deletions(-) diff --git a/opt/gemeinschaft/htdocs/gui/mod/pb_cloud.php b/opt/gemeinschaft/htdocs/gui/mod/pb_cloud.php index 3a399bf5b..ee5df8e1a 100644 --- a/opt/gemeinschaft/htdocs/gui/mod/pb_cloud.php +++ b/opt/gemeinschaft/htdocs/gui/mod/pb_cloud.php @@ -67,10 +67,38 @@ function confirm_delete() { # delete entry $rs = $DB->execute( -'DELETE FROM `pb_cloud` -WHERE `id`='. $delete_entry .' AND `user_id`='. $user_id +'DELETE FROM `pb_cloud` ' . + ' WHERE `id`='. $delete_entry . + ' AND `user_id`='. $user_id ); - + $rs2 = $DB->execute( +'DELETE FROM `pb_cloud_card` ' . + ' WHERE `cloud_id`='. $delete_entry + ); + $rs2 = $DB->execute( +'DELETE p FROM `pb_prv` AS p ' . + ' LEFT JOIN `pb_cloud_card` AS c ' . + ' ON c.id = p.card_id ' . + ' WHERE p.user_id = ' . $user_id . + ' AND p.card_id != 0 ' . + ' AND c.id IS NULL' + ); + $rs2 = $DB->execute( +'DELETE p FROM `pb_prv_category` AS p ' . + ' LEFT JOIN `pb_cloud_card` AS c ' . + ' ON c.id = p.card_id' . + ' WHERE p.user_id = ' . $user_id . + ' AND p.card_id != 0 ' . + ' AND c.id IS NULL' + ); + $rs2 = $DB->execute( +'DELETE c FROM `pb_category` AS c ' . + ' LEFT JOIN `pb_prv_category` AS p ' . + ' ON c.id = p.cat_id ' . + ' WHERE c.user_id = ' . $user_id . + ' AND p.id IS NULL' + ); + } if ($save_url != '' && $save_login != '' && $save_pass != '') { @@ -89,17 +117,21 @@ function confirm_delete() { } if ($save_entry < 1) { - + $rs = $DB->execute( -'INSERT INTO `pb_cloud` (`id`, `user_id`, `url`, `login`, `pass`, `frequency`, `next_poll`) VALUES -(NULL, '. $user_id .', \''. $DB->escape($save_url) .'\', \''. $DB->escape($save_login) .'\', des_encrypt(\''. $save_pass .'\',\'' . $save_login. '\'), \''. $DB->escape($save_frequency) .'\', NOW())' +'INSERT INTO `pb_cloud` ' . + ' (`id`, `user_id`, `url`, `login`, `pass`, `frequency`, `next_poll`, `message`) ' . + ' VALUES' . + '(NULL, '. $user_id .', \''. $DB->escape($save_url) .'\', \''. $DB->escape($save_login) .'\', des_encrypt(\''. $save_pass .'\',\'' . $save_login. '\'), \''. $DB->escape($save_frequency) .'\', NOW(), \'Scheduled\')' ); } else { $rs = $DB->execute( -'UPDATE `pb_cloud` SET `url`=\''. $DB->escape($save_url) .'\', `login`=\''. $DB->escape($save_login) .'\', `pass`=des_encrypt(\''. $save_pass .'\',\'' . $save_login .'\'), `frequency`=\'' . $save_frequency . '\', `next_poll`=NOW() - WHERE `id`='. $save_entry .' AND `user_id`='. $user_id +'UPDATE `pb_cloud` ' . + ' SET `url`=\''. $DB->escape($save_url) .'\', `login`=\''. $DB->escape($save_login) .'\', `pass`=des_encrypt(\''. $save_pass .'\',\'' . $save_login .'\'), ' . + ' `frequency`=\'' . $save_frequency . '\', `next_poll`=NOW(), message=\'Scheduled\', last_remote_modified=\'2000-01-01 00:00:00\', active=1 ' . +' WHERE `id`='. $save_entry .' AND `user_id`='. $user_id ); } @@ -127,7 +159,7 @@ function confirm_delete() { $rs = $DB->execute( 'SELECT SQL_CALC_FOUND_ROWS '. - '`id`, `url`, `login`, cast(des_decrypt(`pass`,`login`) as char(16)) as pass, `frequency` '. + '`id`, `url`, `login`, cast(des_decrypt(`pass`,`login`) as char(16)) as pass, `frequency`, `message` '. 'FROM '. '`pb_cloud` '. 'WHERE '. @@ -154,7 +186,7 @@ function confirm_delete() { $rs = $DB->execute( 'SELECT SQL_CALC_FOUND_ROWS '. - '`id`, `url`, `login`, cast(des_decrypt(`pass`,`login`) as char(16)) as pass, `frequency` '. + '`id`, `url`, `login`, cast(des_decrypt(`pass`,`login`) as char(16)) as pass, `frequency`, `message` '. 'FROM '. '`pb_cloud` '. 'WHERE '. @@ -259,13 +291,13 @@ function confirm_delete() { [1] > - + - - + + - [2] + [2]   @@ -294,7 +326,7 @@ function confirm_delete() { echo '', "\n"; echo ''; - echo ''; + echo ''; echo '', "\n"; echo ''; @@ -328,6 +360,17 @@ function confirm_delete() { echo '', __('bearbeiten'), '   '; echo '', __('entfernen'), ''; echo ''; + if ( !empty($r['message']) ) { + echo ''; + echo ''; + echo '       ' . __('Status') . ': '; + if ( 'OK' != substr($r['message'], 0, 2) ) { + if ( 'Scheduled' == $r['message'] ) $bg = '#FFFF00 '; + else $bg = '#FF0000'; + echo '' . $r['message'] . ''; + } else echo $r['message']; + echo ''; + } } @@ -369,21 +412,28 @@ function confirm_delete() { -
-

Hint: vCards automatically will be fetched on new entry or record changes, besides schedule.

-

[1] URL: Enter the full vCard URL including scheme from your provider. Naiv examples:

+
+
Hints:
+
vCards are imported into your private phone book.
+
Updating vCards is based on changes within the cloud - the cloud always wins.
+
Matching local entries with an equal vCard entry will be removed to avoid dulicates.
+
The next update should be done within ¾ hour.
+
To refresh all vCards of a cloud entry locally, you will need to delete and recreate an entry.
+
+

[1] vCard URL: Any valid URL from your cloud provider, starting with scheme (http/https)://.
+Naiv Examples:

ownCloud
https://example.com/remote.php/carddav/addressbooks/{resource|principal|username}/{collection}/
-
memotoo
https://sync.memotoo.com/cardDAV/
SabreDAV
https://example.com/addressbooks/{resource|principal|username}/{collection}/
radicale
https://example.com/radicale/{resource|principal|username}/{collection}/
SOGo
https://example.com/SOGo/dav/{resource|principal|username}/Contacts/{collection}/
DAViCal
https://example.com/{resource|principal|username}/{collection}/
-
Apple Addressbook Server
https://example.com/addressbooks/users/{resource|principal|username}/{collection}/
+
Apple Adrbook Server
https://example.com/addressbooks/users/{resource|principal|username}/{collection}/
-
-

[2] Schedule: Defaults to '1d', the first/next update will happen within half an hour.
+

+

[2] Schedule: Defaults to '1d', also see hints before.
      Where h=hour, d=day, m=month (Max. 2 digits plus 1 char, no blank/minutes allowed).
-       Example: 12h =~ refresh every 12 hours (~ also during night), starting with now (save time).
-       You can trigger a refresh using edit and save with no other changes.

+       Example: 12h =~ refresh every 12 hours (~ also during night), starting with the saved time.
+       You can simply trigger a refresh using edit and save with no other changes.

+

From 923515dd50fd02213b29b2de08fa2cbf872fa2cc Mon Sep 17 00:00:00 2001 From: Markus Neubauer Date: Mon, 14 Dec 2015 15:55:26 +0100 Subject: [PATCH 36/87] Update pb_private.php --- .../htdocs/gui/mod/pb_private.php | 127 ++++++++++-------- 1 file changed, 73 insertions(+), 54 deletions(-) diff --git a/opt/gemeinschaft/htdocs/gui/mod/pb_private.php b/opt/gemeinschaft/htdocs/gui/mod/pb_private.php index 1ebf54435..5100b7284 100644 --- a/opt/gemeinschaft/htdocs/gui/mod/pb_private.php +++ b/opt/gemeinschaft/htdocs/gui/mod/pb_private.php @@ -57,6 +57,7 @@ function confirm_delete() { $name = trim(@$_REQUEST['name' ]); $number = trim(@$_REQUEST['number' ]); $ptype = trim(@$_REQUEST['ptype' ]); +$catid = trim(@$_REQUEST['catid' ]); $save_lname = trim(@$_REQUEST['slname' ]); $save_fname = trim(@$_REQUEST['sfname' ]); $save_number = trim(@$_REQUEST['snumber']); @@ -101,68 +102,72 @@ function confirm_delete() { $save_ptype = ''; } +if ( empty($catid) && isset($SESSION['catid']) ) $catid=(int)@$SESSION['catid']; +elseif ( empty($catid) ) $catid=0; + +$sel = ( $catid == 0 ) ? ' selected="selected"' : ''; +$ac = array(''); + +$cs = $DB->execute( + 'SELECT `c`.`id`, `c`.`category` '. + 'FROM `pb_category` `c` '. + 'LEFT JOIN `pb_prv_category` `p` ON `c`.`id` = `p`.`cat_id` ' . + 'WHERE '. + '`p`.`id` IS NOT NULL AND ' . + '`c`.`user_id`='. $DB->escape($user_id).' '. + 'GROUP BY `c`.`category` '. + 'ORDER BY `c`.`category`' + ); +while ( $r = $cs->fetchRow() ) { + $sel = ($catid == @$r['id']) ? ' selected="selected"' : ''; + $ac[] = ''; +} - - +$query = 'SELECT SQL_CALC_FOUND_ROWS '. + '`p`.`id`, `p`.`lastname`, `p`.`firstname`, `p`.`number` , `p`.`ptype`, `p`.`card_id`'. + ' FROM `pb_prv` `p`'; +$where = ' WHERE `p`.`user_id`='. $user_id; if ($number != '') { - + # search by number - + $name = ''; $search_url = 'number='. urlEncode($number); - $number_sql = str_replace( array( '*', '?' ), array( '%', '_' ), $number ) .'%'; - - $rs = $DB->execute( - 'SELECT SQL_CALC_FOUND_ROWS '. - '`id`, `lastname`, `firstname`, `number` , `ptype`, `card_id` '. - 'FROM '. - '`pb_prv` '. - 'WHERE '. - '`number` LIKE \''. $DB->escape($number_sql) .'\' '. - 'AND '. - '`user_id`='. $user_id .' '. - 'ORDER BY `lastname`, `firstname`, `pref`, `ptype` '. - 'LIMIT '. ($page*(int)$per_page) .','. (int)$per_page - ); - $num_total = @$DB->numFoundRows(); - $num_pages = ceil($num_total / $per_page); - + $where .= ' AND `p`.`number` LIKE \''. $DB->escape($number_sql) .'\' '; + } else { - + # search by name - $number = ''; $search_url = 'name='. urlEncode($name); - $name_sql = str_replace( array( '*', '?' ), array( '%', '_' ), $name ) .'%'; - - $rs = $DB->execute( - 'SELECT SQL_CALC_FOUND_ROWS '. - '`id`, `lastname`, `firstname`, `number`, `ptype`, `card_id` '. - 'FROM '. - '`pb_prv` '. - 'WHERE '. - '( `lastname` LIKE _utf8\''. $DB->escape($name_sql) .'\' COLLATE utf8_unicode_ci OR '. - ' `firstname` LIKE _utf8\''. $DB->escape($name_sql) .'\' COLLATE utf8_unicode_ci ) '. - 'AND '. - '`user_id`='. $DB->escape($user_id).' '. - 'ORDER BY `lastname`, `firstname`, `pref`, `ptype` '. - 'LIMIT '. ($page*(int)$per_page) .','. (int)$per_page - ); - $num_total = @$DB->numFoundRows(); - $num_pages = ceil($num_total / $per_page); - + $where .= ' AND ( `p`.`lastname` LIKE _utf8\''. $DB->escape($name_sql) .'\' COLLATE utf8_unicode_ci OR '. + ' `p`.`firstname` LIKE _utf8\''. $DB->escape($name_sql) .'\' COLLATE utf8_unicode_ci ) '; } +if ( $catid != 0 ) { + $search_url .= '&catid='. $catid; + $query .= ' LEFT JOIN `pb_prv_category` `pc` ON `p`.`id` = `pc`.`prv_id` '; + $where .= ' AND `pc`.`cat_id` = ' . $catid; +} +$SESSION['catid']=$catid; + +$order = ' ORDER BY `p`.`lastname`, `p`.`firstname`, `p`.`pref`, `p`.`ptype` '; +$limit = ' LIMIT '. ($page*(int)$per_page) .','. (int)$per_page; + +$rs = $DB->execute( $query . $where . $order . $limit); + +$num_total = @$DB->numFoundRows(); +$num_pages = ceil($num_total / $per_page); ?> @@ -170,8 +175,9 @@ function confirm_delete() { - - + + [1] + @@ -195,6 +201,19 @@ function confirm_delete() { + + '; + echo gs_form_hidden($SECTION, $MODULE); + echo ''; + } else echo ' '; + ?> + ', "\n"; echo '', "\n"; echo '', "\n"; +echo '', "\n"; ?> @@ -253,15 +273,13 @@ function confirm_delete() { - - - + @@ -285,7 +303,7 @@ function confirm_delete() { echo '', "\n"; echo '', "\n"; echo ''; } @@ -346,7 +364,7 @@ function confirm_delete() { '; @@ -339,8 +342,8 @@ function confirm_delete() { (@$_SESSION['sudo_user']['name'] == @$_SESSION['real_user']['name']) ? '' : ('&sudo='. @$_SESSION['sudo_user']['name']); echo '', __('wählen'), '   '; - echo '', __('bearbeiten'), '   '; - echo '', __('entfernen'), ''; + echo '', __('bearbeiten'), '   '; + echo '', __('entfernen'), ''; if ( $r['card_id'] ) echo ' [1]'; echo ''; From 9aab0e4d38f79270203c5972e9e3d96c5db23288 Mon Sep 17 00:00:00 2001 From: Markus Neubauer Date: Sat, 19 Dec 2015 12:52:01 +0100 Subject: [PATCH 53/87] enable sip numbers --- opt/gemeinschaft/sbin/gs-carddav-reader-to-db | 17 ++++++++++++----- 1 file changed, 12 insertions(+), 5 deletions(-) diff --git a/opt/gemeinschaft/sbin/gs-carddav-reader-to-db b/opt/gemeinschaft/sbin/gs-carddav-reader-to-db index 44f9ea1ce..2103fd7c7 100644 --- a/opt/gemeinschaft/sbin/gs-carddav-reader-to-db +++ b/opt/gemeinschaft/sbin/gs-carddav-reader-to-db @@ -120,13 +120,19 @@ function gs_vcard_update( $vcr, $head, $vcard, $lvc=array() ) { if ( empty( $ln) ) { $ln = $fn; $fn=''; } elseif ( 'TEL' == $key ) { - if ( '+' == substr($elem, 0, 1) ) - $elem = GS_CANONIZE_INTL_PREFIX . substr($elem, 1); - $number = preg_replace('/\D/', '', $elem); + // do not canonize on sip strings + if ( strpos($elem, '@') === false ) { - if ( GS_CANONIZE_INTL_PREFIX . GS_CANONIZE_COUNTRY_CODE == substr($number, 0, strlen(GS_CANONIZE_INTL_PREFIX . GS_CANONIZE_COUNTRY_CODE) ) ) - $number = GS_CANONIZE_NATL_PREFIX . substr($number, strlen(GS_CANONIZE_INTL_PREFIX . GS_CANONIZE_COUNTRY_CODE)); + if ( '+' == substr($elem, 0, 1) ) + $elem = GS_CANONIZE_INTL_PREFIX . substr($elem, 1); + + $number = preg_replace('/\D/', '', $elem); + + if ( GS_CANONIZE_INTL_PREFIX . GS_CANONIZE_COUNTRY_CODE == substr($number, 0, strlen(GS_CANONIZE_INTL_PREFIX . GS_CANONIZE_COUNTRY_CODE) ) ) + $number = GS_CANONIZE_NATL_PREFIX . substr($number, strlen(GS_CANONIZE_INTL_PREFIX . GS_CANONIZE_COUNTRY_CODE)); + } + else $number = $elem; // add number to array, making it singular $n[$number] = array( 'type' => '', 'pref' => 99 ); @@ -136,6 +142,7 @@ function gs_vcard_update( $vcr, $head, $vcard, $lvc=array() ) { if ( empty($param) ) continue; $k2 = explode('=', strtoupper( $param )); if ( 'TYPE' == $k2[0] ) { + if ( $k2[1] == 'MAIN' ) $n[$number]['pref'] = 1; if ( $k2[1] == 'PREF' ) $n[$number]['pref'] = 1; else $n[$number]['type'] .= strtolower( $k2[1] ) . ','; } From 5aa5b953d004c7fda82ac3b95ba47025699a333c Mon Sep 17 00:00:00 2001 From: Markus Neubauer Date: Sat, 19 Dec 2015 14:30:04 +0100 Subject: [PATCH 54/87] clean up code --- opt/gemeinschaft/sbin/gs-carddav-reader-to-db | 24 ++++++++++--------- 1 file changed, 13 insertions(+), 11 deletions(-) diff --git a/opt/gemeinschaft/sbin/gs-carddav-reader-to-db b/opt/gemeinschaft/sbin/gs-carddav-reader-to-db index 2103fd7c7..96defe999 100644 --- a/opt/gemeinschaft/sbin/gs-carddav-reader-to-db +++ b/opt/gemeinschaft/sbin/gs-carddav-reader-to-db @@ -89,7 +89,7 @@ function gs_vcard_update( $vcr, $head, $vcard, $lvc=array() ) { $lvc = $DB->execute( 'SELECT `id`,`cloud_id`,`vcard_id`,`etag`,`last_modified`' . ' FROM `pb_cloud_card` ' . ' WHERE `cloud_id`=' . $vcr['id'] . - ' and `vcard_id`=\'' . $head['vcard_id'] . '\'' + ' and `vcard_id`=\'' . $head['vcard_id'] . '\' LIMIT 1' )->fetchRow(); } @@ -103,12 +103,16 @@ function gs_vcard_update( $vcr, $head, $vcard, $lvc=array() ) { foreach ( $tmp_vcard as $value ) { if ( empty( $value ) ) continue; + // we need only name, category and tel type records for the phone book + if ( 'N' != $key && 'TEL' != $key && 'CATEGORIES' != $key ) continue; + $pos = strpos($value, ':'); $elem = trim(substr($value, $pos + 1 )); $aparam = explode(';', substr($value, 0, $pos)); $key = strtoupper( array_shift( $aparam ) ); if ( 'N' == $key ) { + // reverse the array N for the phones display $aname = explode(';', $elem); $ln = array_shift( $aname ); for ($i = count($aname); $i >= 0; $i--) { @@ -116,8 +120,8 @@ function gs_vcard_update( $vcr, $head, $vcard, $lvc=array() ) { $fn .= ' ' . $aname[$i]; } $fn = ltrim( $fn ); + if ( empty( $ln) ) { $ln = $fn; $fn=''; } } - if ( empty( $ln) ) { $ln = $fn; $fn=''; } elseif ( 'TEL' == $key ) { @@ -135,7 +139,7 @@ function gs_vcard_update( $vcr, $head, $vcard, $lvc=array() ) { else $number = $elem; // add number to array, making it singular - $n[$number] = array( 'type' => '', 'pref' => 99 ); + if ( ! isset($n[$number]) ) $n[$number] = array( 'type' => '', 'pref' => 99 ); // add attributes to the number foreach ( $aparam as $param ) { @@ -150,7 +154,6 @@ function gs_vcard_update( $vcr, $head, $vcard, $lvc=array() ) { } $n[$number]['type'] = rtrim($n[$number]['type'], ','); } - elseif ( 'CATEGORIES' == $key ) $acat = explode( ',', $elem ); } @@ -158,7 +161,7 @@ function gs_vcard_update( $vcr, $head, $vcard, $lvc=array() ) { foreach ( $n as $number => $param ) { // check_duplicates from within a vcard - if ( $prc = $DB->execute('SELECT `id` FROM `pb_prv` WHERE `user_id`=' . $vcr['user_id'] . ' and `firstname`=\'' . $fn . '\' and `lastname`=\'' . $ln . '\' and `number`=\'' . $number . '\' and `card_id`=0')->fetchRow() ) + if ( $prc = $DB->execute('SELECT `id` FROM `pb_prv` WHERE `user_id`=' . $vcr['user_id'] . ' and `firstname`=\'' . $fn . '\' and `lastname`=\'' . $ln . '\' and `number`=\'' . $number . '\' and `card_id`=0 LIMIT 1')->fetchRow() ) $DB->execute('DELETE FROM `pb_prv` WHERE `id`=' . $prc['id']); // add a phone record @@ -168,7 +171,7 @@ function gs_vcard_update( $vcr, $head, $vcard, $lvc=array() ) { // loop over categories if ( ! empty( $acat) ) { - $prc = $DB->execute( 'SELECT `id` FROM `pb_prv` WHERE `user_id`=' . $vcr['user_id'] . ' and `firstname`=\'' . $fn . '\' and `lastname`=\'' . $ln . '\' and `number`=\'' . $number . '\' and `ptype`=\'' . $param['type'] . '\' and `card_id`=' . $lvc['id'])->fetchRow(); + $prc = $DB->execute( 'SELECT `id` FROM `pb_prv` WHERE `user_id`=' . $vcr['user_id'] . ' and `firstname`=\'' . $fn . '\' and `lastname`=\'' . $ln . '\' and `number`=\'' . $number . '\' and `ptype`=\'' . $param['type'] . '\' and `card_id`=' . $lvc['id'] . ' LIMIT 1')->fetchRow(); foreach ( $acat as $cat ) { if ( empty($cat) ) continue; if ( ! $crc = $DB->execute( 'SELECT `id` FROM `pb_category` WHERE `user_id`=' . $vcr['user_id'] . ' and `category`=\'' . $cat . '\'')->fetchRow() ) { @@ -176,13 +179,13 @@ function gs_vcard_update( $vcr, $head, $vcard, $lvc=array() ) { $DB->execute('INSERT INTO `pb_category` ' . ' (`user_id`,`category`) ' . ' VALUES(' . $vcr['user_id'] .',\'' . $cat .'\')'); - $crc = $DB->execute( 'SELECT `id` FROM `pb_category` WHERE `user_id`=' . $vcr['user_id'] . ' and `category`=\'' . $cat . '\'')->fetchRow(); + $crc = $DB->execute( 'SELECT `id` FROM `pb_category` WHERE `user_id`=' . $vcr['user_id'] . ' and `category`=\'' . $cat . '\' LIMIT 1')->fetchRow(); } // correct xref $DB->execute('INSERT INTO `pb_prv_category` ' . ' (`user_id`,`cat_id`,`card_id`,`prv_id`) ' . ' VALUES(' . $vcr['user_id'] .',' . $crc['id'] .',' . $lvc['id'] .',' . $prc['id'] . ')'); - } + } } } @@ -326,9 +329,8 @@ while ( true ) { $urc = $usrc->fetchRow(); $sudo_user = $urc['user']; gs_log(GS_LOG_NOTICE, getmypid() .': Check vCards for ' . $sudo_user . ': '. $vcr['login'] . ': ' . $vcr['url'], $CARDDAV_LOG, $FIFO ); - } else { - break; //the loop - } + + } else break; //the loop // update next check immediately to avoid concurrent execs in timeout situations $hdm2text = array( From 17fb1eaa4571cca00d1b9f4047cdb84428d41b81 Mon Sep 17 00:00:00 2001 From: Markus Neubauer Date: Sat, 19 Dec 2015 19:02:23 +0100 Subject: [PATCH 55/87] add public cloud book functionality --- misc/scripts/upgrade-pb-3.2-3.3.sql | 3 +++ 1 file changed, 3 insertions(+) diff --git a/misc/scripts/upgrade-pb-3.2-3.3.sql b/misc/scripts/upgrade-pb-3.2-3.3.sql index f432ed23a..25c2d300c 100644 --- a/misc/scripts/upgrade-pb-3.2-3.3.sql +++ b/misc/scripts/upgrade-pb-3.2-3.3.sql @@ -41,6 +41,7 @@ CREATE TABLE IF NOT EXISTS `pb_cloud` ( `message` tinytext COLLATE utf8_unicode_ci NOT NULL, `error_count` tinyint(1) unsigned NOT NULL DEFAULT '0', `active` tinyint(1) unsigned NOT NULL DEFAULT '1', + `public` tinyint(1) NOT NULL DEFAULT '0', PRIMARY KEY (`id`), UNIQUE KEY `uid_url_login` (`user_id`,`url`(255),`login`), KEY `next_poll` (`next_poll`), @@ -107,3 +108,5 @@ ALTER TABLE `pb_prv_category` ADD FOREIGN KEY ( `prv_id` ) // set new modules active INSERT INTO `group_members` (`group`, `member`) VALUES (6, 3005) ON DUPLICATE KEY UPDATE `member` = 3005; +// needed dependency for public cloud entries +INSERT OR REPLACE INTO `users` VALUES ('1', 'public-abook', '', '', '', '', '', '1', '1', NULL, '', NULL, NULL, NULL, '0'); From df60c5c828d1a41d99ef66bc03406617a1dc0406 Mon Sep 17 00:00:00 2001 From: Markus Neubauer Date: Sat, 19 Dec 2015 19:16:20 +0100 Subject: [PATCH 56/87] Update upgrade-pb-3.2-3.3.sql --- misc/scripts/upgrade-pb-3.2-3.3.sql | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/misc/scripts/upgrade-pb-3.2-3.3.sql b/misc/scripts/upgrade-pb-3.2-3.3.sql index 25c2d300c..2a0fe8cf8 100644 --- a/misc/scripts/upgrade-pb-3.2-3.3.sql +++ b/misc/scripts/upgrade-pb-3.2-3.3.sql @@ -107,6 +107,6 @@ ALTER TABLE `pb_prv_category` ADD FOREIGN KEY ( `prv_id` ) REFERENCES `pb_prv` (`id`) ON DELETE CASCADE ON UPDATE CASCADE ; // set new modules active -INSERT INTO `group_members` (`group`, `member`) VALUES (6, 3005) ON DUPLICATE KEY UPDATE `member` = 3005; +INSERT INTO `group_members` VALUES (6, 3005); // needed dependency for public cloud entries -INSERT OR REPLACE INTO `users` VALUES ('1', 'public-abook', '', '', '', '', '', '1', '1', NULL, '', NULL, NULL, NULL, '0'); +INSERT INTO `users` VALUES ('1', 'public-abook', '', '', '', '', '', '1', '1', NULL, '', NULL, NULL, NULL, ''); From 01b02a72fb04c18b4305fba9a3abea8cb54152f8 Mon Sep 17 00:00:00 2001 From: Markus Neubauer Date: Sat, 19 Dec 2015 19:16:29 +0100 Subject: [PATCH 57/87] Update asterisk.sql --- usr/share/doc/gemeinschaft/asterisk.sql | 21 ++++++++++++++++++++- 1 file changed, 20 insertions(+), 1 deletion(-) diff --git a/usr/share/doc/gemeinschaft/asterisk.sql b/usr/share/doc/gemeinschaft/asterisk.sql index 20347fcf8..beb337b92 100644 --- a/usr/share/doc/gemeinschaft/asterisk.sql +++ b/usr/share/doc/gemeinschaft/asterisk.sql @@ -6181,7 +6181,6 @@ INSERT INTO `group_members` VALUES (6,3002); INSERT INTO `group_members` VALUES (6,3003); INSERT INTO `group_members` VALUES (6,3004); INSERT INTO `group_members` VALUES (6,3005); -INSERT INTO `group_members` VALUES (6,3006); INSERT INTO `group_members` VALUES (6,4000); INSERT INTO `group_members` VALUES (6,4001); INSERT INTO `group_members` VALUES (6,4002); @@ -6705,12 +6704,16 @@ CREATE TABLE IF NOT EXISTS `pb_cloud` ( `message` tinytext COLLATE utf8_unicode_ci NOT NULL, `error_count` tinyint(1) unsigned NOT NULL DEFAULT '0', `active` tinyint(1) unsigned NOT NULL DEFAULT '1', + `public` tinyint(1) NOT NULL DEFAULT '0', PRIMARY KEY (`id`), UNIQUE KEY `uid_url_login` (`user_id`,`url`(255),`login`), KEY `next_poll` (`next_poll`), KEY `uid_login_url` (`user_id`,`login`,`url`(255)) ) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci; +ALTER TABLE `pb_cloud` ADD FOREIGN KEY ( `user_id` ) + REFERENCES `users` (`id`) ON DELETE RESTRICT ON UPDATE RESTRICT ; + -- -- Tabellenstruktur für Tabelle `pb_cloud_card` -- @@ -6777,6 +6780,21 @@ CREATE TABLE IF NOT EXISTS `pb_prv_category` ( KEY `cat_id` (`cat_id`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci; +ALTER TABLE `pb_cloud_card` ADD FOREIGN KEY ( `cloud_id` ) + REFERENCES `pb_cloud` (`id`) ON DELETE CASCADE ON UPDATE CASCADE ; +ALTER TABLE `pb_prv` ADD FOREIGN KEY ( `card_id` ) + REFERENCES `pb_cloud_card` (`id`) ON DELETE CASCADE ON UPDATE CASCADE ; +ALTER TABLE `pb_category` ADD FOREIGN KEY ( `user_id` ) + REFERENCES `users` (`id`) ON DELETE CASCADE ON UPDATE CASCADE ; +ALTER TABLE `pb_prv_category` ADD FOREIGN KEY ( `user_id` ) + REFERENCES `users` (`id`) ON DELETE CASCADE ON UPDATE CASCADE ; +ALTER TABLE `pb_prv_category` ADD FOREIGN KEY ( `cat_id` ) + REFERENCES `pb_category` (`id`) ON DELETE CASCADE ON UPDATE CASCADE ; +ALTER TABLE `pb_prv_category` ADD FOREIGN KEY ( `card_id` ) + REFERENCES `pb_cloud_card` (`id`) ON DELETE CASCADE ON UPDATE CASCADE ; +ALTER TABLE `pb_prv_category` ADD FOREIGN KEY ( `prv_id` ) + REFERENCES `pb_prv` (`id`) ON DELETE CASCADE ON UPDATE CASCADE ; + -- -- Table structure for table `penalties` -- @@ -7526,6 +7544,7 @@ CREATE TABLE `users` ( LOCK TABLES `users` WRITE; /*!40000 ALTER TABLE `users` DISABLE KEYS */; +INSERT INTO `users` VALUES ('1', 'public-abook', '', '', '', '', '', '1', '1', NULL, '', NULL, NULL, NULL, '') INSERT INTO `users` VALUES (5,'nobody-00001','','','','','',1,1,NULL,'',NULL,NULL,NULL,''); INSERT INTO `users` VALUES (6,'nobody-00002','','','','','',2,1,NULL,'',NULL,NULL,NULL,''); INSERT INTO `users` VALUES (7,'nobody-00003','','','','','',3,1,NULL,'',NULL,NULL,NULL,''); From ca678e27984960523d5801aed4599fc42b9d7507 Mon Sep 17 00:00:00 2001 From: Markus Neubauer Date: Sat, 19 Dec 2015 20:02:47 +0100 Subject: [PATCH 58/87] Update in-get-callername.agi --- opt/gemeinschaft/dialplan-scripts/in-get-callername.agi | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/opt/gemeinschaft/dialplan-scripts/in-get-callername.agi b/opt/gemeinschaft/dialplan-scripts/in-get-callername.agi index d9b053615..2d9c272a8 100755 --- a/opt/gemeinschaft/dialplan-scripts/in-get-callername.agi +++ b/opt/gemeinschaft/dialplan-scripts/in-get-callername.agi @@ -37,7 +37,7 @@ ob_implicit_flush(1); function search_number ( $user_id, $source, $cid , $db ) { if ($source == 'private') - $query = 'SELECT `firstname`, `lastname`, `number`, `ptype` FROM `pb_prv` WHERE `user_id`=' . $user_id . ' AND `number`= \'' . $db->escape($cid) . '\''; + $query = 'SELECT `firstname`, `lastname`, `number`, `ptype` FROM `pb_prv` WHERE ( `user_id`=' . $user_id . ' OR `user_id`=1 ) AND `number`= \'' . $db->escape($cid) . '\''; else if ($source == 'public') $query = 'SELECT `firstname`, `lastname`, `number` FROM `pb_ldap` WHERE `number`=\''. $db->escape($cid) . '\''; From 97c414f1862d67fad835195c8ae332bd7b82522d Mon Sep 17 00:00:00 2001 From: Markus Neubauer Date: Sat, 19 Dec 2015 20:03:45 +0100 Subject: [PATCH 59/87] Update datenbank-tabellen.xml --- .../doc/de/docbook/datenbank-tabellen.xml | 304 ++++++++++-------- 1 file changed, 168 insertions(+), 136 deletions(-) diff --git a/opt/gemeinschaft/doc/de/docbook/datenbank-tabellen.xml b/opt/gemeinschaft/doc/de/docbook/datenbank-tabellen.xml index ca98ff48c..338baa823 100644 --- a/opt/gemeinschaft/doc/de/docbook/datenbank-tabellen.xml +++ b/opt/gemeinschaft/doc/de/docbook/datenbank-tabellen.xml @@ -17,19 +17,19 @@ Tabellenstruktur eingespielt wird, ist in beschrieben. - Die Datei asterisk.sql enth�lt hier alle zum - Erzeugen der Tabellen n�tigen SQL-Befehle. Einige Eintr�ge (z.B. IP-Adressen - etc.) m�ssen noch an die Installation angepa�t werden. + Die Datei asterisk.sql enthält hier alle zum + Erzeugen der Tabellen nötigen SQL-Befehle. Einige Einträge (z.B. IP-Adressen + etc.) müssen noch an die Installation angepaßt werden.
Datenbank-Struktur In der Datenbank asterisk werden zentral - Laufzeitkonfiguration und Logeintr�ge vorgehalten. Auf alle Tabellen, die + Laufzeitkonfiguration und Logeinträge vorgehalten. Auf alle Tabellen, die mit ast_ beginnen, wird direkt aus Asterisk zugegriffen, wodurch auch die Struktur und Spaltennamen vorgegeben sind. - Zus�tzliche Spalten, die f�r Asterisk keine Bedeutung haben, sind in - diesen Tabellen mit einem f�hrenden Unterstrich (_) + Zusätzliche Spalten, die für Asterisk keine Bedeutung haben, sind in + diesen Tabellen mit einem führenden Unterstrich (_) benannt.
@@ -37,7 +37,7 @@ Tabellenstruktur der Datenbank <quote>asterisk</quote> Die Tabellen der Datenbank werden hier alphabetisch - aufgef�hrt. + aufgeführt.
<literal>ast_cdr</literal> @@ -48,9 +48,9 @@ Konfigurationen dazu werden auf den Asterisk-Servern in der /opt/gemeinschaft/etc/asterisk/cdr_mysql.conf vorgenommen. Im Gegensatz zur Tabelle dial_log wird - diese Tabelle zur Auswertung von Gesp�chsdaten verwendet (z.B. + diese Tabelle zur Auswertung von Gespächsdaten verwendet (z.B. Statistik). Die Tabelle dial_log dient hingegen nur - der Anzeige f�r den Benutzer und wird von AGI-Skripten erstellt. + der Anzeige für den Benutzer und wird von AGI-Skripten erstellt. @@ -83,8 +83,8 @@ dst - Zuletzt f�r den Anruf im Dialplan ausgef�hrte - Ziel-Extension; Achtung: kann auch h (f�r + Zuletzt für den Anruf im Dialplan ausgeführte + Ziel-Extension; Achtung: kann auch h (für Hangup-Extension) sein! @@ -120,7 +120,7 @@ lastapp - Letzte ausgef�hrte Applikation im Dialplan, z.B.: + Letzte ausgeführte Applikation im Dialplan, z.B.: NoOp @@ -129,7 +129,7 @@ lastdata - Die dieser Applikation (s.o.) �bergebenen Argumente, z.B.: + Die dieser Applikation (s.o.) übergebenen Argumente, z.B.: Finish if-to-internal-users-self-79 @@ -147,7 +147,7 @@ billsec - Dauer des Gespr�chs in Sekunden, also ohne Klingeln o.�. + Dauer des Gesprächs in Sekunden, also ohne Klingeln o.ä. (die ggf. in Rechnung zu stellende Zeit), z.B.: 29 @@ -190,7 +190,7 @@ Fehlgeschlagen. - Unbekannte Rufnummer, Stau, - o.�. + o.ä. @@ -198,8 +198,8 @@ UNKNOWN - Unbekannt. - Keine Information �ber den Erfolg - verf�gbar. + Unbekannt. - Keine Information über den Erfolg + verfügbar. @@ -304,7 +304,7 @@ penalty - Legt die Priorit�t fest, nach der die Mitglieder einer + Legt die Priorität fest, nach der die Mitglieder einer Warteschlange (Agenten) angerufen werden. @@ -346,7 +346,7 @@ musicclass - Die Art der Wartemusik kann hiermit f�r die einzelne + Die Art der Wartemusik kann hiermit für die einzelne Warteschlange (z.B. nach Musikrichtung) definiert werden. @@ -366,7 +366,7 @@ Legt einen optionalen Kontext fest. Ein Anrufer wird durch - Dr�cken einer einzigen Ziffer zu der entsprechenden Extension in + Drücken einer einzigen Ziffer zu der entsprechenden Extension in diesem Kontext weitergeleitet. @@ -385,7 +385,7 @@ Legt fest, ob ein Agent automatisch auf "Pause" gesetzt - wird, wenn er einen Anruf nicht beantwortet. M�gliche Werte: + wird, wenn er einen Anruf nicht beantwortet. Mögliche Werte: yes|no @@ -396,7 +396,7 @@ Legt fest, ob das Interface des Mitglieds der Warteschlange, welches mit dem Anrufer verbunden wird, in der Variable - "MEMBERINTERFACE" gespeichert wird. M�gliche Werte: + "MEMBERINTERFACE" gespeichert wird. Mögliche Werte: yes|no @@ -405,9 +405,9 @@ monitor_join - Legt fest, ob bei einem Gespr�chsmitschnitt die Audiodateien + Legt fest, ob bei einem Gesprächsmitschnitt die Audiodateien der eIngehenden und der ausgehenden Richtung zu einer einzigen - Datei zusammengemischt werden. M�gliche Werte: + Datei zusammengemischt werden. Mögliche Werte: yes|no @@ -416,7 +416,7 @@ monitor_format - Legt fest ob und in welchem Audioformat Gespr�chsmitschnitte + Legt fest ob und in welchem Audioformat Gesprächsmitschnitte gespeichert werden sollen. @@ -424,7 +424,7 @@ NULL - Keine Aufzeichnung der Sprachkan�le wird durchgef�hrt, + Keine Aufzeichnung der Sprachkanäle wird durchgeführt, wenn kein Format definiert wurde. @@ -483,8 +483,8 @@ Sekunden, auf welche die Ansage der Wartezeit abgerundet - oder aufgerundet werden soll, um nicht unn�tige Pr�zision - vorzut�uschen. Sinnvolle Werte: 0 (keine Ansage + oder aufgerundet werden soll, um nicht unnötige Präzision + vorzutäuschen. Sinnvolle Werte: 0 (keine Ansage der Sekunden), 1, 5, 10, 15, 30. @@ -542,7 +542,7 @@ Zeit in Sekunden, die ein Mitglied der Warteschlange nicht - angerufen wird, nachdem er ein vorhergehendes Gespr�ch beendet + angerufen wird, nachdem er ein vorhergehendes Gespräch beendet hat. @@ -552,7 +552,7 @@ Maximale Anzahl der Anrufer, die in der Warteschlange - gehalten werden d�rfen. Der Wert 0 steht f�r + gehalten werden dürfen. Der Wert 0 steht für eine unbegrenzte Anzahl. @@ -600,8 +600,8 @@ Das Mitglied der Warteschlange wird angeklingelt, - dessen letztes Telefonat zeitlich am l�ngsten - zur�ckliegt. + dessen letztes Telefonat zeitlich am längsten + zurückliegt. @@ -618,7 +618,7 @@ random - Ein zuf�llig ausgew�hltes Mitglied der Warteschlange + Ein zufällig ausgewähltes Mitglied der Warteschlange wird angeklingelt. @@ -629,7 +629,7 @@ Alle Mitglieder der Warteschlange werden nacheinander angeklingelt, jedoch wird die Anfangsposition aus einem - vorhergehenden Durchlauf ber�cksichtigt. + vorhergehenden Durchlauf berücksichtigt. @@ -641,14 +641,14 @@ Legt fest ob Anrufer in eine Warteschlange aufgenommen - werden, die keine Mitglieder enth�lt. + werden, die keine Mitglieder enthält. yes - Anrufer k�nnen in die Warteschlange aufgenommen + Anrufer können in die Warteschlange aufgenommen werden, auch wenn diese keine Mitglieder definiert hat. @@ -658,8 +658,8 @@ no - Anrufer k�nnen nur in die Warteschlange aufgenommen - werden, mindestens ein Mitglied verf�gbar ist. + Anrufer können nur in die Warteschlange aufgenommen + werden, mindestens ein Mitglied verfügbar ist. @@ -667,8 +667,8 @@ strict - Anrufer k�nnen nur in die Warteschlange aufgenommen - werden, wenn mindestens ein Mitglied definiert ist, mu� aber + Anrufer können nur in die Warteschlange aufgenommen + werden, wenn mindestens ein Mitglied definiert ist, muß aber zu diesem Zeitpunkt nicht unbedingt eingeloggt sein. @@ -720,7 +720,7 @@ Legt fest, ob QueueMemberStatus-Events im Manager-Interface - erzeugt werden. M�gliche Werte: + erzeugt werden. Mögliche Werte: yes|no @@ -729,10 +729,10 @@ eventwhencalled - Legt fest, ob u.a. die folgenden Events f�r das + Legt fest, ob u.a. die folgenden Events für das Manager-Interface erzeugt werden: AgentCalled, AgentDump, AgentConnect, - AgentComplete. M�gliche Werte: + AgentComplete. Mögliche Werte: yes|no @@ -742,8 +742,8 @@ Legt fest ob dem Mitglied der Warteschlange, der das - Gespr�ch annimmt, die Wartezeit des Anrufers angesagt werden soll, - bevor dieser zu ihm durchgestellt wird. M�gliche Werte: + Gespräch annimmt, die Wartezeit des Anrufers angesagt werden soll, + bevor dieser zu ihm durchgestellt wird. Mögliche Werte: yes|no @@ -753,8 +753,8 @@ Legt fest, ob Mitglieder der Warteschlange auch dann - angeklingelt werden ,wenn sie sich in einem Gespr�ch befinden. - M�gliche Werte: + angeklingelt werden ,wenn sie sich in einem Gespräch befinden. + Mögliche Werte: yes|no @@ -774,7 +774,7 @@ Die relative Gewichtung der Warteschlangen. Ist ein Benutzer Mitglied in mehreren Warteschlangen, kann hiermit die Reihenfolge - der Wichtigkeit festgelegt werden. Schlangen mit h�herem Wert + der Wichtigkeit festgelegt werden. Schlangen mit höherem Wert werden bevorzugt. @@ -784,8 +784,8 @@ Bestimmt, ob der Antwort-Timeout eines Mitglieds der - Warteschlange bei einem Besetzt- oder Leitung-�berlastet-Signal - zur�ckgesetzt wird. + Warteschlange bei einem Besetzt- oder Leitung-überlastet-Signal + zurückgesetzt wird. @@ -794,9 +794,9 @@
<literal>ast_sipfriends</literal> - Die SIP Endger�te - Datenbankversion der - sip.conf. F�r diese Tabelle existiert der View ast_sipfriends_gs, - dieser wird von Asterisk ausgewertet, der view beschr�nkt die Tabelle um peers die f�r + Die SIP Endgeräte - Datenbankversion der + sip.conf. Für diese Tabelle existiert der View ast_sipfriends_gs, + dieser wird von Asterisk ausgewertet, der view beschränkt die Tabelle um peers die für Asterisk nicht relevant sind, so zb. User auf externen Hosts (Angenturen) @@ -813,7 +813,7 @@ name - Der Name des Endger�tes zur Identifikation z.B. im + Der Name des Endgerätes zur Identifikation z.B. im Dialplan. @@ -822,8 +822,8 @@ secret - Legt das Passwort fest, welches das SIP-Endger�t zur - Anmeldung benutzten mu�. + Legt das Passwort fest, welches das SIP-Endgerät zur + Anmeldung benutzten muß. @@ -831,7 +831,7 @@ type - Die Art, wie der SIP-Anschluss und damit das SIP-Endger�t + Die Art, wie der SIP-Anschluss und damit das SIP-Endgerät behandelt werden soll @@ -869,7 +869,7 @@ host - Legt fest, ob sich das SIP-Endger�t eine dynamische oder + Legt fest, ob sich das SIP-Endgerät eine dynamische oder eine statische IP-Adresse verwendet. @@ -877,7 +877,7 @@ dynamic - Die IP-Adresse des Endger�tes ist dynamisch, seine IP + Die IP-Adresse des Endgerätes ist dynamisch, seine IP ist dem System nicht bekannt. @@ -886,8 +886,8 @@ <IP>|<hostname> - Die IP-Adresse oder der Hostname des Endger�tes. Das - System kann hier�ber das Endger�t erreichen, ohne dass sich + Die IP-Adresse oder der Hostname des Endgerätes. Das + System kann hierüber das Endgerät erreichen, ohne dass sich dieses erst registrieren muss. @@ -900,7 +900,7 @@ Legt die IP-Adresse fest, unter der das System versucht ein - Endger�t zu erreichen, wenn es sich noch nicht registriert + Endgerät zu erreichen, wenn es sich noch nicht registriert hat. @@ -909,7 +909,7 @@ context - Der Kontext, zu welchem das SIP-Endger�t geh�ren + Der Kontext, zu welchem das SIP-Endgerät gehören soll. @@ -918,7 +918,7 @@ callerid - Die ID des Anrufers, die an die Gegenstelle �betragen + Die ID des Anrufers, die an die Gegenstelle übetragen wird. @@ -927,7 +927,7 @@ mailbox - Die Nummer der Mailbox, die dem Endger�t zugeordnet + Die Nummer der Mailbox, die dem Endgerät zugeordnet ist. @@ -936,8 +936,8 @@ callgroup - Liste numerischer IDs der Call-Groups, zu denen das Endger�t - geh�ren soll. + Liste numerischer IDs der Call-Groups, zu denen das Endgerät + gehören soll. @@ -945,8 +945,8 @@ pickupgroup - Liste numerischer IDs der Call-Groups, f�r die das - Heranholen von Gespr�chen an dieses Endger�t erlaubt ist. + Liste numerischer IDs der Call-Groups, für die das + Heranholen von Gesprächen an dieses Endgerät erlaubt ist. @@ -955,7 +955,7 @@ Legt fest, ob und welche Channelvariable bei Anrufen von - diesem Endger�t gesetzt werden soll. + diesem Endgerät gesetzt werden soll. @@ -963,8 +963,8 @@ call-limit - Legt die Maximale Anzahl von Gespr�chen fest, die �ber - dieses Endger�t gef�hrt werden k�nnen. + Legt die Maximale Anzahl von Gesprächen fest, die über + dieses Endgerät geführt werden können. @@ -973,8 +973,8 @@ Legt den Kontext fest, welcher zur Signalisierung z.B. von - LEDs an einem SIP-Endger�t verwendet wird. In diesem Kontext - befinden sich z.B. die "hint" Eintr�ge im Dialplan. + LEDs an einem SIP-Endgerät verwendet wird. In diesem Kontext + befinden sich z.B. die "hint" Einträge im Dialplan. @@ -983,7 +983,7 @@ Legt fest, welcher Kontest beim ersten Registrieren eines - SIP-Endger�tes automatisch aufgerufen wird. Als Extension wird der + SIP-Endgerätes automatisch aufgerufen wird. Als Extension wird der Inhalt des Feldes name verwendet. @@ -992,7 +992,7 @@ ipaddr - Die aktuelle IP-Adresse des SIP-Endger�tes wird vom + Die aktuelle IP-Adresse des SIP-Endgerätes wird vom Asterisk-Server in diesem Feld abgelegt. @@ -1001,7 +1001,7 @@ port - Die aktuelle Portnummer des SIP-Endger�tes wird vom + Die aktuelle Portnummer des SIP-Endgerätes wird vom Asterisk-Server in diesem Feld abgelegt. @@ -1010,7 +1010,7 @@ regseconds - Zeitstempel der Registrierung des SIP-Endger�tes wird vom + Zeitstempel der Registrierung des SIP-Endgerätes wird vom Asterisk-Server in diesem Feld abgelegt. @@ -1019,7 +1019,7 @@ username - Benutzername, wie er in der Konfiguration des SIP-Endger�tes + Benutzername, wie er in der Konfiguration des SIP-Endgerätes festgelegt wurde. @@ -1028,7 +1028,7 @@ regserver - Name des Servers, an dem das Endger�t registriert ist, wird + Name des Servers, an dem das Endgerät registriert ist, wird vom Asterisk-Server in diesem Feld abgelegt. @@ -1037,7 +1037,7 @@ fullcontact - Die Kontaktdaten des SIP-Endger�tes werden vom + Die Kontaktdaten des SIP-Endgerätes werden vom Asterisk-Server in diesem Feld abgelegt. @@ -1079,7 +1079,7 @@ context - Legt fest, zu welchem Kontext die Mailbox geh�rt. + Legt fest, zu welchem Kontext die Mailbox gehört. @@ -1104,7 +1104,7 @@ fullname - Vollst�ndiger Name des Benutzers der Mailbox. + Vollständiger Name des Benutzers der Mailbox. @@ -1121,8 +1121,8 @@ attach - Legt fest, ob an die Benachrichtigung �ber eMail, eine - Audiodatei mit der Aufnahme angeh�ngt werden soll. M�gliche Werte: + Legt fest, ob an die Benachrichtigung über eMail, eine + Audiodatei mit der Aufnahme angehängt werden soll. Mögliche Werte: yes|no @@ -1132,7 +1132,7 @@ Legt fest, ob nach der Benachrichtigung per eMail die - Audiodatei gel�scht werden soll. + Audiodatei gelöscht werden soll. @@ -1165,7 +1165,7 @@ regexp - Regul�rer Ausdruck zur Definition der + Regulärer Ausdruck zur Definition der Rufnummernsperre @@ -1199,7 +1199,7 @@ case - Legt fest, f�r welchen Fall die Anrufweiterleitung + Legt fest, für welchen Fall die Anrufweiterleitung aktiviert werden soll. @@ -1231,7 +1231,7 @@ offline - Wenn das Endger�t des Benutzers nicht angemeldet + Wenn das Endgerät des Benutzers nicht angemeldet ist. @@ -1319,8 +1319,8 @@ active - Legt fest, ob das Signal f�r einen weiteren, ankommenden - Anruf, w�hrend eines bestehenden Gespr�chs gesendet wird. + Legt fest, ob das Signal für einen weiteren, ankommenden + Anruf, während eines bestehenden Gesprächs gesendet wird. @@ -1330,7 +1330,7 @@ <literal>clir</literal> Konfiguration des Dienstmerkmals "CLIR" - (Rufnummernunterdr�ckung) + (Rufnummernunterdrückung) @@ -1346,8 +1346,8 @@ internal_restrict - Legt fest, ob bei ausgehenden, internen Gespr�chen die - eigene Rufnummer unterdr�ckt wird. M�gliche Werte: + Legt fest, ob bei ausgehenden, internen Gesprächen die + eigene Rufnummer unterdrückt wird. Mögliche Werte: yes|no @@ -1356,8 +1356,8 @@ external_restrict - Legt fest, ob bei ausgehenden, externen Gespr�chen die - eigene Rufnummer unterdr�ckt wird. M�gliche Werte: + Legt fest, ob bei ausgehenden, externen Gesprächen die + eigene Rufnummer unterdrückt wird. Mögliche Werte: yes|no @@ -1367,7 +1367,7 @@
<literal>conferences</literal> - Konferenzr�ume + Konferenzräume @@ -1392,9 +1392,9 @@
<literal>dial_log</literal> - Liste get�tigter, erhaltener oder verpasster Anrufe. Diese Tabelle - wird durch AGI-Skripte im Dialplan gef�llt, und die einzelnen Eintr�ge - k�nnen auch vom Benutzer gel�scht werden. + Liste getätigter, erhaltener oder verpasster Anrufe. Diese Tabelle + wird durch AGI-Skripte im Dialplan gefüllt, und die einzelnen Einträge + können auch vom Benutzer gelöscht werden. @@ -1425,7 +1425,7 @@ out - Get�tigter Anruf + Getätigter Anruf @@ -1480,7 +1480,7 @@
<literal>hosts</literal> - Zum System geh�rende Hosts + Zum System gehörende Hosts @@ -1597,14 +1597,14 @@
<literal>pb_prv</literal> - Die pers�nlichen Telefonb�cher der Benutzer. + Die persönlichen Telefonbücher der Benutzer. id - Fortlaufende Nummer der Eintr�ge. + Fortlaufende Nummer der Einträge. @@ -1613,7 +1613,7 @@ ID des Benutzers (aus der Tabelle users) - dem das Telefonbuch geh�rt. + dem das Telefonbuch gehört. @@ -1638,14 +1638,14 @@
<literal>phones</literal> - Die Endger�te. + Die Endgeräte. id - Eindeutige, numerische ID des Endger�tes. + Eindeutige, numerische ID des Endgerätes. @@ -1653,7 +1653,7 @@ type - Typ des Endger�tes, z.B. snom360 + Typ des Endgerätes, z.B. snom360 @@ -1661,7 +1661,7 @@ mac_addr - Die MAC-Adresse des Endger�tes. + Die MAC-Adresse des Endgerätes. @@ -1680,11 +1680,11 @@ Eindeutige, numerische ID eines Pseudo-Benutzers aus dem Feld nobody_index der Tabelle - users. Jedem Endger�t wird bei der Installation + users. Jedem Endgerät wird bei der Installation ein solcher Benutzer zugewiesen, um auch dann das Telefon - verwenden zu k�nnen, wenn sich noch kein Benutzer an diesem Ger�t - angemeldet hat. Dies erm�glicht Notrufe, kostenlose - Interngespr�che etc. direkt nach der Installation. + verwenden zu können, wenn sich noch kein Benutzer an diesem Gerät + angemeldet hat. Dies ermöglicht Notrufe, kostenlose + Interngespräche etc. direkt nach der Installation. @@ -1733,7 +1733,7 @@ Numerische ID der Pickup-Gruppe, zu welcher der Benutzer - geh�rt, aus der Tabelle pickupgroups. + gehört, aus der Tabelle pickupgroups. @@ -1776,7 +1776,7 @@ event - Ereignis, welches zum Eintrag ins Log gef�hrt hat. + Ereignis, welches zum Eintrag ins Log geführt hat. @@ -1810,8 +1810,8 @@ caller - Die Anrufer-ID, wie sie zum System �bertragen wurde oder - NULL, fals keine Rufnummern�bertragung aktiviert war. + Die Anrufer-ID, wie sie zum System übertragen wurde oder + NULL, fals keine Rufnummernübertragung aktiviert war. @@ -1861,7 +1861,7 @@ info - Zus�tzliche Informationen (z.B. + Zusätzliche Informationen (z.B. <extension>@<context>) bei einer Weiterleitung. @@ -1872,7 +1872,7 @@
<literal>ringtones</literal> - Die pro Benutzer eingestellten Klingelt�ne. + Die pro Benutzer eingestellten Klingeltöne. @@ -1888,7 +1888,7 @@ src - F�r Anrufe von welcher Quelle der Klingelton gelten soll. + Für Anrufe von welcher Quelle der Klingelton gelten soll. internal | external. @@ -1897,10 +1897,10 @@ bellcore - Die Nummer eines Standard-Klingeltons. �blicherweise - 1 - 10 f�r + Die Nummer eines Standard-Klingeltons. Üblicherweise + 1 - 10 für Bellcore-drX oder - 0 f�r Silent + 0 für Silent (lautlos). @@ -1942,10 +1942,10 @@ key - Telefon-Typ-spezifisches K�rzel der Taste. Wird aber vom + Telefon-Typ-spezifisches Kürzel der Taste. Wird aber vom Provisioning-System (z.B. - htdocs/prov/snom/settings.php) nochmal f�r - das Telefon �bersetzt. + htdocs/prov/snom/settings.php) nochmal für + das Telefon übersetzt. @@ -1956,6 +1956,38 @@ Eingestellte Rufnummer. + + + ptype + + + Lokation der Nummer (cell/work/home/fax etc.). + + + + + pref + + + Praeferenz der Nummer (1=highest, 99=lowest, default=9). + + + + + card_id + + + vCard ID Referenz. + + + + + modified + + + Zeitstemples letzter Aenderung. + +
@@ -1979,7 +2011,7 @@ Eindeutige alphanumerische Bezeichnung des Benutzers, z.B. - Personalnummer o.�. + Personalnummer o.ä. @@ -2020,8 +2052,8 @@ Eindeutige, numerische ID eines Pseudo-Benutzers. Diese - speziellen Benutzer werden verwendet, wenn an einem Endger�t noch - kein anderer Benutzer angemeldet ist. Dies erm�glicht z.B. + speziellen Benutzer werden verwendet, wenn an einem Endgerät noch + kein anderer Benutzer angemeldet ist. Dies ermöglicht z.B. Notrufe. @@ -2030,7 +2062,7 @@ host_id - Numerische ID des Asterisk-Servers, an dem sich das Endger�t + Numerische ID des Asterisk-Servers, an dem sich das Endgerät des Benutzer anmeldet. @@ -2039,7 +2071,7 @@ current_ip - Aktuelle IP des Endger�tes, welches der Benutzer aktuell + Aktuelle IP des Endgerätes, welches der Benutzer aktuell verwendet. @@ -2058,7 +2090,7 @@
<literal>users_external_numbers</literal> - M�gliche Ausgangsrufnummern pro Benutzer zur Initiierung von + Mögliche Ausgangsrufnummern pro Benutzer zur Initiierung von Anrufen. @@ -2100,8 +2132,8 @@ internal_active - Legt fest, ob die Anrufbeantworterfunktion f�r interne - Gespr�che aktiviert werden soll. + Legt fest, ob die Anrufbeantworterfunktion für interne + Gespräche aktiviert werden soll. @@ -2109,8 +2141,8 @@ external_active - Legt fest, ob die Anrufbeantworterfunktion f�r externe - Gespr�che aktiviert werden soll. + Legt fest, ob die Anrufbeantworterfunktion für externe + Gespräche aktiviert werden soll. From 666543614c19175e0fd61aacd0ffddf3c77da2f8 Mon Sep 17 00:00:00 2001 From: Markus Neubauer Date: Sat, 19 Dec 2015 20:04:23 +0100 Subject: [PATCH 60/87] Update dial-log-store --- opt/gemeinschaft/dialplan-scripts/dial-log-store | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/opt/gemeinschaft/dialplan-scripts/dial-log-store b/opt/gemeinschaft/dialplan-scripts/dial-log-store index d7a972ad6..25a61f07b 100755 --- a/opt/gemeinschaft/dialplan-scripts/dial-log-store +++ b/opt/gemeinschaft/dialplan-scripts/dial-log-store @@ -76,7 +76,7 @@ $remote_user = $rs->fetchRow(); $is_from_phonebook = false; if (! $remote_user) { # if there is nothing in the ast_sipfriends, check the private phonebook - $rs = $db->execute('SELECT `firstname`, `lastname` FROM `pb_prv` WHERE `user_id`='.$uid.' AND `number`=\''. $db->escape($number) .'\''); + $rs = $db->execute('SELECT `firstname`, `lastname` FROM `pb_prv` WHERE (`user_id`='.$uid.' OR `user_id`=1) AND `number`=\''. $db->escape($number) .'\''); //FIXME - probably doesn't make much sense with uncanonized phone numbers $remote_user = $rs->fetchRow(); $is_from_phonebook = true; @@ -103,4 +103,4 @@ $db->execute( 'INSERT INTO `dial_log` (`user_id`, `type`, `timestamp`, `number`, -?> \ No newline at end of file +?> From ff29797b5f4eeaaf4077ea88b6f110e30fa95b72 Mon Sep 17 00:00:00 2001 From: Markus Neubauer Date: Sat, 19 Dec 2015 20:05:18 +0100 Subject: [PATCH 61/87] Update pb.php --- opt/gemeinschaft/htdocs/prov/snom/pb.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/opt/gemeinschaft/htdocs/prov/snom/pb.php b/opt/gemeinschaft/htdocs/prov/snom/pb.php index fc83adb56..958acb4dc 100644 --- a/opt/gemeinschaft/htdocs/prov/snom/pb.php +++ b/opt/gemeinschaft/htdocs/prov/snom/pb.php @@ -161,7 +161,7 @@ function getUserID( $ext ) switch ($t) { case 'gs' : $cq .= '`users` WHERE `id` IN ('.implode(',',$group_members).') AND `id`!='.$user_id; break; case 'imported': $cq .= '`pb_ldap`' ; break; - case 'prv' : $cq .= '`pb_prv` WHERE `user_id`='. $user_id ; break; + case 'prv' : $cq .= '`pb_prv` WHERE (`user_id`='. $user_id . 'OR `user_id`=1 )' ; break; default : $cq = false; } $c = $cq ? (' ('. (int)@$db->executeGetOne( $cq ) .')') : ''; From 7a809af742505686b7c3925b964f2580446fe5a2 Mon Sep 17 00:00:00 2001 From: Markus Neubauer Date: Sat, 19 Dec 2015 20:05:53 +0100 Subject: [PATCH 62/87] Update pb.php --- opt/gemeinschaft/htdocs/prov/siemens/pb/pb.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/opt/gemeinschaft/htdocs/prov/siemens/pb/pb.php b/opt/gemeinschaft/htdocs/prov/siemens/pb/pb.php index a9ee3a70b..6bd5b7ef0 100644 --- a/opt/gemeinschaft/htdocs/prov/siemens/pb/pb.php +++ b/opt/gemeinschaft/htdocs/prov/siemens/pb/pb.php @@ -283,7 +283,7 @@ function write_alert( $message, $alert_type='ERROR' ) $image = $img_url.'contents.png'; break; case 'prv': - $c = (int)$db->executeGetOne( 'SELECT COUNT(*) FROM `pb_prv` WHERE `user_id`='. $user_id ); + $c = (int)$db->executeGetOne( 'SELECT COUNT(*) FROM `pb_prv` WHERE (`user_id`='. $user_id . 'OR `user_id`=1 )' ); $image = $img_url.'yast_sysadmin.png'; break; case 'imported': From 0e71054748beefd69fee2e3042af64107c756a5e Mon Sep 17 00:00:00 2001 From: Markus Neubauer Date: Sat, 19 Dec 2015 20:06:48 +0100 Subject: [PATCH 63/87] Update pb.php --- opt/gemeinschaft/htdocs/prov/aastra/pb.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/opt/gemeinschaft/htdocs/prov/aastra/pb.php b/opt/gemeinschaft/htdocs/prov/aastra/pb.php index c543a70cd..dbf7fb009 100644 --- a/opt/gemeinschaft/htdocs/prov/aastra/pb.php +++ b/opt/gemeinschaft/htdocs/prov/aastra/pb.php @@ -269,7 +269,7 @@ function _get_userid() FROM `pb_prv` WHERE - `user_id`='. $user_id .' AND ( + (`user_id`='. $user_id . 'OR `user_id`=1 ) AND ( `lastname` LIKE _utf8\''. $db->escape($name_sql) .'\' COLLATE utf8_unicode_ci ) ORDER BY `lastname`, `firstname` @@ -446,4 +446,4 @@ function _get_userid() aastra_transmit_str( $xml ); -?> \ No newline at end of file +?> From bd24cfeadb88b0d445d98ab62af6858887d6b63a Mon Sep 17 00:00:00 2001 From: Markus Neubauer Date: Sat, 19 Dec 2015 20:07:32 +0100 Subject: [PATCH 64/87] Update gs_phonebook.php --- opt/gemeinschaft/htdocs/prov/grandstream/gs_phonebook.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/opt/gemeinschaft/htdocs/prov/grandstream/gs_phonebook.php b/opt/gemeinschaft/htdocs/prov/grandstream/gs_phonebook.php index d60b39881..a7cad3a48 100644 --- a/opt/gemeinschaft/htdocs/prov/grandstream/gs_phonebook.php +++ b/opt/gemeinschaft/htdocs/prov/grandstream/gs_phonebook.php @@ -169,7 +169,7 @@ function _err( $msg='' ) 'query' => 'SELECT `pb`.`lastname` `ln`, `pb`.`firstname` `fn`, `pb`.`number` `ext` FROM `pb_prv` `pb` -WHERE `pb`.`user_id`='.$user_id.' +WHERE (`pb`.`user_id`='. $user_id . 'OR `pb`.`user_id`=1 ) ORDER BY `pb`.`lastname`, `pb`.`firstname` LIMIT 100' ); From 83bb48b0e834113a44fe70a3035593d90a8defe0 Mon Sep 17 00:00:00 2001 From: Markus Neubauer Date: Sat, 19 Dec 2015 20:09:14 +0100 Subject: [PATCH 65/87] Update private-phonebook-xml.inc --- opt/gemeinschaft/htdocs/prov/private-phonebook-xml.inc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/opt/gemeinschaft/htdocs/prov/private-phonebook-xml.inc b/opt/gemeinschaft/htdocs/prov/private-phonebook-xml.inc index 8df33c897..937d95bcc 100644 --- a/opt/gemeinschaft/htdocs/prov/private-phonebook-xml.inc +++ b/opt/gemeinschaft/htdocs/prov/private-phonebook-xml.inc @@ -82,7 +82,7 @@ if ( empty($catid) && ! empty($cat) ) { $query = 'SELECT SQL_CALC_FOUND_ROWS '. '`p`.`id`, `p`.`lastname`, `p`.`firstname`, `p`.`number` , `p`.`ptype`, `p`.`card_id`'. ' FROM `pb_prv` `p`'; -$where = ' WHERE `p`.`user_id`='. $user_id; +$where = ' WHERE ( `p`.`user_id`='. $user_id . ' OR `p`.`user_id`=1 ) '; if ($number != '') { From 48dfdbc0ed374c46f3cac52fadff7c9bb5728c17 Mon Sep 17 00:00:00 2001 From: Markus Neubauer Date: Sat, 19 Dec 2015 20:09:57 +0100 Subject: [PATCH 66/87] Update pb.php --- opt/gemeinschaft/htdocs/prov/tiptel/pb.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/opt/gemeinschaft/htdocs/prov/tiptel/pb.php b/opt/gemeinschaft/htdocs/prov/tiptel/pb.php index 64e09bd23..570a50131 100644 --- a/opt/gemeinschaft/htdocs/prov/tiptel/pb.php +++ b/opt/gemeinschaft/htdocs/prov/tiptel/pb.php @@ -174,7 +174,7 @@ function getUserID( $ext ) switch ($t) { case 'gs' : $cq .= '`users` WHERE `id` IN ('.implode(',',$group_members).') AND `id`!='.$user_id; break; case 'imported': $cq .= '`pb_ldap`' ; break; - case 'prv' : $cq .= '`pb_prv` WHERE `user_id`='. $user_id ; break; + case 'prv' : $cq .= '`pb_prv` WHERE (`user_id`='. $user_id . 'OR `user_id`=1 )' ; break; default : $cq = false; } $c = $cq ? (' ('. (int)@$db->executeGetOne( $cq ) .')') : ''; @@ -324,4 +324,4 @@ function getUserID( $ext ) #################################### PHONEBOOK } -?> \ No newline at end of file +?> From 18c5f87b9a3066fa1cc7edd87cb2fd10531b1efc Mon Sep 17 00:00:00 2001 From: Markus Neubauer Date: Sat, 19 Dec 2015 20:10:28 +0100 Subject: [PATCH 67/87] Update pb_on_phone.php --- opt/gemeinschaft/htdocs/prov/tiptel/pb_on_phone.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/opt/gemeinschaft/htdocs/prov/tiptel/pb_on_phone.php b/opt/gemeinschaft/htdocs/prov/tiptel/pb_on_phone.php index bbf54bf89..3026aabf8 100644 --- a/opt/gemeinschaft/htdocs/prov/tiptel/pb_on_phone.php +++ b/opt/gemeinschaft/htdocs/prov/tiptel/pb_on_phone.php @@ -125,7 +125,7 @@ function _err( $msg='' ) 'query' => 'SELECT `pb`.`lastname` `ln`, `pb`.`firstname` `fn`, `pb`.`number` `ext` FROM `pb_prv` `pb` - WHERE `pb`.`user_id`='.$user_id.' + WHERE (`pb`.`user_id`='. $user_id . 'OR `pb`.`user_id`=1 ) ORDER BY `pb`.`lastname`, `pb`.`firstname`' ); } @@ -172,4 +172,4 @@ function _err( $msg='' ) } @ob_end_flush(); -?> \ No newline at end of file +?> From b8588e55788abb05d63f6c0a69eb12ae5ea86497 Mon Sep 17 00:00:00 2001 From: Markus Neubauer Date: Sat, 19 Dec 2015 20:11:04 +0100 Subject: [PATCH 68/87] Update modules.php --- opt/gemeinschaft/htdocs/gui/inc/modules.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/opt/gemeinschaft/htdocs/gui/inc/modules.php b/opt/gemeinschaft/htdocs/gui/inc/modules.php index 06fbaa2e1..00b75d963 100644 --- a/opt/gemeinschaft/htdocs/gui/inc/modules.php +++ b/opt/gemeinschaft/htdocs/gui/inc/modules.php @@ -77,7 +77,7 @@ 's' => array('title' => __('Kategorien' ), 'id' => 3006) ), 45=>array( 'k' => 'cloud' , - 's' => array('title' => __('Cloud Import' ), 'id' => 3005) ) + 's' => array('title' => __('Cloud Sync' ), 'id' => 3005) ) ); if (gs_get_conf('GS_PB_IMPORTED_ENABLED')) { $pos = (int)gs_get_conf('GS_PB_IMPORTED_ORDER', 9) * 10; From d9a0c85ae4b37b980fde0839fa13794003a995b7 Mon Sep 17 00:00:00 2001 From: Markus Neubauer Date: Sat, 19 Dec 2015 20:12:05 +0100 Subject: [PATCH 69/87] Update pb_private.php --- opt/gemeinschaft/htdocs/gui/mod/pb_private.php | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/opt/gemeinschaft/htdocs/gui/mod/pb_private.php b/opt/gemeinschaft/htdocs/gui/mod/pb_private.php index a1028633e..ae6240065 100644 --- a/opt/gemeinschaft/htdocs/gui/mod/pb_private.php +++ b/opt/gemeinschaft/htdocs/gui/mod/pb_private.php @@ -114,7 +114,7 @@ function confirm_delete() { 'LEFT JOIN `pb_prv_category` `p` ON `c`.`id` = `p`.`cat_id` ' . 'WHERE '. '`p`.`id` IS NOT NULL AND ' . - '`c`.`user_id`='. $DB->escape($user_id).' '. + '( `c`.`user_id`='. $DB->escape($user_id).' OR `c`.`user_id`=1 )'. 'GROUP BY `c`.`category` '. 'ORDER BY `c`.`category`' ); @@ -126,7 +126,7 @@ function confirm_delete() { $query = 'SELECT SQL_CALC_FOUND_ROWS '. '`p`.`id`, `p`.`lastname`, `p`.`firstname`, `p`.`number` , `p`.`ptype`, `p`.`card_id`'. ' FROM `pb_prv` `p`'; -$where = ' WHERE `p`.`user_id`='. $user_id; +$where = ' WHERE ( `p`.`user_id`='. $user_id . ' OR `p`.`user_id`=1 ) '; if ($number != '') { @@ -342,8 +342,10 @@ function confirm_delete() { (@$_SESSION['sudo_user']['name'] == @$_SESSION['real_user']['name']) ? '' : ('&sudo='. @$_SESSION['sudo_user']['name']); echo '', __('wählen'), '   '; - echo '', __('bearbeiten'), '   '; - echo '', __('entfernen'), ''; + if ( $r['user_id'] ) { // edit only own recordsd other's within the cloud + echo '', __('bearbeiten'), '   '; + echo '', __('entfernen'), ''; + } if ( $r['card_id'] ) echo ' [1]'; echo ''; From 9fc7ca4d7e82cbc70b3c6dbff15d2bd822a2622d Mon Sep 17 00:00:00 2001 From: Markus Neubauer Date: Sat, 19 Dec 2015 20:12:42 +0100 Subject: [PATCH 70/87] Update pb_cloud.php --- opt/gemeinschaft/htdocs/gui/mod/pb_cloud.php | 70 ++++++++++++++------ 1 file changed, 51 insertions(+), 19 deletions(-) diff --git a/opt/gemeinschaft/htdocs/gui/mod/pb_cloud.php b/opt/gemeinschaft/htdocs/gui/mod/pb_cloud.php index 9e2955c10..c02164c55 100644 --- a/opt/gemeinschaft/htdocs/gui/mod/pb_cloud.php +++ b/opt/gemeinschaft/htdocs/gui/mod/pb_cloud.php @@ -47,34 +47,38 @@ function confirm_delete() { $per_page = (int)GS_GUI_NUM_RESULTS; -$name = trim(@$_REQUEST['name' ]); -$url = trim(@$_REQUEST['url' ]); -$login = trim(@$_REQUEST['login' ]); -$pass = trim(@$_REQUEST['pass' ]); +$name = trim(@$_REQUEST['name' ]); +$url = trim(@$_REQUEST['url' ]); +$login = trim(@$_REQUEST['login' ]); +$pass = trim(@$_REQUEST['pass' ]); $frequency = trim(@$_REQUEST['frequency' ]); -$save_url = trim(@$_REQUEST['surl']); -$save_login = trim(@$_REQUEST['slogin' ]); -$save_pass = trim(@$_REQUEST['spass' ]); +$public = trim(@$_REQUEST['public' ]); +$save_url = trim(@$_REQUEST['surl' ]); +$save_login = trim(@$_REQUEST['slogin' ]); +$save_pass = trim(@$_REQUEST['spass' ]); $save_frequency = trim(@$_REQUEST['sfrequency' ]); -$page = (int) (@$_REQUEST['page' ]); -$delete_entry = (int)trim(@$_REQUEST['delete' ]); -$edit_entry = (int)trim(@$_REQUEST['edit' ]); -$save_entry = (int)trim(@$_REQUEST['save' ]); +$save_public = trim(@$_REQUEST['spublic' ]); +$page = (int) (@$_REQUEST['page' ]); +$delete_entry = (int)trim(@$_REQUEST['delete' ]); +$edit_entry = (int)trim(@$_REQUEST['edit' ]); +$save_entry = (int)trim(@$_REQUEST['save' ]); $user_id = (int)@$_SESSION['sudo_user']['info']['id']; if ($delete_entry > 0) { - # delete entry + // delete entry $rs = $DB->execute( 'DELETE FROM `pb_cloud` ' . ' WHERE `id`='. $delete_entry . ' AND `user_id`='. $user_id ); + // remove cards $rs2 = $DB->execute( 'DELETE FROM `pb_cloud_card` ' . ' WHERE `cloud_id`='. $delete_entry ); + // remove from phone book $rs2 = $DB->execute( 'DELETE p FROM `pb_prv` AS p ' . ' LEFT JOIN `pb_cloud_card` AS c ' . @@ -83,6 +87,7 @@ function confirm_delete() { ' AND p.card_id != 0 ' . ' AND c.id IS NULL' ); + // remove from categories xref $rs2 = $DB->execute( 'DELETE p FROM `pb_prv_category` AS p ' . ' LEFT JOIN `pb_cloud_card` AS c ' . @@ -91,6 +96,7 @@ function confirm_delete() { ' AND p.card_id != 0 ' . ' AND c.id IS NULL' ); + // remove from categories $rs2 = $DB->execute( 'DELETE c FROM `pb_category` AS c ' . ' LEFT JOIN `pb_prv_category` AS p ' . @@ -115,30 +121,41 @@ function confirm_delete() { if ( ! is_numeric(substr($save_frequency, 0, -1)) || substr($save_frequency, 0, -1) == '0' ) $save_frequency = '1' . substr($save_frequency, -1); } + + if ( $save_public != 1 ) $save_public = 0; if ($save_entry < 1) { $rs = $DB->execute( 'INSERT INTO `pb_cloud` ' . - ' (`id`, `user_id`, `url`, `login`, `pass`, `frequency`, `next_poll`, `message`) ' . + ' (`id`, `user_id`, `url`, `login`, `pass`, `frequency`, `next_poll`, `message`, `public`) ' . ' VALUES' . - '(NULL, '. $user_id .', \''. $DB->escape($save_url) .'\', \''. $DB->escape($save_login) .'\', des_encrypt(\''. $save_pass .'\',\'' . $save_login. '\'), \''. $DB->escape($save_frequency) .'\', NOW(), \'Scheduled\')' + '(NULL, '. $user_id .', \''. $DB->escape($save_url) .'\', \''. $DB->escape($save_login) .'\', des_encrypt(\''. $save_pass .'\',\'' . $save_login. '\'), \''. $DB->escape($save_frequency) .'\', NOW(), \'Scheduled\', ' . $save_public . ')' ); } else { + // get old public status + $r = $DB->execute('SELECT `public` FROM `pb_cloud` WHERE `id`='. $save_entry . ' LIMIT 1')->fetchrow(); $rs = $DB->execute( 'UPDATE `pb_cloud` ' . ' SET `url`=\''. $DB->escape($save_url) .'\', `login`=\''. $DB->escape($save_login) .'\', `pass`=des_encrypt(\''. $save_pass .'\',\'' . $save_login .'\'), ' . - ' `frequency`=\'' . $save_frequency . '\', `next_poll`=NOW(), message=\'Scheduled\', last_remote_modified=\'2000-01-01 00:00:00\', active=1 ' . + ' `frequency`=\'' . $save_frequency . '\', `next_poll`=NOW(), `message`=\'Scheduled\', `last_remote_modified`=\'2000-01-01 00:00:00\', `active`=1, ' . + ' `public`=' . $save_public . ' WHERE `id`='. $save_entry .' AND `user_id`='. $user_id ); + + // delete vcards if it was public and should not be anymore or vs + if ( $r['public'] != $save_public ) { + $DB->execute('DELETE FROM `pb_cloud_card` WHERE `cloud_id`=' . $save_entry); + } } $save_url = ''; $save_login = ''; $save_pass = ''; $save_frequency = ''; + $save_public = 0; } @@ -159,7 +176,7 @@ function confirm_delete() { $rs = $DB->execute( 'SELECT SQL_CALC_FOUND_ROWS '. - '`id`, `url`, `login`, cast(des_decrypt(`pass`,`login`) as char(16)) as pass, `frequency`, `message` '. + '`id`, `url`, `login`, cast(des_decrypt(`pass`,`login`) as char(16)) as pass, `frequency`, `message`, `public` '. 'FROM '. '`pb_cloud` '. 'WHERE '. @@ -186,7 +203,7 @@ function confirm_delete() { $rs = $DB->execute( 'SELECT SQL_CALC_FOUND_ROWS '. - '`id`, `url`, `login`, cast(des_decrypt(`pass`,`login`) as char(16)) as pass, `frequency`, `message` '. + '`id`, `url`, `login`, cast(des_decrypt(`pass`,`login`) as char(16)) as pass, `frequency`, `message`, `public` '. 'FROM '. '`pb_cloud` '. 'WHERE '. @@ -282,6 +299,8 @@ function confirm_delete() { echo gs_form_hidden($SECTION, $MODULE), "\n"; echo '', "\n"; echo '', "\n"; +echo '', "\n"; +echo '', "\n"; ?>
> > + > > - [1] - - + > + [2]  
'; - echo ''; + echo ''; echo ''; @@ -323,7 +341,7 @@ function confirm_delete() { echo '', __('wählen'), '   '; echo '', __('bearbeiten'), '   '; echo '', __('entfernen'), ''; - if ( $r['card_id'] ) echo ' [2]'; + if ( $r['card_id'] ) echo ' [1]'; echo ' - +
+
+ '; - echo '', __('abbrechen'), ''; + echo '', __('abbrechen'), ''; echo '
@@ -299,7 +318,10 @@ function confirm_delete() { - + + @@ -328,6 +350,11 @@ function confirm_delete() { echo '', "\n"; + + echo '', "\n"; echo '', "\n"; + echo '', "\n"; + echo ''; if ( !empty($r['message']) ) { echo ''; - echo ' +
[2]   + +  
'; echo ''; echo ''; + $checked = ($r['public']) ? 'checked' : ''; + echo ''; + echo ''; echo ''; @@ -353,6 +380,8 @@ function confirm_delete() { echo '', htmlEnt($r['frequency']), '', ($r['public']) ? 'public' : ' ', ''; $sudo_url = (@$_SESSION['sudo_user']['name'] == @$_SESSION['real_user']['name']) @@ -362,7 +391,7 @@ function confirm_delete() { echo '
'; + echo ''; echo '       ' . __('Status') . ': '; if ( 'OK' != substr($r['message'], 0, 2) ) { if ( 'Scheduled' == $r['message'] ) $bg = '#FFFF00 '; @@ -397,6 +426,9 @@ function confirm_delete() { + +