From adf48e717d0cdbe1c23a39562d639afebc00515e Mon Sep 17 00:00:00 2001 From: Ralf Becker Date: Thu, 9 Aug 2012 07:25:24 +0000 Subject: [PATCH 001/135] somehow lost merge-print phrases --- etemplate/lang/egw_de.lang | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/etemplate/lang/egw_de.lang b/etemplate/lang/egw_de.lang index 7d6b9124f0..17d46baa31 100644 --- a/etemplate/lang/egw_de.lang +++ b/etemplate/lang/egw_de.lang @@ -69,6 +69,7 @@ cells etemplate de Zellen cellspacing for the table-tag etemplate de Zellenabstand (cellspacing) der Tabelle center etemplate de Zentriert changed etemplate de Geändert +check all etemplate de Alle auswählen check if content should only be displayed but not altered (the content is not send back then!) etemplate de abhaken wenn der Inhalt nur angezeigt aber nicht geändert werden soll (der Inhalt wird dann nicht zurückgesendet!) check if field has to be filled by user etemplate de abhaken wenn das Eingabefeld vom Benutzer zwingend ausgefüllt werden muss checkbox etemplate de Checkbox @@ -215,6 +216,8 @@ hours etemplate de Stunden how many entries should the list show etemplate de Wieviele Einträge soll die Liste anzeigen html etemplate de HTML if field is disabled an empty table-cell is displayed, for (temporal) removement of a field/cell etemplate de wenn das Feld deaktiviert ist, wird eine leere Tabellenzelle angezeigt, zum (zeitweisen) Entfernen eines Feldes +if you specify a directory (full vfs path) here, %1 displays an action for each document. that action allows to download the specified document with the data inserted. preferences de Wenn Sie hier ein Verzeichnis (kompletter VFS Pfad) angeben, zeigt das %1 einen Befehl für jedes Dokument darin. Diese Befehle erlauben das angegebene Dokument mit Kontaktdaten eingefügt herunterzuladen. +if you specify a document (full vfs path) here, %1 displays an extra document icon for each entry. that icon allows to download the specified document with the data inserted. preferences de Wenn Sie hier ein Dokument (kompletter VFS Pfad) angeben, zeigt das %1 ein zusätzliches Dokumenten Icon. Dieses Icon erlaubt das Dokument mit Kontaktdaten eingefügt herunterzuladen. image etemplate de Grafik import etemplate de Import import an etemplate from a xml-file etemplate de Importiert ein eTemplate aus einer XML Datei @@ -414,6 +417,7 @@ tree etemplate de Baum type etemplate de Typ type of the column etemplate de Typ der Spalte type of the field (select label if field should be empty) etemplate de Type des Feldes (Beschriftung auswählen wenn Feld leer sein soll) +uncheck all etemplate de Alle abwählen unique etemplate de Unique unlink etemplate de Lösen update a single entry by passing the fields. etemplate de Aktualisert einen einzelnen Eintrag über seine Felder. @@ -449,5 +453,3 @@ you are not allowed to export more than %1 entries! common de Sie sind nicht ber you can respond by visiting: etemplate de Sie können unter dem folgenden Verweis antworten: you need to select a file first! etemplate de Sie müssen zuerst eine Datei auswählen! your code is incorrect !!! etemplate de Ihr Code ist nicht richtig!!! -check all etemplate de Alle auswählen -uncheck all etemplate de Alle abwählen From b181ab1f3fcce3c5e90640b4eafe0cd388981b71 Mon Sep 17 00:00:00 2001 From: Ralf Becker Date: Thu, 9 Aug 2012 08:16:17 +0000 Subject: [PATCH 002/135] allow to use a setup user and password by prefixing it with 'root_', eg. 'root_admin' for setup user 'admin' --- admin/admin-cli.php | 102 +++++++++++++++++++++++++++++++++++--------- 1 file changed, 81 insertions(+), 21 deletions(-) diff --git a/admin/admin-cli.php b/admin/admin-cli.php index 18069bd564..12e31b27cd 100755 --- a/admin/admin-cli.php +++ b/admin/admin-cli.php @@ -6,7 +6,7 @@ * @link http://www.egroupware.org * @package admin * @author Ralf Becker - * @copyright (c) 2006-10 by Ralf Becker + * @copyright (c) 2006-12 by Ralf Becker * @license http://opensource.org/licenses/gpl-license.php GPL - GNU General Public License * @version $Id$ */ @@ -25,29 +25,13 @@ elseif ($_SERVER['argc'] > 1) } else { - $action = '--help'; + usage(); } -// this is kind of a hack, as the autocreate_session_callback can not change the type of the loaded account-class -// so we need to make sure the right one is loaded by setting the domain before the header gets included. +// allow to specify instance by using a username with appended @domain-name $arg0s = explode(',',@array_shift($arguments)); -@list(,$_REQUEST['domain']) = explode('@',$arg0s[0]); - -if (ini_get('session.save_handler') == 'files' && !is_writable(ini_get('session.save_path')) && is_dir('/tmp') && is_writable('/tmp')) -{ - ini_set('session.save_path','/tmp'); // regular users may have no rights to apache's session dir -} - -$GLOBALS['egw_info'] = array( - 'flags' => array( - 'currentapp' => 'admin', - 'noheader' => true, - 'autocreate_session_callback' => 'user_pass_from_argv', - 'no_exception_handler' => 'cli', - ) -); - -include('../header.inc.php'); +@list($user,$domain) = explode('@',$arg0s[0]); +load_egw($user,$arg0s[1],$domain); switch($action) { @@ -207,6 +191,78 @@ function user_pass_from_argv(&$account) return $sessionid; } +/** + * Start the eGW session, exits on wrong credintials + * + * @param string $user + * @param string $passwd + * @param string $domain + */ +function load_egw($user,$passwd,$domain='default') +{ + //echo "load_egw($user,$passwd,$domain)\n"; + $_REQUEST['domain'] = $domain; + $GLOBALS['egw_login_data'] = array( + 'login' => $user, + 'passwd' => $passwd, + 'passwd_type' => 'text', + ); + + if (ini_get('session.save_handler') == 'files' && !is_writable(ini_get('session.save_path')) && is_dir('/tmp') && is_writable('/tmp')) + { + ini_set('session.save_path','/tmp'); // regular users may have no rights to apache's session dir + } + + $GLOBALS['egw_info'] = array( + 'flags' => array( + 'currentapp' => 'admin', + 'noheader' => true, + 'autocreate_session_callback' => 'user_pass_from_argv', + 'no_exception_handler' => 'cli', + ) + ); + + if (substr($user,0,5) != 'root_') + { + include('../header.inc.php'); + } + else + { + $GLOBALS['egw_info']['flags']['currentapp'] = 'login'; + include('../header.inc.php'); + + if ($user == 'root_'.$GLOBALS['egw_info']['server']['header_admin_user'] && + _check_pw($GLOBALS['egw_info']['server']['header_admin_password'],$passwd) || + $user == 'root_'.$GLOBALS['egw_domain'][$_GET['domain']]['config_user'] && + _check_pw($GLOBALS['egw_domain'][$_GET['domain']]['config_passwd'],$passwd)) + { + echo "\nRoot access granted!\n"; + egw_vfs::$is_root = true; + } + else + { + die("Unknown user or password!\n"); + } + } +} + +/** + * Check password against a md5 hash or cleartext password + * + * @param string $hash_or_cleartext + * @param string $pw + * @return boolean + */ +function _check_pw($hash_or_cleartext,$pw) +{ + //echo "_check_pw($hash_or_cleartext,$pw) md5=".md5($pw)."\n"; + if (preg_match('/^[0-9a-f]{32}$/',$hash_or_cleartext)) + { + return $hash_or_cleartext == md5($pw); + } + return $hash_or_cleartext == $pw; +} + /** * Give a usage message and exit * @@ -218,6 +274,8 @@ function usage($action=null,$ret=0) $cmd = basename($_SERVER['argv'][0]); echo "Usage: $cmd --command admin-account[@domain],admin-password,options,... [--schedule {YYYY-mm-dd|+1 week|+5 days}] [--requested 'Name '] [--comment 'comment ...'] [--remote {id|name}] [--skip-checks]\n\n"; + echo "\tAlternativly you can also use a setup user and password by prefixing it with 'root_', eg. 'root_admin' for setup user 'admin'.\n\n"; + echo "--edit-user admin-account[@domain],admin-password,account[=new-account-name],first-name,last-name,password,email,expires{never(default)|YYYY-MM-DD|already},can-change-pw{yes(default)|no},anon-user{yes|no(default)},primary-group{Default(default)|...}[,groups,...][,homedirectory,loginshell]\n"; echo " Edit or add a user to eGroupWare. If you specify groups, they *replace* the exiting memberships! homedirectory+loginshell are supported only for LDAP and must start with a slash!\n"; echo "--change-pw admin-account[@domain],admin-password,account,password\n"; @@ -235,6 +293,8 @@ function usage($action=null,$ret=0) echo " Changes one or more account_id's in the database (make a backup before!).\n"; echo "--check-acl admin-account[@domain],admin-password\n"; echo " Deletes ACL entries of not longer existing accounts (make a database backup before! --> setup-cli.php).\n"; + echo "--admin-cmd-check-cats admin-account[@domain],admin-password\n"; + echo " Deletes categories of not longer existing accounts.\n"; echo "--exit-codes admin-account[@domain],admin-password\n"; echo " List all exit codes of the command line interface\n"; From 0c5ca986c6f23e63a55a8f0f1b350942fad3cff1 Mon Sep 17 00:00:00 2001 From: Ralf Becker Date: Thu, 9 Aug 2012 08:25:53 +0000 Subject: [PATCH 003/135] quieten warning in delete-category hook, if cat is not used --- addressbook/inc/class.addressbook_bo.inc.php | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/addressbook/inc/class.addressbook_bo.inc.php b/addressbook/inc/class.addressbook_bo.inc.php index 0f20670002..d59adab7b1 100755 --- a/addressbook/inc/class.addressbook_bo.inc.php +++ b/addressbook/inc/class.addressbook_bo.inc.php @@ -1589,14 +1589,15 @@ class addressbook_bo extends addressbook_so // Get addresses that use the category @set_time_limit( 0 ); - $ids = array(); foreach($cat_ids as $cat_id) { - $ids = $this->search(array('cat_id' => $cat_id), false); - foreach($ids as &$info) + if (($ids = $this->search(array('cat_id' => $cat_id), false))) { - $info['cat_id'] = implode(',',array_diff(explode(',',$info['cat_id']), $cat_ids)); - $this->save($info); + foreach($ids as &$info) + { + $info['cat_id'] = implode(',',array_diff(explode(',',$info['cat_id']), $cat_ids)); + $this->save($info); + } } } } From cff9872f1723754ef9e7b8d12d28517beb3436f6 Mon Sep 17 00:00:00 2001 From: Ralf Becker Date: Thu, 9 Aug 2012 08:41:29 +0000 Subject: [PATCH 004/135] cast accounts->members(hips) to array, to cope without PHP warnings for not (longer) existing accounts --- calendar/inc/class.calendar_bo.inc.php | 2 +- calendar/inc/class.calendar_boupdate.inc.php | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/calendar/inc/class.calendar_bo.inc.php b/calendar/inc/class.calendar_bo.inc.php index aea491c444..db82d399a6 100644 --- a/calendar/inc/class.calendar_bo.inc.php +++ b/calendar/inc/class.calendar_bo.inc.php @@ -1145,7 +1145,7 @@ class calendar_bo { foreach($event['participants'] as $uid => $accept) { - if ($uid == $user || $uid < 0 && in_array($user,$GLOBALS['egw']->accounts->members($uid,true))) + if ($uid == $user || $uid < 0 && in_array($user, (array)$GLOBALS['egw']->accounts->members($uid,true))) { // if we are a participant, we have an implicite FREEBUSY, READ and PRIVAT grant $grant |= EGW_ACL_FREEBUSY | EGW_ACL_READ | EGW_ACL_PRIVATE; diff --git a/calendar/inc/class.calendar_boupdate.inc.php b/calendar/inc/class.calendar_boupdate.inc.php index e532b7312b..af5035e368 100644 --- a/calendar/inc/class.calendar_boupdate.inc.php +++ b/calendar/inc/class.calendar_boupdate.inc.php @@ -241,7 +241,7 @@ class calendar_boupdate extends calendar_bo if ($uid < 0) // group, check it's members too { - $users += $GLOBALS['egw']->accounts->members($uid,true); + $users += (array)$GLOBALS['egw']->accounts->members($uid,true); $users = array_unique($users); } $users[] = $uid; From 46f700851a57024f84e755008d5cc33bf35943a2 Mon Sep 17 00:00:00 2001 From: Ralf Becker Date: Thu, 9 Aug 2012 08:50:04 +0000 Subject: [PATCH 005/135] cast accounts->members(hips) to array, to cope without PHP warnings for not (longer) existing accounts --- phpgwapi/inc/class.acl.inc.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/phpgwapi/inc/class.acl.inc.php b/phpgwapi/inc/class.acl.inc.php index 4677602d8b..0be7ffe092 100644 --- a/phpgwapi/inc/class.acl.inc.php +++ b/phpgwapi/inc/class.acl.inc.php @@ -150,7 +150,7 @@ class acl } else { - $acl_acc_list = $GLOBALS['egw']->accounts->memberships($this->account_id, true); + $acl_acc_list = (array)$GLOBALS['egw']->accounts->memberships($this->account_id, true); if (is_array($no_groups)) $acl_acc_list = array_diff($acl_acc_list,$no_groups); array_unshift($acl_acc_list,$this->account_id); } From 51270655f9ec7033520972fe28d74dc21a4eb4c4 Mon Sep 17 00:00:00 2001 From: Ralf Becker Date: Thu, 9 Aug 2012 08:56:28 +0000 Subject: [PATCH 006/135] cast accounts->members(hips) to array, to cope without PHP warnings for not (longer) existing accounts --- phpgwapi/inc/class.accounts.inc.php | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/phpgwapi/inc/class.accounts.inc.php b/phpgwapi/inc/class.accounts.inc.php index 61738c03d1..bffc2ea755 100644 --- a/phpgwapi/inc/class.accounts.inc.php +++ b/phpgwapi/inc/class.accounts.inc.php @@ -271,9 +271,9 @@ class accounts elseif(in_array($param['type'],array('groupmembers','groupmembers+memberships'))) { $members = array(); - foreach($this->memberships($GLOBALS['egw_info']['user']['account_id'],true) as $grp) + foreach((array)$this->memberships($GLOBALS['egw_info']['user']['account_id'],true) as $grp) { - $members = array_unique(array_merge($members,$this->members($grp,true))); + $members = array_unique(array_merge($members, (array)$this->members($grp,true))); if ($param['type'] == 'groupmembers+memberships') $members[] = $grp; } $param['type'] = $param['type'] == 'groupmembers+memberships' ? 'both' : 'accounts'; @@ -663,8 +663,8 @@ class accounts $account_lid != $GLOBALS['egw_info']['user']['account_lid'] || // only allow group-members for account-selection is groupmembers $GLOBALS['egw_info']['user']['preferences']['common']['account_selection'] == 'groupmembers' && - !array_intersect($this->memberships($account_id,true), - $this->memberships($GLOBALS['egw_info']['user']['account_id'],true)))) + !array_intersect((array)$this->memberships($account_id,true), + (array)$this->memberships($GLOBALS['egw_info']['user']['account_id'],true)))) { //error_log(__METHOD__."($account_id='$account_lid') returning FALSE"); return false; // user is not allowed to see given account @@ -793,7 +793,7 @@ class accounts $accounts['groups'][$id] = $id; if ($use != 'groups') { - foreach($this->members($id,true) as $id) + foreach((array)$this->members($id,true) as $id) { $accounts['accounts'][$id] = $id; } From 188e2f80386d6c26999d4344f92081690326b650 Mon Sep 17 00:00:00 2001 From: Ralf Becker Date: Thu, 9 Aug 2012 09:02:50 +0000 Subject: [PATCH 007/135] cast accounts->members(hips) to array, to cope without PHP warnings for not (longer) existing accounts --- phpgwapi/inc/class.uiaccountsel.inc.php | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/phpgwapi/inc/class.uiaccountsel.inc.php b/phpgwapi/inc/class.uiaccountsel.inc.php index ec3a26bf8e..d9c59a2569 100644 --- a/phpgwapi/inc/class.uiaccountsel.inc.php +++ b/phpgwapi/inc/class.uiaccountsel.inc.php @@ -150,12 +150,12 @@ class uiaccountsel } else { - $memberships = $this->accounts->memberships($GLOBALS['egw_info']['user']['account_id'],true); + $memberships = (array)$this->accounts->memberships($GLOBALS['egw_info']['user']['account_id'],true); } $select = count($selected) && !isset($selected[0]) ? array_keys($selected) : $selected; foreach($memberships as $gid) { - foreach($this->accounts->members($gid,true) as $member) + foreach((array)$this->accounts->members($gid,true) as $member) { if (!in_array($member,$select)) $select[] = $member; } @@ -164,7 +164,7 @@ class uiaccountsel { if ($account_sel == 'primary_group') { - $memberships = $this->accounts->memberships($GLOBALS['egw_info']['user']['account_id'],true); + $memberships = (array)$this->accounts->memberships($GLOBALS['egw_info']['user']['account_id'],true); } $select = array_merge($select,$memberships); } @@ -178,6 +178,7 @@ class uiaccountsel 'type' => $use, 'app' => $app, )); + //error_log(__METHOD__."() account_selection='$this->account_selection', accounts->search(array('type'=>'$use', 'app' => '$app')) returns ".array2string($select)); } // make sure everything in $selected is also in $select, as in the other account-selection methods if ($selected && ($missing = array_diff_key($selected,$select))) @@ -270,6 +271,7 @@ class uiaccountsel $select2 += $select; $select =& $select2; unset($select2); } + //error_log(__METHOD__."(..., use='$use', ...) account_selection='$this->account_selection', select=".array2string($select)); if ($nohtml) { From e83a7c1b8dc54d881e20a992f6a63aaee4cf3288 Mon Sep 17 00:00:00 2001 From: Ralf Becker Date: Thu, 9 Aug 2012 09:08:45 +0000 Subject: [PATCH 008/135] cast accounts->members(hips) to array, to cope without PHP warnings for not (longer) existing accounts --- calendar/inc/class.calendar_ical.inc.php | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/calendar/inc/class.calendar_ical.inc.php b/calendar/inc/class.calendar_ical.inc.php index 2772637b7d..6098169620 100644 --- a/calendar/inc/class.calendar_ical.inc.php +++ b/calendar/inc/class.calendar_ical.inc.php @@ -465,8 +465,8 @@ class calendar_ical extends calendar_boupdate case 'g': $cutype = 'GROUP'; $participantURL = 'urn:uuid:'.common::generate_uid('accounts', $uid); - $members = $GLOBALS['egw']->accounts->members($uid, true); - if (!isset($event['participants'][$this->user]) && in_array($this->user, $members)) + if (!isset($event['participants'][$this->user]) && + ($members = $GLOBALS['egw']->accounts->members($uid, true)) && in_array($this->user, $members)) { $user = $this->resource_info($this->user); $attributes['ATTENDEE'][] = 'MAILTO:' . $user['email']; @@ -2826,8 +2826,8 @@ class calendar_ical extends calendar_boupdate $status != 'X' && $status != 'U') { // User tries to reply to the group invitiation - $members = $GLOBALS['egw']->accounts->members($uid, true); - if (in_array($this->user, $members)) + if (($members = $GLOBALS['egw']->accounts->members($uid, true)) && + in_array($this->user, $members)) { //Horde::logMessage("vevent2egw: set status to " . $status, // __FILE__, __LINE__, PEAR_LOG_DEBUG); From f7fa8ea37e79e4a1edb72f35c7f7d26c5c24614a Mon Sep 17 00:00:00 2001 From: Ralf Becker Date: Thu, 9 Aug 2012 12:41:47 +0000 Subject: [PATCH 009/135] * Addressbook/InfoLog/Filemanager/Tracker: added or fixed formatting of certain custom field types using a single shared method --- .../inc/class.addressbook_tracking.inc.php | 21 +---- etemplate/inc/class.bo_merge.inc.php | 41 ++------- etemplate/inc/class.bo_tracking.inc.php | 43 ++++++++- .../inc/class.customfields_widget.inc.php | 89 ++++++++++++++++++- infolog/inc/class.infolog_tracking.inc.php | 33 ++----- 5 files changed, 141 insertions(+), 86 deletions(-) diff --git a/addressbook/inc/class.addressbook_tracking.inc.php b/addressbook/inc/class.addressbook_tracking.inc.php index 786d4c462d..9187aa233d 100644 --- a/addressbook/inc/class.addressbook_tracking.inc.php +++ b/addressbook/inc/class.addressbook_tracking.inc.php @@ -277,24 +277,9 @@ class addressbook_tracking extends bo_tracking break; } } - if ($this->contacts->customfields) - { - foreach($this->contacts->customfields as $name => $custom) - { - if (!$header_done) - { - $details['custom'] = array( - 'value' => lang('Custom fields').':', - 'type' => 'reply', - ); - $header_done = true; - } - $details['#'.$name] = array( - 'label' => $custom['label'], - 'value' => $custom['type'] == 'select' ? $custom['values'][$data['#'.$name]] : $data['#'.$name], - ); - } - } + // add custom fields for given type + $details += $this->get_customfields($data, $data['tid']); + return $details; } } diff --git a/etemplate/inc/class.bo_merge.inc.php b/etemplate/inc/class.bo_merge.inc.php index d1c0f9e166..8f544dbc38 100644 --- a/etemplate/inc/class.bo_merge.inc.php +++ b/etemplate/inc/class.bo_merge.inc.php @@ -245,42 +245,11 @@ abstract class bo_merge } if ($name != 'photo') $replacements['$$'.($prefix ? $prefix.'/':'').$name.'$$'] = $value; } - // set custom fields + // set custom fields, should probably go to a general method all apps can use foreach($this->contacts->customfields as $name => $field) { $name = '#'.$name; - $value = (string)$contact[$name]; - switch($field['type']) - { - case 'select-account': - if ($value) $value = common::grab_owner_name($value); - break; - - case 'select': - if (count($field['values']) == 1 && isset($field['values']['@'])) - { - $field['values'] = customfields_widget::_get_options_from_file($field['values']['@']); - } - $values = array(); - foreach($field['rows'] > 1 ? explode(',',$value) : (array) $value as $value) - { - $values[] = $field['values'][$value]; - } - $value = implode(', ',$values); - break; - - case 'date': - case 'date-time': - if ($value) - { - $format = $field['len'] ? $field['len'] : ($field['type'] == 'date' ? 'Y-m-d' : 'Y-m-d H:i:s'); - $date = array_combine(preg_split('/[\\/. :-]/',$format),preg_split('/[\\/. :-]/',$value)); - $value = common::dateformatorder($date['Y'],$date['m'],$date['d'],true); - if (isset($date['H'])) $value .= ' '.common::formattime($date['H'],$date['i']); - } - break; - } - $replacements['$$'.($prefix ? $prefix.'/':'').$name.'$$'] = $value; + $replacements['$$'.($prefix ? $prefix.'/':'').$name.'$$'] = customfields_widget::format_customfield($field, (string)$contact[$name]); } // Add in extra cat field @@ -1578,7 +1547,7 @@ abstract class bo_merge ),true); } } - + $dircount = array(); foreach($files as $key => $file) { @@ -1635,7 +1604,7 @@ abstract class bo_merge if ($GLOBALS['egw_info']['flags']['currentapp'] == 'addressbook') $current_level[$prefix.$file['name']]['confirm_multiple'] = lang('Do you want to send the message to all selected entries, WITHOUT further editing?'); } break; - + default: if(!is_array($current_level[$prefix.$name_arr[$count]])) { @@ -1687,7 +1656,7 @@ abstract class bo_merge } } } - + return array( 'icon' => 'etemplate/merge', 'caption' => $caption, diff --git a/etemplate/inc/class.bo_tracking.inc.php b/etemplate/inc/class.bo_tracking.inc.php index 5705576b01..781ea51105 100644 --- a/etemplate/inc/class.bo_tracking.inc.php +++ b/etemplate/inc/class.bo_tracking.inc.php @@ -1,12 +1,12 @@ * @package etemplate * @subpackage api - * @copyright (c) 2007-10 by Ralf Becker + * @copyright (c) 2007-12 by Ralf Becker * @license http://opensource.org/licenses/gpl-license.php GPL - GNU General Public License * @version $Id$ */ @@ -210,6 +210,8 @@ abstract class bo_tracking /** * Get the details of an entry * + * You can/should call $this->get_customfields() to add custom fields. + * * @param array|object $data * @param int|string $receiver nummeric account_id or email address * @return array of details as array with values for keys 'label','value','type' @@ -219,6 +221,43 @@ abstract class bo_tracking return array(); } + /** + * Get custom fields of an entry of an entry + * + * @param array|object $data + * @param string $only_type2=null if given only return fields of type2 == $only_type2 + * @return array of details as array with values for keys 'label','value','type' + */ + function get_customfields($data, $only_type2=null) + { + $details = array(); + + if (($cfs = config::get_customfields($this->app, $all_private_too=false, $only_type2))) + { + $header_done = false; + foreach($cfs as $name => $field) + { + if (in_array($field['type'], customfields_widget::$non_printable_fields)) continue; + + if (!$header_done) + { + $details['custom'] = array( + 'value' => lang('Custom fields').':', + 'type' => 'reply', + ); + $header_done = true; + } + //error_log(__METHOD__."() $name: data['#$name']=".array2string($data['#'.$name]).", field[values]=".array2string($field['values'])); + $details['#'.$name] = array( + 'label' => $field['label'], + 'value' => customfields_widget::format_customfield($field, $data['#'.$name]), + ); + //error_log("--> details['#$name']=".array2string($details['#'.$name])); + } + } + return $details; + } + /** * Get a config value, which can depend on $data and $old * diff --git a/etemplate/inc/class.customfields_widget.inc.php b/etemplate/inc/class.customfields_widget.inc.php index db6b7a18ba..2b36d41036 100644 --- a/etemplate/inc/class.customfields_widget.inc.php +++ b/etemplate/inc/class.customfields_widget.inc.php @@ -1,6 +1,6 @@ @@ -514,7 +514,7 @@ class customfields_widget * @param string $file file name inside the eGW server root, either relative to it or absolute * @return array in case of an error we return a single option with the message */ - function _get_options_from_file($file) + public static function _get_options_from_file($file) { if (!($path = realpath($file{0} == '/' ? $file : EGW_SERVER_ROOT.'/'.$file)) || // file does not exist substr($path,0,strlen(EGW_SERVER_ROOT)+1) != EGW_SERVER_ROOT.'/' || // we are NOT inside the eGW root @@ -593,4 +593,89 @@ class customfields_widget } } } + + /** + * Non printable custom fields eg. UI elements + * + * @var array + */ + public static $non_printable_fields = array('button'); + + /** + * Format a single custom field value as string + * + * @param array $field field defintion incl. type + * @param string $value field value + * @return string formatted value + */ + public static function format_customfield(array $field, $value) + { + switch($field['type']) + { + case 'select-account': + if ($value) + { + $values = array(); + foreach($field['rows'] > 1 ? explode(',', $value) : (array) $value as $value) + { + $values[] = common::grab_owner_name($value); + } + $value = implode(', ',$values); + } + break; + + case 'checkbox': + $value = $value ? 'X' : ''; + break; + + case 'select': + case 'radio': + if (count($field['values']) == 1 && isset($field['values']['@'])) + { + $field['values'] = customfields_widget::_get_options_from_file($field['values']['@']); + } + $values = array(); + foreach($field['rows'] > 1 ? explode(',', $value) : (array) $value as $value) + { + $values[] = isset($field['values'][$value]) ? $field['values'][$value] : '#'.$value; + } + $value = implode(', ', $values); + break; + + case 'date': + case 'date-time': + if ($value) + { + $format = $field['len'] ? $field['len'] : ($field['type'] == 'date' ? 'Y-m-d' : 'Y-m-d H:i:s'); + $date = array_combine(preg_split('/[\\/. :-]/',$format), preg_split('/[\\/. :-]/',$value)); + $value = common::dateformatorder($date['Y'], $date['m'], $date['d'],true); + if (isset($date['H'])) $value .= ' '.common::formattime($date['H'], $date['i']); + } + break; + + case 'htmlarea': // ToDo: EMail probably has a nicer html2text method + if ($value) $value = strip_tags(preg_replace('/<(br|p)[^>]*>/i', "\r\n", str_replace(array("\r", "\n"), '', $value))); + break; + + case 'ajax_select': // ToDo: returns unchanged value for now + break; + + default: + // handling for several link types + if ($value && in_array($field['type'], self::get_customfield_link_types())) + { + if ($field['type'] == 'link-entry' || strpos($value, ':') !== false) + { + list($app, $value) = explode(':', $value); + } + else + { + $app = $field['type']; + } + if ($value) $value = egw_link::title($app, $value); + } + break; + } + return $value; + } } diff --git a/infolog/inc/class.infolog_tracking.inc.php b/infolog/inc/class.infolog_tracking.inc.php index e190973264..2a417cfb5c 100644 --- a/infolog/inc/class.infolog_tracking.inc.php +++ b/infolog/inc/class.infolog_tracking.inc.php @@ -189,15 +189,13 @@ class infolog_tracking extends bo_tracking /** * Get the details of an entry * - * @param array $data - * @param string $datetime_format of user to notify, eg. 'Y-m-d H:i' - * @param int $tz_offset_s offset in sec to be add to server-time to get the user-time of the user to notify + * @param array|object $data + * @param int|string $receiver nummeric account_id or email address * @return array of details as array with values for keys 'label','value','type' */ - function get_details($data) + function get_details($data,$receiver=null) { //error_log(__METHOD__.__LINE__.' Data:'.array2string($data)); - $header_done = false; $responsible = array(); if ($data['info_responsible']) { @@ -247,30 +245,9 @@ class infolog_tracking extends bo_tracking 'value' => $data['info_des'], 'type' => 'multiline', ); - // should be moved to bo_tracking because auf the different custom field types - if ($this->infolog->customfields) - { - foreach($this->infolog->customfields as $name => $field) - { - if ($field['type2'] && !in_array($data['info_type'],explode(',',$field['type2']))) continue; // different type + // add custom fields for given type + $details += $this->get_customfields($data, $data['info_type']); - if (!$header_done) - { - $details['custom'] = array( - 'value' => lang('Custom fields').':', - 'type' => 'reply', - ); - $header_done = true; - } - //error_log(__METHOD__."() $name: data['#$name']=".array2string($data['#'.$name]).", field[values]=".array2string($field['values'])); - $details['#'.$name] = array( - 'label' => $field['label'], - 'value' => is_array($field['values']) && $field['values'] && isset($data['#'.$name]) && - array_key_exists((string)$data['#'.$name],$field['values']) ? $field['values'][$data['#'.$name]] : $data['#'.$name], - ); - //error_log("--> details['#$name']=".array2string($details['#'.$name])); - } - } return $details; } From 4c3c423b3d029073c66cbfa36fe9e3a860e18170 Mon Sep 17 00:00:00 2001 From: Ralf Becker Date: Thu, 9 Aug 2012 12:57:19 +0000 Subject: [PATCH 010/135] more German translations from Gudrun --- addressbook/lang/egw_de.lang | 11 ++--- addressbook/lang/egw_en.lang | 26 ++++++++++++ admin/lang/egw_de.lang | 77 +++++++++++++++++++++------------- admin/lang/egw_en.lang | 10 +++++ notifications/lang/egw_de.lang | 2 +- notifications/lang/egw_en.lang | 1 + 6 files changed, 92 insertions(+), 35 deletions(-) diff --git a/addressbook/lang/egw_de.lang b/addressbook/lang/egw_de.lang index a12f8916d5..c890c2972d 100644 --- a/addressbook/lang/egw_de.lang +++ b/addressbook/lang/egw_de.lang @@ -5,12 +5,12 @@ %1 fields in %2 other organisation member(s) changed addressbook de %1 Felder in %2 Mitglied(ern) der Organisation geändert %1 not implemented for %2! addressbook de %1 nicht implementiert für %2! %1 records imported addressbook de %1 Datensätze importiert -%1 records read (not yet imported, you may go %2back%3 and uncheck test import) addressbook de %1 Datensätze gelesen (noch nicht importiert, sie können %2zurück%3 gehen und Test-Import ausschalten)A +%1 records read (not yet imported, you may go %2back%3 and uncheck test import) addressbook de %1 Datensätze gelesen (noch nicht importiert, sie können %2zurück%3 gehen und Test-Import ausschalten) %1 starts with '%2' addressbook de %1 beginnt mit '%2' %s please calculate the result addressbook de %s Bitte berechnen Sie das Ergebnis (e.g. 1969) addressbook de (z.B. 1969) (empty = use global limit, no = no export at all) admin de (leer = globale Begrenzung verwenden, nein = gar kein Export) -no conversion type <none> could be located. please choose a conversion type from the list addressbook de Kein Übersetzungstyp konnte gefunden werden. Bitte wählen Sie einen Übersetzungstyp aus der Liste +no conversion type <none> could be located. please choose a conversion type from the list addressbook de Kein Übersetzungstyp konnte gefunden werden. Bitte wählen Sie einen Übersetzungstyp aus der Liste aus. @-eval() is only availible to admins!!! addressbook de @-eval() ist nur für Administratoren verfügbar !!! account id addressbook de Benutzerkonten ID account repository admin de Speicherort für Benutzerkonten @@ -140,7 +140,7 @@ default document to insert contacts addressbook de Standarddokument zum Einfüge default file as format addressbook de Vorgabe für eigene Sortierung default filter addressbook de Standardfilter default format for fileas, eg. for new entries. addressbook de Vorgegebenes Format für eigene Sortierung, z.B. für neue Einträge -default is to open email addresses in egroupware email application, if user has access to it. addressbook de Vorgabe ist EMail Adressen in EGroupware's EMail Anwendung zu öffnen, wenn der Benutzer darauf Zugriff hat. +default is to open email addresses in egroupware email application, if user has access to it. addressbook de Vorgabe ist E-Mail Adressen in EGroupware's E-Mail Anwendung zu öffnen, wenn der Benutzer darauf Zugriff hat. defines which email address (business or home) to use as the preferred one for distribution lists in mail. addressbook de Legt fest, welche E-Mailadresse (geschäftlich oder privat) für Verteilerlisten in E-Mail bevorzugt benutzt werden soll. delete a single entry by passing the id. addressbook de Löscht einen einzelnen Eintrag durch Übergabe seiner ID. delete selected distribution list! addressbook de Löscht die ausgewählten Verteilerliste! @@ -193,6 +193,7 @@ export definitition to use for nextmatch export addressbook de Export Profil der export file name addressbook de Dateiname zum Exportieren export from addressbook addressbook de Export vom Adressbuch export selection addressbook de Auswahl exportieren +exported addressbook de exportiert exports contacts from your addressbook into a csv file. addressbook de Exportiert Kontakte vom Adressbuch in eine CSV Datei. CSV bedeutet 'Komma getrennte Werte'. exports contacts from your addressbook into a csv file. csv means 'comma seperated values'. however in the options tab you can also choose other seperators. addressbook de Exportiert Kontakte vom Adressbuch in eine CSV Datei. CSV bedeutet 'Komma getrennte Werte'. Im Optionen Reiter können Sie aber auch ein anderes Trennzeichen wählen. extra addressbook de Extra @@ -297,7 +298,7 @@ no fallback addressbook de Keine Ausweichlösung no vcard addressbook de Keine VCard number addressbook de Nummer number of records to read (%1) addressbook de Anzahl der einzulesenden Datensätze (%1) -open email addresses in external mail program addressbook de Öffne EMail Adressen in externem Mail Programm +open email addresses in external mail program addressbook de Öffne E-Mail Adressen in externem Mail Programm options for type admin de Optionen für Typ organisation addressbook de Organisation organisations addressbook de Organisationen @@ -371,7 +372,7 @@ start admin de Starten startrecord addressbook de Startdatensatz state common de Bundesland street common de Straße -subject for email addressbook de Betreff der Email +subject for email addressbook de Betreff der E-mail successfully imported %1 records into your addressbook. addressbook de %1 Kontakte wurden erfolgreich in Ihr Adressbuch importiert suffix addressbook de Zusatz tag to mark positions for address labels addressbook de Markierungszeichen, um die Positionen von Adressetiktetten zu markieren diff --git a/addressbook/lang/egw_en.lang b/addressbook/lang/egw_en.lang index 088655e89d..bd4496c36e 100644 --- a/addressbook/lang/egw_en.lang +++ b/addressbook/lang/egw_en.lang @@ -77,6 +77,7 @@ business zip code addressbook en Business postal code calendar fields: addressbook en Calendar fields: calendar uri addressbook en Calendar URI can be changed via setup >> configuration admin en Can be changed via Setup >> Configuration +can't create dn %1 addressbook en Can't create dn %1 car phone addressbook en Car phone categorie addressbook en Category categorie added addressbook en Category added. @@ -183,16 +184,21 @@ enter the path to the exported file here addressbook en Enter the path to the ex error deleting the contact !!! addressbook en Error deleting the contact! error saving the contact !!! addressbook en Error saving the contact! error: the entry has been updated since you opened it for editing! addressbook en Error: the entry has been updated since you opened it for editing! +example {{if n_prefix~mr~hello mr.~hello ms.}} - search the field "n_prefix", for "mr", if found, write hello mr., else write hello ms. addressbook en Example {{IF n_prefix~Mr~Hello Mr.~Hello Ms.}} - search the field "n_prefix", for "Mr", if found, write Hello Mr., else write Hello Ms. example {{letterprefixcustom n_prefix title n_family}} - example: mr dr. james miller preferences en Example {{LETTERPREFIXCUSTOM n_prefix title n_family}} - Example: Mr Dr. James Miller +example {{nelf role}} - if field role is not empty, you will get a new line with the value of field role addressbook en Example {{NELF role}} - if field role is not empty, you will get a new line with the value of field role +example {{nelfnv role}} - if field role is not empty, set a lf without any value of the field addressbook en Example {{NELFNV role}} - if field role is not empty, set a LF without any value of the field existing links addressbook en Existing links exists addressbook en Exists export as csv addressbook en Export as CSV export as vcard addressbook en Export as vCard export contacts addressbook en Export contacts +export definition to use for nextmatch export addressbook en Export definition to use for nextmatch export export definitition to use for nextmatch export addressbook en Export definition to use for nextmatch export export file name addressbook en Export file name export from addressbook addressbook en Export from address book export selection addressbook en Export selection +exported addressbook en exported exports contacts from your addressbook into a csv file. addressbook en Exports contacts from address book into a CSV file. exports contacts from your addressbook into a csv file. csv means 'comma seperated values'. however in the options tab you can also choose other seperators. addressbook en Exports contacts from address book into a CSV file. CSV means 'Comma Separated Values'. In the options tab you can also choose other separators. extra addressbook en Extra @@ -207,10 +213,13 @@ fields for the csv export addressbook en Fields for the CSV export fields the user is allowed to edit himself admin en Fields the user is allowed to edit himself fields to copy when copying an address? admin en Fields to copy when copying an address fields to show in address list addressbook en Fields to show in address list +fieldseparator addressbook en Fieldseparator for read only ldap admin en For read only LDAP for serial letter use this tag. put the content, you want to repeat between two tags. addressbook en Use this tag for serial letter. Place the content you want to repeat between two tags. freebusy uri addressbook en FreeBusy URI full name addressbook en Full name +general admin en General +general fields: addressbook en General fields: geo addressbook en GEO global categories addressbook en Global categories grant addressbook access common en Grant address book access @@ -232,7 +241,12 @@ home zip code addressbook en Home ZIP code how many contacts should non-admins be able to export admin en How many contacts should non-admins be able to export. icon addressbook en Icon if accounts are already in ldap admin en If accounts are already in LDAP +if you specify a directory (full vfs path) here, %1 displays an action for each document. that action allows to download the specified document with the data inserted. addressbook en If you specify a directory (full vfs path) here, %1 displays an action for each document. That action allows to download the specified document with the data inserted. +if you specify a document (full vfs path) here, %1 displays an extra document icon for each entry. that icon allows to download the specified document with the data inserted. addressbook en If you specify a document (full vfs path) here, %1 displays an extra document icon for each entry. That icon allows to download the specified document with the data inserted. +if you specify an export definition, it will be used when you export addressbook en If you specify an export definition, it will be used when you export +if you specify an export definition, it will be used when you export* addressbook en If you specify an export definition, it will be used when you export* ignore first line addressbook en Ignore first line +import addressbook en Import import contacts addressbook en Import contacts import csv-file into addressbook addressbook en Import CSV file into Address book import file addressbook en Import file @@ -242,6 +256,7 @@ import from outlook addressbook en Import from Outlook import multiple vcard addressbook en Import multiple vCards import next set addressbook en Import next set import_instructions addressbook en In Netscape, open the Address book and select Export from the File menu. The file exported will be in LDIF format.

