Merge branch 'master' into web-components

This commit is contained in:
nathan 2021-11-10 10:25:51 -07:00
commit ed66beaf8f
15 changed files with 82 additions and 24 deletions

View File

@ -1855,7 +1855,10 @@ class addressbook_ui extends addressbook_bo
if ($query['grouped_view']) // view the contacts of one organisation only if ($query['grouped_view']) // view the contacts of one organisation only
{ {
if (strpos($query['grouped_view'],'*AND*') !== false) $query['grouped_view'] = str_replace('*AND*','&',$query['grouped_view']); if (strpos($query['grouped_view'],'*AND*') !== false) $query['grouped_view'] = str_replace('*AND*','&',$query['grouped_view']);
$fields = explode(',',$GLOBALS['egw_info']['user']['preferences']['addressbook']['duplicate_fields']); if (!is_array($fields = $GLOBALS['egw_info']['user']['preferences']['addressbook']['duplicate_fields'] ?? []))
{
$fields = explode(',', $fields);
}
foreach(explode('|||',$query['grouped_view']) as $part) foreach(explode('|||',$query['grouped_view']) as $part)
{ {
list($name,$value) = explode(':',$part,2); list($name,$value) = explode(':',$part,2);
@ -2911,7 +2914,10 @@ class addressbook_ui extends addressbook_bo
*/ */
public function ajax_check_values($values, $name, $own_id=0) public function ajax_check_values($values, $name, $own_id=0)
{ {
$fields = explode(',',$GLOBALS['egw_info']['user']['preferences']['addressbook']['duplicate_fields']); if (!is_array($fields = $GLOBALS['egw_info']['user']['preferences']['addressbook']['duplicate_fields'] ?? []))
{
$fields = explode(',', $fields);
}
$threshold = (int)$GLOBALS['egw_info']['user']['preferences']['addressbook']['duplicate_threshold']; $threshold = (int)$GLOBALS['egw_info']['user']['preferences']['addressbook']['duplicate_threshold'];
$ret = array('doublicates' => array(), 'msg' => null); $ret = array('doublicates' => array(), 'msg' => null);

View File

@ -431,12 +431,13 @@ class admin_mail
'acc_folder_archive' => array('', 'archive'), 'acc_folder_archive' => array('', 'archive'),
) as $name => $common_names) ) as $name => $common_names)
{ {
unset($content[$name]);
// first check special-use attributes // first check special-use attributes
if (($special_use = array_shift($common_names))) if (($special_use = array_shift($common_names)))
{ {
foreach((array)$attributes[$special_use] as $mailbox) foreach((array)$attributes[$special_use] as $mailbox)
{ {
if (empty($content[$name]) || strlen($mailbox) < strlen($content[$name])) if (empty($content[$name]) || is_string($mailbox) && strlen($mailbox) < strlen($content[$name]))
{ {
$content[$name] = $mailbox; $content[$name] = $mailbox;
} }
@ -450,7 +451,7 @@ class admin_mail
$delimiter = !empty($data['delimiter']) ? $data['delimiter'] : '.'; $delimiter = !empty($data['delimiter']) ? $data['delimiter'] : '.';
$name_parts = explode($delimiter, strtolower($mailbox)); $name_parts = explode($delimiter, strtolower($mailbox));
if (array_intersect($name_parts, $common_names) && if (array_intersect($name_parts, $common_names) &&
(empty($content[$name]) || strlen($mailbox) < strlen($content[$name]) && substr($content[$name], 0, 6) != 'INBOX'.$delimiter)) (empty($content[$name]) || is_string($mailbox) && strlen($mailbox) < strlen($content[$name]) && substr($content[$name], 0, 6) != 'INBOX'.$delimiter))
{ {
//error_log(__METHOD__."() $mailbox --> ".substr($name, 11).' folder'); //error_log(__METHOD__."() $mailbox --> ".substr($name, 11).' folder');
$content[$name] = $mailbox; $content[$name] = $mailbox;

View File

@ -168,6 +168,7 @@ class Widget
else else
{ {
libxml_use_internal_errors(true); libxml_use_internal_errors(true);
libxml_clear_errors();
$reader = new XMLReader(); $reader = new XMLReader();
if (!$reader->XML($xml)) if (!$reader->XML($xml))
{ {

View File

@ -405,7 +405,7 @@ class Customfields extends Transformer
$all_readonly = $this->is_readonly($cname, $form_name); $all_readonly = $this->is_readonly($cname, $form_name);
$value_in = self::get_array($content, $form_name); $value_in = self::get_array($content, $form_name);
// if we have no id / use self::GLOBAL_ID, we have to set $value_in in global namespace for regular widgets validation to find // if we have no id / use self::GLOBAL_ID, we have to set $value_in in global namespace for regular widgets validation to find
if (!$this->id) $content = array_merge($content, $value_in); if (!$this->id) $content = array_merge($content, (array)$value_in);
//error_log(__METHOD__."($cname, ...) form_name=$form_name, use-private={$this->attrs['use-private']}, value_in=".array2string($value_in)); //error_log(__METHOD__."($cname, ...) form_name=$form_name, use-private={$this->attrs['use-private']}, value_in=".array2string($value_in));
if($this->getElementAttribute($form_name, 'customfields')) if($this->getElementAttribute($form_name, 'customfields'))
{ {

View File

@ -403,8 +403,8 @@ class History
*/ */
public static function needs_diff($name, $value) public static function needs_diff($name, $value)
{ {
// No diff on encrypted content // No diff on arrays or encrypted content
if(strpos($value, static::BEGIN_PGP) == 0 && strpos($value, static::END_PGP) !== FALSE) if (is_array($value) || strpos($value, static::BEGIN_PGP) == 0 && strpos($value, static::END_PGP) !== FALSE)
{ {
return false; return false;
} }

View File

@ -947,10 +947,15 @@ class Translation
{ {
return utf8_decode($data); return utf8_decode($data);
} }
if (self::$mbstring && !$prefer_iconv && ($data = @mb_convert_encoding($data,$to,$from)) != '') try {
if (self::$mbstring && !$prefer_iconv && ($data = @mb_convert_encoding($data, $to, $from)) != '')
{ {
return $data; return $data;
} }
}
catch (\ValueError $e) {
// ignore encodings unknown to mb_convert_encoding
}
if (function_exists('iconv')) if (function_exists('iconv'))
{ {
// iconv can not convert from/to utf7-imap // iconv can not convert from/to utf7-imap

View File

@ -1829,12 +1829,13 @@ class calendar_boupdate extends calendar_bo
} }
// Update history // Update history
$event = $this->read($cal_id, $recur_date, $ignore_acl, 'server'); if (($event = $this->read($cal_id, $recur_date, $ignore_acl, 'server')))
{
$tracking = new calendar_tracking($this); $tracking = new calendar_tracking($this);
$tracking->track($event, $old_event); $tracking->track($event, $old_event);
}
// notify the link-class about the update, as other apps may be subscribed to it // notify the link-class about the update, as other apps may be subscribed to it
Link::notify_update('calendar',$event['id'],$event,"update"); Link::notify_update('calendar', $cal_id, $event, "update");
} }
return $Ok; return $Ok;
} }

View File

@ -600,8 +600,8 @@ class calendar_ical extends calendar_boupdate
if (empty($event['whole_day'])) if (empty($event['whole_day']))
{ {
// Hack for CalDAVTester to export duration instead of endtime // Hack for CalDAVTester to export duration instead of endtime
if ($tzid == 'UTC' && $event['end'] - $event['start'] <= 86400) if ($tzid == 'UTC' && ($duration = Api\DateTime::to($event['end'], 'ts') - Api\DateTime::to($event['start'], 'ts')) <= 86400)
$attributes['duration'] = $event['end'] - $event['start']; $attributes['duration'] = $duration;
else else
$attributes['DTEND'] = self::getDateTime($event['end'],$tzid,$parameters['DTEND']); $attributes['DTEND'] = self::getDateTime($event['end'],$tzid,$parameters['DTEND']);
} }
@ -871,6 +871,24 @@ class calendar_ical extends calendar_boupdate
{ {
$attr_name = 'X-EGROUPWARE-'.$attr_name; $attr_name = 'X-EGROUPWARE-'.$attr_name;
} }
// fix certain stock fields like GEO, which are not in EGroupware schema, but Horde Icalendar requires a certain format
switch($name)
{
case '##GEO':
if (!is_array($value))
{
if (strpos($value, ';'))
{
list($lat, $long) = explode(';', $value);
}
else
{
list($long, $lat) = explode(',', $value);
}
$value = ['latitude' => $lat, 'logitude' => $long];
}
break;
}
if ($value[0] === '{' && ($attr = json_decode($value, true)) && is_array($attr)) if ($value[0] === '{' && ($attr = json_decode($value, true)) && is_array($attr))
{ {
// check if attribute was stored compressed --> uncompress it // check if attribute was stored compressed --> uncompress it

View File

@ -779,6 +779,7 @@ class calendar_so
} }
if(isset($params['sql_filter']['cal_id'])) if(isset($params['sql_filter']['cal_id']))
{ {
if (!is_array($params['query'])) $params['query'] = [];
$params['query']['cal_id'] = $params['sql_filter']['cal_id']; $params['query']['cal_id'] = $params['sql_filter']['cal_id'];
$where[] = $this->db->column_data_implode(", ", [$this->cal_table.'.cal_id' => $params['sql_filter']['cal_id']], True, False); $where[] = $this->db->column_data_implode(", ", [$this->cal_table.'.cal_id' => $params['sql_filter']['cal_id']], True, False);
unset($params['sql_filter']['cal_id']); unset($params['sql_filter']['cal_id']);

View File

@ -2192,7 +2192,7 @@ class calendar_uiforms extends calendar_ui
break; break;
case 'cancel': case 'cancel':
// first participant is the (external) organizer (our iCal parser adds owner first!) // first participant is the (external) organizer (our iCal parser adds owner first!)
$parts = $event['participants']; $parts = $event['participants'] ?? [];
unset($parts[$existing_event['owner']]); unset($parts[$existing_event['owner']]);
$event['ical_sender_uid'] = key($parts); $event['ical_sender_uid'] = key($parts);
if (empty($existing_event['id']) || !$this->bo->check_perms(Acl::DELETE, $existing_event['id'])) if (empty($existing_event['id']) || !$this->bo->check_perms(Acl::DELETE, $existing_event['id']))

View File

@ -20,7 +20,7 @@
<row> <row>
<box id="portlets"> <box id="portlets">
<!-- Box wrapper needed to get box to auto-repeat --> <!-- Box wrapper needed to get box to auto-repeat -->
<box id="${row}"><portlet id="${_cont[id]}" title="${_cont[title]}" color="@color" parent_node="home-index_portlets" settings="@settings" width="@width" height="@height" row="@row" col="@col" value="@content" class="@class"/></box> <box id="${row}"><portlet id="${_cont[id]}" title="$_cont[title]" color="@color" parent_node="home-index_portlets" settings="@settings" width="@width" height="@height" row="@row" col="@col" value="@content" class="@class"/></box>
</box> </box>
</row> </row>
</rows> </rows>

View File

@ -412,9 +412,30 @@ class infolog_ical extends infolog_bo
{ {
if (substr($name, 0, 2) == '##') if (substr($name, 0, 2) == '##')
{ {
if (($v = json_php_unserialize($value)) && is_array($v))
{
$value = $v;
}
// fix certain stock fields like GEO, which are not in EGroupware schema, but Horde Icalendar requires a certain format
switch($name)
{
case '##GEO':
if (!is_array($value))
{
if (strpos($value, ';') !== false)
{
list($lat, $long) = explode(';', $value);
}
else
{
list($long, $lat) = explode(',', $value);
}
$value = ['latitude' => $lat, 'logitude' => $long];
}
break;
}
if ($name[2] == ':') if ($name[2] == ':')
{ {
if (($v = json_php_unserialize($value)) && is_array($v)) $value = $v;
foreach((array)$value as $compvData) foreach((array)$value as $compvData)
{ {
$comp = Horde_Icalendar::newComponent(substr($name,3), $vevent); $comp = Horde_Icalendar::newComponent(substr($name,3), $vevent);
@ -422,9 +443,9 @@ class infolog_ical extends infolog_bo
$vevent->addComponent($comp); $vevent->addComponent($comp);
} }
} }
elseif (($attr = json_php_unserialize($value)) && is_array($attr)) elseif (is_array($value))
{ {
$vevent->setAttribute(substr($name, 2), $attr['value'], $attr['params'], true, $attr['values']); $vevent->setAttribute(substr($name, 2), $value['value'], $value['params'], true, $value['values']);
} }
else else
{ {

View File

@ -212,6 +212,10 @@ class infolog_tracking extends Api\Storage\Tracking
{ {
$id = ' #'.$data['info_id']; $id = ' #'.$data['info_id'];
} }
if (is_array($data['info_cat']))
{
$data['info_cat'] = array_shift($data['info_cat']);
}
foreach(array( foreach(array(
'info_type' => lang($this->infolog->enums['type'][$data['info_type']]).$id, 'info_type' => lang($this->infolog->enums['type'][$data['info_type']]).$id,
'info_from' => $data['info_from'], 'info_from' => $data['info_from'],

View File

@ -806,7 +806,7 @@ class mail_zpush implements activesync_plugin_write, activesync_plugin_sendmail,
} }
} }
//$BCCmail=''; //$BCCmail='';
if (count($mailAddr)>0) $mailObject->forceBccHeader(); if (!empty($mailAddr)) $mailObject->forceBccHeader();
//$BCCmail = $mailObject->AddrAppend("Bcc",$mailAddr); //$BCCmail = $mailObject->AddrAppend("Bcc",$mailAddr);
foreach($folderArray as $folderName) { foreach($folderArray as $folderName) {
if($this->mail->isSentFolder($folderName)) { if($this->mail->isSentFolder($folderName)) {

View File

@ -750,7 +750,7 @@ class resources_bo
$end = $start->format('ts') + 86399; $end = $start->format('ts') + 86399;
} else { } else {
$start = $start->format('ts'); $start = $start->format('ts');
$end = $start + ($cal_info['duration']); $end = $start + (int)$cal_info['duration'];
} }
// search events matching our timestamps // search events matching our timestamps