Merge branch 'master' of ssh://git.kolabsys.com/git/roundcube

This commit is contained in:
Thomas Bruederli 2012-06-13 17:57:47 +02:00
commit c7c608a455
7 changed files with 74 additions and 33 deletions

View file

@ -220,7 +220,7 @@ function rcube_calendar_ui(settings)
// check if the event has 'real' attendees, excluding the current user // check if the event has 'real' attendees, excluding the current user
var has_attendees = function(event) var has_attendees = function(event)
{ {
return (event.attendees && (event.attendees.length > 1 || event.attendees[0].email != settings.identity.email)); return (event.attendees && event.attendees.length && (event.attendees.length > 1 || event.attendees[0].email != settings.identity.email));
}; };
// check if the current user is an attendee of this event // check if the current user is an attendee of this event
@ -1453,7 +1453,7 @@ function rcube_calendar_ui(settings)
// delete icon // delete icon
var icon = rcmail.env.deleteicon ? '<img src="' + rcmail.env.deleteicon + '" alt="" />' : rcmail.gettext('delete'); var icon = rcmail.env.deleteicon ? '<img src="' + rcmail.env.deleteicon + '" alt="" />' : rcmail.gettext('delete');
var dellink = '<a href="#delete" class="deletelink" title="' + Q(rcmail.gettext('delete')) + '">' + icon + '</a>'; var dellink = '<a href="#delete" class="iconlink delete deletelink" title="' + Q(rcmail.gettext('delete')) + '">' + icon + '</a>';
var html = '<td class="role">' + select + '</td>' + var html = '<td class="role">' + select + '</td>' +
'<td class="name">' + dispname + '</td>' + '<td class="name">' + dispname + '</td>' +

View file

@ -429,9 +429,10 @@ class kolab_calendar
$record['end'] = $record['start'] + 3600; $record['end'] = $record['start'] + 3600;
if (!empty($record['_attachments'])) { if (!empty($record['_attachments'])) {
foreach ($record['_attachments'] as $name => $attachment) { foreach ($record['_attachments'] as $key => $attachment) {
if ($attachment !== false) { if ($attachment !== false) {
$attachment['name'] = $name; if (!$attachment['name'])
$attachment['name'] = $key;
$attachments[] = $attachment; $attachments[] = $attachment;
} }
} }
@ -460,29 +461,34 @@ class kolab_calendar
{ {
$object = &$event; $object = &$event;
// in Horde attachments are indexed by name // in kolab_storage attachments are indexed by content-id
$object['_attachments'] = array(); $object['_attachments'] = array();
if (is_array($event['attachments'])) { if (is_array($event['attachments'])) {
$collisions = array(); $collisions = array();
foreach ($event['attachments'] as $idx => $attachment) { foreach ($event['attachments'] as $idx => $attachment) {
// Roundcube ID has nothing to do with Horde ID, remove it $key = null;
if ($attachment['content']) // Roundcube ID has nothing to do with the storage ID, remove it
if ($attachment['content']) {
unset($attachment['id']); unset($attachment['id']);
}
else {
foreach ((array)$old['_attachments'] as $cid => $oldatt) {
if ($attachment['id'] == $oldatt['id'])
$key = $cid;
}
}
// flagged for deletion => set to false // flagged for deletion => set to false
if ($attachment['_deleted']) { if ($attachment['_deleted']) {
$object['_attachments'][$attachment['name']] = false; $object['_attachments'][$key] = false;
} }
// replace existing entry
else if ($key) {
$object['_attachments'][$key] = $attachment;
}
// append as new attachment
else { else {
// Horde code assumes that there will be no more than $object['_attachments'][] = $attachment;
// one file with the same name: make filenames unique
$filename = $attachment['name'];
if ($collisions[$filename]++) {
$ext = preg_match('/(\.[a-z0-9]{1,6})$/i', $filename, $m) ? $m[1] : null;
$attachment['name'] = basename($filename, $ext) . '-' . $collisions[$filename] . $ext;
}
$object['_attachments'][$attachment['name']] = $attachment;
} }
} }

View file

@ -582,6 +582,7 @@ class kolab_driver extends calendar_driver
} }
} }
} }
unset($event['deleted_attachments']);
} }
// handle attachments to add // handle attachments to add

View file