Or, in Outlook, select your Contacts folder, select Import and Export... from the File menu and export your contacts into a comma separated text (CSV) file.

Or, in Palm Desktop 4.0 or greater, visit your address book and select Export from the File menu. The file exported will be in vCard format. +importer's personal addressbook en Importer's personal imports contacts into your addressbook from a csv file. csv means 'comma seperated values'. however in the options tab you can also choose other seperators. addressbook en Imports contacts into address book from a CSV File. CSV means 'Comma Separated Values'. In the options tab you can also choose other separators. in %1 days (%2) is %3's birthday. addressbook en In %1 days (%2) is %3's birthday. income addressbook en Income @@ -261,15 +276,20 @@ ldif addressbook en LDIF line 2 addressbook en Line 2 link title for contacts show addressbook en Link title for contacts links addressbook en Links +links and attached files addressbook en Links and attached files +links to specified application. example: {{links/infolog}} addressbook en Links to specified application. Example: {{links/infolog}} list all categories addressbook en List all categories list all customfields addressbook en List all custom fields list already exists! addressbook en List already exists! list created addressbook en List created. list creation failed, no rights! addressbook en List creation failed, no rights! +list of files linked to the current record addressbook en List of files linked to the current record load vcard addressbook en Load vCard location addressbook en Location locations addressbook en Locations +mail vcard addressbook en Mail VCard main categories in their own field addressbook en Main categories in their own field +manage mapping addressbook en Manage mapping mark records as private addressbook en Mark records as private merge contacts addressbook en Merge contacts merge into first or account, deletes all other! addressbook en Merge into first or account, deletes all other! @@ -297,6 +317,7 @@ no fallback addressbook en No fallback no vcard addressbook en No vCard number addressbook en Number number of records to read (%1) addressbook en Number of records to read (%1) +old fixed definition addressbook en Old fixed definition open email addresses in external mail program addressbook en Open EMail addresses in external mail program options for type admin en Options for type organisation addressbook en Organisation @@ -383,6 +404,8 @@ that field name has been used already ! addressbook en The field name has been u the anonymous user has probably no add rights for this addressbook. addressbook en The anonymous user has no add rights for this address book. the anonymous user needs add rights for it! addressbook en The anonymous user needs add rights! the anonymous user needs read it! addressbook en The anonymous user needs read rights! +the document can contain placeholder like {{%3}}, to be replaced with the data (%1full list of placeholder names%2). addressbook en The document can contain placeholder like {{%3}}, to be replaced with the data (%1full list of placeholder names%2). +the following document-types are supported: addressbook en The following document-types are supported: the zip extension is needed, to insert contact data in openoffice or msoffice documents. addressbook en The zip extension is needed, to insert contact data in OpenOffice or MSOffice documents. there was an error saving your data :-( addressbook en ERROR saving data! this module displays a contactform, that stores direct into the addressbook. addressbook en This module displays a contact form, that stores directly into the address book. @@ -391,9 +414,11 @@ this person's first name was not in the address book. addressbook en This person this person's last name was not in the address book. addressbook en This person's last name was not in the address book. timezone addressbook en Time zone title addressbook en Job title +titles of any entries linked to the current record, excluding attached files addressbook en Titles of any entries linked to the current record, excluding attached files to many might exceed your execution-time-limit addressbook en Too many might exceed your execution time limit. today is %1's birthday! common en Today is %1's birthday! tomorrow is %1's birthday. common en Tomorrow is %1's birthday. +translation addressbook en Translation two of: %1 addressbook en Two of: %1 type addressbook en Type un-delete addressbook en Un-delete @@ -405,6 +430,7 @@ update fields by edited organisations? admin en Fields to update of edited organ updated addressbook en Updated upload or delete the photo addressbook en Upload or delete the photo url to link telephone numbers to (use %1 = number to call, %u = account name, %t = account phone) admin en URL to link telephone numbers to. Use %1 = number to call, %u = account name, %t = account phone. +use addressbooks "own sorting" attribute addressbook en use addressbooks "own sorting" attribute use an extra category tab? addressbook en Use an extra tab for categories use an extra tab for private custom fields? admin en Use an extra tab for private custom fields use country list addressbook en Use country list diff --git a/admin/lang/egw_de.lang b/admin/lang/egw_de.lang index a6225a3896..63e3db4f32 100644 --- a/admin/lang/egw_de.lang +++ b/admin/lang/egw_de.lang @@ -1,6 +1,9 @@ %1 - %2 of %3 user accounts admin de %1 - %2 von %3 Benutzerkonten %1 - %2 of %3 user groups admin de %1 - %2 von %3 Benutzergruppen %1 acl records of not (longer) existing accounts deleted. admin de %1 ACL Einträge von nicht (mehr) existierenden Accounts gelöscht. +%1 categories of not (longer) existing accounts deleted. admin de %1 Kategorien von nicht (mehr) existierenden Accounts gelöscht. +%1 category(s) %2 admin de %1 Kategorie(n) %2 +%1 category(s) %2, %3 failed because of insufficent rights !!! admin de %1 Kategorie(n) %2, %3 fehlgeschlagen wegen fehlender Rechte! %1 class not instanciated admin de %1 Klasse nicht instanziert %1 group %2 admin de %1 Gruppe %2 %1 is no command! admin de %1 ist kein Befehl ! @@ -60,10 +63,11 @@ after how many unsuccessful attempts to login, an account should be blocked (def after how many unsuccessful attempts to login, an ip should be blocked (default 3) ? admin de Nach wievielen erfolglosen Anmeldeversuchen soll eine IP-Adresse gesperrt werden (Vorgabe 3)? aliases admin de E-Mail-Alias all applications admin de Alle Anwendungen +all categories admin de Alle Kategorien all records and account information will be lost! admin de Alle Datensätze und Kontoinformationen sind dann verloren! all users admin de Alle Benutzer allow anonymous access to this app admin de Anonymen Zugriff auf diese Anwendung zulassen -allow remote administration from following install id's (comma separated) admin de Erlaube die Remote-Verwaltung identifiziert durch folgende (Komma separierte) Install IDs +allow remote administration from following install id's (comma separated) admin de Erlaube die Remote-Verwaltung durch folgende (Komma separierte) Install IDs alternate email address admin de Alternative E-Mail-Adresse anonymous user admin de Anonymer Benutzer anonymous user (not shown in list sessions) admin de Anonymer Benutzer (wird bei 'Sitzungen anzeigen' nicht angezeigt) @@ -91,7 +95,7 @@ are you sure you want to kill this session ? admin de Sind Sie sicher, dass Sie async services last executed admin de Asynchroner Dienst zuletzt ausgeführt asynchronous timed services admin de Asynchroner zeitgesteuerter Dienst asyncservices not yet installed or other error (%1) !!! admin de Asynchroner Dienst ist noch nicht installiert oder ein anderer Fehler ist aufgetreten (%1) !!! -attempt to use correct mimetype for ftp instead of default 'application/octet-stream' admin de Soll versucht werden, den richtigen MINE-typ für FTP zu verwenden, statt dem Vorgabewert "application/octet-stream" +attempt to use correct mimetype for ftp instead of default 'application/octet-stream' admin de Es wird versucht, den richtigen MIME-typ für FTP zu verwenden, statt dem Vorgabewert "application/octet-stream". attribute accountstatus explained admin de Dies betrifft das Attribut -accountStatus- aus dem QMAIL Schema attribute mail explained admin de Dies betrifft das Attribut -mail- aus dem CORE Schema. Dieses Attribut darf nicht leer sein und wird gleichzeitig als E-Mail-Adresse innerhalb eGW verwendet. attribute mailalternateaddress explained admin de Dies betrifft das Attribut -mailAlternateAddress- aus dem QMAIL Schema. Das experimentelle Schema verwendet dies auch als Alias für mailLocalAddress. @@ -119,13 +123,16 @@ change account_id admin de Änderung der account_id change acl rights admin de ACL-Rechte ändern change config settings admin de Konfiguration der Anwendung ändern change main screen message admin de Nachricht der Startseite ändern +change owner admin de Besitzer ändern change password for %1 admin de Ändern des Passworts für %1 -change password hash to admin de Passwort Verschlüsselung ändern zu +change password hash to admin de Passwort Verschlüsselung ändern in +changed password hash for %1 to %2. admin de Passwort Verschlüsselung für %1 ändern in %2. check acl for entries of not (longer) existing accounts admin de Prüfe ACL Einträge auf Bezüge zu nicht (mehr) existierenden Benutzerkonten +check categories for not (longer) existing accounts admin de Prüfe Kategorien auf Bezüge zu nicht (mehr) existierenden Benutzerkonten check ip address of all sessions admin de IP-Adresse für alle Sessions überprüfen check items to %1 to %2 for %3 admin de Durch Abhaken %3 in %2 %1 children admin de Kinder -click to select a color admin de Anclicken um eine Farbe auszuwählen +click to select a color admin de Anklicken um eine Farbe auszuwählen color admin de Farbe command scheduled to run at %1 admin de Ausführung des Befehls eingeplant am/um %1 commercial: all sorts of companies admin de Kommerziell: alle Arten von Firmen @@ -155,7 +162,7 @@ default file system space per user admin de Vorgabewert für Dateisystemplatz pr default file system space per user/group ? admin de Vorgabewert für Dateisystemplatz pro Benutzer/Gruppe verwenden? deinstall crontab admin de Crontab deinstallieren delete account admin de Benutzerkonto löschen -delete account %1 admin de Löschen des Benutzerkontos %1 +delete account %1 admin de Benutzerkonto %1 löschen delete all records admin de Alle Einträge löschen delete application admin de Anwendung löschen delete category admin de Kategorie löschen @@ -169,6 +176,7 @@ delete this category admin de Kategorie löschen delete this group admin de Gruppe löschen delete this log entry admin de Diesen Protokolleintrag löschen delete this user admin de Benutzer löschen +deleted admin de gelöscht deletes this field admin de löscht dieses Feld deliver extern admin de Extern ausliefern deny access to access log admin de Zugriff auf Zugangsprotokoll verbieten @@ -194,10 +202,10 @@ disable admin de abschalten disable "auto completion" of the login form admin de Automatisches Vervollständigen der Logindaten abschalten disable wysiwyg-editor admin de WYSIWYG Editor (formatierter Text) abschalten disabled (not recomended) admin de abgeschaltet (nicht empfohlen) -display admin de Anzeigen +display admin de anzeigen do not delete the category and return back to the list admin de Kategorie NICHT löschen und zurück zur Liste gehen do you also want to delete all global subcategories ? admin de Wollen Sie auch alle globalen Unterkategorien löschen? -do you want to delete all global subcategories ? admin de Möchten Sie alle Globale Unterkategorien löschen? +do you want to delete all global subcategories ? admin de Möchten Sie alle globale Unterkategorien löschen? do you want to move all global subcategories one level down ? admin de Wollen Sie alle globalen Unterkategorien eine Ebene nach unten verschieben? document root (default) admin de Wurzelverzeichnis des Webservers (Vorgabe) down admin de unten @@ -259,19 +267,21 @@ enter your http proxy server port admin de HTTP-Proxy-Server-Port enter your smtp server hostname or ip address admin de SMTP-Server Hostname oder IP-Adresse enter your smtp server port admin de SMTP-Server Port error canceling timer, maybe there's none set !!! admin de Fehler beim Abbrechen des Test-Jobs, eventuell läuft gar kein Job !!! -error changing the password for % !!! admin de Fehler beim Ändern des Passworts für % !!! +error changing the password for % !!! admin de Fehler beim Ändern des Passworts für % ! error changing the password for %1 !!! admin de Fehler beim Ändern des Passworts für %1 ! error deleting log entry! admin de Fehler beim Löschen des Protokolleintrags! error saving admin de Fehler beim Speichern error saving account! admin de Fehler beim Speichern des Benutzerkontos! error saving the command! admin de Fehler beim Speichern des Befehls! error saving to db: admin de Fehler beim Speichern in der Datenbank: -error setting timer, wrong syntax or maybe there's one already running !!! admin de Fehler beim Starten des Test-Jobs, falsche Syntax oder es läuft schon einer!!! +error setting timer, wrong syntax or maybe there's one already running !!! admin de Fehler beim Starten des Test-Jobs, falsche Syntax oder es läuft schon einer! error! no appname found admin de Fehler: Kein Anwendungsname gefunden -error: %1 not found or other error !!! admin de Fehler: %1 nicht gefunden oder anderer Fehler!!! +error: %1 not found or other error !!! admin de Fehler: %1 nicht gefunden oder anderer Fehler! exists admin de existiert expires admin de abgelaufen explanation of ldapman admin de Dieses Modul ist derzeit nur für folgende Konfiguration getestet: Postfix, LDAP, Courier-Imap, Procmail und erfordert die Schemas: core und qmail(OID 7914). Weitere Konfigurationshinweise sind im README.ldapman im DOC Verzeichnis des Moduls ADMIN zu finden. +exports groups into a csv file. admin de Benutzergruppen in eine CSV-Datei exportieren. +exports users into a csv file. admin de Benutzer in eine CSV-Datei exportieren. failed to change password for account "%1"! admin de Fehler beim Ändern des Passwortes für Benutzer "%1"! failed to mount backup directory! admin de Konnte Datensicherungsverzeichnis nicht mounten! fallback (after each pageview) admin de Ausweichmöglichkeit (nach jedem Seitenaufbau) @@ -294,7 +304,9 @@ go directly to admin menu, returning here the next time you click on administrat governmental: incl. state or municipal authorities or services admin de Öffentlicher Dienst: Bundes-, Länder- oder stättische Behörden und Dienstleistungen grant admin de Berechtigungen group ? admin de Gruppe ? +group csv export admin de CSV Export von Gruppen group csv import admin de CSV Import von Gruppen +group excepted from above export limit (admins are always excepted) admin de Gruppen die vom oben angegeben Exportlimit ausgenommen sind (Administratoren sind immer ausgenommen) group has been added common de Gruppe wurde hinzugefügt group has been deleted common de Gruppe wurde gelöscht group has been updated common de Gruppe wurde aktualisiert @@ -306,7 +318,7 @@ hide php information admin de PHP-Informationen ausblenden home directory admin de Benutzerverzeichnis host information admin de Host-Information hour
(0-23) admin de Stunde
(0-23) -how big should thumbnails for linked images be (maximum in pixels) ? admin de Wie gross sollen Thumbnails für verknüpfte Bilder sein (maximum in Bildpunkten) +how big should thumbnails for linked images be (maximum in pixels) ? admin de Wie gross sollen Thumbnails für verknüpfte Bilder sein (maximum in Bildpunkten)? how many days should entries stay in the access log, before they get deleted (default 90) ? admin de Wie viele Tage sollen Einträge im Zugangsprotokoll bleiben, bevor sie gelöscht werden (Vorgabe 90)? how many entries should non-admins be able to export (empty = no limit, no = no export) admin de Wie viele Einträge sollen Nicht-Administratoren exportieren können (leer = kein Limit, Nein = kein Export) how many minutes should an account or ip be blocked (default 30) ? admin de Wie viele Minuten soll ein Benutzerkonto oder eine IP gesperrt werden (Vorgabe 30)? @@ -327,6 +339,7 @@ installed crontab admin de Installierte Crontab instance admin de Instanz interface admin de Schnittstelle international use admin de Internationale Benutzung +invalid argument '%1' !!! admin de Ungültiges Argument "%1"! invalid formated date "%1"! admin de Ungültig formatiertes Datum "%1"! invalid remote id or name "%1"! admin de Ungültige RemoteID oder Name "%1"! invalid value "%1" use yes or no! admin de Ungültiger Wert "%1". Verwenden Sie Ja oder Nein (yes/no) @@ -339,6 +352,7 @@ last %1 logins for %2 admin de Letze %1 Logins für %2 last action admin de Letzte Aktion last login admin de Letzter Login last login from admin de Letzer Login von +last password change admin de Letzte Passwortänderung last submission: admin de Letzte Absendung: last time read admin de Zuletzt gelesen ldap accounts context admin de LDAP-Kontext für Benutzerkonten @@ -352,12 +366,12 @@ ldap rootdn admin de LDAP rootdn leave empty for no quota admin de Leer lassen für keine Quota leave the category untouched and return back to the list admin de Kategorie unverändert lassen und zur Liste zurückkehren leave the group untouched and return back to the list admin de Gruppe unverändert lassen und zur Liste zurückkehren -leave unchanged admin de Unverändert lassen +leave unchanged admin de unverändert lassen leave without saveing the entry admin de beendet ohne den Eintrag zu speichern leaves without saveing admin de beendet ohne zu speichern length
rows admin de Länge
Zeilen limit global category to members of a certain group admin de Beschränkt die global Kategorie auf der Mitglieder einer bestimmten Gruppe -limit to members of admin de Beschränken auf Mitglieder von +limit to members of admin de beschränken auf Mitglieder von list config settings admin de Konfigurationseinstellungen auflisten list current sessions admin de aktive Sitzungen anzeigen list of current users admin de Liste der gegenwärtigen Benutzer @@ -390,7 +404,7 @@ month admin de Monat more secure admin de sicherer mount backup directory to %1 admin de Datensicherungsverzeichnis unter %1 mounten must change password upon next login admin de Muss das Passwort beim nächsten Login ändern -name must not be empty !!! admin de Name darf nicht leer sein !!! +name must not be empty !!! admin de Name darf nicht leer sein! name of the egroupware instance, eg. default admin de Name der EGroupware Instanz, z.B. default new group name admin de Neuer Gruppenname new name admin de neuer Name @@ -399,7 +413,7 @@ new password [ leave blank for no change ] admin de Neues Passwort [ Feld leer l next run admin de nächste Ausführung no algorithms available admin de Kein Algorithmus verfügbar no alternate email address admin de keine Aliase definiert -no jobs in the database !!! admin de Keine Jobs in der Datenbank !!! +no jobs in the database !!! admin de Keine Jobs in der Datenbank! no login history exists for this user admin de Benutzer hat sich noch nie angemeldet no matches found admin de Keine Übereinstimmungen gefunden no modes available admin de Kein Modus verfügbar @@ -409,10 +423,10 @@ no permission to create groups admin de Sie haben keine ausreichenden Rechte um non profit: clubs, associations, ... admin de Gemeinnützig: Vereine, Verbände, ... note: ssl available only if php is compiled with curl support admin de Notiz: SSL ist nur verfügbar, wenn PHP mit CURL-Unterstützung gebaut wurde notification mail admin de Benachrichtigungsmail -notify user by email admin de Benutzer per Mail benachrichtigen -notifying account "%1" %2 failed! admin de Benachrichtigen von Benutzer "%1" %2 fehl geschlagen! +notify user by email admin de Benutzer per E-Mail benachrichtigen +notifying account "%1" %2 failed! admin de Benachrichtigen von Benutzer "%1" %2 fehlgeschlagen! number applications serially admin de Numeriere Anwendungen aufeinander folgend -number of active users admin de Anzahl aktive User +number of active users admin de Anzahl aktiver User number of row for a multiline inputfield or line of a multi-select-box admin de Anzahl der Zeilen in einem mehrzeiligen Feld oder eine multi-select-box number of sessions / egroupware logins in the last 30 days admin de Anzahl Sitzungen / EGroupware Logins in den letzten 30 Tagen number of users admin de Anzahl Benutzer @@ -427,7 +441,9 @@ only below displayed information is directly submitted to %s. admin de Nur die u operating system admin de Betriebssystem order admin de Reihenfolge outbound admin de ausgehend -own install id: admin de Eigene Install-ID +own categories admin de eigene Kategorien +own install id: admin de eigene Install-ID +owner "%1" removed, please select group-owner admin de Besitzer "%1" entfernt, bitte einen Gruppenbesitzer auswählen. passthrough admin de durchgehend password for smtp-authentication admin de Passwort für SMTP Authentifizierung password updated admin de Passwort aktualisiert @@ -463,10 +479,11 @@ register application hooks admin de Registrieren der "Hooks" der Anwendungen remote administration instances admin de Remote Administrations Instanzen remote administration need to be enabled in the remote instance under admin > site configuration! admin de Die Remote Administration muss von der Remote-Instanz (unter Admin -> Konfiguration der Anwendung) freigegeben werden. remote instance saved admin de Remote Instanz gespeichert -remove admin de Entfernen -remove all users from this group admin de Entferne alle Benutzer aus dieser Gruppe -remove all users from this group ? admin de Entferne alle Benutzer aus dieser Gruppe ? -requested admin de Angefordert +remove admin de entfernen +remove all users from this group admin de Entferne alle Benutzer aus dieser Gruppe. +remove all users from this group ? admin de Entferne alle Benutzer aus dieser Gruppe? +removing access for groups may cause problems for data in this category. are you sure? users in these groups may no longer have access: admin de Sind Sie sicher? Den Zugriff für Gruppen zu nehmen kann zu Problemen mit den Daten dieser Kategorie führen. Benutzer dieser Gruppen haben möglicherweise keinen Zugriff mehr: +requested admin de angefordert return to admin mainscreen admin de zum Administrationsmenü zurückkehren return to view account admin de Zurück zum Anzeigen des Benutzerkontos route all mails to admin de Alle E-Mails senden an @@ -475,7 +492,7 @@ run asynchronous services admin de Asynchrone Dienste ausführen save the category admin de Kategorie speichern save the category and return back to the list admin de Kategorie speichern und zur Liste zurückkehren saves the changes made and leaves admin de beendet und speichert die Änderungen -saves this entry admin de Speichert diesen Eintrag +saves this entry admin de speichert diesen Eintrag scheduled admin de geplant search accounts admin de Benutzerkonten durchsuchen search categories admin de Kategorien durchsuchen @@ -484,7 +501,7 @@ search peer servers admin de Serververbund durchsuchen security admin de Sicherheit select accounts for which the custom field should be visible admin de Benutzer auswählen, für die dieses benutzerdefinierte Feld sichtbar sein soll. select group managers admin de Gruppenmanager auswählen -select permissions this group will have admin de Wählen Sie die Zugriffsrechte für diese Gruppe. +select permissions this group will have admin de wählen Sie die Zugriffsrechte für diese Gruppe. select the parent category. if this is a main category select no category admin de Eine übergeordnete Kategorie auswählen. Wenn dies eine Hauptkategorie ist, KEINE KATEGORIE auswählen. select users admin de Benutzer auswählen select users for inclusion admin de Benutzer für diese Gruppe auswählen @@ -512,9 +529,9 @@ show phpinfo() admin de phpinfo() anzeigen show session ip address admin de IP-Adresse der Sitzung anzeigen site admin de Site soap admin de SOAP -sorry, that group name has already been taken. admin de Der Gruppenname wird bereits verwendet. -sorry, the above users are still a member of the group %1 admin de Der Benutzer ist immer noch Mitglied der Gruppe %1. -sorry, the follow users are still a member of the group %1 admin de Sorry, die folgenden Benutzer sind noch Mitglied der Gruppe %1 +sorry, that group name has already been taken. admin de Dieser Gruppenname wird bereits verwendet. +sorry, the above users are still a member of the group %1 admin de Diese Benutzer sind noch Mitglied der Gruppe %1. +sorry, the follow users are still a member of the group %1 admin de Die folgenden Benutzer sind noch Mitglied der Gruppe %1. sort the entries admin de Einträge sortieren ssl admin de verschlüsselt (SSL) standard admin de Standard @@ -587,6 +604,7 @@ use cookies to pass sessionid admin de Sitzungs-ID in einem Cookie speichern use pure html compliant code (not fully working yet) admin de Vollständig HTML kompatiblen Code verwenden (nicht vollständig implementiert) use theme admin de Benutztes Farbschema user accounts admin de Benutzerkonten +user csv export admin de CSV Export von Benutzern user csv import admin de CSV Import von Benutzern user data common de Benutzerdaten user for smtp-authentication (leave it empty if no auth required) admin de Benutzer für SMTP Authentifizierung (leer lassen falls keine Authentifizierung nötig) @@ -594,6 +612,7 @@ user groups admin de Benutzergruppen userdata admin de Benutzerkonto users choice admin de Benutzerauswahl value for column %1 is not unique! admin de Wert für die Spalte %1 ist nicht eindeutig! +vfs directory "%1" not found! admin de VFS Verzeichnis "%1" nicht gefunden! view access log admin de Zugangsprotokoll anzeigen view account admin de Benutzerkonto anzeigen view category admin de Kategorie anzeigen @@ -601,7 +620,7 @@ view error log admin de Fehlerprotokoll anzeigen view sessions admin de Sitzungen anzeigen view this user admin de Diesen Benutzer anzeigen view user account admin de Benutzerkonto anzeigen -warn users about the need to change their password? the number set here should be lower than the value used to enforce the change of passwords every x days. only effective when enforcing of password change is enabled. (empty for no,number for number of days before they must change) admin de Warne Benutzer, dass Ihr Passwort in X Tagen abläuft? Der Wert hier gibt an, ab wieviel Tagen vorher die Benutzer einmal pro Sitzung gewarnt werden. Die hier eingetragene Zahl sollte kleiner sein, als der Wert der für das Erzwingen des Änderns von Passwörtern alle Y Tage verwendet wird. Diese Option ist nur wirksam, wenn das Erzwingen von Passwortänderungen alle Y Tage aktiviert ist. (leer für nein, eine positive Zahl für Warnung ab X Tagen bevor das Passwort abläuft) +warn users about the need to change their password? the number set here should be lower than the value used to enforce the change of passwords every x days. only effective when enforcing of password change is enabled. (empty for no,number for number of days before they must change) admin de Benutzer warnen, dass Ihr Passwort in X Tagen abläuft? Der Wert hier gibt an, ab wieviel Tagen vorher die Benutzer einmal pro Sitzung gewarnt werden. Die hier eingetragene Zahl sollte kleiner sein, als der Wert der für das Erzwingen des Änderns von Passwörtern alle Y Tage verwendet wird. Diese Option ist nur wirksam, wenn das Erzwingen von Passwortänderungen alle Y Tage aktiviert ist. (leer für nein, eine positive Zahl für Warnung ab X Tagen bevor das Passwort abläuft) we ask for the data to improve our profile in the press and to get a better understanding of egroupware's user base and it's needs. admin de Wir erheben diese Daten zu auschliesslich statistischen Zwecken, um einen Überblick über den weltweiten Einsatz von EGroupware zu gewinnen. we hope you understand the importance for this voluntary statistic and not deny it lightly. admin de Wir speichern keine Herkunftsdaten oder Informationen, die einen Rückschluss auf Ihre Identität ermöglichen würden. who would you like to transfer all records owned by the deleted user to? admin de Wem sollen alle Datensätze, die dem zu löschenden Benutzer gehören, übertragen werden? diff --git a/admin/lang/egw_en.lang b/admin/lang/egw_en.lang index 4e4344d3c0..127633c72f 100644 --- a/admin/lang/egw_en.lang +++ b/admin/lang/egw_en.lang @@ -1,6 +1,9 @@ %1 - %2 of %3 user accounts admin en %1 - %2 of %3 user accounts %1 - %2 of %3 user groups admin en %1 - %2 of %3 user groups %1 acl records of not (longer) existing accounts deleted. admin en %1 ACL records of not longer existing accounts deleted. +%1 categories of not (longer) existing accounts deleted. admin en %1 categories of not (longer) existing accounts deleted. +%1 category(s) %2 admin en %1 category(s) %2 +%1 category(s) %2, %3 failed because of insufficent rights !!! admin en %1 category(s) %2, %3 failed because of insufficent rights !!! %1 class not instanciated admin en %1 class not instanciated %1 group %2 admin en %1 group %2 %1 is no command! admin en %1 is no command! @@ -60,6 +63,7 @@ after how many unsuccessful attempts to login, an account should be blocked (def after how many unsuccessful attempts to login, an ip should be blocked (default 3) ? admin en After how many unsuccessful attempts to login an IP should be blocked. Default = 3 aliases admin en Aliases all applications admin en All applications +all categories admin en All categories all records and account information will be lost! admin en All records and account information will be lost! all users admin en All users allow anonymous access to this app admin en Allow anonymous access to this app @@ -124,6 +128,7 @@ change password for %1 admin en Change password for %1 change password hash to admin en Change password hash to changed password hash for %1 to %2. admin en Changed password hash for %1 to %2. check acl for entries of not (longer) existing accounts admin en Check ACL for entries of not existing accounts. +check categories for not (longer) existing accounts admin en Check categories for not (longer) existing accounts check ip address of all sessions admin en Check IP address of all sessions check items to %1 to %2 for %3 admin en Check items to %1 to %2 for %3 children admin en Children @@ -171,6 +176,7 @@ delete this category admin en Delete this category delete this group admin en Delete this group delete this log entry admin en Delete this log entry delete this user admin en Delete this user +deleted admin en deleted deletes this field admin en Deletes this field deliver extern admin en Deliver extern deny access to access log admin en Deny access to access log @@ -300,6 +306,7 @@ grant admin en Grant group ? admin en Group? group csv export admin en Group CSV export group csv import admin en Group CSV import +group excepted from above export limit (admins are always excepted) admin en Group excepted from above export limit (admins are always excepted) group has been added common en Group has been added. group has been deleted common en Group has been deleted. group has been updated common en Group has been updated. @@ -332,6 +339,7 @@ installed crontab admin en Installed crontab instance admin en Instance interface admin en Interface international use admin en International use +invalid argument '%1' !!! admin en Invalid argument '%1' !!! invalid formated date "%1"! admin en Invalid formated date "%1"! invalid remote id or name "%1"! admin en Invalid remote ID or name "%1"! invalid value "%1" use yes or no! admin en Invalid value "%1" use yes or no! @@ -433,6 +441,7 @@ only below displayed information is directly submitted to %s. admin en Only belo operating system admin en Operating system order admin en Order outbound admin en Outbound +own categories admin en Own categories own install id: admin en Own install ID: owner "%1" removed, please select group-owner admin en Owner "%1" removed, please select group owner passthrough admin en Passthrough @@ -603,6 +612,7 @@ user groups admin en User groups userdata admin en User data users choice admin en Users choice value for column %1 is not unique! admin en Value for column %1 is not unique! +vfs directory "%1" not found! admin en VFS directory "%1" NOT found! view access log admin en View access log view account admin en View account view category admin en View category diff --git a/notifications/lang/egw_de.lang b/notifications/lang/egw_de.lang index 86dcba5713..839ef3f067 100644 --- a/notifications/lang/egw_de.lang +++ b/notifications/lang/egw_de.lang @@ -24,7 +24,7 @@ from notifications de von how verbose should the egroupware-popup behave if a notification is sent to the user:
low: just display the notification bell in the topmenu - topmenu must be enabled!
medium: bring notification window to front
high: bring notification window to front and let the browser do something to announce itself notifications de Wie hoch soll das EGroupware-Popup die Priorität setzen wenn eine Benachrichtigung an den Benutzer gesendet wird:
Niedrig: Es wird nur die Benachrichtigungsglocke im Topmenü angezeigt - das Topmenü muss hierfür eingeschaltet sein!
Mittel: Holt das Benachrichtigungsfenster in den Vordergrund
Hoch: Holt das Benachrichtigungsfenster in den Vordergrund und aktiviert den Browser zur besseren Erkennung der Benachrichtigung. if set, embedded links get rendered special for external clients notifications de Wenn diese Option aktiviert ist, werden "eingebettete Links" besser graphisch aufbereitet. linked entries: common de Verknüpfte Einträge: -mail backend admin de Mail Schnittstelle +mail backend admin de E-Mail Schnittstelle maximum sms messages per notification admin de Maximale Anzahl an SMS Nachrichten pro Benachrichtigung message from notifications de Nachricht von minutes notifications de Minuten diff --git a/notifications/lang/egw_en.lang b/notifications/lang/egw_en.lang index 9f1bec331e..26b7cc029c 100644 --- a/notifications/lang/egw_en.lang +++ b/notifications/lang/egw_en.lang @@ -36,6 +36,7 @@ preferences for notification notifications en Preferences for notification received notifications en Received sms backend admin en SMS back end sms only notifications en SMS only +this egroupware notification has been sent to you by mail because your notifications en This eGroupWare notification has been sent to you by mail because your this egroupware notification has been sent to you by mail because your chosen notification-chain has been disabled by the administrator. please choose another notification-chain in your preferences! notifications en This EGroupware notification has been sent to you by mail because your chosen notification chain has been disabled by the administrator. Please choose another notification chain in your preferences! windows-popup and e-mail notifications en Windows popup and email windows-popup backend admin en Windows popup back end From 56a4bdfbbe1dbf3041d816e65a7266a03aa39396 Mon Sep 17 00:00:00 2001 From: Ralf Becker Date: Sat, 11 Aug 2012 10:01:02 +0000 Subject: [PATCH 011/135] * Calendar: fixed issue of deleted first recurrence shortens event and causes it not to be find in CalDAV or eSync ("event has exceptions before startdate"), REQUIRES SCHEMA UPDATE (visit setup)! --- calendar/inc/class.calendar_boupdate.inc.php | 6 +- calendar/inc/class.calendar_so.inc.php | 79 ++++++++++++-------- calendar/setup/setup.inc.php | 3 +- calendar/setup/tables_current.inc.php | 6 +- calendar/setup/tables_update.inc.php | 51 +++++++++++++ 5 files changed, 107 insertions(+), 38 deletions(-) diff --git a/calendar/inc/class.calendar_boupdate.inc.php b/calendar/inc/class.calendar_boupdate.inc.php index af5035e368..1937ec4751 100644 --- a/calendar/inc/class.calendar_boupdate.inc.php +++ b/calendar/inc/class.calendar_boupdate.inc.php @@ -1404,6 +1404,7 @@ class calendar_boupdate extends calendar_bo */ function delete($cal_id,$recur_date=0,$ignore_acl=false,$skip_notification=false) { + //error_log(__METHOD__."(cal_id=$cal_id, recur_date=$recur_date, ignore_acl=$ignore_acl, skip_notifications=$skip_notification)"); if (!($event = $this->read($cal_id,$recur_date)) || !$ignore_acl && !$this->check_perms(EGW_ACL_DELETE,$event)) { @@ -1446,7 +1447,10 @@ class calendar_boupdate extends calendar_bo } else // delete an exception { - $event['recur_exception'][] = $recur_date = $this->date2ts($event['start']); + // need to read series master, as otherwise existing exceptions will be lost! + $recur_date = $this->date2ts($event['start']); + $event = $this->read($cal_id); + $event['recur_exception'][] = $recur_date; unset($event['start']); unset($event['end']); $this->save($event); // updates the content-history diff --git a/calendar/inc/class.calendar_so.inc.php b/calendar/inc/class.calendar_so.inc.php index 33d266c9d8..2436e50280 100644 --- a/calendar/inc/class.calendar_so.inc.php +++ b/calendar/inc/class.calendar_so.inc.php @@ -60,7 +60,7 @@ define('WEEK_s',7*DAY_s); * - egw_cal_repeats: recur-data: type, optional enddate, etc. * - egw_cal_extra: custom fields (multiple entries per cal_id possible) * - * The new UI, BO and SO classes have a strikt definition, in which time-zone they operate: + * The new UI, BO and SO classes have a strict definition, in which timezone they operate: * UI only operates in user-time, so there have to be no conversation at all !!! * BO's functions take and return user-time only (!), they convert internaly everything to servertime, because * SO operates only on server-time @@ -178,9 +178,8 @@ class calendar_so ",$this->dates_table LEFT JOIN $this->repeats_table ON $this->dates_table.cal_id=$this->repeats_table.cal_id". " WHERE $this->cal_table.cal_id=$this->dates_table.cal_id") as $row) { - $row['recur_exception'] = $row['recur_exception'] ? explode(',',$row['recur_exception']) : array(); if (!$row['recur_type']) $row['recur_type'] = MCAL_RECUR_NONE; - $row['alarm'] = array(); + $row['recur_exception'] = $row['alarm'] = array(); $events[$row['cal_id']] = egw_db::strip_array_keys($row,'cal_'); // if a uid was supplied, convert it for the further code to an id @@ -193,28 +192,21 @@ class calendar_so if (!isset($event['uid']) || strlen($event['uid']) < $minimum_uid_length) { // event (without uid), not strong enough uid => create new uid - $event['uid'] = $GLOBALS['egw']->common->generate_uid('calendar',$event['id']); + $event['uid'] = common::generate_uid('calendar',$event['id']); $this->db->update($this->cal_table, array('cal_uid' => $event['uid']), array('cal_id' => $event['id']),__LINE__,__FILE__,'calendar'); } - if ((int) $recur_date == 0 && - $event['recur_type'] != MCAL_RECUR_NONE && - !empty($event['recur_exception'])) + if (!(int)$recur_date && $event['recur_type'] != MCAL_RECUR_NONE) { - sort($event['recur_exception']); - if ($event['recur_exception'][0] < $event['start']) + foreach($this->db->select($this->dates_table, 'cal_id,cal_start', array( + 'cal_id' => $ids, + 'recur_exception' => true, + ), __LINE__, __FILE__, false, 'ORDER BY cal_id,cal_start', 'calendar') as $row) { - /* Do NOT move start- and end-date, to the earliest exception, as they will NOT be found in CalDAV or ActiveSync, because - * we only recognice recuring events which start before or in the current timerange and end in or after it or have no end-date. - * --> give an error message, as it is a debuging/support nightmare, if this get's silently fixed when reading events. - * No idea how this situation (exceptions before startdate) can be created anyway. - * - * $event['end'] -= $event['start'] - $event['recur_exception'][0]; - * $event['start'] = $event['recur_exception'][0]; - */ - error_log(__METHOD__."() recuring event #$event[id]: $event[title] has exceptions before it's startdate ".date('Y-m-d H:i:s',$event['start'])); + $events[$row['cal_id']]['recur_exception'][] = $row['cal_start']; } - }//*/ + break; // as above select read all exceptions (and I dont think too short uid problem still exists) + } } // check if we have a real recurance, if not set $recur_date=0 @@ -424,7 +416,7 @@ class calendar_so $cols = self::get_columns('calendar', $this->cal_table); $cols[0] = $this->db->to_varchar($this->cal_table.'.cal_id'); - $cols = isset($params['cols']) ? $params['cols'] : "$this->repeats_table.recur_type,$this->repeats_table.recur_enddate,$this->repeats_table.recur_interval,$this->repeats_table.recur_data,$this->repeats_table.recur_exception,".implode(',',$cols).",cal_start,cal_end,$this->user_table.cal_recur_date"; + $cols = isset($params['cols']) ? $params['cols'] : "$this->repeats_table.recur_type,$this->repeats_table.recur_enddate,$this->repeats_table.recur_interval,$this->repeats_table.recur_data,".implode(',',$cols).",cal_start,cal_end,$this->user_table.cal_recur_date"; $where = array(); if (is_array($params['query'])) @@ -639,7 +631,7 @@ class calendar_so // we only select cal_table.cal_id (and not cal_table.*) to be able to use DISTINCT (eg. MsSQL does not allow it for text-columns) foreach(array_keys($selects) as $key) { - $selects[$key]['cols'] = "DISTINCT $this->repeats_table.recur_type,$this->repeats_table.recur_enddate,$this->repeats_table.recur_interval,$this->repeats_table.recur_data,$this->repeats_table.recur_exception,".$this->db->to_varchar($this->cal_table.'.cal_id').",cal_start,cal_end,$this->user_table.cal_recur_date"; + $selects[$key]['cols'] = "DISTINCT $this->repeats_table.recur_type,$this->repeats_table.recur_enddate,$this->repeats_table.recur_interval,$this->repeats_table.recur_data,".$this->db->to_varchar($this->cal_table.'.cal_id').",cal_start,cal_end,$this->user_table.cal_recur_date"; if (!$params['enum_recuring']) { $selects[$key]['cols'] = str_replace('cal_start','MIN(cal_start) AS cal_start',$selects[$key]['cols']); @@ -698,8 +690,7 @@ class calendar_so { $row['participants'] = array(); } - $row['alarm'] = array(); - $row['recur_exception'] = $row['recur_exception'] ? explode(',',$row['recur_exception']) : array(); + $row['recur_exception'] = $row['alarm'] = array(); // compile a list of recurrences per cal_id if (!in_array($id,(array)$recur_ids[$row['cal_id']])) $recur_ids[$row['cal_id']][] = $id; @@ -755,6 +746,20 @@ class calendar_so $events[$id]['max_user_modified'] = $modified; } } + // query recurrance exceptions, if needed + if (!$params['enum_recuring']) + { + foreach($this->db->select($this->dates_table, 'cal_id,cal_start', array( + 'cal_id' => $ids, + 'recur_exception' => true, + ), __LINE__, __FILE__, false, 'ORDER BY cal_id,cal_start', 'calendar') as $row) + { + foreach((array)$recur_ids[$row['cal_id']] as $i) + { + $events[$i]['recurce_id'][] = $row['cal_start']; + } + } + } // max_user_modified for recurring events has to include all recurrences, above code only querys $recur_date! if (!$params['enum_recuring'] && $need_max_user_modified) { @@ -1070,7 +1075,7 @@ ORDER BY cal_user_type, cal_usre_id // event without uid or not strong enough uid if (!isset($event['cal_uid']) || strlen($event['cal_uid']) < $minimum_uid_length) { - $update['cal_uid'] = $event['cal_uid'] = $GLOBALS['egw']->common->generate_uid('calendar',$cal_id); + $update['cal_uid'] = $event['cal_uid'] = common::generate_uid('calendar',$cal_id); } // set caldav_name, if not given by caller if (empty($event['caldav_name']) && version_compare($GLOBALS['egw_info']['apps']['calendar']['version'], '1.9.003', '>=')) @@ -1103,11 +1108,13 @@ ORDER BY cal_user_type, cal_usre_id $old_min = (int) $this->db->select($this->dates_table,'MIN(cal_start)',array('cal_id'=>$cal_id),__LINE__,__FILE__,false,'','calendar')->fetchColumn(); $old_duration = (int) $this->db->select($this->dates_table,'MIN(cal_end)',array('cal_id'=>$cal_id),__LINE__,__FILE__,false,'','calendar')->fetchColumn() - $old_min; $old_repeats = $this->db->select($this->repeats_table,'*',array('cal_id' => $cal_id),__LINE__,__FILE__,false,'','calendar')->fetch(); - $old_exceptions = $old_repeats['recur_exception'] ? explode(',',$old_repeats['recur_exception']) : array(); - if (!empty($old_exceptions)) + $old_exceptions = array(); + foreach($this->db->select($this->dates_table, 'cal_start', array( + 'cal_id' => $cal_id, + 'recur_exception' => true + ), __LINE__, __FILE__, false, 'ORDER BY cal_start', 'calendar') as $row) { - sort($old_exceptions); - if ($old_min > $old_exceptions[0]) $old_min = $old_exceptions[0]; + $old_exceptions[] = $row['cal_start']; } $event['recur_exception'] = is_array($event['recur_exception']) ? $event['recur_exception'] : array(); @@ -1116,8 +1123,10 @@ ORDER BY cal_user_type, cal_usre_id sort($event['recur_exception']); } - $where = array('cal_id' => $cal_id, - 'cal_recur_date' => 0); + $where = array( + 'cal_id' => $cal_id, + 'cal_recur_date' => 0, + ); $old_participants = array(); foreach ($this->db->select($this->user_table,'cal_user_type,cal_user_id,cal_status,cal_quantity,cal_role', $where, __LINE__,__FILE__,false,'','calendar') as $row) @@ -1197,14 +1206,18 @@ ORDER BY cal_user_type, cal_usre_id // truncate recurrences by given exceptions if (count($event['recur_exception'])) { - // added and existing exceptions: delete the execeptions from the user and dates table, it could be the first time + // added and existing exceptions: delete the execeptions from the user table, it could be the first time $this->db->delete($this->user_table,array('cal_id' => $cal_id,'cal_recur_date' => $event['recur_exception']),__LINE__,__FILE__,'calendar'); - $this->db->delete($this->dates_table,array('cal_id' => $cal_id,'cal_start' => $event['recur_exception']),__LINE__,__FILE__,'calendar'); + // update recur_exception flag based on current exceptions + $this->db->update($this->dates_table, 'recur_exception='.$this->db->expression($this->dates_table,array( + 'cal_start' => $event['recur_exception'], + )), array( + 'cal_id' => $cal_id, + ), __LINE__, __FILE__, 'calendar'); } } // write the repeats table - $event['recur_exception'] = empty($event['recur_exception']) ? null : implode(',',$event['recur_exception']); unset($event[0]); // unset the 'etag=etag+1', as it's not in the repeats table $this->db->insert($this->repeats_table,$event,array('cal_id' => $cal_id),__LINE__,__FILE__,'calendar'); } diff --git a/calendar/setup/setup.inc.php b/calendar/setup/setup.inc.php index be7330243e..c85a3276fe 100755 --- a/calendar/setup/setup.inc.php +++ b/calendar/setup/setup.inc.php @@ -10,7 +10,7 @@ */ $setup_info['calendar']['name'] = 'calendar'; -$setup_info['calendar']['version'] = '1.9.004'; +$setup_info['calendar']['version'] = '1.9.005'; $setup_info['calendar']['app_order'] = 3; $setup_info['calendar']['enable'] = 1; $setup_info['calendar']['index'] = 'calendar.calendar_uiviews.index'; @@ -70,3 +70,4 @@ $setup_info['calendar']['check_install'] = array( ); + diff --git a/calendar/setup/tables_current.inc.php b/calendar/setup/tables_current.inc.php index aa17d845ee..51eb97b535 100644 --- a/calendar/setup/tables_current.inc.php +++ b/calendar/setup/tables_current.inc.php @@ -62,7 +62,6 @@ $phpgw_baseline = array( 'recur_enddate' => array('type' => 'int','precision' => '8'), 'recur_interval' => array('type' => 'int','precision' => '2','default' => '1'), 'recur_data' => array('type' => 'int','precision' => '2','default' => '1'), - 'recur_exception' => array('type' => 'text','comment' => 'comma-separated start timestamps of exceptions') ), 'pk' => array('cal_id'), 'fk' => array(), @@ -100,11 +99,12 @@ $phpgw_baseline = array( 'fd' => array( 'cal_id' => array('type' => 'int','precision' => '4','nullable' => False), 'cal_start' => array('type' => 'int','precision' => '8','nullable' => False,'comment' => 'starttime in server time'), - 'cal_end' => array('type' => 'int','precision' => '8','nullable' => False,'comment' => 'endtime in server time') + 'cal_end' => array('type' => 'int','precision' => '8','nullable' => False,'comment' => 'endtime in server time'), + 'recur_exception' => array('type' => 'bool','nullable' => False,'default' => '','comment' => 'date is an exception') ), 'pk' => array('cal_id','cal_start'), 'fk' => array(), - 'ix' => array(), + 'ix' => array(array('recur_exception','cal_id')), 'uc' => array() ), 'egw_cal_timezones' => array( diff --git a/calendar/setup/tables_update.inc.php b/calendar/setup/tables_update.inc.php index a39e3f431d..1a77264cb3 100644 --- a/calendar/setup/tables_update.inc.php +++ b/calendar/setup/tables_update.inc.php @@ -2076,3 +2076,54 @@ function calendar_upgrade1_9_003() return $GLOBALS['setup_info']['calendar']['currentver'] = '1.9.004'; } + +/** + * Store exceptions as flag in egw_cal_dates.recur_exception, instead of egw_cal_repleats.recur_exception + * + * Keeps information of original start in egw_cal_dates (if first recurrance got deleted) and allows for unlimited number of exceptions. + */ +function calendar_upgrade1_9_004() +{ + $GLOBALS['egw_setup']->oProc->AddColumn('egw_cal_dates','recur_exception',array( + 'type' => 'bool', + 'default' => '', + 'null' => false, + 'comment' => 'date is an exception' + )); + + // migrate existing exceptions to egw_cal_dates + foreach($GLOBALS['egw_setup']->db->select('egw_cal_repeats', + 'egw_cal_repeats.cal_id AS cal_id,egw_cal_repeats.recur_exception AS recur_exception,MIN(cal_start) AS cal_start,MIN(cal_end) AS cal_end', + 'egw_cal_repeats.recur_exception IS NOT NULL', __LINE__, __FILE__, false, + 'GROUP BY egw_cal_repeats.cal_id,egw_cal_repeats.recur_exception', 'calendar', '', + 'JOIN egw_cal_dates ON egw_cal_repeats.cal_id=egw_cal_dates.cal_id') as $row) + { + foreach($row['recur_exception'] ? explode(',', $row['recur_exception']) : array() as $recur_exception) + { + $GLOBALS['egw_setup']->db->insert('egw_cal_dates', array( + 'cal_id' => $row['cal_id'], + 'cal_start' => $recur_exception, + 'cal_end' => $recur_exception+$row['cal_end']-$row['cal_start'], + 'recur_exception' => true, + ), false, __LINE__, __FILE__, 'calendar'); + } + } + $GLOBALS['egw_setup']->oProc->CreateIndex('egw_cal_dates', array('recur_exception', 'cal_id')); + + $GLOBALS['egw_setup']->oProc->DropColumn('egw_cal_repeats', array( + 'fd' => array( + 'cal_id' => array('type' => 'int','precision' => '4','nullable' => False), + 'recur_type' => array('type' => 'int','precision' => '2','nullable' => False), + 'recur_enddate' => array('type' => 'int','precision' => '8'), + 'recur_interval' => array('type' => 'int','precision' => '2','default' => '1'), + 'recur_data' => array('type' => 'int','precision' => '2','default' => '1'), + ), + 'pk' => array('cal_id'), + 'fk' => array(), + 'ix' => array(), + 'uc' => array() + ), 'recur_exception'); + + return $GLOBALS['setup_info']['calendar']['currentver'] = '1.9.005'; +} + From c0f83a275d17efb698c25be99155335bc33def7a Mon Sep 17 00:00:00 2001 From: Ralf Becker Date: Sun, 12 Aug 2012 09:49:06 +0000 Subject: [PATCH 012/135] * API/Setup/MySQL: fixed backup to correctly report boolean columns and support MySQL 5.0+ varchar(>255) --- phpgwapi/inc/class.schema_proc.inc.php | 18 +++++++++++++++++- 1 file changed, 17 insertions(+), 1 deletion(-) diff --git a/phpgwapi/inc/class.schema_proc.inc.php b/phpgwapi/inc/class.schema_proc.inc.php index bded628880..40ae7e9b3b 100644 --- a/phpgwapi/inc/class.schema_proc.inc.php +++ b/phpgwapi/inc/class.schema_proc.inc.php @@ -127,6 +127,14 @@ class schema_proc case 'maxdb': $this->max_varchar_length = 8000; break; + case 'mysql': + // since MySQL 5.0 65535, but with utf8 and row-size-limit of 64k: + // it's effective 65535/3 - size of other columns, so we use 20000 (mysql silently convert to text anyway) + if ((float)$this->m_odb->ServerInfo['version'] >= 5.0) + { + $this->max_varchar_length = 20000; + } + break; } if (is_object($GLOBALS['egw_setup'])) { @@ -1155,7 +1163,7 @@ class schema_proc function GetTableDefinition($sTableName) { // MetaType returns all varchar >= blobSize as blob, it's by default 100, which is wrong - if ($this->dict->blobSize < 255) $this->dict->blobSize = 255; + $this->dict->blobSize = $this->max_varchar_length; if (!method_exists($this->dict,'MetaColumns') || !($columns = $this->dict->MetaColumns($sTableName))) @@ -1266,6 +1274,14 @@ class schema_proc $column->has_default = False; } } + // fix MySQL stores bool columns as smallint + if ($this->sType == 'mysql' && $definition['fd'][$name]['precision'] == 1 && + $this->m_odb->get_column_attribute($name, $sTableName, true, 'type') === 'bool') + { + $definition['fd'][$name]['type'] = 'bool'; + unset($definition['fd'][$name]['precision']); + $column->default_value = (bool)$column->default_value; + } break; } if ($column->has_default) From 7eec30c57a3f511c5c0567991eaa8cad73e228f5 Mon Sep 17 00:00:00 2001 From: Ralf Becker Date: Sun, 12 Aug 2012 09:49:54 +0000 Subject: [PATCH 013/135] * Calendar: Try alter description to varchar(16384), to not force temp. tables to disk on MySQL (because of text columns) --- calendar/setup/setup.inc.php | 5 +---- calendar/setup/tables_current.inc.php | 8 ++++---- calendar/setup/tables_update.inc.php | 29 +++++++++++++++++++++++++++ 3 files changed, 34 insertions(+), 8 deletions(-) diff --git a/calendar/setup/setup.inc.php b/calendar/setup/setup.inc.php index c85a3276fe..c7e091ece3 100755 --- a/calendar/setup/setup.inc.php +++ b/calendar/setup/setup.inc.php @@ -10,7 +10,7 @@ */ $setup_info['calendar']['name'] = 'calendar'; -$setup_info['calendar']['version'] = '1.9.005'; +$setup_info['calendar']['version'] = '1.9.006'; $setup_info['calendar']['app_order'] = 3; $setup_info['calendar']['enable'] = 1; $setup_info['calendar']['index'] = 'calendar.calendar_uiviews.index'; @@ -68,6 +68,3 @@ $setup_info['calendar']['check_install'] = array( 'from' => 'Calendar', ), ); - - - diff --git a/calendar/setup/tables_current.inc.php b/calendar/setup/tables_current.inc.php index 51eb97b535..e681a62019 100644 --- a/calendar/setup/tables_current.inc.php +++ b/calendar/setup/tables_current.inc.php @@ -15,12 +15,12 @@ $phpgw_baseline = array( 'cal_id' => array('type' => 'auto','nullable' => False), 'cal_uid' => array('type' => 'varchar','precision' => '255','nullable' => False,'comment' => 'unique id of event(-series)'), 'cal_owner' => array('type' => 'int','precision' => '4','nullable' => False,'comment' => 'event owner / calendar'), - 'cal_category' => array('type' => 'varchar','precision' => '30','comment' => 'category id'), + 'cal_category' => array('type' => 'varchar','precision' => '64','comment' => 'category id(s)'), 'cal_modified' => array('type' => 'int','precision' => '8','comment' => 'ts of last modification'), 'cal_priority' => array('type' => 'int','precision' => '2','nullable' => False,'default' => '2'), 'cal_public' => array('type' => 'int','precision' => '2','nullable' => False,'default' => '1','comment' => '1=public, 0=private event'), - 'cal_title' => array('type' => 'varchar','precision' => '255','nullable' => False,'default' => '1'), - 'cal_description' => array('type' => 'text'), + 'cal_title' => array('type' => 'varchar','precision' => '255','nullable' => False), + 'cal_description' => array('type' => 'varchar','precision' => '16384'), 'cal_location' => array('type' => 'varchar','precision' => '255'), 'cal_reference' => array('type' => 'int','precision' => '4','nullable' => False,'default' => '0','comment' => 'cal_id of series for exception'), 'cal_modifier' => array('type' => 'int','precision' => '4','comment' => 'user who last modified event'), @@ -61,7 +61,7 @@ $phpgw_baseline = array( 'recur_type' => array('type' => 'int','precision' => '2','nullable' => False), 'recur_enddate' => array('type' => 'int','precision' => '8'), 'recur_interval' => array('type' => 'int','precision' => '2','default' => '1'), - 'recur_data' => array('type' => 'int','precision' => '2','default' => '1'), + 'recur_data' => array('type' => 'int','precision' => '2','default' => '1') ), 'pk' => array('cal_id'), 'fk' => array(), diff --git a/calendar/setup/tables_update.inc.php b/calendar/setup/tables_update.inc.php index 1a77264cb3..d2295eeea1 100644 --- a/calendar/setup/tables_update.inc.php +++ b/calendar/setup/tables_update.inc.php @@ -2127,3 +2127,32 @@ function calendar_upgrade1_9_004() return $GLOBALS['setup_info']['calendar']['currentver'] = '1.9.005'; } +/** + * Try alter description to varchar(16384), to not force temp. tables to disk on MySQL (because of text columns) + */ +function calendar_upgrade1_9_005() +{ + // only alter description to varchar(16384), if it does NOT contain longer input and it can be stored as varchar + $max_description_length = $GLOBALS['egw']->db->query('SELECT MAX(CHAR_LENGTH(cal_description)) FROM egw_cal')->fetchColumn(); + if (is_numeric($max_description_length) && $max_description_length <= 16384 && $GLOBALS['egw_setup']->oProc->max_varchar_length >= 16384) + { + $GLOBALS['egw_setup']->oProc->AlterColumn('egw_cal','cal_description',array( + 'type' => 'varchar', + 'precision' => '16384' + )); + } + // allow more categories + $GLOBALS['egw_setup']->oProc->AlterColumn('egw_cal','cal_category',array( + 'type' => 'varchar', + 'precision' => '64', + 'comment' => 'category id(s)' + )); + // remove silly default of 1 + $GLOBALS['egw_setup']->oProc->AlterColumn('egw_cal','cal_title',array( + 'type' => 'varchar', + 'precision' => '255', + 'nullable' => False + )); + return $GLOBALS['setup_info']['calendar']['currentver'] = '1.9.006'; +} + From c23f7fc95bbcfbcbc9104e976c546bb162dcbe1c Mon Sep 17 00:00:00 2001 From: Ralf Becker Date: Mon, 13 Aug 2012 09:32:03 +0000 Subject: [PATCH 014/135] * WebDAV/GroupDAV/CalDAV/CardDAV: removed option only used for old KDE GroupDAV resource and unknown WebDAV clients producing invalid XML, fix for community bug #3152 --- files/webdav.php | 8 -------- phpgwapi/inc/class.groupdav.inc.php | 14 ++------------ webdav.php | 8 -------- 3 files changed, 2 insertions(+), 28 deletions(-) diff --git a/files/webdav.php b/files/webdav.php index 9e4a674c3a..37b8ea96fc 100644 --- a/files/webdav.php +++ b/files/webdav.php @@ -86,13 +86,5 @@ if (strpos($_SERVER['REQUEST_URI'],'/webdav.php/clientsync') !== false && $GLOBALS['egw']->session->commit_session(); $webdav_server = new vfs_webdav_server(); -$user_agent = strtolower($_SERVER['HTTP_USER_AGENT']); -if (strstr($user_agent, 'microsoft-webdav') !== false || - strstr($user_agent, 'neon') !== false || - strstr($user_agent, 'bitkinex') !== false) -{ - // Windows 7 et.al. special treatment - $webdav_server->cnrnd = true; -} $webdav_server->ServeRequest(); //error_log(sprintf('WebDAV %s request: status "%s", took %5.3f s'.($headertime?' (header include took %5.3f s)':''),$_SERVER['REQUEST_METHOD'].' '.$_SERVER['PATH_INFO'],$webdav_server->_http_status,microtime(true)-$starttime,$headertime-$starttime)); diff --git a/phpgwapi/inc/class.groupdav.inc.php b/phpgwapi/inc/class.groupdav.inc.php index d6ada704b8..6f1f516e97 100644 --- a/phpgwapi/inc/class.groupdav.inc.php +++ b/phpgwapi/inc/class.groupdav.inc.php @@ -209,39 +209,29 @@ class groupdav extends HTTP_WebDAV_Server set_exception_handler(array(__CLASS__,'exception_handler')); // crrnd: client refuses redundand namespace declarations - // cnrnd: client needs redundand namespace declarations // setting redundand namespaces as the default for (Cal|Card|Group)DAV, as the majority of the clients either require or can live with it - $this->cnrnd = true; + $this->crrnd = false; // identify clients, which do NOT support path AND full url in of PROPFIND request switch(($agent = groupdav_handler::get_agent())) { - case 'akonadi': - $this->cnrnd = true; // Akonadi seems to require redundant namespaces, see KDE bug #265096 https://bugs.kde.org/show_bug.cgi?id=265096 - break; case 'kde': // KAddressbook (at least in 3.5 can NOT subscribe / does NOT find addressbook) $this->client_require_href_as_url = true; - $this->cnrnd = false; // KDE before Akonadi seems NOT to work with cnrnd (redundant namespaces) break; case 'cfnetwork': // Apple addressbook app case 'dataaccess': // iPhone addressbook $this->client_require_href_as_url = false; - $this->cnrnd = true; break; case 'davkit': // iCal app in OS X 10.6 created wrong request, if full url given case 'coredav': // iCal app in OS X 10.7 case 'calendarstore': // Apple iCal 5.0.1 under OS X 10.7.2 $this->client_require_href_as_url = false; - $this->cnrnd = true; break; case 'cfnetwork_old': $this->crrnd = true; // Older Apple Addressbook.app does not cope with namespace redundancy break; - case 'neon': - $this->cnrnd = true; // neon clients like cadaver - break; } - if ($this->debug) error_log(__METHOD__."() HTTP_USER_AGENT='$_SERVER[HTTP_USER_AGENT]' --> '$agent' --> client_requires_href_as_url=$this->client_require_href_as_url, crrnd(client refuses redundand namespace declarations)=$this->crrnd, cnrnd(client needs redundand namespace declarations)=$this->cnrnd"); + if ($this->debug) error_log(__METHOD__."() HTTP_USER_AGENT='$_SERVER[HTTP_USER_AGENT]' --> '$agent' --> client_requires_href_as_url=$this->client_require_href_as_url, crrnd(client refuses redundand namespace declarations)=$this->crrnd"); // adding EGroupware version to X-Dav-Powered-By header eg. "EGroupware 1.8.001 CalDAV/CardDAV/GroupDAV server" $this->dav_powered_by = str_replace('EGroupware','EGroupware '.$GLOBALS['egw_info']['server']['versions']['phpgwapi'], diff --git a/webdav.php b/webdav.php index eb427dbf67..927c9816ce 100644 --- a/webdav.php +++ b/webdav.php @@ -70,13 +70,5 @@ catch (egw_exception_no_permission_app $e) $GLOBALS['egw']->session->commit_session(); $webdav_server = new vfs_webdav_server(); -$user_agent = strtolower($_SERVER['HTTP_USER_AGENT']); -if (strstr($user_agent, 'microsoft-webdav') !== false || - strstr($user_agent, 'neon') !== false || - strstr($user_agent, 'bitkinex') !== false) -{ - // Windows 7 et.al. special treatment - $webdav_server->cnrnd = true; -} $webdav_server->ServeRequest(); //error_log(sprintf('WebDAV %s request: status "%s", took %5.3f s'.($headertime?' (header include took %5.3f s)':''),$_SERVER['REQUEST_METHOD'].' '.$_SERVER['PATH_INFO'],$webdav_server->_http_status,microtime(true)-$starttime,$headertime-$starttime)); From e64013f4137ab00022e0b9799074c9fd82b67aad Mon Sep 17 00:00:00 2001 From: Ralf Becker Date: Mon, 13 Aug 2012 12:14:37 +0000 Subject: [PATCH 015/135] a little more sophisticated test if we have a functioning database, before trying to store a setup_cmd object, otherwise it stalls the update --- setup/inc/class.setup_cmd.inc.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/setup/inc/class.setup_cmd.inc.php b/setup/inc/class.setup_cmd.inc.php index f1b2199106..ac2d23b8ca 100644 --- a/setup/inc/class.setup_cmd.inc.php +++ b/setup/inc/class.setup_cmd.inc.php @@ -90,7 +90,7 @@ abstract class setup_cmd extends admin_cmd */ function save($set_modifier=true) { - if (is_object($GLOBALS['egw']->db)) + if (isset($GLOBALS['egw']->db) && is_object($GLOBALS['egw']->db) && $GLOBALS['egw']->db->Database) { return parent::save($set_modifier); } From 1d519c483466969fc3fcdc563cd12d4a2948c44a Mon Sep 17 00:00:00 2001 From: Ralf Becker Date: Mon, 13 Aug 2012 13:13:57 +0000 Subject: [PATCH 016/135] MAX(CHAR_LENGTH(cal_description)) returns NULL, if there are no rows --> casting to int --- calendar/setup/tables_update.inc.php | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/calendar/setup/tables_update.inc.php b/calendar/setup/tables_update.inc.php index d2295eeea1..f85bb56adb 100644 --- a/calendar/setup/tables_update.inc.php +++ b/calendar/setup/tables_update.inc.php @@ -2134,7 +2134,8 @@ function calendar_upgrade1_9_005() { // only alter description to varchar(16384), if it does NOT contain longer input and it can be stored as varchar $max_description_length = $GLOBALS['egw']->db->query('SELECT MAX(CHAR_LENGTH(cal_description)) FROM egw_cal')->fetchColumn(); - if (is_numeric($max_description_length) && $max_description_length <= 16384 && $GLOBALS['egw_setup']->oProc->max_varchar_length >= 16384) + // returns NULL, if there are no rows! + if ((int)$max_description_length <= 16384 && $GLOBALS['egw_setup']->oProc->max_varchar_length >= 16384) { $GLOBALS['egw_setup']->oProc->AlterColumn('egw_cal','cal_description',array( 'type' => 'varchar', From 1d743830c966f3491f579173308b85bae3a9d74b Mon Sep 17 00:00:00 2001 From: Ralf Becker Date: Mon, 13 Aug 2012 14:26:00 +0000 Subject: [PATCH 017/135] need to allow account_lid string as parameter for accounts::id2name(), it is used in many places --- phpgwapi/inc/class.accounts.inc.php | 6 +++++- phpgwapi/inc/class.accounts_ldap.inc.php | 2 +- 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/phpgwapi/inc/class.accounts.inc.php b/phpgwapi/inc/class.accounts.inc.php index bffc2ea755..b17b90db7c 100644 --- a/phpgwapi/inc/class.accounts.inc.php +++ b/phpgwapi/inc/class.accounts.inc.php @@ -591,12 +591,16 @@ class accounts * * Uses the read method to fetch all data. * - * @param int $account_id numerica account_id + * @param int|string $account_id numeric account_id or account_lid * @param string $which='account_lid' type to convert to: account_lid (default), account_email, ... * @return string|boolean converted value or false on error ($account_id not found) */ static function id2name($account_id, $which='account_lid') { + if (!is_numeric($account_id) && !($account_id = self::getInstance()->name2id($account_id))) + { + return false; + } try { if (!($data = self::cache_read($account_id))) return false; } diff --git a/phpgwapi/inc/class.accounts_ldap.inc.php b/phpgwapi/inc/class.accounts_ldap.inc.php index a593f9bce6..4e3ab561bb 100644 --- a/phpgwapi/inc/class.accounts_ldap.inc.php +++ b/phpgwapi/inc/class.accounts_ldap.inc.php @@ -285,7 +285,7 @@ class accounts_ldap if (!$members) $members = $this->members($data['account_id']); $to_write[$forward] = array(); - foreach ($members as $member) + foreach ($members as $member => $account_lid) { if (($email = $this->id2name($member,'account_email'))) { From 25ddf016f429a18e63aae6873e874329cdfef495 Mon Sep 17 00:00:00 2001 From: Ralf Becker Date: Mon, 13 Aug 2012 14:42:55 +0000 Subject: [PATCH 018/135] only truncate string if length given and <= 255, to not unnecessary truncate varchar(>255) as PostgreSQL uses text anyway and MySQL truncates itself silently (unless strict mode!) --- phpgwapi/inc/class.egw_db.inc.php | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/phpgwapi/inc/class.egw_db.inc.php b/phpgwapi/inc/class.egw_db.inc.php index b27e580093..1c770371be 100644 --- a/phpgwapi/inc/class.egw_db.inc.php +++ b/phpgwapi/inc/class.egw_db.inc.php @@ -1463,7 +1463,9 @@ class egw_db { $value = implode($glue,$value); } - if (!is_null($length) && strlen($value) > $length) + // only truncate string if length given and <= 255 + // to not unnecessary truncate varchar(>255) as PostgreSQL uses text anyway and MySQL truncates itself silently (unless strict mode!) + if (!is_null($length) && $length <= 255 && strlen($value) > $length) { $value = substr($value,0,$length); } From 4ac5e799ebb7bbd59a50aa604519b39aa2f5352c Mon Sep 17 00:00:00 2001 From: Ralf Becker Date: Tue, 14 Aug 2012 07:55:05 +0000 Subject: [PATCH 019/135] fixed some more "Illegal string offset" --- calendar/inc/class.calendar_boupdate.inc.php | 8 ++++---- calendar/inc/class.calendar_uilist.inc.php | 19 +++++++++++-------- 2 files changed, 15 insertions(+), 12 deletions(-) diff --git a/calendar/inc/class.calendar_boupdate.inc.php b/calendar/inc/class.calendar_boupdate.inc.php index 1937ec4751..bd9205d410 100644 --- a/calendar/inc/class.calendar_boupdate.inc.php +++ b/calendar/inc/class.calendar_boupdate.inc.php @@ -640,7 +640,7 @@ class calendar_boupdate extends calendar_bo $version = $GLOBALS['egw_info']['apps']['calendar']['version']; // ignore events in the past (give a tolerance of 10 seconds for the script) - if($old_event != False && $this->date2ts($old_event['start']) < ($this->now_su - 10)) + if($old_event && $this->date2ts($old_event['start']) < ($this->now_su - 10)) { return False; } @@ -745,7 +745,7 @@ class calendar_boupdate extends calendar_bo $startdate = new egw_time($event['start']); $enddate = new egw_time($event['end']); $modified = new egw_time($event['modified']); - if ($old_event != False) $olddate = new egw_time($old_event['start']); + if ($old_event) $olddate = new egw_time($old_event['start']); foreach($to_notify as $userid => $statusid) { unset($res_info); @@ -762,7 +762,7 @@ class calendar_boupdate extends calendar_bo // check if event-owner wants non-EGroupware users notified if (is_null($owner_prefs)) { - $preferences = new preferences($old_event['owner']); + $preferences = new preferences($owner); $owner_prefs = $preferences->read_repository(); } if ($role != 'CHAIR' && // always notify externals CHAIRs @@ -797,7 +797,7 @@ class calendar_boupdate extends calendar_bo { if (is_null($owner_prefs)) { - $preferences = new preferences($old_event['owner']); + $preferences = new preferences($owner); $GLOBALS['egw_info']['user']['preferences'] = $owner_prefs = $preferences->read_repository(); } $part_prefs = $owner_prefs; diff --git a/calendar/inc/class.calendar_uilist.inc.php b/calendar/inc/class.calendar_uilist.inc.php index dd071064c1..ef52376911 100644 --- a/calendar/inc/class.calendar_uilist.inc.php +++ b/calendar/inc/class.calendar_uilist.inc.php @@ -5,7 +5,7 @@ * @link http://www.egroupware.org * @package calendar * @author Ralf Becker - * @copyright (c) 2005-11 by RalfBecker-At-outdoor-training.de + * @copyright (c) 2005-12 by RalfBecker-At-outdoor-training.de * @license http://opensource.org/licenses/gpl-license.php GPL - GNU General Public License * @version $Id$ */ @@ -247,14 +247,17 @@ class calendar_uilist extends calendar_ui } } $old_params = egw_session::appsession('calendar_list','calendar'); - if ($old_params['filter'] && $old_params['filter'] != $params['filter']) // filter changed => order accordingly + if (is_array($old_params)) { - $params['order'] = 'cal_start'; - $params['sort'] = $params['filter'] == 'after' ? 'ASC' : 'DESC'; - } - if ($old_params['search'] != $params['search']) - { - $this->adjust_for_search($params['search'],$params); + if ($old_params['filter'] && $old_params['filter'] != $params['filter']) // filter changed => order accordingly + { + $params['order'] = 'cal_start'; + $params['sort'] = $params['filter'] == 'after' ? 'ASC' : 'DESC'; + } + if ($old_params['search'] != $params['search']) + { + $this->adjust_for_search($params['search'],$params); + } } if (!$params['csv_export']) egw_session::appsession('calendar_list','calendar',$params); From d43c0c1a6bc81dbd5ff785e4413006fd892fb062 Mon Sep 17 00:00:00 2001 From: Christian Binder Date: Tue, 14 Aug 2012 11:52:36 +0000 Subject: [PATCH 020/135] forgotten css styles for et2_itempicker --- etemplate/templates/default/etemplate2.css | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/etemplate/templates/default/etemplate2.css b/etemplate/templates/default/etemplate2.css index 1474a98a36..489e446536 100644 --- a/etemplate/templates/default/etemplate2.css +++ b/etemplate/templates/default/etemplate2.css @@ -857,12 +857,27 @@ div.et2_progress > div { } .et2_itempicker_search { + display: inline-block; margin: 1em; margin-bottom: 0; + margin-right: 0; width: 67%; padding: 0.2em; } +.et2_itempicker_clear { + position: relative; + top: 3px; + left: -20px; +} + +.et2_itempicker_button_action { + position: absolute; + margin: 1em; + top: 0; + right: 0; +} + .et2_itempicker_itemlist { display: block; border: 1px solid #b6b6b6; From de5041ef1394abc5c38632ab22a21ad5a524e2af Mon Sep 17 00:00:00 2001 From: Christian Binder Date: Tue, 14 Aug 2012 11:54:37 +0000 Subject: [PATCH 021/135] accidentally seen typo --- etemplate/inc/class.nextmatch_widget.inc.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/etemplate/inc/class.nextmatch_widget.inc.php b/etemplate/inc/class.nextmatch_widget.inc.php index 7ff3354f14..de25762445 100644 --- a/etemplate/inc/class.nextmatch_widget.inc.php +++ b/etemplate/inc/class.nextmatch_widget.inc.php @@ -601,7 +601,7 @@ class nextmatch_widget * }, * ] * - * @param array $actions id indexed array of actions / array with valus for keys: 'iconUrl', 'caption', 'onExecute', ... + * @param array $actions id indexed array of actions / array with values for keys: 'iconUrl', 'caption', 'onExecute', ... * @param string $template_name='' name of the template, used as default for app name of images * @param string $prefix='' prefix for ids * @param array &$action_links=array() on return all first-level actions plus the ones with enabled='javaScript:...' From 98d17d7ca48e31c2b7d1647d3bf5bd9f78dfc8d7 Mon Sep 17 00:00:00 2001 From: Christian Binder Date: Tue, 14 Aug 2012 12:02:47 +0000 Subject: [PATCH 022/135] removed accidentally found typo and logging --- phpgwapi/js/egw_action/egw_action.js | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/phpgwapi/js/egw_action/egw_action.js b/phpgwapi/js/egw_action/egw_action.js index 89f9c9a7f1..8d277f96a8 100644 --- a/phpgwapi/js/egw_action/egw_action.js +++ b/phpgwapi/js/egw_action/egw_action.js @@ -327,7 +327,6 @@ egwAction.prototype.updateActions = function(_actions) } else { - console.log(this); throw "This action element cannot have children!"; } } @@ -379,7 +378,7 @@ egwAction.prototype.execute = function(_senders, _target) * will be executed. * 2. _value may be a boolean, which specifies whether the external onExecute handler * (passed as "_handler" in the constructor) will be used. - * 3. _value may be a JS functino which will then be called. + * 3. _value may be a JS function which will then be called. * In all possible situation, the called function will get the following parameters: * 1. A reference to this action * 2. The senders, an array of all objects (JS)/object ids (PHP) which evoked the event From e5a80d758a555792528c51f2ae7f0fb2a9329e49 Mon Sep 17 00:00:00 2001 From: Klaus Leithoff Date: Tue, 14 Aug 2012 13:52:26 +0000 Subject: [PATCH 023/135] fix bug regarding certain russian filenames when forwarding/compose as new, as AddStringAttachment is using basename to make sure only a filename will be used for the namepart; some fixes backported from phpmailer5.2.1 --- phpgwapi/inc/class.egw_mailer.inc.php | 31 ++++++++++++++++++++++++++- phpgwapi/inc/class.phpmailer.inc.php | 6 +++--- 2 files changed, 33 insertions(+), 4 deletions(-) diff --git a/phpgwapi/inc/class.egw_mailer.inc.php b/phpgwapi/inc/class.egw_mailer.inc.php index ddf9656965..2a74331808 100644 --- a/phpgwapi/inc/class.egw_mailer.inc.php +++ b/phpgwapi/inc/class.egw_mailer.inc.php @@ -28,7 +28,7 @@ class egw_mailer extends PHPMailer parent::__construct(true); // throw exceptions instead of echoing errors // setting EGroupware specific path for PHPMailer lang files - list($lang,$nation) = explode('-',$GLOBALS['egw_info']['user']['preferences']['common']['lang']); + if (!empty($GLOBALS['egw_info']['user']['preferences']['common']['lang'])) list($lang,$nation) = explode('-',$GLOBALS['egw_info']['user']['preferences']['common']['lang']); $lang_path = EGW_SERVER_ROOT.'/phpgwapi/lang/'; if ($nation && file_exists($lang_path."phpmailer.lang-$nation.php")) // atm. only for pt-br => br { @@ -198,4 +198,33 @@ class egw_mailer extends PHPMailer return parent::AddBCC($address, $name); } + + /** + * Adds a string or binary attachment (non-filesystem) to the list. + * This method can be used to attach ascii or binary data, + * such as a BLOB record from a database. + * @param string $string String attachment data. + * @param string $filename Name of the attachment. We assume that this is NOT a path + * @param string $encoding File encoding (see $Encoding). + * @param string $type File extension (MIME) type. + * @return void + */ + public function AddStringAttachment($string, $filename, $encoding = 'base64', $type = 'application/octet-stream') + { + // Append to $attachment array + //already encoded? + //TODO: maybe add an parameter to AddStringAttachment to avoid using the basename + $x += preg_match_all('/[\000-\010\013\014\016-\037\177-\377]/', $filename, $matches); + $this->attachment[] = array( + 0 => $string, + 1 => $filename, + 2 => ($x?basename($filename):$filename), + 3 => $encoding, + 4 => $type, + 5 => true, // isStringAttachment + 6 => 'attachment', + 7 => 0 + ); + } + } diff --git a/phpgwapi/inc/class.phpmailer.inc.php b/phpgwapi/inc/class.phpmailer.inc.php index 2b8292cb33..45875b87db 100644 --- a/phpgwapi/inc/class.phpmailer.inc.php +++ b/phpgwapi/inc/class.phpmailer.inc.php @@ -345,7 +345,7 @@ class PHPMailer { private $bcc = array(); private $ReplyTo = array(); private $all_recipients = array(); - private $attachment = array(); + protected $attachment = array(); //this way extended classes may use this variable private $CustomHeader = array(); private $message_type = ''; private $boundary = array(); @@ -1265,7 +1265,7 @@ class PHPMailer { $body = ''; if ($this->sign_key_file) { - $body .= $this->GetMailMIME(); + $body .= $this->GetMailMIME()."\n"; } $this->SetWordWrap(); @@ -1330,8 +1330,8 @@ class PHPMailer { $signed = tempnam("", "signed"); if (@openssl_pkcs7_sign($file, $signed, "file://".$this->sign_cert_file, array("file://".$this->sign_key_file, $this->sign_key_pass), NULL)) { @unlink($file); - @unlink($signed); $body = file_get_contents($signed); + @unlink($signed); } else { @unlink($file); @unlink($signed); From 89a10f6234a4e0163ff1d107f24418df63ce4cec Mon Sep 17 00:00:00 2001 From: Ralf Becker Date: Tue, 14 Aug 2012 13:55:02 +0000 Subject: [PATCH 024/135] * Filemanager/WebDAV: fixed not working Subscribtions (Notifications) when using WebDAV, caused by PHPs internal stat-cache --- phpgwapi/inc/class.vfs_stream_wrapper.inc.php | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/phpgwapi/inc/class.vfs_stream_wrapper.inc.php b/phpgwapi/inc/class.vfs_stream_wrapper.inc.php index c82389b1e6..717f2f7dff 100644 --- a/phpgwapi/inc/class.vfs_stream_wrapper.inc.php +++ b/phpgwapi/inc/class.vfs_stream_wrapper.inc.php @@ -312,6 +312,9 @@ class vfs_stream_wrapper implements iface_stream_wrapper function stream_close ( ) { $ret = fclose($this->opened_stream); + // clear PHP's stat cache, it contains wrong size of just closed file, + // causing eg. notifications to be ignored, because of previous size 0, when using WebDAV + clearstatcache(false); if (isset($GLOBALS['egw']) && isset($GLOBALS['egw']->hooks)) { @@ -863,8 +866,6 @@ class vfs_stream_wrapper implements iface_stream_wrapper */ static function url_stat ( $path, $flags, $try_create_home=false, $check_symlink_components=true ) { - if (self::LOG_LEVEL > 1) error_log(__METHOD__."('$path',$flags,try_create_home=$try_create_home,check_symlink_components=$check_symlink_components)"); - if (!($url = self::resolve_url($path,!($flags & STREAM_URL_STAT_LINK), $check_symlink_components))) { if (self::LOG_LEVEL > 0) error_log(__METHOD__."('$path',$flags) can NOT resolve path!"); @@ -918,6 +919,8 @@ class vfs_stream_wrapper implements iface_stream_wrapper { $stat['url'] = $url; } + if (self::LOG_LEVEL > 1) error_log(__METHOD__."('$path',$flags,try_create_home=$try_create_home,check_symlink_components=$check_symlink_components) returning ".array2string($stat)); + return $stat; // Todo: if we hide non readables, we should return false on url_stat for consitency (if dir is not writabel) From df83423ca314c91b2d757b253b4d826f750aedb3 Mon Sep 17 00:00:00 2001 From: Ralf Becker Date: Tue, 14 Aug 2012 17:02:34 +0000 Subject: [PATCH 025/135] * Calendar: if deleting next recurrance of an event series containing alarms, move alarms to next recurrance, to not alarm for deleted recurance --- calendar/inc/class.calendar_boupdate.inc.php | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/calendar/inc/class.calendar_boupdate.inc.php b/calendar/inc/class.calendar_boupdate.inc.php index bd9205d410..b17350199c 100644 --- a/calendar/inc/class.calendar_boupdate.inc.php +++ b/calendar/inc/class.calendar_boupdate.inc.php @@ -1447,6 +1447,26 @@ class calendar_boupdate extends calendar_bo } else // delete an exception { + // check if deleted recurrance has alarms (because it's the next recurrance) --> move it to next recurrance + if ($event['alarm']) + { + foreach($event['alarm'] as &$alarm) + { + if ($alarm['time'] == $recur_date) + { + if (is_null($next_recurrance)) + { + foreach(calendar_rrule::event2rrule($event, true) as $time) + { + $time->setUser(); // $time is in timezone of event, convert it to usertime used here + if (($next_recurrance = $this->date2ts($time)) > $recur_date) break; + } + } + $alarm['time'] = $this->date2ts($next_recurrance, true); // user to server-time + $this->so->save_alarm($event['id'], $alarm); + } + } + } // need to read series master, as otherwise existing exceptions will be lost! $recur_date = $this->date2ts($event['start']); $event = $this->read($cal_id); From c888134a0418f3c71074a95225184c103a2da19a Mon Sep 17 00:00:00 2001 From: Klaus Leithoff Date: Wed, 15 Aug 2012 14:55:02 +0000 Subject: [PATCH 026/135] * email: fix for ->no initial border on plaintext editor textarea<- --- phpgwapi/inc/class.html.inc.php | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/phpgwapi/inc/class.html.inc.php b/phpgwapi/inc/class.html.inc.php index 51389a72c3..9ce781b2e3 100644 --- a/phpgwapi/inc/class.html.inc.php +++ b/phpgwapi/inc/class.html.inc.php @@ -172,7 +172,8 @@ class html $Protocol = '(http:\/\/|(ftp:\/\/|https:\/\/))'; // only http:// gets removed, other protocolls are shown $Domain = '([\w-]+\.[\w-.]+)'; $Subdir = '([\w\-\.,@?^=%&;:\/~\+#]*[\w\-\@?^=%&\/~\+#])?'; - $Expr = '/' . $NotAnchor . $Protocol . $Domain . $Subdir . '/i'; + $optBracket = ''; + $Expr = '/' . $NotAnchor . $Protocol . $Domain . $Subdir . $optBracket . '/i'; $result = preg_replace( $Expr, "$2$3$4", $result ); @@ -556,13 +557,15 @@ class html * @param string $_height='400px' * @param string $_width='100%' * @param boolean $_purify=true + * @param string $_border='0px' NOT used for CKEditor * @return string the necessary html for the textarea */ - static function fckEditorQuick($_name, $_mode, $_content='', $_height='400px', $_width='100%',$_purify=true) + static function fckEditorQuick($_name, $_mode, $_content='', $_height='400px', $_width='100%',$_purify=true, $_border='0px') { if (!self::htmlarea_availible() || $_mode == 'ascii') { - return ""; + //TODO: use self::textarea + return ""; } else { From 81e1bff44dc4d39ccc194b8a80babe5291d41437 Mon Sep 17 00:00:00 2001 From: Ralf Becker Date: Wed, 15 Aug 2012 15:27:11 +0000 Subject: [PATCH 027/135] * Calendar/CalDAV: fixed not working accepting or rejecting recurrences of event series via CalDAV scheduling (eg. iOS devices) --- calendar/inc/class.calendar_groupdav.inc.php | 58 +++++++++++++++----- 1 file changed, 45 insertions(+), 13 deletions(-) diff --git a/calendar/inc/class.calendar_groupdav.inc.php b/calendar/inc/class.calendar_groupdav.inc.php index d755520954..7fe2996bc5 100644 --- a/calendar/inc/class.calendar_groupdav.inc.php +++ b/calendar/inc/class.calendar_groupdav.inc.php @@ -617,33 +617,61 @@ class calendar_groupdav extends groupdav_handler if (!(count($oldEvent['participants']) == 1 && isset($oldEvent['participants'][$user])) && ($events = $handler->icaltoegw($vCalendar))) { - // todo check behavior for recuring events - foreach($events as $event) + $modified = 0; + foreach($events as $n => $event) { - if ($this->debug) error_log(__METHOD__."(, $id, $user, '$prefix') eventId=$eventId, user=$user, old-status='{$oldEvent['participants'][$user]}', new-status='{$event['participants'][$user]}', event=".array2string($event)); + // for recurrances of event series, we need to read correct recurrence (or if series master is no first event) + if ($event['recurrence'] || $n && !$event['recurrence']) + { + // first try reading (virtual and real) exceptions + if (!isset($series)) + { + $series = self::get_series($event['uid'], $this->bo); + //foreach($series as $s => $sEvent) error_log("series[$s]: ".array2string($sEvent)); + } + foreach($series as $oldEvent) + { + if ($oldEvent['recurrence'] == $event['recurrence']) break; + } + // if no exception found, check if it might be just a recurrence (no exception) + if ($oldEvent['recurrence'] != $event['recurrence']) + { + if (!($oldEvent = $this->bo->read($eventId, $event['recurrence'], true)) || + // virtual exceptions have recurrence=0 and recur_date=recurrence (series master or real exceptions have recurence=0) + !($oldEvent['recur_date'] == $event['recurrence'] || !$event['recurrence'] && !$oldEvent['recurrence'])) + { + // if recurrence not found --> log it and continue with other recurrence + $this->groupdav->log(__METHOD__."(,,$user) could NOT find recurrence=$event[recurrence]=".egw_time::to($event['recurrence']).' of event series! event='.array2string($event)); + continue; + } + } + } + if ($this->debug) error_log(__METHOD__."(, $id, $user, '$prefix') eventId=$eventId ($oldEvent[id]), user=$user, old-status='{$oldEvent['participants'][$user]}', new-status='{$event['participants'][$user]}', recurrence=$event[recurrence]=".egw_time::to($event['recurrence']).", event=".array2string($event)); if (isset($event['participants']) && $event['participants'][$user] !== $oldEvent['participants'][$user]) { - if (!$this->bo->set_status($eventId, $user, $event['participants'][$user], $event['recurrence'])) + if (!$this->bo->set_status($oldEvent['id'], $user, $event['participants'][$user], + // real (not virtual) exceptions use recurrence 0 in egw_cal_user.cal_recurrence! + $recurrence = $eventId == $oldEvent['id'] ? $event['recurrence'] : 0)) { - if ($this->debug) error_log(__METHOD__."(,,$user) failed to set_status($eventId, $user, '{$event['participants'][$user]}')"); + if ($this->debug) error_log(__METHOD__."(,,$user) failed to set_status($oldEvent[id], $user, '{$event['participants'][$user]}', $recurrence=".egw_time::to($recurrence).')'); return '403 Forbidden'; } else { - if ($this->debug) error_log(__METHOD__."() set_status($eventId, $user, ".array2string($event['participants'][$user])." , $event[recurrence])"); + ++$modified; + if ($this->debug) error_log(__METHOD__."() set_status($oldEvent[id], $user, {$event['participants'][$user]} , $recurrence=".egw_time::to($recurrence).')'); } } // import alarms, if given and changed if ((array)$event['alarm'] !== (array)$oldEvent['alarm']) { - $this->sync_alarms($eventId, (array)$event['alarm'], (array)$oldEvent['alarm'], $user, $event['start']); - } - elseif (!isset($event['participants']) || $event['participants'][$user] === $oldEvent['participants'][$user]) - { - $this->groupdav->log(__METHOD__."(,,$user) schedule-tag given, but NO change for current user event=".array2string($event).', old-event='.array2string($oldEvent)); - return '412 Precondition Failed'; + $modified += $this->sync_alarms($oldEvent['id'], (array)$event['alarm'], (array)$oldEvent['alarm'], $user, $event['start']); } } + if (!$modified) // NO modififictions, or none we understood --> log it and return Ok: "204 No Content" + { + $this->groupdav->log(__METHOD__."(,,$user) schedule-tag given, but NO changes for current user events=".array2string($events).', old-event='.array2string($oldEvent)); + } // we should not return an etag here, as we never store the PUT ical byte-by-byte //header('ETag: "'.$etag.'"'); header('Schedule-Tag: "'.$schedule_tag.'"'); @@ -721,11 +749,12 @@ class calendar_groupdav extends groupdav_handler * @param int $user account_id of user to create alarm for * @param int $start start-time of event * @ToDo store other alarm properties like: ACTION, DESCRIPTION, X-WR-ALARMUID + * @return int number of modified alarms */ private function sync_alarms($cal_id, array $alarms, array $old_alarms, $user, $start) { if ($this->debug) error_log(__METHOD__."($cal_id, ".array2string($alarms).', '.array2string($old_alarms).", $user, $start)"); - // todo import alarms + $modified = 0; foreach($alarms as $alarm) { if ($alarm['owner'] != $this->user) continue; // only import alarms of current user @@ -745,6 +774,7 @@ class calendar_groupdav extends groupdav_handler $alarm['time'] = $start - $alarm['offset']; if ($this->debug) error_log(__METHOD__."() adding new alarm from client ".array2string($alarm)); $this->bo->save_alarm($cal_id, $alarm); + ++$modified; } } // remove all old alarms left from current user @@ -752,7 +782,9 @@ class calendar_groupdav extends groupdav_handler { if ($this->debug) error_log(__METHOD__."() deleting alarm '$id' deleted on client ".array2string($old_alarm)); $this->bo->delete_alarm($id); + ++$modified; } + return $modified; } /** From 6c6eeed21c182eeec63180511b49a087d71e8424 Mon Sep 17 00:00:00 2001 From: Ralf Becker Date: Thu, 16 Aug 2012 14:41:57 +0000 Subject: [PATCH 028/135] more translations from Gudrun, Ingo & Stefan --- addressbook/lang/egw_de.lang | 18 ++++++++++++++++++ addressbook/lang/egw_en.lang | 7 ------- filemanager/lang/egw_de.lang | 28 +++++++++++++++++++++++++--- filemanager/lang/egw_en.lang | 19 +++++++++++++++++-- importexport/lang/egw_de.lang | 18 ++++++++++++++++++ notifications/lang/egw_en.lang | 1 - 6 files changed, 78 insertions(+), 13 deletions(-) diff --git a/addressbook/lang/egw_de.lang b/addressbook/lang/egw_de.lang index c890c2972d..074769c20d 100644 --- a/addressbook/lang/egw_de.lang +++ b/addressbook/lang/egw_de.lang @@ -77,6 +77,7 @@ business zip code addressbook de PLZ geschäftl. calendar fields: addressbook de Kalender Felder: calendar uri addressbook de Kalender URI can be changed via setup >> configuration admin de Kann über Setup >> Konfiguration geändert werden +can't create dn %1 addressbook de dn %1 kann nicht erstellt werden car phone addressbook de Autotelefon categorie addressbook de Kategorie categorie added addressbook de Kategorie (n) hinzugefügt @@ -183,12 +184,16 @@ enter the path to the exported file here addressbook de Bitte geben Sie den Pfad error deleting the contact !!! addressbook de Fehler beim Löschen des Kontakts !!! error saving the contact !!! addressbook de Fehler beim Speichern des Kontakts !!! error: the entry has been updated since you opened it for editing! addressbook de Fehler: der Eintrag wurde geändert, seit Sie ihn zum Bearbeiten geöffnet haben! +example {{if n_prefix~mr~hello mr.~hello ms.}} - search the field "n_prefix", for "mr", if found, write hello mr., else write hello ms. addressbook de Beispiel: "{{IF n_prefix~Herr~Sehr geehrter~Sehr geehrte}}" - suche in dem Feld "n_prefix" nach "Herr", wenn gefunden, schreibe "Sehr geehrter", wenn nicht gefunden schreibe "Sehr geehrte". Es ist auch möglich anstatt fixer Werte, den Wert eines andren Feldes zu übernehmen. Beispiel (Land wird nur dann angezeigt, denn es nicht DEUTSCHLAND ist: } example {{letterprefixcustom n_prefix title n_family}} - example: mr dr. james miller preferences de Beispiel für {{LETTERPREFIXCUSTOM n_prefix title n_family}} - Beispiel: Herr Dr. James Miller +example {{nelf role}} - if field role is not empty, you will get a new line with the value of field role addressbook de Beispiel {{NELF role}} - Erzeugt einen Zeilenumbruch, wenn das Feld role nicht leer ist. Der Wert des Feldes role (Funktion) wird nach dem Zeilenumbruch ausgegeben. +example {{nelfnv role}} - if field role is not empty, set a lf without any value of the field addressbook de Beispiel {{NELFNV role}} -Erzeugt einen Zeilenumbruch, wenn das Feld role (Funktion) einen Wert besitzt. Der Wert role (Funktion) wird auch bei Vorhandensein des Feldes role nicht ausgegeben. existing links addressbook de Bestehende Verknüpfungen exists addressbook de besteht bereits export as csv addressbook de Exportieren als CSV export as vcard addressbook de Exportieren als VCard export contacts addressbook de Kontakte exportieren +export definition to use for nextmatch export addressbook de Export Profil der Listenansicht (Disketten Symbol) export definitition to use for nextmatch export addressbook de Export Profil der Listenansicht (Disketten Symbol) export file name addressbook de Dateiname zum Exportieren export from addressbook addressbook de Export vom Adressbuch @@ -208,10 +213,13 @@ fields for the csv export addressbook de Felder für den CSV Export fields the user is allowed to edit himself admin de Felder, die der Benutzer selbst bearbeiten darf fields to copy when copying an address? admin de Welche Felder sollen beim Kopieren berücksichtigt werden? fields to show in address list addressbook de Felder, die in der Adressliste angezeigt werden sollen +fieldseparator addressbook de Feldtrenner for read only ldap admin de für nur lesendes LDAP for serial letter use this tag. put the content, you want to repeat between two tags. addressbook de Wenn Sie Serienbriefe erzeugen möchten, dann benutzen Sie dieses 'Markierungszeichen'. Setzen Sie den Inhalt, der wiederholt werden soll (Anschriftstags und Briefinhalt) zwischen zwei 'Seiten-Wiederholungs-Zeichen'. freebusy uri addressbook de Freebusy URI full name addressbook de vollständiger Name +general admin de Allgemein +general fields: addressbook de Allgemeine Felder: geo addressbook de GEO global categories addressbook de Globale Kategorien grant addressbook access common de Berechtigungen @@ -234,6 +242,7 @@ how many contacts should non-admins be able to export admin de Wieviele Kontakte icon addressbook de Icon if accounts are already in ldap admin de wenn die Benutzer bereits im LDAP sind ignore first line addressbook de Erste Zeile ignorieren +import addressbook de Importieren import contacts addressbook de Kontakte importieren import csv-file into addressbook addressbook de Import CSV-Datei ins Adressbuch import file addressbook de Datei importieren @@ -243,6 +252,7 @@ import from outlook addressbook de Aus Outlook importieren import multiple vcard addressbook de Import mehrere VCards import next set addressbook de Nächsten Satz importieren import_instructions addressbook de In Netscape: Öffnen Sie das Adressbuch und wählen Sie Exportieren aus dem Datei Menü aus. Die Dateien werden im LDIF Format exportiert.

In Outlook wählen Sie den Ordner Kontakte aus, wählen Sie Importieren und Exportieren...

aus dem Datei Menü aus und Exportieren Sie die Kontakte als eine CSV Datei.

In Palm Desktop 4.0 oder größer, öffnen Sie Ihr Adressbuch und wählen Sie Export aus dem Datei-Menü aus. Die Datei wird im VCard-Format exportiert. +importer's personal addressbook de Persönliche Adressbuch des Importierenden imports contacts into your addressbook from a csv file. csv means 'comma seperated values'. however in the options tab you can also choose other seperators. addressbook de Importiert Kontakte aus einer CSV Datei in Ihr Adressbuch. CSV bedeutet Komma getrennte Werte. Sie können in dem Reiter Einstellungen auch ein anderes Trennzeichen wählen. in %1 days (%2) is %3's birthday. addressbook de In %1 Tagen (%2) ist der Geburtstag von %3. income addressbook de Einkommen @@ -262,15 +272,20 @@ ldif addressbook de LDIF line 2 addressbook de Zeile 2 link title for contacts show addressbook de Titel der Verknüpfung für Kontakte zeigt links addressbook de Verknüpfungen +links and attached files addressbook de Verknüpfungen zu anderen Datensätzen und angefügten Dateien +links to specified application. example: {{links/infolog}} addressbook de Verknüpfungen zu bestimmten Anwendungen. Beispiel: {{links/infolog}} list all categories addressbook de Liste alle Kategorien list all customfields addressbook de Liste alle benutzerdefinierten Felder list already exists! addressbook de Die Liste existiert bereits! list created addressbook de Verteiler erzeugt list creation failed, no rights! addressbook de Verteiler erzeugen fehlgeschlagen, keine Rechte! +list of files linked to the current record addressbook de Liste der Dokumente, die zu dem aktuellen Datensatz gehören. load vcard addressbook de VCard laden location addressbook de Standort locations addressbook de Standorte +mail vcard addressbook de VCard per E-Mail zusenden. main categories in their own field addressbook de Haupkategorien in einem eigenen Feld +manage mapping addressbook de Feldzuordnungen verwalten mark records as private addressbook de Eintrag als Privat kennzeichnen merge contacts addressbook de Kontakte vereinigen merge into first or account, deletes all other! addressbook de Vereinige im ersten oder Benutzerkonto, löscht alle anderen ! @@ -392,9 +407,11 @@ this person's first name was not in the address book. addressbook de Der Vorname this person's last name was not in the address book. addressbook de Der Nachname dieser Person ist nicht im Adressbuch vorhanden. timezone addressbook de Zeitzone title addressbook de Position +titles of any entries linked to the current record, excluding attached files addressbook de Titel der Verknüpften zu dem aktuellem Eintrag ohne Dateien. to many might exceed your execution-time-limit addressbook de Zu viele können Ihre Laufzeitbeschränkung überschreiten today is %1's birthday! common de Heute ist der Geburtstag von %1! tomorrow is %1's birthday. common de Morgen ist der Geburtstag von %1. +translation addressbook de Übersetzung two of: %1 addressbook de Zwei von: %1 type addressbook de Typ un-delete addressbook de Gelöschte Adressen wieder herstellen @@ -406,6 +423,7 @@ update fields by edited organisations? admin de Welche Felder sollen beim Bearb updated addressbook de Aktualisiert upload or delete the photo addressbook de Foto hochladen oder löschen url to link telephone numbers to (use %1 = number to call, %u = account name, %t = account phone) admin de URL mit denen Telefonnummern verlinkt werden sollen (verwenden Sie %1 = anzurufende Nummer, %u = Benutzernamen, %t = Telefon des Benutzers) +use addressbooks "own sorting" attribute addressbook de Verwende die Einstellung "eigene Sortierung" use an extra category tab? addressbook de Separaten Reiter für Kategorien verwenden? use an extra tab for private custom fields? admin de Separaten Reiter für private benutzerdefinierte Felder verwenden? use country list addressbook de Länderliste benutzen diff --git a/addressbook/lang/egw_en.lang b/addressbook/lang/egw_en.lang index bd4496c36e..c816736271 100644 --- a/addressbook/lang/egw_en.lang +++ b/addressbook/lang/egw_en.lang @@ -241,10 +241,6 @@ home zip code addressbook en Home ZIP code how many contacts should non-admins be able to export admin en How many contacts should non-admins be able to export. icon addressbook en Icon if accounts are already in ldap admin en If accounts are already in LDAP -if you specify a directory (full vfs path) here, %1 displays an action for each document. that action allows to download the specified document with the data inserted. addressbook en If you specify a directory (full vfs path) here, %1 displays an action for each document. That action allows to download the specified document with the data inserted. -if you specify a document (full vfs path) here, %1 displays an extra document icon for each entry. that icon allows to download the specified document with the data inserted. addressbook en If you specify a document (full vfs path) here, %1 displays an extra document icon for each entry. That icon allows to download the specified document with the data inserted. -if you specify an export definition, it will be used when you export addressbook en If you specify an export definition, it will be used when you export -if you specify an export definition, it will be used when you export* addressbook en If you specify an export definition, it will be used when you export* ignore first line addressbook en Ignore first line import addressbook en Import import contacts addressbook en Import contacts @@ -317,7 +313,6 @@ no fallback addressbook en No fallback no vcard addressbook en No vCard number addressbook en Number number of records to read (%1) addressbook en Number of records to read (%1) -old fixed definition addressbook en Old fixed definition open email addresses in external mail program addressbook en Open EMail addresses in external mail program options for type admin en Options for type organisation addressbook en Organisation @@ -404,8 +399,6 @@ that field name has been used already ! addressbook en The field name has been u the anonymous user has probably no add rights for this addressbook. addressbook en The anonymous user has no add rights for this address book. the anonymous user needs add rights for it! addressbook en The anonymous user needs add rights! the anonymous user needs read it! addressbook en The anonymous user needs read rights! -the document can contain placeholder like {{%3}}, to be replaced with the data (%1full list of placeholder names%2). addressbook en The document can contain placeholder like {{%3}}, to be replaced with the data (%1full list of placeholder names%2). -the following document-types are supported: addressbook en The following document-types are supported: the zip extension is needed, to insert contact data in openoffice or msoffice documents. addressbook en The zip extension is needed, to insert contact data in OpenOffice or MSOffice documents. there was an error saving your data :-( addressbook en ERROR saving data! this module displays a contactform, that stores direct into the addressbook. addressbook en This module displays a contact form, that stores directly into the address book. diff --git a/filemanager/lang/egw_de.lang b/filemanager/lang/egw_de.lang index 10cd66aa44..350c1f94f2 100644 --- a/filemanager/lang/egw_de.lang +++ b/filemanager/lang/egw_de.lang @@ -15,14 +15,21 @@ %1 successful uploaded. filemanager de %1 erfolgreich hochgeladen. %1 the following files into current directory filemanager de Die folgenden Dateien in das aktuelle Verzeichnis %1 %1 urls %2 to clipboard. filemanager de %1 Adressen in die Zwischenablage %2. +%d errors while copying, %d files successfully copied. filemanager de %d Fehler beim Kopieren (%d Dateien erfolgreich kopiert)! +%d errors while moving, %d files successfully moved. filemanager de %d Fehler beim Verschieben (%d Dateien erfolgreich verschoben)! +%d erros while copying, %d files successfully copied. filemanager de %d Fehler beim Kopieren (%d Dateien erfolgreich kopiert)! +%d erros while moving, %d files successfully moved. filemanager de %d Fehler beim Verschieben (%d Dateien erfolgreich verschoben)! +%d files successfully copied. filemanager de %d Dateien erfolgreich kopiert +%d files successfully moved. filemanager de %d Dateien erfolgreich verschoben accessrights filemanager de Zugangsberechtigungen acl added. filemanager de Zugriffsrecht hinzugefügt. acl deleted. filemanager de Zugriffsrecht gelöscht. actions filemanager de Befehle -add to clipboard filemanager de Anhängen an Zwischenablage +add to clipboard filemanager de Anhängen an die Zwischenablage all files common de Alle Dateien allow a maximum of the above configured folderlinks to be configured in settings admin de erlaube das oben eingestellte Maximum an Einstellungen für Verzeichnisverweise -and all it's childeren filemanager de und alle seine Kinder +and all it's childeren filemanager de und alle seine Kinderelemente +application fields filemanager de Anwendungsfelder applications common de Anwendungen basedirectory filemanager de Basisverzeichnis can't open directory %1! filemanager de Kann Verzeichnis %1 nicht öffnen! @@ -32,6 +39,7 @@ cautiously rejecting to remove folder '%1'! filemanager de Löschen des Verzeich check all filemanager de Alle auswählen check virtual filesystem filemanager de Virtuelles Dateisystem überprüfen clear search filemanager de Suchfelder zurücksetzen +clipboard is empty! filemanager de Zwischenablage ist leer! comment filemanager de Kommentar copied filemanager de kopiert copied %1 to %2 filemanager de %1 nach %2 kopiert @@ -55,6 +63,7 @@ custom fields filemanager de Benutzerdefinierte Felder cut filemanager de Ausschneiden cut to clipboard filemanager de Ausschneiden in die Zwischenablage default behavior is no. the link will not be shown, but you are still able to navigate to this location, or configure this paricular location as startfolder or folderlink. filemanager de Vorgabe ist NEIN. Der Verweis wird nicht angezeigt, Sie können aber immer zu diesem Verzeichnis navigieren, Sie können aber das Verzeichnis als Startverzeichnis oder als Verzeichnisverweis konfigurieren. +default document to insert entries filemanager de Standarddokument zum Einfügen von Daten delete these files or directories? filemanager de Diese Dateien oder Verzeichnisse löschen? delete this file or directory filemanager de Datei oder Verzeichnis löschen deleted %1 filemanager de %1 gelöscht @@ -64,6 +73,7 @@ directory %1 already exists filemanager de Verzeichnis %1 existiert bereits directory %1 does not exist filemanager de Verzeichnis %1 existiert nicht directory not found or no permission to access it! filemanager de Verzeichnis wurde nicht gefunden oder Sie haben keine Rechte um darauf zuzugreifen! directory successfully created. filemanager de Verzeichnis erfolgreich angelegt. +directory with documents to insert entries filemanager de Verzeichnis mit Dokumenten zum Einfügen von Daten display and modification of content filemanager de Anzeigen und Verändern des Inhaltes display of content filemanager de Anzeigen des Inhaltes do you want to overwrite the existing file %1? filemanager de Wollen Sie die existierende Datei %1 überschreiben? @@ -79,6 +89,9 @@ error creating symlink to target %1! filemanager de Fehler beim Anlegen einer Ve error deleting the acl entry! filemanager de Fehler beim Löschen des Zugriffsrechts! error uploading file! filemanager de Fehler beim Hochladen der Datei! error while creating directory. filemanager de Fehler beim Anlegen des Verzeichnisses +example {{if n_prefix~mr~hello mr.~hello ms.}} - search the field "n_prefix", for "mr", if found, write hello mr., else write hello ms. filemanager de Beispiel: {{IF n_prefix~Herr~Sehr geehrter~Sehr geehrte}} - Suche im Feld "n_prefix", wenn es "Herr" enthält, dann schreibe "Sehr geehrter", wenn nicht schreibe "Sehr geehrte". +example {{letterprefixcustom n_prefix title n_family}} - example: mr dr. james miller filemanager de Beispiel: {{LETTERPREFIXCUSTOM n_prefix title n_family}} - Beispiel: Herr Dr. Hans Müller +example {{nelf role}} - if field role is not empty, you will get a new line with the value of field role filemanager de Beispiel: {{NELF role}} - Wenn das Feld "role" nicht leer ist, dann wird der Inhalt des Feldes "role" in eine neue Zeile geschrieben. executable filemanager de Ausführbar extended access control list filemanager de Erweiterte Zugriffsrechte extended acl filemanager de Erweiterte ACL @@ -94,14 +107,18 @@ file or directory not found! filemanager de Datei oder Verzeichnis nicht gefunde file successful uploaded. filemanager de Datei erfolgreich hochgeladen. filemanager common de Dateimanager filemanager configuration admin de Dateimanager Konfiguration +filemanager fields: filemanager de Dateimanager Felder: filename must not be empty! filemanager de Dateinamen darf nicht leer sein! files from subdirectories filemanager de Dateien aus Unterverzeichnissen files in this directory filemanager de Dateien in diesem Verzeichnis filesystem check reported no problems. filemanager de Überprüfung des Dateisystem ergab keine Probleme. fix reported problems filemanager de Gefundene Probleme beheben folder up filemanager de darüberliegendes Verzeichnis +for files linked to an application entry (inside /apps/appname/id/) the placeholders for that application are also available. see the specific application for a list of available placeholders. filemanager de Die Platzhalter für Verknüpfte Eintrage bzw. Dateien (unter /apps/appname/id) der entsprechenden Anwendung stehen Ihnen hier auch zur Verfügung. Sie können die Platzhalter auch unter der Liste der Platzhalter der entsprechenden Anwendung einsehen. +for files linked to an application entry (inside /apps/appname/id/) the placeholders for that application are also available. see the specific application for a list of placeholders filemanager de Die Platzhalter für Verknüpfte Eintrage bzw. Dateien (unter /apps/appname/id) der entsprechenden Anwendung stehen Ihnen hier auch zur Verfügung. Sie können die Platzhalter auch unter der Liste der Platzhalter der entsprechenden Anwendung einsehen. general filemanager de Allgemein -go home filemanager de Heimatverzeichnis +general fields: filemanager de Allgemeine Platzhalter +go home filemanager de Heimverzeichnis go to filemanager de Gehe zu go to your home directory filemanager de Zu Ihrem Heimverzeichnis wechseln go up filemanager de in das darüber liegende Verzeichnis wechseln @@ -122,6 +139,7 @@ modify all subdirectories and their content filemanager de Änderungen auf alle move filemanager de verschieben move to filemanager de Verschieben nach moved %1 to %2 filemanager de %1 nach %2 verschoben +name of current user, all other contact fields are valid too filemanager de Name des aktuellen Benutzers, alle anderen Kontakt Felder können Sie hier auch verwenden. new directory filemanager de Neues Verzeichnis no access filemanager de Kein Zugriff no files in this directory. filemanager de Keine Dateien in diesem Verzeichnis. @@ -148,12 +166,14 @@ rename, change permissions or ownership filemanager de Umbennen, Zugriffsrechte renamed %1 to %2 filemanager de %1 nach %2 umbenannt renamed %1 to %2. filemanager de %1 nach %2 umbenannt. replaced %1 filemanager de %1 ersetzt +replacements for inserting entries into documents filemanager de Platzhalter zum Einfügen in ein Dokument. rights filemanager de Rechte root filemanager de root root access granted. filemanager de Root Zugriff gewährt. root access stopped. filemanager de Root Zugriff gestoppt. save %1 filemanager de %1 speichern save %1, and go back to file listing filemanager de %1 speichern und zurück zur Verzeichnisansicht +save as filemanager de Speichern als save changes filemanager de Änderungen speichern saved %1 filemanager de %1 gespeichert saving properties failed! filemanager de Speichern der Eigenschaften fehlgeschlagen! @@ -164,6 +184,8 @@ select file to upload in current directory filemanager de Datei zum hochladen in show filemanager de Zeige show hidden files filemanager de Zeige versteckte Dateien show link "%1" in side box menu? filemanager de Zeige die Verknüpfung "%1" im Seitenmenü? +show link "users and groups*" in side box menu?* filemanager de Möchten Sie die Verknüpfung "Benutzer und Gruppen" innerhalb des Seitenmenüs anzeigen? +show link "your home directory*" in side box menu?* filemanager de Möchten Sie den Verknüpfung "Ihr Home Verzeichnis" innerhalb des Seitenmenüs angezeigt bekommen? show link to filemanagers basedirectory (/) in side box menu? filemanager de Zeige die Verknüpfung zum Basisverzeichnis (/) des Dateimanagers im Seitenmenü? size filemanager de Größe start search filemanager de Suche starten diff --git a/filemanager/lang/egw_en.lang b/filemanager/lang/egw_en.lang index b343eb54fb..54278a2004 100644 --- a/filemanager/lang/egw_en.lang +++ b/filemanager/lang/egw_en.lang @@ -15,6 +15,8 @@ %1 successful uploaded. filemanager en %1 successfully uploaded. %1 the following files into current directory filemanager en %1 the following files into current directory %1 urls %2 to clipboard. filemanager en %1 URLs %2 to clipboard +%d errors while copying, %d files successfully copied. filemanager en %d errors while copying, %d files successfully copied. +%d errors while moving, %d files successfully moved. filemanager en %d errors while moving, %d files successfully moved. %d erros while copying, %d files successfully copied. filemanager en %d errors while copying, %d files successfully copied. %d erros while moving, %d files successfully moved. filemanager en %d errors while moving, %d files successfully moved. %d files successfully copied. filemanager en %d files successfully copied. @@ -27,6 +29,7 @@ add to clipboard filemanager en Add to clipboard all files common en All files allow a maximum of the above configured folderlinks to be configured in settings admin en Maximum number of folder links to be configured in preferences. and all it's childeren filemanager en and all it's children +application fields filemanager en Application fields applications common en Applications basedirectory filemanager en Base directory can't open directory %1! filemanager en Can't open directory %1! @@ -36,6 +39,7 @@ cautiously rejecting to remove folder '%1'! filemanager en Cautiously rejecting check all filemanager en Check all check virtual filesystem filemanager en Check virtual filesystem clear search filemanager en Clear search +clipboard is empty! filemanager en Clipboard is empty! comment filemanager en Comment copied filemanager en Copied copied %1 to %2 filemanager en Copied %1 to %2 @@ -59,6 +63,7 @@ custom fields filemanager en Custom fields cut filemanager en Cut cut to clipboard filemanager en Cut to clipboard default behavior is no. the link will not be shown, but you are still able to navigate to this location, or configure this paricular location as startfolder or folderlink. filemanager en Default = No. The link will not be shown, but you are still able to navigate to this location, or configure this particular location as start folder or folder link. +default document to insert entries filemanager en Default document to insert entries delete these files or directories? filemanager en Delete these files or directories? delete this file or directory filemanager en Delete this file or directory deleted %1 filemanager en Deleted %1 @@ -68,6 +73,7 @@ directory %1 already exists filemanager en Directory %1 already exists. directory %1 does not exist filemanager en Directory %1 does not exist. directory not found or no permission to access it! filemanager en Directory not found or no permission to access it! directory successfully created. filemanager en Directory successfully created. +directory with documents to insert entries filemanager en Directory with documents to insert entries display and modification of content filemanager en Display and modification of content display of content filemanager en Display of content do you want to overwrite the existing file %1? filemanager en Do you want to overwrite the existing file %1? @@ -83,8 +89,10 @@ error creating symlink to target %1! filemanager en Error creating symlink to ta error deleting the acl entry! filemanager en Error deleting the ACL entry! error uploading file! filemanager en Error uploading file! error while creating directory. filemanager en Error while creating directory +example {{if n_prefix~mr~hello mr.~hello ms.}} - search the field "n_prefix", for "mr", if found, write hello mr., else write hello ms. filemanager en Example {{IF n_prefix~Mr~Hello Mr.~Hello Ms.}} - search the field "n_prefix", for "Mr", if found, write Hello Mr., else write Hello Ms. +example {{letterprefixcustom n_prefix title n_family}} - example: mr dr. james miller filemanager en Example {{LETTERPREFIXCUSTOM n_prefix title n_family}} - Example: Mr Dr. James Miller +example {{nelf role}} - if field role is not empty, you will get a new line with the value of field role filemanager en Example {{NELF role}} - if field role is not empty, you will get a new line with the value of field role executable filemanager en Executable -export definitition to use for nextmatch export filemanager en Export definition to use for nextmatch export extended access control list filemanager en Extended access control list extended acl filemanager en Extended ACL failed to change permissions of %1! filemanager en Failed to change permissions of %1! @@ -99,20 +107,22 @@ file or directory not found! filemanager en File or directory not found! file successful uploaded. filemanager en File successfully uploaded. filemanager common en File Manager filemanager configuration admin en File Manager configuration +filemanager fields: filemanager en Filemanager fields: filename must not be empty! filemanager en File name must not be empty! files from subdirectories filemanager en Files from sub directories files in this directory filemanager en Files in this directory filesystem check reported no problems. filemanager en Filesystem check reported no problems. fix reported problems filemanager en Fix reported problems folder up filemanager en Folder up +for files linked to an application entry (inside /apps/appname/id/) the placeholders for that application are also available. see the specific application for a list of available placeholders. filemanager en For files linked to an application entry (inside /apps/appname/id/) the placeholders for that application are also available. See the specific application for a list of available placeholders. for files linked to an application entry (inside /apps/appname/id/) the placeholders for that application are also available. see the specific application for a list of placeholders filemanager en For files linked to an application entry (inside /apps/appname/id/) the placeholders for that application are also available. See the specific application for a list of placeholders general filemanager en General +general fields: filemanager en General fields: go home filemanager en Go home go to filemanager en Go to go to your home directory filemanager en Go to your home directory go up filemanager en Go up id filemanager en ID -if you specify an export definition, it will be used when you export filemanager en If you specify an export definition, it will be used when you export inherited filemanager en Inherited link filemanager en Link link %1: %2 filemanager en Link %1: %2 @@ -129,6 +139,7 @@ modify all subdirectories and their content filemanager en Modify all sub direct move filemanager en Move move to filemanager en Move to moved %1 to %2 filemanager en Moved %1 to %2 +name of current user, all other contact fields are valid too filemanager en Name of current user, all other contact fields are valid too new directory filemanager en New directory no access filemanager en No access no files in this directory. filemanager en No files in this directory. @@ -155,12 +166,14 @@ rename, change permissions or ownership filemanager en Rename, change permission renamed %1 to %2 filemanager en Renamed %1 to %2 renamed %1 to %2. filemanager en Renamed %1 to %2 replaced %1 filemanager en Replaced %1 +replacements for inserting entries into documents filemanager en Replacements for inserting entries into documents rights filemanager en Rights root filemanager en Root root access granted. filemanager en Root access granted. root access stopped. filemanager en Root access stopped. save %1 filemanager en Save %1 save %1, and go back to file listing filemanager en Save %1, and go back to file listing. +save as filemanager en Save as save changes filemanager en Save changes saved %1 filemanager en Saved %1 saving properties failed! filemanager en Saving properties failed! @@ -171,6 +184,8 @@ select file to upload in current directory filemanager en Select file to upload show filemanager en Show show hidden files filemanager en Show hidden files show link "%1" in side box menu? filemanager en Show link "%1" in side menu +show link "users and groups*" in side box menu?* filemanager en Show link "Users and groups*" in side box menu?* +show link "your home directory*" in side box menu?* filemanager en Show link "Your home directory*" in side box menu?* show link to filemanagers basedirectory (/) in side box menu? filemanager en Show link to File Manager's base directory (/) in side menu? size filemanager en Size start search filemanager en Start search diff --git a/importexport/lang/egw_de.lang b/importexport/lang/egw_de.lang index 61b88eef7e..24cc73e32f 100644 --- a/importexport/lang/egw_de.lang +++ b/importexport/lang/egw_de.lang @@ -1,3 +1,6 @@ +%1 definition(s) %2 importexport de %1 Profildefinition(en) %2 +%1 definition(s) %2, %3 failed because of insufficent rights !!! importexport de %1 Import/Exportdefonition(en) %2, %3 konnte wegen fehlender Rechte nicht ausgeführt wegen !!! +%1 is not a known user or group importexport de %1 ist kein Benutzer oder eine Benutzergrupper %1 is not readable importexport de %1 ist nicht lesbar %1 is not writable importexport de %1 ist nicht möglich zu schreiben %1 records processed importexport de %1 Einträge ausgeführt @@ -7,9 +10,11 @@ (0-6, 0=sun) importexport de (0-6, 0=Sonntag) *contact id cannot be changed by import importexport de *Contact ID kann nicht durch den Import verändert werden admin disabled exporting importexport de Ihr Adminisrator hat den Export deaktiviert +all encodings importexport de Alle Kopierungen allowed users importexport de Erlaubte Benutzer automatically created by importexport importexport de Wurde automatisch vom Import/Export Modul erstellt basic csv import importexport de Basis CSV Import +changed importexport de Geändert changed allowed_users importexport de Erlaubten Benutzer geändert changed owner importexport de Besitzer geändert charset of file importexport de Zeichensatz der Datei @@ -20,24 +25,32 @@ choose an application importexport de Wählen sei eine Anwendung. choose fields to export importexport de Wählen Sie die Felder für den Export aus. choose seperator and charset importexport de Wählen Sie das Trennzeichen und den Zeichensatz aus condition importexport de Bendingungen +copied importexport de Kopiert csv field importexport de CSV Feld (Importdatei) database values importexport de Werte der Datenbank day of week importexport de Wochentag define imports|exports common de Profil definieren definition importexport de Definition delete all selected definitions importexport de Alle ausgewählten Definitionen löschen +deleted importexport de Gelöscht +duplicate name, please choose another. importexport de Doppelter Name, bitte wählen Sie einen anderen Namen edit conditions importexport de Einstellmöglichkeiten bearbeiten expert options importexport de Export Optionen export importexport de Exportieren export all selected definitions importexport de Alle ausgewählten Definitionen exportieren export data as importexport de Daten exportieren als export definition to use for nextmatch export preferences de Export Definition für den Export über die Benutzeroberfläche (nextmatch) +export spreadsheet importexport de Export Tabellenkalkulation +exported importexport de Exportiert. +extra charsets for import / export importexport de Anderen Zeichensatz für den Impor/Export wählen false importexport de Unwahr field labels importexport de Feld Beschreibung field names importexport de Feld Name fieldseperator importexport de Feldtrenner finish importexport de Fertig +from definition importexport de Von der Vorlage general preferences de Generell +general fields: preferences de Allgemeine Felder header lines to skip importexport de Kopfzeilen zu überspringen human friendly values importexport de Verwendet die Beschreibungen, anstatt der Internen Bezeichnungen if you specify an export definition, it will be used when you export preferences de Wenn Sie Export Definition erfassen , wird dieses Profil für den Export verwendet. @@ -66,20 +79,25 @@ save as definition importexport de Als Definition speichern schedule common de Zeitplan schedule import / export common de Zeitplan für Import/Export schedule not found importexport de Kein Zeitplan gefunden +schedule times are server time! currently %s. importexport de Zeitgesteuerter Import bezieht sich auf die Serverzeit. Aktuell %s. select definition importexport de Definition auswählen select plugin importexport de Plugin auswählen select... importexport de Auswählen... some nice text importexport de Ein schöner Text some records may not have been imported importexport de Einige Datensätze konnten nicht importiert werden stop importexport de Stopp +stylite template folder importexport de Stylite Template Editor target importexport de Ziel target examples: vfs://default/home/user/export.csv or http://server.net/prices.csv importexport de Beispiel für Importpfade: vfs://default/home/user/export.csv oder http://server.net/prices.csv target field importexport de Zielfeld (EGroupware) test only importexport de Nur Test translation importexport de Umwandlung true importexport de Wahr +try importexport de Testen unable to schedule importexport de Zeitplan nicht möglich update categories importexport de Kategorien aktualisieren +user preference importexport de Einstellen verwenden +user template folder importexport de Vorlageverzeichnis verwenden users allowed to create their own definitions importexport de Benutzern erlauben, Ihre eigenen Definitionen zu erstellen. users allowed to share their own definitions importexport de Benutzer dürfen Ihre Profile auch anderen Nutzern zur Verfügung stellen. which useres are allowed for this definition importexport de Welche Benutzer dürden diese Definition verwenden? diff --git a/notifications/lang/egw_en.lang b/notifications/lang/egw_en.lang index 26b7cc029c..9f1bec331e 100644 --- a/notifications/lang/egw_en.lang +++ b/notifications/lang/egw_en.lang @@ -36,7 +36,6 @@ preferences for notification notifications en Preferences for notification received notifications en Received sms backend admin en SMS back end sms only notifications en SMS only -this egroupware notification has been sent to you by mail because your notifications en This eGroupWare notification has been sent to you by mail because your this egroupware notification has been sent to you by mail because your chosen notification-chain has been disabled by the administrator. please choose another notification-chain in your preferences! notifications en This EGroupware notification has been sent to you by mail because your chosen notification chain has been disabled by the administrator. Please choose another notification chain in your preferences! windows-popup and e-mail notifications en Windows popup and email windows-popup backend admin en Windows popup back end From 6db28c5a1aef7d1fd01e44c744ce908f0e07f399 Mon Sep 17 00:00:00 2001 From: Ralf Becker Date: Thu, 16 Aug 2012 14:42:33 +0000 Subject: [PATCH 029/135] spanish translations from Rafael --- admin/lang/egw_es-es.lang | 71 +++++++++++++++++++++++++++++++++ filemanager/lang/egw_es-es.lang | 48 +++++++++++++++++++++- 2 files changed, 118 insertions(+), 1 deletion(-) diff --git a/admin/lang/egw_es-es.lang b/admin/lang/egw_es-es.lang index 2adf2d26a1..22413db067 100644 --- a/admin/lang/egw_es-es.lang +++ b/admin/lang/egw_es-es.lang @@ -1,24 +1,32 @@ %1 - %2 of %3 user accounts admin es-es %1 - %2 de %3 cuentas de usuarios %1 - %2 of %3 user groups admin es-es %1 - %2 de %3 grupos de usuarios %1 acl records of not (longer) existing accounts deleted. admin es-es Se han borrado %1 registros de cuentas inexistentes. +%1 categories of not (longer) existing accounts deleted. admin es-es Se han borrado %1 categorías de cuentas que ya no existen. +%1 category(s) %2 admin es-es %1 categorías %2 +%1 category(s) %2, %3 failed because of insufficent rights !!! admin es-es %1 categorías %2, %3 fallaron por permisos insuficiente %1 class not instanciated admin es-es La clase %1 no está instanciada %1 group %2 admin es-es %1 grupo %2 %1 is no command! admin es-es ¡%1 no es un comando! %1 log entries deleted. admin es-es Se han borrado %1 entradas del log. %1 not found or not executable !!! admin es-es No se encontró %1 o no es un ejecutable +%1 phrases saved. admin es-es Se han guardado %1 frases. %1 rights for %2 and applications %3 admin es-es Derechos de %1 para %2 y aplicaciones %3 +%1 sessions killed admin es-es Se han matado %1 sesiones %1 user %2 admin es-es %1 usuario %2 (default no, leave it off if you dont use it) admin es-es (por defecto, No, desactivar si no se usa) (stored password will not be shown here) admin es-es (las claves guardadas no se mostrarán aquí) (to install new applications use
setup [manage applications] !!!) admin es-es (Para instalar nuevas aplicaciones, utilice
Instalación [Administrar Aplicaciones]) - type admin es-es - tipo accesslog and bruteforce defense admin es-es Defensa de acceso al registro y fuerza bruta +account "%1" has no email address --> not notified! admin es-es La cuenta "%1" no tiene correo --> ¡no se notifica! +account "%1" has no plaintext password! admin es-es ¡La cuenta "%1" NO tiene la contraseña en texto claro! account %1 %2 admin es-es Cuenta %1 %2 account '%1' deleted. admin es-es Se ha borrado la cuenta '%1'. account active admin es-es Cuenta activa account has been created common es-es La cuenta ha sido creada account has been deleted common es-es La cuenta ha sido borrada account has been updated common es-es La cuenta ha sido actualizada +account id admin es-es ID de la cuenta account list admin es-es Lista de cuentas account permissions admin es-es Permisos de la cuenta account preferences admin es-es Preferencias de la cuenta @@ -54,6 +62,8 @@ advanced options admin es-es opciones avanzadas after how many unsuccessful attempts to login, an account should be blocked (default 3) ? admin es-es ¿Después de cuántos intentos fallidos de conexión debe bloquearse una cuenta? (por defecto, 3) after how many unsuccessful attempts to login, an ip should be blocked (default 3) ? admin es-es ¿Después de cuántos intentos fallidos de conexión debe bloquearse una IP? (por defecto, 3) aliases admin es-es Alias +all applications admin es-es Todas las aplicaciones +all categories admin es-es Todas las categorías all records and account information will be lost! admin es-es ¡Se perderán todos los registros y la información de las cuentas! all users admin es-es Todos los usuarios allow anonymous access to this app admin es-es Permitir acceso anónimo a esta aplicación @@ -92,10 +102,13 @@ attribute mailalternateaddress explained admin es-es Esto maneja el atributo attribute mailforwardingaddress explained admin es-es Esto maneja el atributo -mailForwardingAddress- del esquema de QMAIL y no debe estar vacío si está asignado. authentication / accounts admin es-es Identificación / Cuentas auto create account records for authenticated users admin es-es Crear cuentas automáticamente para usuarios identificados +available placeholders admin es-es Marcadores disponibles back to the list admin es-es volver a la lista +backup directory %1 mounted as %2 admin es-es El directorio de copias de seguridad %1 está montado como %2 bi-dir passthrough admin es-es bidireccional passthrough bi-directional admin es-es bidireccional bottom admin es-es parte inferior +bulk password reset admin es-es Restablecimiento de contraseña en bruto calculate next run admin es-es Calcular la siguiente ejecución calendar recurrence horizont in days (default 1000) admin es-es Horizonte de recurrencia del calendario en días (predeterminado: 1000) can change password admin es-es Puede cambiar la contraseña @@ -110,8 +123,12 @@ change account_id admin es-es Cambiar el campo account_id change acl rights admin es-es cambiar permisos de ACL change config settings admin es-es Cambiar opciones de configuración change main screen message admin es-es Cambiar mensaje de la pantalla principal +change owner admin es-es Cambiar el propietario change password for %1 admin es-es cambiar la contraseña para %1 +change password hash to admin es-es Cambiar el hash de la contraseña a +changed password hash for %1 to %2. admin es-es Se ha cambiado el hash de la contraseña de %1 a %2. check acl for entries of not (longer) existing accounts admin es-es Comprobar las ACL para las entradas de cuentas que no existen +check categories for not (longer) existing accounts admin es-es Comprobar las categorías para las cuentas que ya no existen check ip address of all sessions admin es-es Comprobar la IP de todas las sesiones check items to %1 to %2 for %3 admin es-es Seleccionar los elementos para %1 a %2 para %3 children admin es-es Hijos @@ -128,9 +145,13 @@ country selection admin es-es Selección de país create group admin es-es Crear grupo created admin es-es Creado created with id #%1 admin es-es Creado con id nº %1 +creates / updates user accounts from csv file admin es-es Crea o actualiza las cuentas de usuario desde un fichero CSV +creates / updates user groups from csv file admin es-es Crea o actualiza los grupos de usuarios desde un fichero CSV creates a new field admin es-es crea un campo nuevo crontab only (recomended) admin es-es Sólo mediante crontab (recomendado) +current hash admin es-es Hash actual custom fields admin es-es Campos personalizados +custom translation admin es-es Traducción personalizada cyrus imap server admin es-es Servidor IMAP Cyrus data admin es-es Datos day admin es-es Día @@ -150,10 +171,12 @@ delete peer server admin es-es Borrar servidor 'peer' delete selected entries admin es-es Borrar las entradas seleccionadas delete the category admin es-es borrar la categoría delete the group admin es-es borrar el grupo +delete the selected entries admin es-es Borrar las entradas seleccionadas delete this category admin es-es borrar esta categoría delete this group admin es-es borrar este grupo delete this log entry admin es-es Borrar esta entrada del log delete this user admin es-es borrar este usuario +deleted admin es-es borradas deletes this field admin es-es borra este campo deliver extern admin es-es entrega externa deny access to access log admin es-es Denegar acceso al registro de accesos @@ -175,6 +198,7 @@ deny all users access to grant other users access to their entries ? admin es-es deny all users access to preferences ? admin es-es ¿Denegar a todos los usuarios el acceso a las preferencias? description can not exceed 255 characters in length ! admin es-es ¡La descripción no puede exceder de 255 caracteres de longitud! determines the order the fields are displayed admin es-es determina el orden en que se muestran los campos +disable admin es-es Desactivar disable "auto completion" of the login form admin es-es Desactivar completado automático en el formulario de inicio de sesión disable wysiwyg-editor admin es-es desactivar editor WYSIWYG disabled (not recomended) admin es-es desactivado (no se recomienda) @@ -184,6 +208,8 @@ do you also want to delete all global subcategories ? admin es-es ¿Desea elimin do you want to delete all global subcategories ? admin es-es ¿Desea borrar todas las subcategorías globales? do you want to move all global subcategories one level down ? admin es-es ¿Desea mover todas las subcategorías globales un nivel hacia abajo? document root (default) admin es-es Raíz de los documentos (Document root) (predeterminado) +down admin es-es Abajo +download csv admin es-es Descargar CSV each value is a line like [=