mirror of
https://github.com/EGroupware/egroupware.git
synced 2024-12-27 00:58:56 +01:00
Fix encoding issues; improvements for Funambol clients
This commit is contained in:
parent
058a820eb7
commit
49823ecd7e
@ -225,7 +225,7 @@ class addressbook_vcal extends addressbook_bo
|
||||
}
|
||||
foreach ($databaseFields as $databaseField)
|
||||
{
|
||||
$value = "";
|
||||
$value = '';
|
||||
|
||||
if (!empty($databaseField))
|
||||
{
|
||||
@ -282,21 +282,44 @@ class addressbook_vcal extends addressbook_bo
|
||||
{
|
||||
$values = (array) $GLOBALS['egw']->translation->convert($values, $sysCharSet, $_charset);
|
||||
$value = implode(',', $values); // just for the CHARSET recognition
|
||||
if ($extra_charset_attribute && preg_match('/([\177-\377])/', $value))
|
||||
if (($size > 0) && strlen($value) > $size)
|
||||
{
|
||||
$options['CHARSET'] = $_charset;
|
||||
// let us try with only the first category
|
||||
$value = $values[0];
|
||||
if (strlen($value) > $size)
|
||||
{
|
||||
error_log(__FILE__ . __LINE__ . __METHOD__ . " vCalAddressbook $vcardField omitted due to maximum size $size");
|
||||
// Horde::logMessage("vCalAddressbook $vcardField omitted due to maximum size $size",
|
||||
// __FILE__, __LINE__, PEAR_LOG_WARNING);
|
||||
continue;
|
||||
}
|
||||
$values = array();
|
||||
}
|
||||
if (preg_match('/[^\x20-\x7F]/', $value))
|
||||
{
|
||||
if ($extra_charset_attribute || $this->productName == 'kde')
|
||||
{
|
||||
$options['CHARSET'] = $_charset;
|
||||
}
|
||||
// KAddressbook requires non-ascii chars to be qprint encoded, other clients eg. nokia phones have trouble with that
|
||||
if ($this->productName == 'kde' ||
|
||||
($this->productManufacturer == 'funambol' && $this->productName == 'blackberry plug-in'))
|
||||
if ($this->productName == 'kde')
|
||||
{
|
||||
$options['ENCODING'] = 'QUOTED-PRINTABLE';
|
||||
}
|
||||
else
|
||||
elseif ($this->productManufacturer == 'funambol')
|
||||
{
|
||||
$options['ENCODING'] = 'FUNAMBOL-QP';
|
||||
}
|
||||
elseif (preg_match('/([\000-\012\015\016\020-\037\075])/', $value))
|
||||
{
|
||||
$options['ENCODING'] = 'QUOTED-PRINTABLE';
|
||||
}
|
||||
elseif (!$extra_charset_attribute)
|
||||
{
|
||||
$options['ENCODING'] = '';
|
||||
}
|
||||
}
|
||||
$hasdata++;
|
||||
$hasdata++;
|
||||
}
|
||||
break;
|
||||
|
||||
@ -331,33 +354,29 @@ class addressbook_vcal extends addressbook_bo
|
||||
{
|
||||
$value = $GLOBALS['egw']->translation->convert(trim($value), $sysCharSet, $_charset);
|
||||
$values[] = $value;
|
||||
if ($extra_charset_attribute)
|
||||
if (preg_match('/[^\x20-\x7F]/', $value))
|
||||
{
|
||||
if (preg_match('/([\177-\377])/', $value))
|
||||
if ($extra_charset_attribute || $this->productName == 'kde')
|
||||
{
|
||||
$options['CHARSET'] = $_charset;
|
||||
// KAddressbook requires non-ascii chars to be qprint encoded, other clients eg. nokia phones have trouble with that
|
||||
if ($this->productName == 'kde' ||
|
||||
($this->productManufacturer == 'funambol' && $this->productName == 'blackberry plug-in'))
|
||||
{
|
||||
$options['ENCODING'] = 'QUOTED-PRINTABLE';
|
||||
}
|
||||
else
|
||||
{
|
||||
$options['ENCODING'] = '';
|
||||
}
|
||||
}
|
||||
// protect the CardDAV
|
||||
if (preg_match('/([\000-\012\015\016\020-\037\075])/', $value))
|
||||
// KAddressbook requires non-ascii chars to be qprint encoded, other clients eg. nokia phones have trouble with that
|
||||
if ($this->productName == 'kde')
|
||||
{
|
||||
$options['ENCODING'] = 'QUOTED-PRINTABLE';
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// avoid that these options are inserted from horde code
|
||||
$options['CHARSET'] = '';
|
||||
$options['ENCODING'] = '';
|
||||
elseif ($this->productManufacturer == 'funambol')
|
||||
{
|
||||
$options['ENCODING'] = 'FUNAMBOL-QP';
|
||||
}
|
||||
elseif (preg_match('/([\000-\012\015\016\020-\037\075])/', $value))
|
||||
{
|
||||
$options['ENCODING'] = 'QUOTED-PRINTABLE';
|
||||
}
|
||||
elseif (!$extra_charset_attribute)
|
||||
{
|
||||
$options['ENCODING'] = '';
|
||||
}
|
||||
}
|
||||
if ($vcardField == 'TEL' && $entry['tel_prefer'] &&
|
||||
($databaseField == $entry['tel_prefer']))
|
||||
|
@ -513,10 +513,16 @@ class calendar_ical extends calendar_boupdate
|
||||
break;
|
||||
|
||||
case 'CATEGORIES':
|
||||
if ($event['category'])
|
||||
if ($event['category'] && ($values['CATEGORIES'] = $this->get_categories($event['category'])))
|
||||
{
|
||||
$attributes['CATEGORIES'] = '';
|
||||
$values['CATEGORIES'] = $this->get_categories($event['category']);
|
||||
if (count($values['CATEGORIES']) == 1)
|
||||
{
|
||||
$attributes['CATEGORIES'] = array_shift($values['CATEGORIES']);
|
||||
}
|
||||
else
|
||||
{
|
||||
$attributes['CATEGORIES'] = '';
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
@ -698,12 +704,37 @@ class calendar_ical extends calendar_boupdate
|
||||
$vevent->setAttribute($key, $valueData, $paramData, true, $valuesData);
|
||||
$options = array();
|
||||
if ($paramData['CN']) $valueData .= $paramData['CN']; // attendees or organizer CN can contain utf-8 content
|
||||
/*if($key != 'RRULE' && preg_match('/([\000-\012\015\016\020-\037\075])/',$valueData)) {
|
||||
$options['ENCODING'] = 'QUOTED-PRINTABLE';
|
||||
}*/
|
||||
if ($this->productManufacturer != 'groupdav' && preg_match('/([\177-\377])/', $valueData))
|
||||
|
||||
if (preg_match('/[^\x20-\x7F]/', $valueData))
|
||||
{
|
||||
$options['CHARSET'] = 'UTF-8';
|
||||
switch ($this->productManufacturer)
|
||||
{
|
||||
case 'groupdav':
|
||||
if ($this->productName == 'kde')
|
||||
{
|
||||
$options['CHARSET'] = 'UTF-8';
|
||||
$options['ENCODING'] = 'QUOTED-PRINTABLE';
|
||||
}
|
||||
else
|
||||
{
|
||||
$options['CHARSET'] = '';
|
||||
|
||||
if (preg_match('/([\000-\012\015\016\020-\037\075])/', $valueData))
|
||||
{
|
||||
$options['ENCODING'] = 'QUOTED-PRINTABLE';
|
||||
}
|
||||
else
|
||||
{
|
||||
$options['ENCODING'] = '';
|
||||
}
|
||||
}
|
||||
break;
|
||||
case 'funambol':
|
||||
$options['ENCODING'] = 'FUNAMBOL-QP';
|
||||
default:
|
||||
// force UTF-8
|
||||
$options['CHARSET'] = 'UTF-8';
|
||||
}
|
||||
}
|
||||
if (preg_match('/([\000-\012])/', $valueData))
|
||||
{
|
||||
@ -764,13 +795,13 @@ class calendar_ical extends calendar_boupdate
|
||||
{
|
||||
if ($this->log) error_log(__FILE__.'['.__LINE__.'] '.__METHOD__."()\n".array2string($_vcalData)."\n",3,$this->logfile);
|
||||
|
||||
if (!is_array($this->supportedFields)) $this->setSupportedFields();
|
||||
|
||||
if (!($events = $this->icaltoegw($_vcalData,$cal_id,$etag,$recur_date)))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!is_array($this->supportedFields)) $this->setSupportedFields();
|
||||
|
||||
// check if we are importing an event series with exceptions in CalDAV
|
||||
// only first event / series master get's cal_id from URL
|
||||
// other events are exceptions and need to be checked if they are new
|
||||
@ -784,6 +815,7 @@ class calendar_ical extends calendar_boupdate
|
||||
}
|
||||
foreach ($events as $event)
|
||||
{
|
||||
if ($this->log) error_log(__FILE__.'['.__LINE__.'] '.__METHOD__."()\n".array2string($event)."\n",3,$this->logfile);
|
||||
$updated_id = false;
|
||||
$event_info = $this->get_event_info($event);
|
||||
|
||||
@ -1275,6 +1307,12 @@ class calendar_ical extends calendar_boupdate
|
||||
'etag' => 'etag',
|
||||
);
|
||||
|
||||
$defaultFields['funambol'] = $defaultFields['basic'] + array(
|
||||
'category' => 'category',
|
||||
'non_blocking' => 'non_blocking',
|
||||
'recurrence' => 'recurrence',
|
||||
);
|
||||
|
||||
$defaultFields['evolution'] = $defaultFields['basic'] + array(
|
||||
'participants' => 'participants',
|
||||
'owner' => 'owner',
|
||||
@ -1402,7 +1440,7 @@ class calendar_ical extends calendar_boupdate
|
||||
break;
|
||||
|
||||
case 'funambol':
|
||||
$this->supportedFields = $defaultFields['synthesis'];
|
||||
$this->supportedFields = $defaultFields['funambol'];
|
||||
break;
|
||||
|
||||
// the fallback for SyncML
|
||||
@ -1430,6 +1468,7 @@ class calendar_ical extends calendar_boupdate
|
||||
$vcal = new Horde_iCalendar;
|
||||
if (!$vcal->parsevCalendar($_vcalData))
|
||||
{
|
||||
if ($this->log) error_log(__FILE__.'['.__LINE__.'] '.__METHOD__."(): No vCalendar Container found!\n",3,$this->logfile);
|
||||
if ($this->tzid)
|
||||
{
|
||||
date_default_timezone_set($GLOBALS['egw_info']['server']['server_timezone']);
|
||||
@ -2047,7 +2086,6 @@ class calendar_ical extends calendar_boupdate
|
||||
// fall through
|
||||
case 'LAST-MODIFIED': // will be written direct to the event
|
||||
$event['modified'] = $attributes['value'];
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
@ -2127,6 +2165,7 @@ class calendar_ical extends calendar_boupdate
|
||||
}
|
||||
|
||||
if ($this->calendarOwner) $event['owner'] = $this->calendarOwner;
|
||||
if ($this->log) error_log(__FILE__.'['.__LINE__.'] '.__METHOD__."()\n".array2string($event)."\n",3,$this->logfile);
|
||||
//Horde::logMessage("vevent2egw:\n" . print_r($event, true),
|
||||
// __FILE__, __LINE__, PEAR_LOG_DEBUG);
|
||||
return $event;
|
||||
|
@ -169,20 +169,40 @@ class infolog_ical extends infolog_bo
|
||||
|
||||
if ($field == 'RELATED-TO')
|
||||
{
|
||||
$options = array('RELTYPE' => 'PARENT');
|
||||
$options = array('RELTYPE' => 'PARENT',
|
||||
'CHARSET' => 'UTF-8');
|
||||
}
|
||||
else
|
||||
{
|
||||
$options = array();
|
||||
$options = array('CHARSET' => 'UTF-8');
|
||||
}
|
||||
|
||||
/*if(preg_match('/([\000-\012\015\016\020-\037\075])/', $value)) {
|
||||
$options['ENCODING'] = 'QUOTED-PRINTABLE';
|
||||
}*/
|
||||
if ($this->productManufacturer != 'groupdav'
|
||||
&& preg_match('/([\177-\377])/',$value))
|
||||
if (preg_match('/[^\x20-\x7F]/', $value))
|
||||
{
|
||||
$options['CHARSET'] = 'UTF-8';
|
||||
switch ($this->productManufacturer)
|
||||
{
|
||||
case 'groupdav':
|
||||
if ($this->productName == 'kde')
|
||||
{
|
||||
$options['ENCODING'] = 'QUOTED-PRINTABLE';
|
||||
}
|
||||
else
|
||||
{
|
||||
$options['CHARSET'] = '';
|
||||
|
||||
if (preg_match('/([\000-\012\015\016\020-\037\075])/', $value))
|
||||
{
|
||||
$options['ENCODING'] = 'QUOTED-PRINTABLE';
|
||||
}
|
||||
else
|
||||
{
|
||||
$options['ENCODING'] = '';
|
||||
}
|
||||
}
|
||||
break;
|
||||
case 'funambol':
|
||||
$options['ENCODING'] = 'FUNAMBOL-QP';
|
||||
}
|
||||
}
|
||||
$vevent->setAttribute($field, $value, $options);
|
||||
}
|
||||
@ -462,19 +482,48 @@ class infolog_ical extends infolog_bo
|
||||
break;
|
||||
|
||||
case 'text/x-vnote':
|
||||
if (!empty($note['info_cat']))
|
||||
{
|
||||
$cats = $this->get_categories(array($note['info_cat']));
|
||||
$note['info_cat'] = $GLOBALS['egw']->translation->convert($cats[0],
|
||||
$GLOBALS['egw']->translation->charset(), 'UTF-8');
|
||||
}
|
||||
$vnote = new Horde_iCalendar_vnote();
|
||||
$options = array('CHARSET' => 'UTF-8');
|
||||
$vNote->setAttribute('VERSION', '1.1');
|
||||
foreach (array( 'SUMMARY' => $note['info_subject'],
|
||||
'BODY' => $note['info_des'],
|
||||
foreach (array( 'SUMMARY' => $note['info_subject'],
|
||||
'BODY' => $note['info_des'],
|
||||
'CATEGORIES' => $note['info_cat'],
|
||||
) as $field => $value)
|
||||
{
|
||||
$vnote->setAttribute($field, $value);
|
||||
if ($this->productManufacturer != 'groupdav'
|
||||
&& preg_match('/([\177-\377])/', $value))
|
||||
$options = array('CHARSET' => 'UTF-8');
|
||||
if (preg_match('/[^\x20-\x7F]/', $value))
|
||||
{
|
||||
$vevent->setParameter($field, $options);
|
||||
switch ($this->productManufacturer)
|
||||
{
|
||||
case 'groupdav':
|
||||
if ($this->productName == 'kde')
|
||||
{
|
||||
$options['ENCODING'] = 'QUOTED-PRINTABLE';
|
||||
}
|
||||
else
|
||||
{
|
||||
$options['CHARSET'] = '';
|
||||
|
||||
if (preg_match('/([\000-\012\015\016\020-\037\075])/', $value))
|
||||
{
|
||||
$options['ENCODING'] = 'QUOTED-PRINTABLE';
|
||||
}
|
||||
else
|
||||
{
|
||||
$options['ENCODING'] = '';
|
||||
}
|
||||
}
|
||||
break;
|
||||
case 'funambol':
|
||||
$options['ENCODING'] = 'FUNAMBOL-QP';
|
||||
}
|
||||
}
|
||||
$vevent->setAttribute($field, $value, $options);
|
||||
}
|
||||
if ($note['info_startdate'])
|
||||
{
|
||||
@ -483,18 +532,6 @@ class infolog_ical extends infolog_bo
|
||||
$vnote->setAttribute('DCREATED',$GLOBALS['egw']->contenthistory->getTSforAction('infolog_note',$_noteID,'add'));
|
||||
$vnote->setAttribute('LAST-MODIFIED',$GLOBALS['egw']->contenthistory->getTSforAction('infolog_note',$_noteID,'modify'));
|
||||
|
||||
if (!empty($note['info_cat']))
|
||||
{
|
||||
$cats = $this->get_categories(array($note['info_cat']));
|
||||
$value = $cats[0];
|
||||
$vnote->setAttribute('CATEGORIES', $value);
|
||||
if ($this->productManufacturer != 'groupdav'
|
||||
&& preg_match('/([\177-\377])/', $value))
|
||||
{
|
||||
$vevent->setParameter('CATEGORIES', $options);
|
||||
}
|
||||
}
|
||||
|
||||
#$vnote->setAttribute('CLASS',$taskData['info_access'] == 'public' ? 'PUBLIC' : 'PRIVATE');
|
||||
|
||||
return $vnote->exportvCalendar();
|
||||
|
@ -48,7 +48,7 @@ class Horde_SyncML_Command_Sync_ContentSyncElement extends Horde_SyncML_Command_
|
||||
}
|
||||
*/
|
||||
if (isset($this->_content) && !$this->_moreData) {
|
||||
$this->_content = trim($this->_content);
|
||||
//$this->_content = trim($this->_content);
|
||||
$this->_contentSize = strlen($this->_content);
|
||||
if (strtolower($this->_contentFormat) == 'b64') {
|
||||
$this->_content = base64_encode($this->_content);
|
||||
|
@ -602,6 +602,7 @@ class Horde_iCalendar {
|
||||
|
||||
// Unfold any folded lines.
|
||||
if ($this->isOldFormat()) {
|
||||
// old formats force folding at whitespace which must therefore be preserved
|
||||
$vCal = preg_replace('/[\r\n]+([ \t])/', '\1', $vCal);
|
||||
} else {
|
||||
$vCal = preg_replace('/[\r\n]+[ \t]/', '', $vCal);
|
||||
@ -899,7 +900,7 @@ class Horde_iCalendar {
|
||||
&& (!$this->isOldFormat() || empty($param_value))) {
|
||||
continue;
|
||||
}
|
||||
if ($param_name == 'ENCODING' && empty($param_value)) {
|
||||
if ($param_name == 'ENCODING') {
|
||||
continue;
|
||||
}
|
||||
/* Skip VALUE=DATE for vCalendar 1.0 data, not allowed. */
|
||||
@ -1080,20 +1081,20 @@ class Horde_iCalendar {
|
||||
// Text containing newlines or ASCII >= 127 must be BASE64
|
||||
// or QUOTED-PRINTABLE encoded. Currently we use
|
||||
// QUOTED-PRINTABLE as default.
|
||||
if (preg_match("/[^\x20-\x7F]/", $value) &&
|
||||
!isset($params['ENCODING'])) {
|
||||
$params['ENCODING'] = 'QUOTED-PRINTABLE';
|
||||
$params_str .= ';ENCODING=QUOTED-PRINTABLE';
|
||||
// Add CHARSET as well. At least the synthesis client
|
||||
// gets confused otherwise
|
||||
if (!isset($params['CHARSET'])) {
|
||||
$params['CHARSET'] = NLS::getCharset();
|
||||
$params_str .= ';CHARSET=' . $params['CHARSET'];
|
||||
}
|
||||
if (preg_match('/[^\x20-\x7F]/', $value) &&
|
||||
!isset($params['ENCODING'])) {
|
||||
$params['ENCODING'] = 'QUOTED-PRINTABLE';
|
||||
}
|
||||
if (preg_match('/([\177-\377])/', $value) &&
|
||||
!isset($params['CHARSET'])) {
|
||||
// Add CHARSET as well. At least the synthesis client
|
||||
// gets confused otherwise
|
||||
$params['CHARSET'] = NLS::getCharset();
|
||||
$params_str .= ';CHARSET=' . $params['CHARSET'];
|
||||
}
|
||||
} else {
|
||||
if (is_array($attribute['values']) &&
|
||||
count($attribute['values'])) {
|
||||
count($attribute['values']) > 1) {
|
||||
$values = $attribute['values'];
|
||||
if ($name == 'N' || $name == 'ADR' || $name == 'ORG') {
|
||||
$glue = ';';
|
||||
@ -1118,30 +1119,40 @@ class Horde_iCalendar {
|
||||
}
|
||||
|
||||
if (!empty($params['ENCODING']) && strlen(trim($value))) {
|
||||
switch($params['ENCODING']) {
|
||||
case 'Q':
|
||||
case 'QUOTED-PRINTABLE':
|
||||
$value = str_replace("\r", '', $value);
|
||||
$result .= $name . $params_str . ':'
|
||||
. str_replace('=0A', '=0D=0A',
|
||||
$this->_quotedPrintableEncode($value))
|
||||
. $this->_newline;
|
||||
break;
|
||||
case 'B':
|
||||
case 'BASE64':
|
||||
$attr_string = $name . $params_str . ":" . $this->_newline . ' ' . $this->_base64Encode($value);
|
||||
$attr_string = String::wordwrap($attr_string, 75, $this->_newline . ' ',
|
||||
true, 'utf-8', true);
|
||||
$result .= $attr_string . $this->_newline;
|
||||
if ($this->isOldFormat()) {
|
||||
$result .= $this->_newline; // Append an empty line
|
||||
}
|
||||
break;
|
||||
}
|
||||
switch($params['ENCODING']) {
|
||||
case 'Q':
|
||||
case 'QUOTED-PRINTABLE':
|
||||
$params_str .= ';ENCODING=' . $params['ENCODING'];
|
||||
$value = str_replace("\r", '', $value);
|
||||
$result .= $name . $params_str . ':'
|
||||
. str_replace('=0A', '=0D=0A',
|
||||
$this->_quotedPrintableEncode($value))
|
||||
. $this->_newline;
|
||||
break;
|
||||
case 'FUNAMBOL-QP':
|
||||
// Funambol does not support wrapping and needs some special quoting
|
||||
$params_str .= ';ENCODING=QUOTED-PRINTABLE';
|
||||
$value = str_replace(array('<', "\r"), array('<', ''), $value);
|
||||
$result .= $name . $params_str . ':'
|
||||
. str_replace('=0A', '=0D=0A',
|
||||
$this->_quotedPrintableEncode($value, false))
|
||||
. $this->_newline;
|
||||
break;
|
||||
case 'B':
|
||||
case 'BASE64':
|
||||
$params_str .= ';ENCODING=' . $params['ENCODING'];
|
||||
$attr_string = $name . $params_str . ':' . $this->_newline . ' ' . $this->_base64Encode($value);
|
||||
$attr_string = String::wordwrap($attr_string, 75, $this->_newline . ' ',
|
||||
true, 'utf-8', true);
|
||||
$result .= $attr_string . $this->_newline;
|
||||
if ($this->isOldFormat()) {
|
||||
$result .= $this->_newline; // Append an empty line
|
||||
}
|
||||
}
|
||||
} else {
|
||||
$value = str_replace(array("\r", "\n"), array('', '\\n'), $value);
|
||||
$attr_string = $name . $params_str;
|
||||
if (!empty($value) || $value === 0 || (is_string($value) && strlen($value) > 0)) {
|
||||
if (strlen($value) > 0) {
|
||||
$attr_string .= ':' . $value;
|
||||
} elseif ($name != 'RRULE') {
|
||||
$attr_string .= ':';
|
||||
@ -1537,7 +1548,7 @@ class Horde_iCalendar {
|
||||
*
|
||||
* @return string The quoted-printable encoded string.
|
||||
*/
|
||||
function _quotedPrintableEncode($input = '')
|
||||
function _quotedPrintableEncode($input = '', $withFolding=true)
|
||||
{
|
||||
$output = $line = '';
|
||||
$len = strlen($input);
|
||||
@ -1555,7 +1566,7 @@ class Horde_iCalendar {
|
||||
}
|
||||
$line .= $chunk;
|
||||
// Wrap long lines (rule 5)
|
||||
if (strlen($line) + 1 > 76) {
|
||||
if ($withFolding && strlen($line) + 1 > 76) {
|
||||
$line = String::wordwrap($line, 75, "=\r\n", true, 'us-ascii', true);
|
||||
$newline = strrchr($line, "\r\n");
|
||||
if ($newline !== false) {
|
||||
@ -1567,7 +1578,7 @@ class Horde_iCalendar {
|
||||
continue;
|
||||
}
|
||||
// Wrap at line breaks for better readability (rule 4).
|
||||
if (substr($line, -3) == '=0A') {
|
||||
if ($withFolding && substr($line, -3) == '=0A') {
|
||||
$output .= $line . "=\r\n";
|
||||
$line = '';
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user