* Mail/Addressbook/Calendar: add and use charset when sending/receiving mails with vCard/iCals, change default vCard charset preference to utf-8

This commit is contained in:
Ralf Becker 2016-04-29 07:51:13 +00:00
parent b74b3d84f4
commit 0eb3619cd1
10 changed files with 63 additions and 29 deletions

View File

@ -305,7 +305,7 @@ class addressbook_hooks
'help' => 'Which charset should be used for the vCard import and export.',
'xmlrpc' => True,
'admin' => false,
'default'=> 'iso-8859-1',
'default'=> 'utf-8',
);
}
return $settings;

View File

@ -12,9 +12,10 @@
* @version $Id$
*/
use EGroupware\Api;
/**
* Addressbook - vCard parser
*
*/
class addressbook_vcal extends addressbook_bo
{
@ -555,11 +556,17 @@ class addressbook_vcal extends addressbook_bo
$container = false;
$vCard = Horde_Icalendar::newComponent('vcard', $container);
if (!$vCard->parsevCalendar($_vcard, 'VCARD', $charset))
if ($charset && $charset != 'utf-8')
{
$_vcard = Api\Translation::convert($_vcard, $charset, 'utf-8');
}
if (!$vCard->parsevCalendar($_vcard, 'VCARD'))
{
return False;
}
} else {
}
else
{
$vCard = $_vcard;
}
$vcardValues = $vCard->getAllAttributes();

View File