@ -575,6 +575,15 @@ td.topalign {
text-overflow: ellipsis; text-overflow: ellipsis;
} }
#edit-attendees-table a.deletelink {
display: block;
width: 17px;
height: 17px;
padding: 0;
overflow: hidden;
text-indent: 1000px;
}
#edit-attendees-form { #edit-attendees-form {
position: relative; position: relative;
margin-top: 1em; margin-top: 1em;

View file

@ -77,12 +77,12 @@ class kolab_format_event extends kolab_format_xcal
// save attachments // save attachments
$vattach = new vectorattachment; $vattach = new vectorattachment;
foreach ((array)$object['_attachments'] as $name => $attr) { foreach ((array)$object['_attachments'] as $cid => $attr) {
if (empty($attr)) if (empty($attr))
continue; continue;
$attach = new Attachment; $attach = new Attachment;
$attach->setLabel($name); $attach->setLabel((string)$attr['name']);
$attach->setUri('cid:' . $name, $attr['mimetype']); $attach->setUri('cid:' . $cid, $attr['mimetype']);
$vattach->push($attach); $vattach->push($attach);
} }
$this->obj->setAttachments($vattach); $this->obj->setAttachments($vattach);
@ -148,6 +148,7 @@ class kolab_format_event extends kolab_format_xcal
$name = $attach->label(); $name = $attach->label();
$data = $attach->data(); $data = $attach->data();
$object['_attachments'][$name] = array( $object['_attachments'][$name] = array(
'name' => $name,
'mimetype' => $attach->mimetype(), 'mimetype' => $attach->mimetype(),
'size' => strlen($data), 'size' => strlen($data),
'content' => $data, 'content' => $data,

View file

@ -215,8 +215,8 @@ class kolab_storage_cache
$result = $this->db->query( $result = $this->db->query(
"INSERT INTO kolab_cache ". "INSERT INTO kolab_cache ".
" (resource, type, msguid, uid, data, xml, dtstart, dtend, tags, words)". " (resource, type, msguid, uid, created, data, xml, dtstart, dtend, tags, words)".
" VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?)", " VALUES (?, ?, ?, ?, " . $this->db->now() . ", ?, ?, ?, ?, ?, ?)",
$this->resource_uri, $this->resource_uri,
$objtype, $objtype,
$msguid, $msguid,
@ -542,6 +542,7 @@ class kolab_storage_cache
$this->db->quote($objtype), $this->db->quote($objtype),
$this->db->quote($msguid), $this->db->quote($msguid),
$this->db->quote($object['uid']), $this->db->quote($object['uid']),
$this->db->now(),
$this->db->quote($sql_data['data']), $this->db->quote($sql_data['data']),
$this->db->quote($sql_data['xml']), $this->db->quote($sql_data['xml']),
$this->db->quote($sql_data['dtstart']), $this->db->quote($sql_data['dtstart']),
@ -555,7 +556,7 @@ class kolab_storage_cache
if ($buffer && (!$msguid || (strlen($buffer) + strlen($line) > $this->max_sql_packet))) { if ($buffer && (!$msguid || (strlen($buffer) + strlen($line) > $this->max_sql_packet))) {
$result = $this->db->query( $result = $this->db->query(
"INSERT INTO kolab_cache ". "INSERT INTO kolab_cache ".
" (resource, type, msguid, uid, data, xml, dtstart, dtend, tags, words)". " (resource, type, msguid, uid, created, data, xml, dtstart, dtend, tags, words)".
" VALUES $buffer" " VALUES $buffer"
); );
if (!$this->db->affected_rows($result)) { if (!$this->db->affected_rows($result)) {

View file

@ -415,6 +415,7 @@ class kolab_storage_folder
$key = $part->content_id ? trim($part->content_id, '<>') : $part->filename; $key = $part->content_id ? trim($part->content_id, '<>') : $part->filename;
$attachments[$key] = array( $attachments[$key] = array(
'id' => $part->mime_id, 'id' => $part->mime_id,
'name' => $part->filename,
'mimetype' => $part->mimetype, 'mimetype' => $part->mimetype,
'size' => $part->size, 'size' => $part->size,
); );
@ -509,14 +510,35 @@ class kolab_storage_folder
// copy attachments from old message // copy attachments from old message
if (!empty($object['_msguid']) && ($old = $this->cache->get($object['_msguid'], $type, $object['_mailbox']))) { if (!empty($object['_msguid']) && ($old = $this->cache->get($object['_msguid'], $type, $object['_mailbox']))) {
foreach ((array)$old['_attachments'] as $name => $att) { foreach ((array)$old['_attachments'] as $key => $att) {
if (!isset($object['_attachments'][$name])) { if (!isset($object['_attachments'][$key])) {
$object['_attachments'][$name] = $old['_attachments'][$name]; $object['_attachments'][$key] = $old['_attachments'][$key];
}
// unset deleted attachment entries
if ($object['_attachments'][$key] == false) {
unset($object['_attachments'][$key]);
} }
// load photo.attachment from old Kolab2 format to be directly embedded in xcard block // load photo.attachment from old Kolab2 format to be directly embedded in xcard block
if ($name == 'photo.attachment' && !isset($object['photo']) && !$object['_attachments'][$name]['content'] && $att['id']) { else if ($key == 'photo.attachment' && !isset($object['photo']) && !$object['_attachments'][$key]['content'] && $att['id']) {
$object['photo'] = $this->get_attachment($object['_msguid'], $att['id'], $object['_mailbox']); $object['photo'] = $this->get_attachment($object['_msguid'], $att['id'], $object['_mailbox']);
unset($object['_attachments'][$name]); unset($object['_attachments'][$key]);
}
}
}
// generate unique keys (used as content-id) for attachments
if (is_array($object['_attachments'])) {
$numatt = count($object['_attachments']);
foreach ($object['_attachments'] as $key => $attachment) {
if (is_numeric($key) && $key < $numatt) {
// derrive content-id from attachment file name
$ext = preg_match('/(\.[a-z0-9]{1,6})$/i', $attachment['name'], $m) ? $m[1] : null;
$basename = preg_replace('/[^a-z0-9_.-]/i', '', basename($attachment['name'], $ext)); // to 7bit ascii
if (!$basename) $basename = 'noname';
$cid = $basename . '.' . microtime(true) . $ext;
$object['_attachments'][$cid] = $attachment;
unset($object['_attachments'][$key]);
} }
} }
} }
@ -685,24 +707,25 @@ class kolab_storage_folder
// save object attachments as separate parts // save object attachments as separate parts
// TODO: optimize memory consumption by using tempfiles for transfer // TODO: optimize memory consumption by using tempfiles for transfer
foreach ((array)$object['_attachments'] as $name => $att) { foreach ((array)$object['_attachments'] as $key => $att) {
if (empty($att['content']) && !empty($att['id'])) { if (empty($att['content']) && !empty($att['id'])) {
$msguid = !empty($object['_msguid']) ? $object['_msguid'] : $object['uid']; $msguid = !empty($object['_msguid']) ? $object['_msguid'] : $object['uid'];
$att['content'] = $this->get_attachment($msguid, $att['id'], $object['_mailbox']); $att['content'] = $this->get_attachment($msguid, $att['id'], $object['_mailbox']);
} }
$headers = array('Content-ID' => Mail_mimePart::encodeHeader('Content-ID', '<' . $name . '>', RCMAIL_CHARSET, 'quoted-printable')); $headers = array('Content-ID' => Mail_mimePart::encodeHeader('Content-ID', '<' . $key . '>', RCMAIL_CHARSET, 'quoted-printable'));
$name = !empty($att['name']) ? $att['name'] : $key;
if (!empty($att['content'])) { if (!empty($att['content'])) {
$mime->addAttachment($att['content'], $att['mimetype'], $name, false, 'base64', 'attachment', '', '', '', null, null, '', null, $headers); $mime->addAttachment($att['content'], $att['mimetype'], $name, false, 'base64', 'attachment', '', '', '', null, null, '', RCMAIL_CHARSET, $headers);
$part_id++; $part_id++;
} }
else if (!empty($att['path'])) { else if (!empty($att['path'])) {
$mime->addAttachment($att['path'], $att['mimetype'], $name, true, 'base64', 'attachment', '', '', '', null, null, '', null, $headers); $mime->addAttachment($att['path'], $att['mimetype'], $name, true, 'base64', 'attachment', '', '', '', null, null, '', RCMAIL_CHARSET, $headers);
$part_id++; $part_id++;
} }
$object['_attachments'][$name]['id'] = $part_id; $object['_attachments'][$key]['id'] = $part_id;
} }
return $mime->getMessage(); return $mime->getMessage();