@ -704,13 +704,13 @@ app.classes.addressbook = AppJS.extend(
adb_mail_vcard: function(_action, _elems)
{
var app_registry = egw.link_get_registry('mail');
if (typeof app_registry['view'] == 'undefined') app_registry = egw.link_get_registry('felamimail');
var link = egw().link("/index.php","menuaction="+app_registry['add']['menuaction']);
for (var i = 0; i < _elems.length; i++)
{
var idToUse = _elems[i].id;
var idToUseArray = idToUse.split('::');
idToUse = idToUseArray[1];
link += "&preset[type][]="+encodeURIComponent("text/vcard; charset="+(egw.preference('vcard_charset', 'addressbook') || 'utf-8'));
link += "&preset[file][]="+encodeURIComponent("vfs://default/apps/addressbook/"+idToUse+"/.entry");
}
if (typeof app_registry['view'] != 'undefined' && typeof app_registry['view_popup'] != 'undefined' )

View File

@ -253,8 +253,12 @@ class IcalIterator extends Horde_Icalendar implements \Iterator
return;
//return PEAR::raiseError("Unable to create object for type $type");
}
//error_log(__METHOD__."() about to call parsevCalendar('".substr($data,0,100)."...','$type','$this->charset')");
$this->component->parsevCalendar($data, $type, $this->charset);
if ($this->charset && $this->charset != 'utf-8')
{
$data = Api\Translation::convert($data, $this->charset, 'utf-8');
}
//error_log(__METHOD__."() about to call parsevCalendar('".substr($data,0,100)."...','$type')");
$this->component->parsevCalendar($data, $type);
// VTIMEZONE components are NOT returned, they are only processed internally
if ($type == 'VTIMEZONE')

View File

@ -5708,11 +5708,10 @@ class Mail
if ($part && ($partDisposition=='attachment' || $partDisposition=='inline' || ($part->getPrimaryType() == 'text' && $part->getSubType() == 'calendar')))
{
//$headerObject=$part->getAllDispositionParameters();//not used anywhere around here
$structure_bytes = $part->getBytes();
$structure_mime=$part->getType();
$structure_partID=$part->getMimeId();
$filename=$part->getName();
//error_log(__METHOD__.__LINE__." fetchPartContents(".array2string($_uid).", $structure_partID, $_stream, $_preserveSeen,$structure_mime)" );
$structure_mime = $part->getType();
$filename = $part->getName();
$charset = $part->getContentTypeParameter('charset');
//$structure_bytes = $part->getBytes(); $structure_partID=$part->getMimeId(); error_log(__METHOD__.__LINE__." fetchPartContents(".array2string($_uid).", $structure_partID, $_stream, $_preserveSeen,$structure_mime)" );
$this->fetchPartContents($_uid, $part, $_stream, $_preserveSeen=true,$structure_mime);
if ($_returnPart) return $part;
}
@ -5727,8 +5726,8 @@ class Mail
}
$attachmentData = array(
'type' => $structure_mime,
'charset' => $charset,
'filename' => $filename,
//'attachment' => $part->getContents(array('stream'=>$_stream))
'attachment' => $part->getContents(array(
// tnef_decode needs strings not a stream
'stream' => $_stream && !($filename == 'winmail.dat' && $_winmail_nr)

View File

@ -321,19 +321,18 @@ class Mailer extends Horde_Mime_Mail
* "text/calendar; method=..." get automatic detected and added as highest priority alternative
*
* @param string|resource $data Path to the attachment or open file-descriptor
* @param string $name The file name to use for the attachment.
* @param string $type The content type of the file.
* @param string $charset The character set of the part, only relevant for text parts.
* @param string $name =null file name to use for the attachment
* @param string $type =null content type of the file, incl. parameters eg. "text/plain; charset=utf-8"
* @param string $old_type =null used to support phpMailer signature (deprecated)
* @return integer part-number
* @throws Exception\NotFound if $file could not be opened for reading
*/
public function addAttachment($data, $name = null, $type = null, $charset = 'us-ascii')
public function addAttachment($data, $name = null, $type = null, $old_type=null)
{
// deprecated PHPMailer::AddAttachment($path, $name = '', $encoding = 'base64', $type = 'application/octet-stream') call
if ($type === 'base64')
{
$type = $charset;
$charset = 'us-ascii';
$type = $old_type;
}
// pass file as resource to Horde_Mime_Part::setContent()
@ -358,6 +357,14 @@ class Mailer extends Horde_Mime_Mail
$part = new Horde_Mime_Part();
$part->setType($type);
// set content-type parameters, which get ignored by setType
if (preg_match_all('/;\s*([^=]+)=([^;]*)/', $type, $matches))
{
foreach($matches[1] as $n => $label)
{
$part->setContentTypeParameter($label, $matches[2][$n]);
}
}
$part->setContents($resource);
// setting name, also sets content-disposition attachment (!), therefore we have to do it after "text/calendar; method=" handling
@ -365,7 +372,7 @@ class Mailer extends Horde_Mime_Mail
// this should not be necessary, because binary data get detected by mime-type,
// but at least Cyrus complains about NUL characters
$part->setTransferEncoding('base64', array('send' => true));
if (substr($type, 0, 5) != 'text/') $part->setTransferEncoding('base64', array('send' => true));
$part->setDisposition('attachment');
return $this->addMimePart($part);

View File

@ -2264,7 +2264,11 @@ class calendar_ical extends calendar_boupdate
$events = array();
$vcal = new Horde_Icalendar;
if (!$vcal->parsevCalendar($_vcalData, 'VCALENDAR', $charset))
if ($charset && $charset != 'utf-8')
{
$_vcalData = Api\Translation::convert($_vcalData, $charset, 'utf-8');
}
if (!$vcal->parsevCalendar($_vcalData, 'VCALENDAR'))
{
if ($this->log)
{

View File

@ -405,7 +405,7 @@ class infolog_ical extends infolog_bo
foreach((array)$value as $compvData)
{
$comp = Horde_Icalendar::newComponent(substr($name,3), $vevent);
$comp->parsevCalendar($compvData,substr($name,3),'utf-8');
$comp->parsevCalendar($compvData,substr($name,3));
$vevent->addComponent($comp);
}
}
@ -654,7 +654,11 @@ class infolog_ical extends infolog_bo
}
$vcal = new Horde_Icalendar;
if (!($vcal->parsevCalendar($_vcalData, 'VCALENDAR', $charset)))
if ($charset && $charset != 'utf-8')
{
$_vcalData = Api\Translation::convert($_vcalData, $charset, 'utf-8');
}
if (!($vcal->parsevCalendar($_vcalData, 'VCALENDAR')))
{
if ($this->log)
{
@ -1096,7 +1100,11 @@ class infolog_ical extends infolog_bo
case 'text/x-vnote':
$vnote = new Horde_Icalendar;
if (!$vnote->parsevCalendar($_data, 'VCALENDAR', $charset)) return false;
if ($charset && $charset != 'utf-8')
{
$_data = Api\Translation::convert($_data, $charset, 'utf-8');
}
if (!$vnote->parsevCalendar($_data, 'VCALENDAR')) return false;
$components = $vnote->getComponent();
foreach ($components as $component)

View File

@ -913,6 +913,11 @@ class mail_compose
{
$name .= '.'.mime_magic::mime2ext($type);
}
// use type specified by caller, if Vfs reports only default, or contains specified type (eg. "text/vcard; charset=utf-8")
if (!empty($types[$k]) && ($type == 'application/octet-stream' || stripos($types[$k], $type) === 0))
{
$type = $types[$k];
}
$path = str_replace('+','%2B',$path);
$formData = array(
'name' => $name,

View File

@ -2383,7 +2383,7 @@ $filter['before']= date("d-M-Y", $cutoffdate2);
$eventid = $calendar_ical->search($attachment['attachment'],-1);
//error_log(__METHOD__.array2string($eventid));
if (!$eventid) $eventid = -1;
$event = $calendar_ical->importVCal($attachment['attachment'],(is_array($eventid)?$eventid[0]:$eventid),null,true);
$event = $calendar_ical->importVCal($attachment['attachment'],(is_array($eventid)?$eventid[0]:$eventid),null,true,0,'',null,$attachment['charset']);
//error_log(__METHOD__.$event);
if ((int)$event > 0)
{
@ -2401,7 +2401,7 @@ $filter['before']= date("d-M-Y", $cutoffdate2);
// double \r\r\n seems to end a vcard prematurely, so we set them to \r\n
//error_log(__METHOD__.__LINE__.$attachment['attachment']);
$attachment['attachment'] = str_replace("\r\r\n", "\r\n", $attachment['attachment']);
$vcard = $addressbook_vcal->vcardtoegw($attachment['attachment']);
$vcard = $addressbook_vcal->vcardtoegw($attachment['attachment'], $attachment['charset']);
if ($vcard['uid'])
{
$vcard['uid'] = trim($vcard['uid']);
@ -2412,7 +2412,7 @@ $filter['before']= date("d-M-Y", $cutoffdate2);
// if there are not enough fields in the vcard (or the parser was unable to correctly parse the vcard (as of VERSION:3.0 created by MSO))
if ($contact || count($vcard)>2)
{
$contact = $addressbook_vcal->addVCard($attachment['attachment'],(is_array($contact)?array_shift($contact):$contact),true);
$contact = $addressbook_vcal->addVCard($attachment['attachment'],(is_array($contact)?array_shift($contact):$contact),true,$attachment['charset']);
}
if ((int)$contact > 0)
{