Projects
Kolab:3.4
roundcubemail-plugins-kolab
Log In
Username
Password
We truncated the diff of some files because they were too big. If you want to see the full diff for every file,
click here
.
Overview
Repositories
Revisions
Requests
Users
Attributes
Meta
Expand all
Collapse all
Changes of Revision 101
View file
roundcubemail-plugins-kolab.spec
Changed
@@ -23,8 +23,8 @@ %global tmpdir %{_var}/lib/roundcubemail Name: roundcubemail-plugins-kolab -Version: 3.2.3 -Release: 5%{?dist} +Version: 3.2.4 +Release: 1%{?dist} Summary: Kolab Groupware plugins for Roundcube Webmail Group: Applications/Internet @@ -34,8 +34,6 @@ Source0: http://mirror.kolabsys.com/pub/releases/%{name}-%{version}.tar.gz Source1: comm.py -Patch0001: 0001-Fix-bug-where-relations-tags-members-changes-were-ig.patch - BuildRoot: %(mktemp -ud %{_tmppath}/%{name}-%{version}-%{release}-XXXXXX) BuildArch: noarch @@ -902,8 +900,6 @@ # Remove hidden files find . -type f -name ".*" -delete -%patch0001 -p1 - # Eliminate links for link in `find . -type l`; do source=$(readlink -f ${link}) @@ -1967,6 +1963,9 @@ %defattr(-,root,root,-) %changelog +* Wed Feb 4 2015 Jeroen van Meeuwen <vanmeeuwen@kolabsys.com> - 3.2.4-1 +- Release of version 3.2.4 + * Sat Jan 24 2015 Jeroen van Meeuwen <vanmeeuwen@kolabsys.com> - 3.2.3-5 - Fix symbolic link to go up far enough (#4307, comment #4).
View file
0001-Fix-bug-where-relations-tags-members-changes-were-ig.patch
Deleted
@@ -1,26 +0,0 @@ -From 23e4d1b25aa0cbcf72bde36eda4340e0623fab85 Mon Sep 17 00:00:00 2001 -From: Aleksander Machniak <machniak@kolabsys.com> -Date: Thu, 22 Jan 2015 06:18:27 -0500 -Subject: [PATCH] Fix bug where relations/tags members changes were ignored on - relation update (#4095) - ---- - plugins/libkolab/lib/kolab_format_configuration.php | 2 ++ - 1 file changed, 2 insertions(+) - -diff --git a/plugins/libkolab/lib/kolab_format_configuration.php b/plugins/libkolab/lib/kolab_format_configuration.php -index 30ddaf3..ceb7ebb 100644 ---- a/plugins/libkolab/lib/kolab_format_configuration.php -+++ b/plugins/libkolab/lib/kolab_format_configuration.php -@@ -125,6 +125,8 @@ class kolab_format_configuration extends kolab_format - // adjust content-type string - $this->CTYPEv2 = 'application/x-vnd.kolab.configuration.' . $object['type']; - -+ // reset old object data, otherwise set() will overwrite current data (#4095) -+ $this->xmldata = null; - // set common object properties - parent::set($object); - --- -2.1.0 -
View file
debian.changelog
Changed
@@ -1,3 +1,9 @@ +roundcubemail-plugins-kolab (1:3.2.4-0~kolab1) unstable; urgency=low + + * Release of version 3.2.4 + + -- Jeroen van Meeuwen (Kolab Systems) <vanmeeuwen@kolabsys.com> Wed, 4 Feb 2015 18:41:13 +0200 + roundcubemail-plugins-kolab (1:3.2.3-0~kolab3) unstable; urgency=low * Removed empty kolab/skins/images folder
View file
debian.series
Changed
@@ -1,1 +0,0 @@ -0001-Fix-bug-where-relations-tags-members-changes-were-ig.patch -p1
View file
roundcubemail-plugins-kolab-3.2.3.tar.gz/plugins/odfviewer/files
Deleted
-(directory)
View file
roundcubemail-plugins-kolab-3.2.3.tar.gz/plugins/odfviewer/files/.htaccess
Deleted
@@ -1,5 +0,0 @@ -<IfModule mod_deflate.c> -SetOutputFilter NONE -</IfModule> - -Options -Indexes
View file
roundcubemail-plugins-kolab-3.2.3.tar.gz/plugins/calendar/calendar.php -> roundcubemail-plugins-kolab-3.2.4.tar.gz/plugins/calendar/calendar.php
Changed
@@ -497,7 +497,7 @@ foreach (array('-M','-H','-D','+M','+H','+D') as $trigger) $select_offset->add(rcube_label('trigger' . $trigger, 'libcalendaring'), $trigger); - $preset = libcalendaring::parse_alaram_value($this->rc->config->get('calendar_default_alarm_offset', '-15M')); + $preset = libcalendaring::parse_alarm_value($this->rc->config->get('calendar_default_alarm_offset', '-15M')); $p['blocks']['view']['options']['alarmoffset'] = array( 'title' => html::label($field_id . 'value', Q($this->gettext('defaultalarmoffset'))), 'content' => $input_value->show($preset[0]) . ' ' . $select_offset->show($preset[1]), @@ -665,7 +665,7 @@ foreach (array('-M','-H','-D') as $trigger) $select_offset->add(rcube_label('trigger' . $trigger, 'libcalendaring'), $trigger); - $preset = libcalendaring::parse_alaram_value($this->rc->config->get('calendar_birthdays_alarm_offset', '-1D')); + $preset = libcalendaring::parse_alarm_value($this->rc->config->get('calendar_birthdays_alarm_offset', '-1D')); $p['blocks']['birthdays']['options']['birthdays_alarmoffset'] = array( 'title' => html::label($field_id . 'value', rcube::Q($this->gettext('showalarms'))), 'content' => $select_type->show($this->rc->config->get('calendar_birthdays_alarm_type', '')) . ' ' . $input_value->show($preset[0]) . ' ' . $select_offset->show($preset[1]), @@ -842,7 +842,7 @@ $success = $reload = $got_msg = false; // don't notify if modifying a recurring instance (really?) - if ($event['_savemode'] && $event['_savemode'] != 'all' && $event['_notify']) + if ($event['_savemode'] && in_array($event['_savemode'], array('current','future')) && $event['_notify'] && $action != 'remove') unset($event['_notify']); // force notify if hidden + active else if ((int)$this->rc->config->get('calendar_itip_send_option', $this->defaults['calendar_itip_send_option']) === 1) @@ -866,20 +866,35 @@ case "edit": $this->write_preprocess($event, $action); - if ($success = $this->driver->edit_event($event)) - $this->cleanup_event($event); + if ($success = $this->driver->edit_event($event)) { + $this->cleanup_event($event); + if ($success !== true) { + $event['id'] = $success; + $old = null; + } + } $reload = $success && ($event['recurrence'] || $event['_savemode'] || $event['_fromcalendar']) ? 2 : 1; break; case "resize": $this->write_preprocess($event, $action); - $success = $this->driver->resize_event($event); + if ($success = $this->driver->resize_event($event)) { + if ($success !== true) { + $event['id'] = $success; + $old = null; + } + } $reload = $event['_savemode'] ? 2 : 1; break; case "move": $this->write_preprocess($event, $action); - $success = $this->driver->move_event($event); + if ($success = $this->driver->move_event($event)) { + if ($success !== true) { + $event['id'] = $success; + $old = null; + } + } $reload = $success && $event['_savemode'] ? 2 : 1; break; @@ -957,6 +972,7 @@ $ev = $this->driver->get_event($event); $ev['attendees'] = $event['attendees']; + $ev['free_busy'] = $event['free_busy']; // send invitation to delegatee + add it as attendee if ($status == 'delegated' && $event['to']) { @@ -1110,6 +1126,12 @@ // make sure we have the complete record $event = $action == 'remove' ? $old : $this->driver->get_event($event); + // sending notification on a recurrence instance -> re-send the main event + if ($event['recurrence_id']) { + $event = $this->driver->get_event(array('id' => $event['recurrence_id'], 'cal' => $event['calendar'])); + $action = 'edit'; + } + // only notify if data really changed (TODO: do diff check on client already) if (!$old || $action == 'remove' || self::event_diff($event, $old)) { $sent = $this->notify_attendees($event, $old, $action, $event['_comment']); @@ -1205,6 +1227,16 @@ $event['_part'] = $mime_id; $events[] = $this->_client_event($event, true); + + // add recurring instances + if (!empty($event['recurrence'])) { + foreach ($this->driver->get_recurring_events($event, $event['start']) as $recurring) { + $recurring['temporary'] = true; + $recurring['readonly'] = true; + $recurring['calendar'] = '--invitation--itip'; + $events[] = $this->_client_event($recurring, true); + } + } } return $events; @@ -1756,7 +1788,7 @@ */ public function attachment_upload() { - $this->lib->attachment_upload(self::SESSION_KEY, 'cal:'); + $this->lib->attachment_upload(self::SESSION_KEY, 'cal-'); } /** @@ -1820,7 +1852,8 @@ } $attachments = array(); - $eventid = 'cal:'.$event['id']; + $eventid = 'cal-'.$event['id']; + if (is_array($_SESSION[self::SESSION_KEY]) && $_SESSION[self::SESSION_KEY]['id'] == $eventid) { if (!empty($_SESSION[self::SESSION_KEY]['attachments'])) { foreach ($_SESSION[self::SESSION_KEY]['attachments'] as $id => $attachment) { @@ -2419,6 +2452,7 @@ } // send itip reply to organizer + $invitation['event']['comment'] = rcube_utils::get_input_value('_comment', rcube_utils::INPUT_POST); if ($status && $itip->update_invitation($invitation, $invitation['attendee'], strtoupper($status))) { $this->invitestatus = html::div('rsvp-status ' . strtolower($status), $itip->gettext('youhave'.strtolower($status))); } @@ -2442,8 +2476,10 @@ $this->register_handler('plugin.event_inviteform', array($this, 'itip_event_inviteform')); $this->register_handler('plugin.event_invitebox', array($this->ui, 'event_invitebox')); - if (!$this->invitestatus) + if (!$this->invitestatus) { + $this->itip->set_rsvp_actions(array('accepted','tentative','declined')); $this->register_handler('plugin.event_rsvp_buttons', array($this->ui, 'event_rsvp_buttons')); + } $this->rc->output->set_pagetitle($itip->gettext('itipinvitation') . ' ' . $this->event['title']); } @@ -2665,6 +2701,7 @@ $metadata['attendee'] = $attendee['email']; $metadata['rsvp'] = $attendee['role'] != 'NON-PARTICIPANT'; $reply_sender = $attendee['email']; + $event_attendee = $attendee; } } @@ -2787,6 +2824,9 @@ $error_msg = $this->gettext('newerversionexists'); } else if (!$existing && ($status != 'declined' || $this->rc->config->get('kolab_invitation_calendars'))) { + if ($status == 'declined' || $event['status'] == 'CANCELLED' || $event_attendee['role'] == 'NON-PARTICIPANT') { + $event['free_busy'] = 'free'; + } $success = $this->driver->new_event($event); } else if ($status == 'declined') @@ -2957,7 +2997,7 @@ } // copy mail attachments to event else if ($message->attachments) { - $eventid = 'cal:'; + $eventid = 'cal-'; if (!is_array($_SESSION[self::SESSION_KEY]) || $_SESSION[self::SESSION_KEY]['id'] != $eventid) { $_SESSION[self::SESSION_KEY] = array(); $_SESSION[self::SESSION_KEY]['id'] = $eventid;
View file
roundcubemail-plugins-kolab-3.2.3.tar.gz/plugins/calendar/calendar_ui.js -> roundcubemail-plugins-kolab-3.2.4.tar.gz/plugins/calendar/calendar_ui.js
Changed
@@ -742,9 +742,11 @@ // show warning if editing a recurring event if (event.id && event.recurrence) { - var sel = event.thisandfuture ? 'future' : (event.isexception ? 'current' : 'all'); + var allow_exceptions = !has_attendees(event) || !is_organizer(event), + sel = event._savemode || (allow_exceptions && event.thisandfuture ? 'future' : (allow_exceptions && event.isexception ? 'current' : 'all')); $('#edit-recurring-warning').show(); $('input.edit-recurring-savemode[value="'+sel+'"]').prop('checked', true); + $('input.edit-recurring-savemode[value="current"], input.edit-recurring-savemode[value="future"]').prop('disabled', !allow_exceptions); } else $('#edit-recurring-warning').hide(); @@ -764,6 +766,11 @@ if (event.attendees) { for (j=0; j < event.attendees.length; j++) { data = event.attendees[j]; + // reset attendee status + if (event._savemode == 'new' && data.role != 'ORGANIZER') { + data.status = 'NEEDS-ACTION'; + delete data.noreply; + } add_attendee(data, !allow_invitations); if (allow_invitations && data.role != 'ORGANIZER' && !data.noreply) reply_selected++; @@ -1977,7 +1984,7 @@ var img_src = rcmail.assets_path('program/resources/blank.gif'); var html = '<td class="role">' + select + '</td>' + - '<td class="name">' + dispname + '</td>' + + '<td class="name"><span class="attendee-name">' + dispname + '</span></td>' + '<td class="availability"><img src="' + img_src + '" class="availabilityicon ' + avail + '" data-email="' + data.email + '" alt="" /></td>' + '<td class="confirmstate"><span class="' + String(data.status).toLowerCase() + '" title="' + Q(tooltip) + '">' + Q(data.status || '') + '</span></td>' + (data.cutype != 'RESOURCE' ? '<td class="invite">' + (organizer || readonly || !invbox ? '' : invbox) + '</td>' : '') + @@ -1995,7 +2002,7 @@ tr.find('a.deletelink').click({ id:(data.email || data.name) }, function(e) { remove_attendee(this, e.data.id); return false; }); tr.find('a.mailtolink').click(event_attendee_click); - tr.find('a.expandlink').click(data, function(e) { me.expand_attendee_group(e, add_attendee, remove_attendee); }); + tr.find('a.expandlink').click(data, function(e) { me.expand_attendee_group(e, add_attendee, remove_attendee); return false; }); tr.find('input.edit-attendee-reply').click(function() { var enabled = $('#edit-attendees-invite:checked').length || $('input.edit-attendee-reply:checked').length; $('#eventedit .attendees-commentbox')[enabled ? 'show' : 'hide'](); @@ -2217,7 +2224,7 @@ } // load resource calendar - resources_events_source.url = "./?_task=calendar&_action=resources-calendar&_id="+escape(resource.ID); + resources_events_source.url = "./?_task=calendar&_action=resources-calendar&_id="+urlencode(resource.ID); $(rcmail.gui_objects.resourceinfocalendar).fullCalendar('addEventSource', resources_events_source); } }; @@ -2394,6 +2401,14 @@ } } } + + // set free_busy status to transparent if declined (#4425) + if (data.status == 'DECLINED' || data.role == 'NON-PARTICIPANT') { + me.selected_event.free_busy = 'free'; + } + else { + me.selected_event.free_busy = 'busy'; + } } // submit status change to server @@ -2519,12 +2534,13 @@ var update_event_confirm = function(action, event, data) { if (!data) data = event; - var decline = false, notify = false, html = '', cal = me.calendars[event.calendar]; + var decline = false, notify = false, html = '', cal = me.calendars[event.calendar], + _has_attendees = has_attendees(event), _is_organizer = is_organizer(event); // event has attendees, ask whether to notify them - if (has_attendees(event)) { + if (_has_attendees) { var checked = (settings.itip_notify & 1 ? ' checked="checked"' : ''); - if (is_organizer(event)) { + if (_is_organizer) { notify = true; if (settings.itip_notify & 2) { html += '<div class="message">' + @@ -2550,11 +2566,25 @@ // recurring event: user needs to select the savemode if (event.recurrence) { + var disabled_state = '', message_label = (action == 'remove' ? 'removerecurringeventwarning' : 'changerecurringeventwarning'); + + if (_has_attendees) { + if (action == 'remove') { + if (!_is_organizer) { + message_label = 'removerecurringallonly'; + disabled_state = ' disabled'; + } + } + else if (is_organizer(event)) { + disabled_state = ' disabled'; + } + } + html += '<div class="message"><span class="ui-icon ui-icon-alert"></span>' + - rcmail.gettext((action == 'remove' ? 'removerecurringeventwarning' : 'changerecurringeventwarning'), 'calendar') + '</div>' + + rcmail.gettext(message_label, 'calendar') + '</div>' + '<div class="savemode">' + - '<a href="#current" class="button">' + rcmail.gettext('currentevent', 'calendar') + '</a>' + - '<a href="#future" class="button">' + rcmail.gettext('futurevents', 'calendar') + '</a>' + + '<a href="#current" class="button' + disabled_state + '">' + rcmail.gettext('currentevent', 'calendar') + '</a>' + + '<a href="#future" class="button' + disabled_state + '">' + rcmail.gettext('futurevents', 'calendar') + '</a>' + '<a href="#all" class="button">' + rcmail.gettext('allevents', 'calendar') + '</a>' + (action != 'remove' ? '<a href="#new" class="button">' + rcmail.gettext('saveasnew', 'calendar') + '</a>' : '') + '</div>'; @@ -2564,14 +2594,24 @@ if (html) { var $dialog = $('<div>').html(html); - $dialog.find('a.button').button().click(function(e) { + $dialog.find('a.button').button().filter(':not(.disabled)').click(function(e) { data._savemode = String(this.href).replace(/.+#/, ''); data._notify = settings.itip_notify; - if ($dialog.find('input.confirm-attendees-donotify').length) - data._notify = $dialog.find('input.confirm-attendees-donotify').get(0).checked ? 1 : 0; - if (decline && $dialog.find('input.confirm-attendees-decline:checked').length) - data.decline = 1; - update_event(action, data); + + // open event edit dialog when saving as new + if (data._savemode == 'new') { + event._savemode = 'new'; + event_edit_dialog('edit', event); + fc.fullCalendar('refetchEvents'); + } + else { + if ($dialog.find('input.confirm-attendees-donotify').length) + data._notify = $dialog.find('input.confirm-attendees-donotify').get(0).checked ? 1 : 0; + if (decline && $dialog.find('input.confirm-attendees-decline:checked').length) + data.decline = 1; + update_event(action, data); + } + $dialog.dialog("close"); return false; });
View file
roundcubemail-plugins-kolab-3.2.3.tar.gz/plugins/calendar/composer.json -> roundcubemail-plugins-kolab-3.2.4.tar.gz/plugins/calendar/composer.json
Changed
@@ -4,7 +4,7 @@ "description": "Calendar plugin", "homepage": "http://git.kolab.org/roundcubemail-plugins-kolab/", "license": "AGPLv3", - "version": "3.2.3", + "version": "3.2.4", "authors": [ { "name": "Thomas Bruederli", @@ -26,6 +26,6 @@ "require": { "php": ">=5.3.0", "roundcube/plugin-installer": ">=0.1.3", - "kolab/libcalendaring": ">=3.2.3" + "kolab/libcalendaring": ">=3.2.4" } }
View file
roundcubemail-plugins-kolab-3.2.3.tar.gz/plugins/calendar/drivers/calendar_driver.php -> roundcubemail-plugins-kolab-3.2.4.tar.gz/plugins/calendar/drivers/calendar_driver.php
Changed
@@ -432,6 +432,61 @@ } /** + * Create instances of a recurring event + * + * @param array Hash array with event properties + * @param object DateTime Start date of the recurrence window + * @param object DateTime End date of the recurrence window + * @return array List of recurring event instances + */ + public function get_recurring_events($event, $start, $end = null) + { + $events = array(); + + if ($event['recurrence']) { + // include library class + require_once(dirname(__FILE__) . '/../lib/calendar_recurrence.php'); + + $rcmail = rcmail::get_instance(); + $recurrence = new calendar_recurrence($rcmail->plugins->get_plugin('calendar'), $event); + + // determine a reasonable end date if none given + if (!$end) { + switch ($event['recurrence']['FREQ']) { + case 'YEARLY': $intvl = 'P100Y'; break; + case 'MONTHLY': $intvl = 'P20Y'; break; + default: $intvl = 'P10Y'; break; + } + + $end = clone $event['start']; + $end->add(new DateInterval($intvl)); + } + + $i = 0; + while ($next_event = $recurrence->next_instance()) { + $next_event['uid'] = $event['uid'] . '-' . ++$i; + // add to output if in range + if (($next_event['start'] <= $end && $next_event['end'] >= $start)) { + $next_event['id'] = $next_event['uid']; + $next_event['recurrence_id'] = $event['uid']; + $next_event['_instance'] = $i; + $events[] = $next_event; + } + else if ($next_event['start'] > $end) { // stop loop if out of range + break; + } + + // avoid endless recursion loops + if ($i > 1000) { + break; + } + } + } + + return $events; + } + + /** * Provide a list of revisions for the given event * * @param array $event Hash array with event properties:
View file
roundcubemail-plugins-kolab-3.2.3.tar.gz/plugins/calendar/drivers/database/database_driver.php -> roundcubemail-plugins-kolab-3.2.4.tar.gz/plugins/calendar/drivers/database/database_driver.php
Changed
@@ -1163,7 +1163,7 @@ // convert legacy alarms data else if (strlen($alarms)) { list($trigger, $action) = explode(':', $alarms, 2); - if ($trigger = libcalendaring::parse_alaram_value($trigger)) { + if ($trigger = libcalendaring::parse_alarm_value($trigger)) { $valarms = array(array('action' => $action, 'trigger' => $trigger[3] ?: $trigger[0])); } }
View file
roundcubemail-plugins-kolab-3.2.3.tar.gz/plugins/calendar/drivers/kolab/kolab_calendar.php -> roundcubemail-plugins-kolab-3.2.4.tar.gz/plugins/calendar/drivers/kolab/kolab_calendar.php
Changed
@@ -76,7 +76,7 @@ // fetch objects from the given IMAP folder $this->storage = kolab_storage::get_folder($this->name); - $this->ready = $this->storage && !PEAR::isError($this->storage) && $this->storage->type !== null; + $this->ready = $this->storage && $this->storage->valid; // Set readonly and alarms flags according to folder permissions if ($this->ready) { @@ -196,7 +196,7 @@ $this->events[$master_id] = $this->_to_rcube_event($record); if (($master = $this->events[$master_id]) && $master['recurrence']) { - $this->_get_recurring_events($record, $master['start'], null, $id); + $this->get_recurring_events($record, $master['start'], null, $id); } } @@ -323,7 +323,7 @@ // resolve recurring events if ($record['recurrence'] && $virtual == 1) { - $events = array_merge($events, $this->_get_recurring_events($record, $start, $end)); + $events = array_merge($events, $this->get_recurring_events($record, $start, $end)); } } @@ -455,7 +455,7 @@ // refresh local cache with recurring instances if ($exception_id) { - $this->_get_recurring_events($object, $event['start'], $event['end'], $exception_id); + $this->get_recurring_events($object, $event['start'], $event['end'], $exception_id); } } @@ -538,7 +538,7 @@ * @param string ID of a specific recurring event instance * @return array List of recurring event instances */ - public function _get_recurring_events($event, $start, $end = null, $event_id = null) + public function get_recurring_events($event, $start, $end = null, $event_id = null) { $object = $event['_formatobj']; if (!$object) {
View file
roundcubemail-plugins-kolab-3.2.3.tar.gz/plugins/calendar/drivers/kolab/kolab_driver.php -> roundcubemail-plugins-kolab-3.2.4.tar.gz/plugins/calendar/drivers/kolab/kolab_driver.php
Changed
@@ -704,7 +704,7 @@ // removing the first instance => just move to next occurence if ($master['id'] == $event['id']) { - $recurring = reset($storage->_get_recurring_events($event, $event['start'], null, $event['id'].'-1')); + $recurring = reset($storage->get_recurring_events($event, $event['start'], null, $event['id'].'-1')); // no future instances found: delete the master event (bug #1677) if (!$recurring['start']) { @@ -889,14 +889,16 @@ // save submitted data as new (non-recurring) event $event['recurrence'] = array(); $event['uid'] = $this->cal->generate_uid(); - + unset($event['recurrence_id'], $event['id'], $event['_savemode'], $event['_fromcalendar'], $event['_identity'], $event['_notify']); + // copy attachment data to new event foreach ((array)$event['attachments'] as $idx => $attachment) { - if (!$attachment['data']) - $attachment['data'] = $fromcalendar->get_attachment_body($attachment['id'], $event); + if (!$attachment['content']) + $event['attachments'][$idx]['content'] = $this->get_attachment_body($attachment['id'], $master); } - - $success = $storage->insert_event($event); + + if ($success = $storage->insert_event($event)) + $success = $event['uid']; break; case 'future': @@ -906,7 +908,7 @@ $event['thisandfuture'] = $savemode == 'future'; // remove some internal properties which should not be saved - unset($event['_savemode'], $event['_fromcalendar'], $event['_identity']); + unset($event['_savemode'], $event['_fromcalendar'], $event['_identity'], $event['_notify']); // save properties to a recurrence exception instance if ($old['recurrence_id']) { @@ -1244,6 +1246,28 @@ } /** + * Create instances of a recurring event + * + * @param array Hash array with event properties + * @param object DateTime Start date of the recurrence window + * @param object DateTime End date of the recurrence window + * @return array List of recurring event instances + */ + public function get_recurring_events($event, $start, $end = null) + { + // load the given event data into a libkolabxml container + if (!$event['_formatobj']) { + $event_xml = new kolab_format_event(); + $event_xml->set($event); + $event['_formatobj'] = $event_xml; + } + + $this->_read_calendars(); + $storage = reset($this->calendars); + return $storage->get_recurring_events($event, $start, $end); + } + + /** * Fetch free/busy information from a person within the given range */ public function get_freebusy_list($email, $start, $end)
View file
roundcubemail-plugins-kolab-3.2.3.tar.gz/plugins/calendar/lib/calendar_ui.php -> roundcubemail-plugins-kolab-3.2.4.tar.gz/plugins/calendar/lib/calendar_ui.php
Changed
@@ -886,7 +886,7 @@ function event_rsvp_buttons($attrib = array()) { - return $this->cal->itip->itip_rsvp_buttons($attrib, array('accepted','tentative','declined','delegated')); + return $this->cal->itip->itip_rsvp_buttons($attrib); } }
View file
roundcubemail-plugins-kolab-3.2.3.tar.gz/plugins/calendar/localization/en_US.inc -> roundcubemail-plugins-kolab-3.2.4.tar.gz/plugins/calendar/localization/en_US.inc
Changed
@@ -261,6 +261,7 @@ $labels['removeeventconfirm'] = 'Delete event'; $labels['changerecurringeventwarning'] = 'This is a recurring event. Would you like to edit the current event only, this and all future occurences, all occurences or save it as a new event?'; $labels['removerecurringeventwarning'] = 'This is a recurring event. Would you like to delete the current event only, this and all future occurences or all occurences of this event?'; +$labels['removerecurringallonly'] = 'This is a recurring event. As a participant, you can only delete the entire event with all occurences.'; $labels['currentevent'] = 'Current'; $labels['futurevents'] = 'Future'; $labels['allevents'] = 'All';
View file
roundcubemail-plugins-kolab-3.2.3.tar.gz/plugins/calendar/skins/larry/calendar.css -> roundcubemail-plugins-kolab-3.2.4.tar.gz/plugins/calendar/skins/larry/calendar.css
Changed
@@ -1056,6 +1056,7 @@ .event-update-confirm a.button { margin: 0 0.5em 0 0.2em; min-width: 5em; + text-align: center; } #event-rsvp, @@ -1129,13 +1130,21 @@ white-space: nowrap; overflow: hidden; text-overflow: ellipsis; - position: relative; } #eventedit .edit-attendees-table td.name select { width: 100%; } +#eventedit .edit-attendees-table td.name .attendee-name { + display: block; + position: relative; + overflow: hidden; + text-overflow: ellipsis; + padding: 5px 7px 6px; + margin: -5px -7px -6px; +} + #eventedit .edit-attendees-table a.deletelink { display: inline-block; width: 17px; @@ -1177,6 +1186,7 @@ #edit-attendees-form #edit-attendee-schedule { position: absolute; right: 0; + top: 0; } .edit-attendees-table select.edit-attendee-role {
View file
roundcubemail-plugins-kolab-3.2.3.tar.gz/plugins/kolab_activesync/composer.json -> roundcubemail-plugins-kolab-3.2.4.tar.gz/plugins/kolab_activesync/composer.json
Changed
@@ -26,6 +26,6 @@ "require": { "php": ">=5.3.0", "roundcube/plugin-installer": ">=0.1.3", - "kolab/libkolab": ">=3.2.3" + "kolab/libkolab": ">=3.2.4" } }
View file
roundcubemail-plugins-kolab-3.2.3.tar.gz/plugins/kolab_addressbook/composer.json -> roundcubemail-plugins-kolab-3.2.4.tar.gz/plugins/kolab_addressbook/composer.json
Changed
@@ -26,6 +26,6 @@ "require": { "php": ">=5.3.0", "roundcube/plugin-installer": ">=0.1.3", - "kolab/libkolab": ">=3.2.3" + "kolab/libkolab": ">=3.2.4" } }
View file
roundcubemail-plugins-kolab-3.2.3.tar.gz/plugins/kolab_config/composer.json -> roundcubemail-plugins-kolab-3.2.4.tar.gz/plugins/kolab_config/composer.json
Changed
@@ -21,6 +21,6 @@ "require": { "php": ">=5.3.0", "roundcube/plugin-installer": ">=0.1.3", - "kolab/libkolab": ">=3.2.3" + "kolab/libkolab": ">=3.2.4" } }
View file
roundcubemail-plugins-kolab-3.2.3.tar.gz/plugins/kolab_delegation/composer.json -> roundcubemail-plugins-kolab-3.2.4.tar.gz/plugins/kolab_delegation/composer.json
Changed
@@ -21,7 +21,7 @@ "require": { "php": ">=5.3.0", "roundcube/plugin-installer": ">=0.1.3", - "kolab/libkolab": ">=3.2.3", + "kolab/libkolab": ">=3.2.4", "kolab/kolab_auth": ">=3.2.2" } }
View file
roundcubemail-plugins-kolab-3.2.3.tar.gz/plugins/kolab_files/composer.json -> roundcubemail-plugins-kolab-3.2.4.tar.gz/plugins/kolab_files/composer.json
Changed
@@ -21,6 +21,6 @@ "require": { "php": ">=5.3.0", "roundcube/plugin-installer": ">=0.1.3", - "kolab/libkolab": ">=3.2.3" + "kolab/libkolab": ">=3.2.4" } }
View file
roundcubemail-plugins-kolab-3.2.3.tar.gz/plugins/kolab_folders/composer.json -> roundcubemail-plugins-kolab-3.2.4.tar.gz/plugins/kolab_folders/composer.json
Changed
@@ -21,6 +21,6 @@ "require": { "php": ">=5.3.0", "roundcube/plugin-installer": ">=0.1.3", - "kolab/libkolab": ">=3.2.3" + "kolab/libkolab": ">=3.2.4" } }
View file
roundcubemail-plugins-kolab-3.2.3.tar.gz/plugins/kolab_notes/composer.json -> roundcubemail-plugins-kolab-3.2.4.tar.gz/plugins/kolab_notes/composer.json
Changed
@@ -21,7 +21,7 @@ "require": { "php": ">=5.3.0", "roundcube/plugin-installer": ">=0.1.3", - "kolab/libkolab": ">=3.2.3", + "kolab/libkolab": ">=3.2.4", "roundcube/jqueryui": ">=1.10.4" } }
View file
roundcubemail-plugins-kolab-3.2.3.tar.gz/plugins/kolab_notes/kolab_notes.php -> roundcubemail-plugins-kolab-3.2.4.tar.gz/plugins/kolab_notes/kolab_notes.php
Changed
@@ -60,7 +60,7 @@ public function startup($args) { // the notes module can be enabled/disabled by the kolab_auth plugin - if ($this->rc->config->get('notes_disabled', false) || !$this->rc->config->get('notes_enabled', true)) { + if ($this->rc->config->get('kolab_notes_disabled', false) || !$this->rc->config->get('kolab_notes_enabled', true)) { return; }
View file
roundcubemail-plugins-kolab-3.2.3.tar.gz/plugins/kolab_notes/skins/larry/notes.css -> roundcubemail-plugins-kolab-3.2.4.tar.gz/plugins/kolab_notes/skins/larry/notes.css
Changed
@@ -281,6 +281,11 @@ box-sizing: border-box; } +/* Firefox 3.6 */ +_:not(), _:-moz-handler-blocked, .notesview #notedetailstitle .tagedit-list { + min-height: 26px; +} + .notesview #notedetailstitle .disabled .tagedit-list { min-height: 26px; }
View file
roundcubemail-plugins-kolab-3.2.3.tar.gz/plugins/kolab_tags/composer.json -> roundcubemail-plugins-kolab-3.2.4.tar.gz/plugins/kolab_tags/composer.json
Changed
@@ -21,6 +21,6 @@ "require": { "php": ">=5.3.0", "roundcube/plugin-installer": ">=0.1.3", - "kolab/libkolab": ">=3.2.3" + "kolab/libkolab": ">=3.2.4" } }
View file
roundcubemail-plugins-kolab-3.2.3.tar.gz/plugins/libcalendaring/composer.json -> roundcubemail-plugins-kolab-3.2.4.tar.gz/plugins/libcalendaring/composer.json
Changed
@@ -4,7 +4,7 @@ "description": "Library providing common functions for calendaring plugins", "homepage": "http://git.kolab.org/roundcubemail-plugins-kolab/", "license": "AGPLv3", - "version": "3.2.3", + "version": "3.2.4", "authors": [ { "name": "Thomas Bruederli",
View file
roundcubemail-plugins-kolab-3.2.3.tar.gz/plugins/libcalendaring/lib/libcalendaring_itip.php -> roundcubemail-plugins-kolab-3.2.4.tar.gz/plugins/libcalendaring/lib/libcalendaring_itip.php
Changed
@@ -125,7 +125,8 @@ 'name' => $bodytext, 'vars' => array( 'title' => $event['title'], - 'date' => $this->lib->event_date_text($event, true), + 'date' => $this->lib->event_date_text($event, true) . + (empty($event['recurrence']) ? '' : sprintf("\n%s: %s", $this->gettext('recurring'), $this->lib->recurrence_text($event['recurrence']))), 'attendees' => join(",\n ", $attendees_list), 'sender' => $this->sender['name'], 'organizer' => $this->sender['name'], @@ -682,7 +683,7 @@ // add input field for reply comment $rsvp_additions .= html::a(array('href' => '#toggle', 'class' => 'reply-comment-toggle'), $this->gettext('itipeditresponse')); $rsvp_additions .= html::div('itip-reply-comment', - html::tag('textarea', array('id' => 'reply-comment-'.$dom_id, 'cols' => 40, 'rows' => 6, 'style' => 'display:none', 'placeholder' => $this->gettext('itipcomment')), '') + html::tag('textarea', array('id' => 'reply-comment-'.$dom_id, 'name' => '_comment', 'cols' => 40, 'rows' => 6, 'style' => 'display:none', 'placeholder' => $this->gettext('itipcomment')), '') ); return $rsvp_additions; @@ -697,27 +698,31 @@ $table->add('ititle', $title); $table->add('title', Q($event['title'])); if ($event['start'] && $event['end']) { - $table->add('label', $this->plugin->gettext('date'), $this->domain); + $table->add('label', $this->gettext('date')); $table->add('date', Q($this->lib->event_date_text($event))); } else if ($event['due'] && $event['_type'] == 'task') { - $table->add('label', $this->plugin->gettext('date'), $this->domain); + $table->add('label', $this->gettext('date')); $table->add('date', Q($this->lib->event_date_text($event))); } + if (!empty($event['recurrence'])) { + $table->add('label', $this->gettext('recurring')); + $table->add('recurrence', $this->lib->recurrence_text($event['recurrence'])); + } if ($event['location']) { - $table->add('label', $this->plugin->gettext('location'), $this->domain); + $table->add('label', $this->gettext('location')); $table->add('location', Q($event['location'])); } if ($event['sensitivity'] && $event['sensitivity'] != 'public') { - $table->add('label', $this->plugin->gettext('sensitivity'), $this->domain); - $table->add('sensitivity', ucfirst($this->plugin->gettext($event['sensitivity'], $this->domain)) . '!'); + $table->add('label', $this->gettext('sensitivity')); + $table->add('sensitivity', ucfirst($this->gettext($event['sensitivity'])) . '!'); } if ($event['status'] == 'COMPLETED' || $event['status'] == 'CANCELLED') { - $table->add('label', $this->plugin->gettext('status'), $this->domain); - $table->add('status', $this->plugin->gettext('status-' . strtolower($event['status']), $this->domain)); + $table->add('label', $this->gettext('status')); + $table->add('status', $this->gettext('status-' . strtolower($event['status']))); } if ($event['comment']) { - $table->add('label', $this->plugin->gettext('comment'), $this->domain); + $table->add('label', $this->gettext('comment')); $table->add('location', Q($event['comment'])); }
View file
roundcubemail-plugins-kolab-3.2.3.tar.gz/plugins/libcalendaring/libcalendaring.php -> roundcubemail-plugins-kolab-3.2.4.tar.gz/plugins/libcalendaring/libcalendaring.php
Changed
@@ -341,7 +341,7 @@ $select_offset->add($this->gettext('trigger@'), '@'); // pre-set with default values from user settings - $preset = self::parse_alaram_value($this->rc->config->get('calendar_default_alarm_offset', '-15M')); + $preset = self::parse_alarm_value($this->rc->config->get('calendar_default_alarm_offset', '-15M')); $hidden = array('style' => 'display:none'); $html = html::span('edit-alarm-set', $select_type->show($this->rc->config->get('calendar_default_alarm_type', '')) . ' ' . @@ -421,7 +421,7 @@ * Helper function to convert alarm trigger strings * into two-field values (e.g. "-45M" => 45, "-M") */ - public static function parse_alaram_value($val) + public static function parse_alarm_value($val) { if ($val[0] == '@') { return array(new DateTime($val)); @@ -432,6 +432,12 @@ foreach ($m2 as $seg) { $prefix = $seg[2] == 'D' || $seg[2] == 'W' ? 'P' : 'PT'; if ($seg[1] > 0) { // ignore zero values + // convert seconds to minutes + if ($seg[2] == 'S') { + $seg[2] = 'M'; + $seg[1] = max(1, round($seg[1]/60)); + } + return array($seg[1], $m[1].$seg[2], $m[1].$seg[1].$seg[2], $m[1].$prefix.$seg[1].$seg[2]); } } @@ -452,7 +458,7 @@ if ($alarm['trigger'] instanceof DateTime) { $alarm['trigger'] = '@' . $alarm['trigger']->format('U'); } - else if ($trigger = libcalendaring::parse_alaram_value($alarm['trigger'])) { + else if ($trigger = libcalendaring::parse_alarm_value($alarm['trigger'])) { $alarm['trigger'] = $trigger[2]; } return $alarm; @@ -472,7 +478,7 @@ } catch (Exception $e) { /* handle this ? */ } } - else if ($trigger = libcalendaring::parse_alaram_value($alarm['trigger'])) { + else if ($trigger = libcalendaring::parse_alarm_value($alarm['trigger'])) { $alarm['trigger'] = $trigger[3]; } return $alarm; @@ -538,7 +544,7 @@ 'vars' => array('datetime' => $rcube->format_date($m[1])) )); } - else if ($val = self::parse_alaram_value($trigger)) { + else if ($val = self::parse_alarm_value($trigger)) { // TODO: for all-day events say 'on date of event at XX' ? if ($val[0] == 0) $text .= ' ' . $rcube->gettext('libcalendaring.triggerattime'); @@ -577,7 +583,7 @@ // support legacy format if (!$rec['valarms']) { list($trigger, $action) = explode(':', $rec['alarms'], 2); - if ($alarm = self::parse_alaram_value($trigger)) { + if ($alarm = self::parse_alarm_value($trigger)) { $rec['valarms'] = array(array('action' => $action, 'trigger' => $alarm[3] ?: $alarm[0])); } }
View file
roundcubemail-plugins-kolab-3.2.3.tar.gz/plugins/libcalendaring/libvcalendar.php -> roundcubemail-plugins-kolab-3.2.4.tar.gz/plugins/libcalendaring/libvcalendar.php
Changed
@@ -320,7 +320,12 @@ if ($object['recurrence']) { foreach ($vobject->children as $component) { if ($component->name == 'VEVENT' && isset($component->{'RECURRENCE-ID'})) { - $object['recurrence']['EXCEPTIONS'][] = $this->_to_array($component); + try { + $object['recurrence']['EXCEPTIONS'][] = $this->_to_array($component); + } + catch (Exception $e) { + console("iCal data parse error: " . $e->getMessage(), $component->serialize()); + } } } } @@ -588,7 +593,7 @@ $alarm['trigger'] = $prop->getDateTime(); } } - if (!$trigger && ($values = libcalendaring::parse_alaram_value($prop->value))) { + if (!$trigger && ($values = libcalendaring::parse_alarm_value($prop->value))) { $trigger = $values[2]; } @@ -1057,7 +1062,7 @@ else if ($event['alarms']) { $va = VObject\Component::create('VALARM'); list($trigger, $va->action) = explode(':', $event['alarms']); - $val = libcalendaring::parse_alaram_value($trigger); + $val = libcalendaring::parse_alarm_value($trigger); if ($val[3]) $va->add('TRIGGER', $val[3]); else if ($val[0] instanceof DateTime)
View file
roundcubemail-plugins-kolab-3.2.3.tar.gz/plugins/libcalendaring/localization/en_US.inc -> roundcubemail-plugins-kolab-3.2.4.tar.gz/plugins/libcalendaring/localization/en_US.inc
Changed
@@ -46,6 +46,7 @@ $labels['showmore'] = 'Show more...'; // recurrence related labels +$labels['recurring'] = 'Repeats'; $labels['frequency'] = 'Repeat'; $labels['never'] = 'never'; $labels['daily'] = 'daily';
View file
roundcubemail-plugins-kolab-3.2.3.tar.gz/plugins/libcalendaring/tests/libcalendaring.php -> roundcubemail-plugins-kolab-3.2.4.tar.gz/plugins/libcalendaring/tests/libcalendaring.php
Changed
@@ -29,29 +29,29 @@ } /** - * libcalendaring::parse_alaram_value() + * libcalendaring::parse_alarm_value() */ - function test_parse_alaram_value() + function test_parse_alarm_value() { - $alarm = libcalendaring::parse_alaram_value('-15M'); + $alarm = libcalendaring::parse_alarm_value('-15M'); $this->assertEquals('15', $alarm[0]); $this->assertEquals('-M', $alarm[1]); $this->assertEquals('-PT15M', $alarm[3]); - $alarm = libcalendaring::parse_alaram_value('-PT5H'); + $alarm = libcalendaring::parse_alarm_value('-PT5H'); $this->assertEquals('5', $alarm[0]); $this->assertEquals('-H', $alarm[1]); - $alarm = libcalendaring::parse_alaram_value('P0DT1H0M0S'); + $alarm = libcalendaring::parse_alarm_value('P0DT1H0M0S'); $this->assertEquals('1', $alarm[0]); $this->assertEquals('+H', $alarm[1]); // FIXME: this should return something like (1140 + 120 + 30)M - $alarm = libcalendaring::parse_alaram_value('-P1DT2H30M'); + $alarm = libcalendaring::parse_alarm_value('-P1DT2H30M'); // $this->assertEquals('1590', $alarm[0]); // $this->assertEquals('-M', $alarm[1]); - $alarm = libcalendaring::parse_alaram_value('@1420722000'); + $alarm = libcalendaring::parse_alarm_value('@1420722000'); $this->assertInstanceOf('DateTime', $alarm[0]); }
View file
roundcubemail-plugins-kolab-3.2.3.tar.gz/plugins/libcalendaring/tests/libvcalendar.php -> roundcubemail-plugins-kolab-3.2.4.tar.gz/plugins/libcalendaring/tests/libvcalendar.php
Changed
@@ -177,7 +177,7 @@ $event = $events[0]; $this->assertEquals('-12H:DISPLAY', $event['alarms'], "Serialized alarms string"); - $alarm = libcalendaring::parse_alaram_value($event['alarms']); + $alarm = libcalendaring::parse_alarm_value($event['alarms']); $this->assertEquals('12', $alarm[0], "Alarm value"); $this->assertEquals('-H', $alarm[1], "Alarm unit"); @@ -189,7 +189,7 @@ $event = $events[0]; $this->assertEquals('-30M:DISPLAY', $event['alarms'], "Stripped alarm string"); - $alarm = libcalendaring::parse_alaram_value($event['alarms']); + $alarm = libcalendaring::parse_alarm_value($event['alarms']); $this->assertEquals('30', $alarm[0], "Alarm value"); $this->assertEquals('-M', $alarm[1], "Alarm unit"); $this->assertEquals('-30M', $alarm[2], "Alarm string"); @@ -242,7 +242,7 @@ // alarms $this->assertEquals('-45M:AUDIO', $event['alarms'], "Relative alarm string"); - $alarm = libcalendaring::parse_alaram_value($event['alarms']); + $alarm = libcalendaring::parse_alarm_value($event['alarms']); $this->assertEquals('45', $alarm[0], "Alarm value"); $this->assertEquals('-M', $alarm[1], "Alarm unit");
View file
roundcubemail-plugins-kolab-3.2.3.tar.gz/plugins/libkolab/composer.json -> roundcubemail-plugins-kolab-3.2.4.tar.gz/plugins/libkolab/composer.json
Changed
@@ -4,7 +4,7 @@ "description": "Plugin to setup a basic environment for the interaction with a Kolab server.", "homepage": "http://git.kolab.org/roundcubemail-plugins-kolab/", "license": "AGPLv3", - "version": "3.2.3", + "version": "3.2.4", "authors": [ { "name": "Thomas Bruederli",
View file
roundcubemail-plugins-kolab-3.2.3.tar.gz/plugins/libkolab/lib/kolab_format_configuration.php -> roundcubemail-plugins-kolab-3.2.4.tar.gz/plugins/libkolab/lib/kolab_format_configuration.php
Changed
@@ -125,6 +125,8 @@ // adjust content-type string $this->CTYPEv2 = 'application/x-vnd.kolab.configuration.' . $object['type']; + // reset old object data, otherwise set() will overwrite current data (#4095) + $this->xmldata = null; // set common object properties parent::set($object);
View file
roundcubemail-plugins-kolab-3.2.3.tar.gz/plugins/libkolab/lib/kolab_format_event.php -> roundcubemail-plugins-kolab-3.2.4.tar.gz/plugins/libkolab/lib/kolab_format_event.php
Changed
@@ -96,11 +96,13 @@ // save recurrence exceptions if (is_array($object['recurrence']) && $object['recurrence']['EXCEPTIONS']) { $vexceptions = new vectorevent; - foreach((array)$object['recurrence']['EXCEPTIONS'] as $exception) { + foreach((array)$object['recurrence']['EXCEPTIONS'] as $i => $exception) { $exevent = new kolab_format_event; - $exevent->set($this->compact_exception($exception)); // only save differing values + $exevent->set(($compacted = $this->compact_exception($exception, $object))); // only save differing values $exevent->obj->setRecurrenceID(self::get_datetime($exception['start'], null, true), (bool)$exception['thisandfuture']); $vexceptions->push($exevent->obj); + // write cleaned-up exception data back to memory/cache + $object['recurrence']['EXCEPTIONS'][$i] = $this->expand_exception($compacted, $object); } $this->obj->setExceptions($vexceptions); } @@ -207,7 +209,7 @@ /** * Remove some attributes from the exception container */ - private function compact_exception($exception) + private function compact_exception($exception, $master) { $forbidden = array('recurrence','organizer','attendees','sequence'); @@ -217,6 +219,12 @@ } } + foreach ($master as $prop => $value) { + if (isset($exception[$prop]) && gettype($exception[$prop]) == gettype($value) && $exception[$prop] == $value) { + unset($exception[$prop]); + } + } + return $exception; }
View file
roundcubemail-plugins-kolab-3.2.3.tar.gz/plugins/libkolab/lib/kolab_storage.php -> roundcubemail-plugins-kolab-3.2.4.tar.gz/plugins/libkolab/lib/kolab_storage.php
Changed
@@ -35,6 +35,11 @@ const UID_KEY_PRIVATE = '/private/vendor/kolab/uniqueid'; const UID_KEY_CYRUS = '/shared/vendor/cmu/cyrus-imapd/uniqueid'; + const ERROR_IMAP_CONN = 1; + const ERROR_CACHE_DB = 2; + const ERROR_NO_PERMISSION = 3; + const ERROR_INVALID_FOLDER = 4; + public static $version = '3.0'; public static $last_error; public static $encode_ids = false; @@ -139,7 +144,6 @@ return self::$ldap; } - /** * Get a list of storage folders for the given data type * @@ -154,7 +158,7 @@ if (self::setup()) { foreach ((array)self::list_folders('', '*', $type, $subscribed, $folderdata) as $foldername) { - $folders[$foldername] = new kolab_storage_folder($foldername, $folderdata[$foldername]); + $folders[$foldername] = new kolab_storage_folder($foldername, $type, $folderdata[$foldername]); } } @@ -171,26 +175,26 @@ { if (self::setup()) { foreach ((array)self::list_folders('', '*', $type . '.default', false, $folderdata) as $foldername) { - return new kolab_storage_folder($foldername, $folderdata[$foldername]); + return new kolab_storage_folder($foldername, $type, $folderdata[$foldername]); } } return null; } - /** * Getter for a specific storage folder * - * @param string IMAP folder to access (UTF7-IMAP) + * @param string IMAP folder to access (UTF7-IMAP) + * @param string Expected folder type + * * @return object kolab_storage_folder The folder object */ - public static function get_folder($folder) + public static function get_folder($folder, $type = null) { - return self::setup() ? new kolab_storage_folder($folder) : null; + return self::setup() ? new kolab_storage_folder($folder, $type) : null; } - /** * Getter for a single Kolab object, identified by its UID. * This will search all folders storing objects of the given type. @@ -203,11 +207,11 @@ { self::setup(); $folder = null; - foreach ((array)self::list_folders('', '*', $type) as $foldername) { + foreach ((array)self::list_folders('', '*', $type, null, $folderdata) as $foldername) { if (!$folder) - $folder = new kolab_storage_folder($foldername); + $folder = new kolab_storage_folder($foldername, $type, $folderdata[$foldername]); else - $folder->set_folder($foldername); + $folder->set_folder($foldername, $type, $folderdata[$foldername]); if ($object = $folder->get_object($uid, '*')) return $object; @@ -230,11 +234,11 @@ $folder = null; $result = array(); - foreach ((array)self::list_folders('', '*', $type) as $foldername) { + foreach ((array)self::list_folders('', '*', $type, null, $folderdata) as $foldername) { if (!$folder) - $folder = new kolab_storage_folder($foldername); + $folder = new kolab_storage_folder($foldername, $type, $folderdata[$foldername]); else - $folder->set_folder($foldername); + $folder->set_folder($foldername, $type, $folderdata[$foldername]); foreach ($folder->select($query, '*') as $object) { $result[] = $object; @@ -901,7 +905,7 @@ !self::folder_is_subscribed($foldername, true) && !in_array(self::$imap->folder_namespace($foldername), (array)$exclude_ns) ) { - $folders[] = new kolab_storage_folder($foldername, $folderdata[$foldername]); + $folders[] = new kolab_storage_folder($foldername, $type, $folderdata[$foldername]); } } @@ -974,7 +978,7 @@ $parent_parent = join($delim, $path); if (!$refs[$parent]) { if ($folder->type && self::folder_type($parent) == $folder->type) { - $refs[$parent] = new kolab_storage_folder($parent, $folder->type); + $refs[$parent] = new kolab_storage_folder($parent, $folder->type, $folder->type); $refs[$parent]->parent = $parent_parent; } else if ($parent_parent == $other_ns) { @@ -1193,7 +1197,7 @@ } } else if (self::$imap->subscribe($folder)) { - self::$subscriptions === null; + self::$subscriptions = null; return true; } @@ -1221,7 +1225,7 @@ return true; } else if (self::$imap->unsubscribe($folder)) { - self::$subscriptions === null; + self::$subscriptions = null; return true; } @@ -1542,7 +1546,7 @@ foreach ($folders as $userfolder) { foreach ((array)self::list_folders($userfolder->name . $delimiter, '*', $type, false, $folderdata) as $foldername) { if (!$folders[$foldername]) { - $folders[$foldername] = new kolab_storage_folder($foldername, $folderdata[$foldername]); + $folders[$foldername] = new kolab_storage_folder($foldername, $type, $folderdata[$foldername]); $userfolder->children[] = $folders[$foldername]; } }
View file
roundcubemail-plugins-kolab-3.2.3.tar.gz/plugins/libkolab/lib/kolab_storage_cache.php -> roundcubemail-plugins-kolab-3.2.4.tar.gz/plugins/libkolab/lib/kolab_storage_cache.php
Changed
@@ -48,6 +48,7 @@ protected $extra_cols = array(); protected $order_by = null; protected $limit = null; + protected $error = 0; /** @@ -80,6 +81,7 @@ $this->db = $rcmail->get_dbh(); $this->imap = $rcmail->get_storage(); $this->enabled = $rcmail->config->get('kolab_cache', false); + $this->folders_table = $this->db->table_name('kolab_folders'); if ($this->enabled) { // always read folder cache and lock state from DB master @@ -98,8 +100,7 @@ */ public function select_by_id($folder_id) { - $folders_table = $this->db->table_name('kolab_folders', true); - $sql_arr = $this->db->fetch_assoc($this->db->query("SELECT * FROM $folders_table WHERE `folder_id` = ?", $folder_id)); + $sql_arr = $this->db->fetch_assoc($this->db->query("SELECT * FROM `{$this->folders_table}` WHERE `folder_id` = ?", $folder_id)); if ($sql_arr) { $this->metadata = $sql_arr; $this->folder_id = $sql_arr['folder_id']; @@ -120,14 +121,13 @@ { $this->folder = $storage_folder; - if (empty($this->folder->name)) { + if (empty($this->folder->name) || !$this->folder->valid) { $this->ready = false; return; } // compose fully qualified ressource uri for this instance $this->resource_uri = $this->folder->get_resource_uri(); - $this->folders_table = $this->db->table_name('kolab_folders'); $this->cache_table = $this->db->table_name('kolab_cache_' . $this->folder->type); $this->ready = $this->enabled && !empty($this->folder->type); $this->folder_id = null; @@ -151,6 +151,16 @@ } /** + * Returns code of last error + * + * @return int Error code + */ + public function get_error() + { + return $this->error; + } + + /** * Synchronize local cache data with remote */ public function synchronize() @@ -244,6 +254,7 @@ } } + $this->check_error(); $this->synched = time(); } @@ -260,7 +271,12 @@ { // delegate to another cache instance if ($foldername && $foldername != $this->folder->name) { - return kolab_storage::get_folder($foldername)->cache->get($msguid, $type); + $success = false; + if ($targetfolder = kolab_storage::get_folder($foldername)) { + $success = $targetfolder->cache->get($msguid, $type); + $this->error = $targetfolder->cache->get_error(); + } + return $success; } // load object if not in memory @@ -289,6 +305,7 @@ } } + $this->check_error(); return $this->objects[$msguid]; } @@ -308,8 +325,11 @@ // delegate to another cache instance if ($foldername && $foldername != $this->folder->name) { - kolab_storage::get_folder($foldername)->cache->set($msguid, $object); - return; + if ($targetfolder = kolab_storage::get_folder($foldername)) { + $targetfolder->cache->set($msguid, $object); + $this->error = $targetfolder->cache->get_error(); + } + return; } // remove old entry @@ -327,6 +347,8 @@ // ...or set in-memory cache to false $this->objects[$msguid] = $object; } + + $this->check_error(); } @@ -385,6 +407,8 @@ // keep a copy in memory for fast access $this->objects = array($msguid => $object); $this->uid2msg = array($object['uid'] => $msguid); + + $this->check_error(); } @@ -424,6 +448,7 @@ } unset($this->uid2msg[$uid]); + $this->check_error(); } @@ -457,15 +482,20 @@ return; } - $target = kolab_storage::get_folder($new_folder); + if ($target = kolab_storage::get_folder($new_folder)) { + // resolve new message UID in target folder + $this->db->query( + "UPDATE `{$this->folders_table}` SET `resource` = ? ". + "WHERE `resource` = ?", + $target->get_resource_uri(), + $this->resource_uri + ); - // resolve new message UID in target folder - $this->db->query( - "UPDATE `{$this->folders_table}` SET `resource` = ? ". - "WHERE `resource` = ?", - $target->get_resource_uri(), - $this->resource_uri - ); + $this->check_error(); + } + else { + $this->error = kolab_storage::ERROR_IMAP_CONN; + } } /** @@ -530,6 +560,7 @@ } if ($index->is_error()) { + $this->check_error(); if ($uids) { return null; } @@ -552,6 +583,8 @@ } } + $this->check_error(); + return $result; } @@ -594,6 +627,7 @@ } if ($index->is_error()) { + $this->check_error(); return null; } @@ -602,6 +636,7 @@ $count = $index->count(); } + $this->check_error(); return $count; } @@ -935,24 +970,29 @@ return; $this->_read_folder_data(); - $sql_query = "SELECT `synclock`, `ctag` FROM `{$this->folders_table}` WHERE `folder_id` = ?"; // abort if database is not set-up if ($this->db->is_error()) { + $this->check_error();
View file
roundcubemail-plugins-kolab-3.2.3.tar.gz/plugins/libkolab/lib/kolab_storage_folder.php -> roundcubemail-plugins-kolab-3.2.4.tar.gz/plugins/libkolab/lib/kolab_storage_folder.php
Changed
@@ -30,18 +30,28 @@ */ public $cache; - private $type_annotation; - private $resource_uri; + /** + * Indicate validity status + * @var boolean + */ + public $valid = false; + + protected $error = 0; + + protected $resource_uri; /** * Default constructor + * + * @param string The folder name/path + * @param string Expected folder type */ - function __construct($name, $type = null) + function __construct($name, $type = null, $type_annotation = null) { parent::__construct($name); $this->imap->set_options(array('skip_deleted' => true)); - $this->set_folder($name, $type); + $this->set_folder($name, $type, $type_annotation); } @@ -49,30 +59,63 @@ * Set the IMAP folder this instance connects to * * @param string The folder name/path + * @param string Expected folder type * @param string Optional folder type if known */ - public function set_folder($name, $type = null) + public function set_folder($name, $type = null, $type_annotation = null) { - $this->type_annotation = $type ? $type : kolab_storage::folder_type($name); + if (empty($type_annotation)) { + $type_annotation = kolab_storage::folder_type($name); + } $oldtype = $this->type; - list($this->type, $suffix) = explode('.', $this->type_annotation); + list($this->type, $suffix) = explode('.', $type_annotation); $this->default = $suffix == 'default'; $this->subtype = $this->default ? '' : $suffix; $this->name = $name; $this->id = kolab_storage::folder_id($name); + $this->valid = !empty($this->type) && $this->type != 'mail' && (!$type || $this->type == $type); + + if (!$this->valid) { + $this->error = $this->imap->get_error_code() < 0 ? kolab_storage::ERROR_IMAP_CONN : kolab_storage::ERROR_INVALID_FOLDER; + } // reset cached object properties $this->owner = $this->namespace = $this->resource_uri = $this->info = $this->idata = null; - // get a new cache instance of folder type changed - if (!$this->cache || $type != $oldtype) + // get a new cache instance if folder type changed + if (!$this->cache || $this->type != $oldtype) $this->cache = kolab_storage_cache::factory($this); + else + $this->cache->set_folder($this); $this->imap->set_folder($this->name); - $this->cache->set_folder($this); } + /** + * Returns code of last error + * + * @return int Error code + */ + public function get_error() + { + return $this->error ?: $this->cache->get_error(); + } + + /** + * Check IMAP connection error state + */ + public function check_error() + { + if (($err_code = $this->imap->get_error_code()) < 0) { + $this->error = kolab_storage::ERROR_IMAP_CONN; + if (($res_code = $this->imap->get_response_code()) !== 0 && in_array($res_code, array(rcube_storage::NOPERM, rcube_storage::READONLY))) { + $this->error = kolab_storage::ERROR_NO_PERMISSION; + } + } + + return $this->error; + } /** * Compose a unique resource URI for this IMAP folder @@ -138,6 +181,8 @@ if (!($success = $this->set_metadata(array(kolab_storage::UID_KEY_SHARED => $uid)))) { $success = $this->set_metadata(array(kolab_storage::UID_KEY_PRIVATE => $uid)); } + + $this->check_error(); return $success; } @@ -147,6 +192,7 @@ public function get_ctag() { $fdata = $this->get_imap_data(); + $this->check_error(); return sprintf('%d-%d-%d', $fdata['UIDVALIDITY'], $fdata['HIGHESTMODSEQ'], $fdata['UIDNEXT']); } @@ -204,6 +250,10 @@ */ public function count($query = null) { + if (!$this->valid) { + return 0; + } + // synchronize cache first $this->cache->synchronize(); @@ -221,6 +271,10 @@ { if (!$type) $type = $this->type; + if (!$this->valid) { + return array(); + } + // synchronize caches $this->cache->synchronize(); @@ -238,9 +292,14 @@ */ public function select($query = array()) { + if (!$this->valid) { + return array(); + } + // check query argument - if (empty($query)) + if (empty($query)) { return $this->get_objects(); + } // synchronize caches $this->cache->synchronize(); @@ -258,6 +317,10 @@ */ public function get_uids($query = array()) { + if (!$this->valid) { + return array(); + } + // synchronize caches $this->cache->synchronize(); @@ -319,6 +382,10 @@ */ public function get_object($uid, $type = null) { + if (!$this->valid) { + return false; + } + // synchronize caches $this->cache->synchronize(); @@ -348,7 +415,7 @@ */ public function get_attachment($uid, $part, $mailbox = null, $print = false, $fp = null, $skip_charset_conv = false) { - if ($msguid = ($mailbox ? $uid : $this->cache->uid2msguid($uid))) { + if ($this->valid && ($msguid = ($mailbox ? $uid : $this->cache->uid2msguid($uid)))) { $this->imap->set_folder($mailbox ? $mailbox : $this->name); if (substr($part, 0, 2) == 'i:') { @@ -392,6 +459,10 @@ */ public function read_object($msguid, $type = null, $folder = null) { + if (!$this->valid) { + return false; + } + if (!$type) $type = $this->type; if (!$folder) $folder = $this->name;
View file
roundcubemail-plugins-kolab-3.2.4.tar.gz/plugins/libkolab/tests
Added
+(directory)
View file
roundcubemail-plugins-kolab-3.2.4.tar.gz/plugins/libkolab/tests/README.md
Added
@@ -0,0 +1,43 @@ +libkolab plugin tests +===================== + +In order to run the functional tests for libkolab classes, some configuration +for the Roundcube test instance need to be created. Along with the default +config for a given Roundcube instance, you should provide a config specifically +for running tests. To do so, create a config file named `config-test.inc.php` +in the regular Roundcube config dir. That should provide specific `db_dsnw` and +`default_host` values for testing purposes as well as the credentials of a +valid IMAP user account used for running the tests with. + +Add these config options used by the libkolab tests: + +``` + // Unit tests settings + $config['tests_username'] = 'roundcube.test@example.org'; + $config['tests_password'] = '<test-account-password>'; + $config['default_host'] = '<kolab-server>'; + + // disable all plugins + $config['plugins'] = array(); +``` + +WARNING +------- +Please note that the configured IMAP account as well as the Roundcube database +configred in `db_dsnw` will be wiped and filled with test data in every test +run. Under no circumstances you should use credentials of a production database +or email account! + + +Run the tests +------------- + +The tests are based on PHPUnit and need to be exected from the Roundcube +test directory in order to load and initialize the Roundcube framework context. + +To execute individual tests, call `phpunit` from the tests directory: + +``` + cd <roundcube-dir>/tests/ + phpunit ../plugins/libkolab/tests/<filename> +``` \ No newline at end of file
View file
roundcubemail-plugins-kolab-3.2.4.tar.gz/plugins/libkolab/tests/kolab_storage_folder.php
Added
@@ -0,0 +1,168 @@ +<?php + +/** + * libkolab/kolab_storage_folder class tests + * + * @author Thomas Bruederli <bruederli@kolabsys.com> + * + * Copyright (C) 2015, Kolab Systems AG <contact@kolabsys.com> + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +class kolab_storage_folder_test extends PHPUnit_Framework_TestCase +{ + public static function setUpBeforeClass() + { + // load libkolab plugin + $rcmail = rcmail::get_instance(); + $rcmail->plugins->load_plugin('libkolab', true, true); + + if ($rcmail->config->get('tests_username')) { + $authenticated = $rcmail->login( + $rcmail->config->get('tests_username'), + $rcmail->config->get('tests_password'), + $rcmail->config->get('default_host'), + false + ); + + if (!$authenticated) { + throw new Exception('IMAP login failed for user ' . $rcmail->config->get('tests_username')); + } + + // check for defult groupware folders and clear them + $imap = $rcmail->get_storage(); + $folders = $imap->list_folders('', '*'); + + foreach (array('Calendar','Contacts','Files','Tasks','Notes') as $folder) { + if (in_array($folder, $folders)) { + if (!$imap->clear_folder($folder)) { + throw new Exception("Failed to clear folder '$folder'"); + } + } + else { + throw new Exception("Default folder '$folder' doesn't exits in test user account"); + } + } + } + else { + throw new Exception('Missing test account username/password in config-test.inc.php'); + } + + kolab_storage::setup(); + } + + function test_001_folder_type_check() + { + $folder = new kolab_storage_folder('Calendar', 'event', 'event.default'); + $this->assertTrue($folder->valid); + $this->assertEquals($folder->get_error(), 0); + + $folder = new kolab_storage_folder('Calendar', 'event', 'mail'); + $this->assertFalse($folder->valid); + $this->assertEquals($folder->get_error(), kolab_storage::ERROR_INVALID_FOLDER); + + $folder = new kolab_storage_folder('INBOX'); + $this->assertFalse($folder->valid); + $this->assertEquals($folder->get_error(), kolab_storage::ERROR_INVALID_FOLDER); + } + + function test_002_get_owner() + { + $rcmail = rcmail::get_instance(); + $folder = new kolab_storage_folder('Calendar', 'event', 'event'); + $this->assertEquals($folder->get_owner(), $rcmail->config->get('tests_username')); + + $domain = preg_replace('/^.+@/', '@', $rcmail->config->get('tests_username')); + + $shared_ns = kolab_storage::namespace_root('shared'); + $folder = new kolab_storage_folder($shared_ns . 'A-shared-folder', 'event', 'event'); + $this->assertEquals($folder->get_owner(true), 'anonymous' . $domain); + + $other_ns = kolab_storage::namespace_root('other'); + $folder = new kolab_storage_folder($other_ns . 'major.tom/Calendar', 'event', 'event'); + $this->assertEquals($folder->get_owner(true), 'major.tom' . $domain); + } + + function test_003_get_resource_uri() + { + $rcmail = rcmail::get_instance(); + $foldername = 'Calendar'; + + $folder = new kolab_storage_folder($foldername, 'event', 'event.default'); + $this->assertEquals($folder->get_resource_uri(), sprintf('imap://%s@%s/%s', + urlencode($rcmail->config->get('tests_username')), + $rcmail->config->get('default_host'), + $foldername + )); + } + + function test_004_get_uid() + { + $rcmail = rcmail::get_instance(); + $folder = new kolab_storage_folder('Doesnt-Exist', 'event', 'event'); + + // generate UID from folder name if IMAP operations fail + $uid1 = $folder->get_uid(); + $this->assertEquals($folder->get_uid(), $uid1); + $this->assertEquals($folder->get_error(), kolab_storage::ERROR_IMAP_CONN); + } + + function test_005_subscribe() + { + $folder = new kolab_storage_folder('Contacts', 'contact'); + $this->assertTrue($folder->subscribe(true)); + $this->assertTrue($folder->is_subscribed()); + + $this->assertTrue($folder->subscribe(false)); + $this->assertFalse($folder->is_subscribed()); + + $folder->subscribe(true); + } + + function test_006_activate() + { + $folder = new kolab_storage_folder('Calendar', 'contact'); + $this->assertTrue($folder->activate(true)); + $this->assertTrue($folder->is_active()); + + $this->assertTrue($folder->activate(false)); + $this->assertFalse($folder->is_active()); + } + + function test_010_write_contacts() + { + $contacts = array( + 'name' => 'FN', + 'surname' => 'Last', + 'firstname' => 'First', + 'email' => array( + array('type' => 'home', 'address' => 'first.last@example.org'), + ), + ); + + $folder = new kolab_storage_folder('Contacts', 'contact'); + $saved = $folder->save($contact, 'contact'); + $this->assertTrue((bool)$saved); + } + + /** + * @depends test_010_write_contacts + */ + function test_011_list_contacts() + { + $folder = new kolab_storage_folder('Contacts', 'contact'); + $this->assertEquals($folder->count(), 1); + } +}
View file
roundcubemail-plugins-kolab-3.2.3.tar.gz/plugins/odfviewer/ODFViewerPlugin.js -> roundcubemail-plugins-kolab-3.2.4.tar.gz/plugins/odfviewer/ODFViewerPlugin.js
Changed
@@ -1,43 +1,67 @@ /** - * @license * Copyright (C) 2012 KO GmbH <copyright@kogmbh.com> * * @licstart - * The JavaScript code in this page is free software: you can redistribute it - * and/or modify it under the terms of the GNU Affero General Public License - * (GNU AGPL) as published by the Free Software Foundation, either version 3 of - * the License, or (at your option) any later version. The code is distributed - * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU AGPL for more details. + * This file is part of WebODF. * - * As additional permission under GNU AGPL version 3 section 7, you - * may distribute non-source (e.g., minimized or compacted) forms of - * that code without the copy of the GNU GPL normally required by - * section 4, provided you include this license notice and a URL - * through which recipients can access the Corresponding Source. + * WebODF is free software: you can redistribute it and/or modify it + * under the terms of the GNU Affero General Public License (GNU AGPL) + * as published by the Free Software Foundation, either version 3 of + * the License, or (at your option) any later version. * - * As a special exception to the AGPL, any HTML file which merely makes function - * calls to this code, and for that purpose includes it by reference shall be - * deemed a separate work for copyright law purposes. In addition, the copyright - * holders of this code give you permission to combine this code with free - * software libraries that are released under the GNU LGPL. You may copy and - * distribute such a system following the terms of the GNU AGPL for this code - * and the LGPL for the libraries. If you modify this code, you may extend this - * exception to your version of the code, but you are not obligated to do so. - * If you do not wish to do so, delete this exception statement from your - * version. + * WebODF is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. * - * This license applies to this entire compilation. + * You should have received a copy of the GNU Affero General Public License + * along with WebODF. If not, see <http://www.gnu.org/licenses/>. * @licend + * * @source: http://www.webodf.org/ - * @source: http://gitorious.org/webodf/webodf/ + * @source: https://github.com/kogmbh/WebODF/ */ -/*global runtime, document, odf, console*/ +/*global runtime, document, odf, gui, console, webodf*/ function ODFViewerPlugin() { "use strict"; + function init(callback) { +/* + var lib = document.createElement('script'), + pluginCSS; + + lib.async = false; + lib.src = './webodf.js'; + lib.type = 'text/javascript'; + lib.onload = function () { +*/ + runtime.loadClass('gui.HyperlinkClickHandler'); + runtime.loadClass('odf.OdfCanvas'); + runtime.loadClass('ops.Session'); + runtime.loadClass('gui.CaretManager'); + runtime.loadClass("gui.HyperlinkTooltipView"); + runtime.loadClass('gui.SessionController'); + runtime.loadClass('gui.SvgSelectionView'); + runtime.loadClass('gui.SelectionViewManager'); + runtime.loadClass('gui.ShadowCursor'); + runtime.loadClass('gui.SessionView'); + + callback(); +/* + }; + + document.getElementsByTagName('head')[0].appendChild(lib); + + pluginCSS = document.createElement('link'); + pluginCSS.setAttribute("rel", "stylesheet"); + pluginCSS.setAttribute("type", "text/css"); + pluginCSS.setAttribute("href", "./ODFViewerPlugin.css"); + document.head.appendChild(pluginCSS); +*/ + } + // that should probably be provided by webodf function nsResolver(prefix) { var ns = { @@ -50,6 +74,8 @@ } var self = this, + pluginName = "WebODF", + pluginURL = "http://webodf.org", odfCanvas = null, odfElement = null, initialized = false, @@ -59,18 +85,61 @@ currentPage = null; this.initialize = function (viewerElement, documentUrl) { - odfElement = document.getElementById('canvas'); - odfCanvas = new odf.OdfCanvas(odfElement); - odfCanvas.load(documentUrl); - - odfCanvas.addListener('statereadychange', function () { - root = odfCanvas.odfContainer().rootElement; - initialized = true; - documentType = odfCanvas.odfContainer().getDocumentType(root); - if (documentType === 'text' && odfCanvas.enableAnnotations) { - odfCanvas.enableAnnotations(true); - } - self.onLoad(); + // If the URL has a fragment (#...), try to load the file it represents + init(function () { + var session, + sessionController, + sessionView, + odtDocument, + shadowCursor, + selectionViewManager, + caretManager, + localMemberId = 'localuser', + hyperlinkTooltipView, + eventManager; + + odfElement = document.getElementById('canvas'); + odfCanvas = new odf.OdfCanvas(odfElement); + odfCanvas.load(documentUrl); + + odfCanvas.addListener('statereadychange', function () { + root = odfCanvas.odfContainer().rootElement; + initialized = true; + documentType = odfCanvas.odfContainer().getDocumentType(root); + + if (documentType === 'text') { + odfCanvas.enableAnnotations(true, false); + + session = new ops.Session(odfCanvas); + odtDocument = session.getOdtDocument(); + shadowCursor = new gui.ShadowCursor(odtDocument); + sessionController = new gui.SessionController(session, localMemberId, shadowCursor, {}); + eventManager = sessionController.getEventManager(); + caretManager = new gui.CaretManager(sessionController, odfCanvas.getViewport()); + selectionViewManager = new gui.SelectionViewManager(gui.SvgSelectionView); + sessionView = new gui.SessionView({ + caretAvatarsInitiallyVisible: false + }, localMemberId, session, sessionController.getSessionConstraints(), caretManager, selectionViewManager); + selectionViewManager.registerCursor(shadowCursor); + hyperlinkTooltipView = new gui.HyperlinkTooltipView(odfCanvas, + sessionController.getHyperlinkClickHandler().getModifier); + eventManager.subscribe("mousemove", hyperlinkTooltipView.showTooltip); + eventManager.subscribe("mouseout", hyperlinkTooltipView.hideTooltip); + + var op = new ops.OpAddMember(); + op.init({ + memberid: localMemberId, + setProperties: { + fillName: runtime.tr("Unknown Author"), + color: "blue" + } + }); + session.enqueue([op]); + sessionController.insertLocalCursor(); + } + + self.onLoad(); + }); }); }; @@ -128,9 +197,28 @@ } return pages; }; - + this.showPage = function (n) { odfCanvas.showPage(n); }; - + + this.getPluginName = function () { + return pluginName; + }; + + this.getPluginVersion = function () { + var version; + + if (String(typeof webodf) !== "undefined") { + version = webodf.Version; + } else { + version = "Unknown"; + } +
View file
roundcubemail-plugins-kolab-3.2.3.tar.gz/plugins/odfviewer/README -> roundcubemail-plugins-kolab-3.2.4.tar.gz/plugins/odfviewer/README
Changed
@@ -6,11 +6,5 @@ INSTALLATION ------------ -Make the the folder 'files' in this directory writeable for the webserver. -It is used to temporarily store attachment files. Also make sure in the -webserver configuraton that this directory is not browsable. For Apache -webservers the included .htaccess file should already do the job. - Add 'odfviewer' to the list of plugins in the config/main.inc.php file of your Roundcube installation. -
View file
roundcubemail-plugins-kolab-3.2.3.tar.gz/plugins/odfviewer/odf.html -> roundcubemail-plugins-kolab-3.2.4.tar.gz/plugins/odfviewer/odf.html
Changed
@@ -1,11 +1,13 @@ +<!DOCTYPE html> <html dir="ltr" lang="en-US"> <head> -<meta http-equiv="Content-Type" content="text/html; charset=utf-8"></meta> +<meta http-equiv="Content-Type" content="text/html; charset=utf-8" /> +<meta name="viewport" content="width=device-width, initial-scale=1.0, user-scalable=no, minimum-scale=1.0, maximum-scale=1.0"/> <title>Roundcube WebODF Viewer</title> -<link rel="stylesheet" type="text/css" href="%%DOCROOT%%viewer.css"/> -<script type="text/javascript" src="%%DOCROOT%%viewer.js" charset="utf-8"></script> -<script type="text/javascript" src="%%DOCROOT%%ODFViewerPlugin.js" charset="utf-8"></script> -<script type="text/javascript" src="%%DOCROOT%%webodf.js" charset="utf-8"></script> +<link rel="stylesheet" type="text/css" href="%%viewer.css%%"/> +<script type="text/javascript" src="%%viewer.js%%" charset="utf-8"></script> +<script type="text/javascript" src="%%ODFViewerPlugin.js%%" charset="utf-8"></script> +<script type="text/javascript" src="%%webodf.js%%" charset="utf-8"></script> <script type="text/javascript" charset="utf-8"> /** @@ -33,74 +35,74 @@ */ -function init() { - viewer = new Viewer(new ODFViewerPlugin(), '%%DOCURL%%'); -} -window.setTimeout(init, 0); +window.onload = function () { + var viewer = new Viewer(new ODFViewerPlugin(), %%PARAMS%%); +}; </script> </head> - <body> - <div id="viewer"> - <div id="titlebar"> - <div id="documentName"></div> - <div id="toolbarRight"> - <button id="presentation" class="toolbarButton presentation" title="Presentation"></button> - <button id="fullscreen" class="toolbarButton fullscreen" title="Fullscreen"></button> - <button id="download" class="toolbarButton download" title="Download"></button> - </div> - </div> - <div id="toolbarContainer"> - <div id="toolbar"> - <div id="toolbarLeft"> - <div id="navButtons" class="splitToolbarButton"> - <button id="previous" class="toolbarButton pageUp" title="Previous Page"></button> - <div class="splitToolbarButtonSeparator"></div> - <button id="next" class="toolbarButton pageDown" title="Next Page"></button> - </div> - <label id="pageNumberLabel" class="toolbarLabel" for="pageNumber">Page:</label> - <input type="number" id="pageNumber" class="toolbarField pageNumber"></input> - <span id="numPages" class="toolbarLabel"></span> + <div id="viewer"> + <div id="titlebar"> + <div id="documentName"></div> + <div id="toolbarRight"> + <button id="presentation" class="toolbarButton presentation" title="Presentation"></button> + <button id="fullscreen" class="toolbarButton fullscreen" title="Fullscreen"></button> + <button id="download" class="toolbarButton download" title="Download"></button> </div> - <div id="toolbarMiddleContainer" class="outerCenter"> - <div id="toolbarMiddle" class="innerCenter"> - <div id = 'zoomButtons' class="splitToolbarButton"> - <button id="zoomOut" class="toolbarButton zoomOut" title="Zoom Out"></button> + </div> + <div id="toolbarContainer"> + <div id="toolbar"> + <div id="toolbarLeft"> + <div id="navButtons" class="splitToolbarButton"> + <button id="previous" class="toolbarButton pageUp" title="Previous Page"></button> <div class="splitToolbarButtonSeparator"></div> - <button id="zoomIn" class="toolbarButton zoomIn" title="Zoom In"></button> + <button id="next" class="toolbarButton pageDown" title="Next Page"></button> </div> - <span id="scaleSelectContainer" class="dropdownToolbarButton"> - <select id="scaleSelect" title="Zoom" oncontextmenu="return false;"> - <option id="pageAutoOption" value="auto" selected>Automatic</option> - <option id="pageActualOption" value="page-actual">Actual Size</option> - <option id="pageWidthOption" value="page-width">Full Width</option> - <option id="customScaleOption" value="custom"></option> - <option value="0.5">50%</option> - <option value="0.75">75%</option> - <option value="1">100%</option> - <option value="1.25">125%</option> - <option value="1.5">150%</option> - <option value="2">200%</option> - </select> - </span> - <div id="sliderContainer"> - <div id="slider"></div> + <label id="pageNumberLabel" class="toolbarLabel" for="pageNumber">Page:</label> + <input type="number" id="pageNumber" class="toolbarField pageNumber"/> + <span id="numPages" class="toolbarLabel"></span> + </div> + <div id="toolbarMiddleContainer" class="outerCenter"> + <div id="toolbarMiddle" class="innerCenter"> + <div id = 'zoomButtons' class="splitToolbarButton"> + <button id="zoomOut" class="toolbarButton zoomOut" title="Zoom Out"></button> + <div class="splitToolbarButtonSeparator"></div> + <button id="zoomIn" class="toolbarButton zoomIn" title="Zoom In"></button> + </div> + <span id="scaleSelectContainer" class="dropdownToolbarButton"> + <select id="scaleSelect" title="Zoom" oncontextmenu="return false;"> + <option id="pageAutoOption" value="auto" selected>Automatic</option> + <option id="pageActualOption" value="page-actual">Actual Size</option> + <option id="pageWidthOption" value="page-width">Full Width</option> + <option id="customScaleOption" value="custom"> </option> + <option value="0.5">50%</option> + <option value="0.75">75%</option> + <option value="1">100%</option> + <option value="1.25">125%</option> + <option value="1.5">150%</option> + <option value="2">200%</option> + </select> + </span> + <div id="sliderContainer"> + <div id="slider"></div> + </div> </div> </div> </div> </div> + <div id="canvasContainer"> + <div id="canvas"></div> + </div> + <div id="overlayNavigator"> + <div id="previousPage"></div> + <div id="nextPage"></div> + </div> + <div id="overlayCloseButton"> + ✖ + </div> + <div id="dialogOverlay"></div> + <div id="blanked"></div> </div> - <div id="canvasContainer"> - <div id="canvas"></div> - </div> - <div id="overlayNavigator"> - <div id="previousPage"></div> - <div id="nextPage"></div> - </div> - <div id="overlayCloseButton"> - ✖ - </div> - </div> </body> </html>
View file
roundcubemail-plugins-kolab-3.2.3.tar.gz/plugins/odfviewer/odfviewer.php -> roundcubemail-plugins-kolab-3.2.4.tar.gz/plugins/odfviewer/odfviewer.php
Changed
@@ -26,132 +26,84 @@ */ class odfviewer extends rcube_plugin { - public $task = 'mail|calendar|tasks|logout'; - - private $tempdir = 'plugins/odfviewer/files/'; - private $tempbase = 'plugins/odfviewer/files/'; - - private $odf_mimetypes = array( - 'application/vnd.oasis.opendocument.chart', - 'application/vnd.oasis.opendocument.chart-template', - 'application/vnd.oasis.opendocument.formula', - 'application/vnd.oasis.opendocument.formula-template', - 'application/vnd.oasis.opendocument.graphics', - 'application/vnd.oasis.opendocument.graphics-template', - 'application/vnd.oasis.opendocument.presentation', - 'application/vnd.oasis.opendocument.presentation-template', - 'application/vnd.oasis.opendocument.text', - 'application/vnd.oasis.opendocument.text-master', - 'application/vnd.oasis.opendocument.text-template', - 'application/vnd.oasis.opendocument.spreadsheet', - 'application/vnd.oasis.opendocument.spreadsheet-template', - ); + public $task = 'mail|calendar|tasks'; - function init() - { - $this->tempdir = $this->home . '/files/'; - $this->tempbase = $this->urlbase . 'files/'; + private $odf_mimetypes = array( + 'application/vnd.oasis.opendocument.chart', + 'application/vnd.oasis.opendocument.chart-template', + 'application/vnd.oasis.opendocument.formula', + 'application/vnd.oasis.opendocument.formula-template', + 'application/vnd.oasis.opendocument.graphics', + 'application/vnd.oasis.opendocument.graphics-template', + 'application/vnd.oasis.opendocument.presentation', + 'application/vnd.oasis.opendocument.presentation-template', + 'application/vnd.oasis.opendocument.text', + 'application/vnd.oasis.opendocument.text-master', + 'application/vnd.oasis.opendocument.text-template', + 'application/vnd.oasis.opendocument.spreadsheet', + 'application/vnd.oasis.opendocument.spreadsheet-template', + ); - // webODF only supports IE9 or higher - $ua = new rcube_browser; - if ($ua->ie && $ua->ver < 9) - return; - // extend list of mimetypes that should open in preview - $rcmail = rcube::get_instance(); - if ($rcmail->action == 'preview' || $rcmail->action == 'show' || $rcmail->task == 'calendar' || $rcmail->task == 'tasks') { - $mimetypes = (array)$rcmail->config->get('client_mimetypes'); - $rcmail->config->set('client_mimetypes', array_merge($mimetypes, $this->odf_mimetypes)); - } - - $this->add_hook('message_part_get', array($this, 'get_part')); - $this->add_hook('session_destroy', array($this, 'session_cleanup')); - } + function init() + { + // webODF only supports IE9 or higher + $ua = new rcube_browser; + if ($ua->ie && $ua->ver < 9) { + return; + } - /** - * Handler for message attachment download - */ - function get_part($args) - { - if (!$args['download'] && $args['mimetype'] && in_array($args['mimetype'], $this->odf_mimetypes)) { - if (empty($_GET['_load'])) { + // extend list of mimetypes that should open in preview $rcmail = rcube::get_instance(); - $exts = rcube_mime::get_mime_extensions($args['mimetype']); - $suffix = $exts ? '.'.$exts[0] : '.odt'; - $fn = md5(session_id() . $_SERVER['REQUEST_URI']) . $suffix; - - // FIXME: copy file to disk because only apache can send the file correctly - $tempfn = $this->tempdir . $fn; - if (!file_exists($tempfn)) { - if ($args['body']) { - file_put_contents($tempfn, $args['body']); - } - else { - $fp = fopen($tempfn, 'w'); - $imap = rcube::get_instance()->get_storage(); - $imap->get_message_part($args['uid'], $args['id'], $args['part'], false, $fp); - fclose($fp); - } - - // remember tempfiles in session to clean up on logout - $_SESSION['odfviewer']['tempfiles'][] = $fn; - } - - // send webODF viewer page - $html = file_get_contents($this->home . '/odf.html'); - header("Content-Type: text/html; charset=" . RCMAIL_CHARSET); - echo strtr($html, array( - '%%DOCROOT%%' => $rcmail->output->asset_url($this->urlbase), - '%%DOCURL%%' => $rcmail->output->asset_url($this->tempbase . $fn), # $_SERVER['REQUEST_URI'].'&_load=1', - )); - $args['abort'] = true; - } -/* - else { - if ($_SERVER['REQUEST_METHOD'] == 'HEAD') { - header("Content-Length: " . max(10, $args['part']->size)); # content-length has to be present - $args['body'] = ' '; # send empty body - return $args; + if ($rcmail->action == 'preview' || $rcmail->action == 'show' || $rcmail->task == 'calendar' || $rcmail->task == 'tasks') { + $mimetypes = (array)$rcmail->config->get('client_mimetypes'); + $rcmail->config->set('client_mimetypes', array_merge($mimetypes, $this->odf_mimetypes)); } - } -*/ + + $this->add_hook('message_part_get', array($this, 'get_part')); } - return $args; - } + /** + * Handler for message attachment download + */ + function get_part($args) + { + if (!$args['download'] && $args['mimetype'] && in_array($args['mimetype'], $this->odf_mimetypes)) { + $rcmail = rcube::get_instance(); + $params = array( + 'documentUrl' => $_SERVER['REQUEST_URI'] . '&_download=1', + 'filename' => $args['part']->filename ?: 'file.odt', + 'type' => $args['mimetype'], + ); + + // send webODF viewer page + $html = file_get_contents($this->home . '/odf.html'); + header("Content-Type: text/html; charset=" . RCMAIL_CHARSET); + echo strtr($html, array( + '%%PARAMS%%' => rcube_output::json_serialize($params), + '%%viewer.css%%' => $this->asset_path('viewer.css'), + '%%viewer.js%%' => $this->asset_path('viewer.js'), + '%%ODFViewerPlugin.js%%' => $this->asset_path('ODFViewerPlugin.js'), + '%%webodf.js%%' => $this->asset_path('webodf.js'), + )); + + $args['abort'] = true; + } - /** - * Remove temp files opened during this session - */ - function session_cleanup() - { - foreach ((array)$_SESSION['odfviewer']['tempfiles'] as $fn) { - @unlink($this->tempdir . $fn); + return $args; } - - // also trigger general garbage collection because not everybody logs out properly - $this->gc_cleanup(); - } - /** - * Garbage collector function for temp files. - * Remove temp files older than two days - */ - function gc_cleanup() - { - $tmp = unslashify($this->tempdir); - $expire = mktime() - 172800; // expire in 48 hours + private function asset_path($path) + { + $rcmail = rcube::get_instance(); + $assets_dir = $rcmail->config->get('assets_dir'); - if ($dir = opendir($tmp)) { - while (($fname = readdir($dir)) !== false) { - if ($fname[0] == '.') - continue; + $mtime = filemtime($this->home . '/' . $path); + if (!$mtime && $assets_dir) { + $mtime = filemtime($assets_dir . '/plugins/odfviewer/' . $path); + } - if (filemtime($tmp.'/'.$fname) < $expire) - @unlink($tmp.'/'.$fname); - } + $path = $this->urlbase . $path . ($mtime ? '?s=' . $mtime : ''); - closedir($dir); + return $rcmail->output->asset_url($path); } - } } -
View file
roundcubemail-plugins-kolab-3.2.3.tar.gz/plugins/odfviewer/viewer.css -> roundcubemail-plugins-kolab-3.2.4.tar.gz/plugins/odfviewer/viewer.css
Changed
@@ -28,7 +28,7 @@ -webkit-box-shadow: 0px 1px 3px rgba(50, 50, 50, 0.75); -moz-box-shadow: 0px 1px 3px rgba(50, 50, 50, 0.75); box-shadow: 0px 1px 3px rgba(50, 50, 50, 0.75); - + background-image: url(images/texture.png), linear-gradient(rgba(69, 69, 69, .95), rgba(82, 82, 82, .99)); background-image: url(images/texture.png), -webkit-linear-gradient(rgba(69, 69, 69, .95), rgba(82, 82, 82, .99)); background-image: url(images/texture.png), -moz-linear-gradient(rgba(69, 69, 69, .95), rgba(82, 82, 82, .99));
View file
roundcubemail-plugins-kolab-3.2.3.tar.gz/plugins/odfviewer/viewer.js -> roundcubemail-plugins-kolab-3.2.4.tar.gz/plugins/odfviewer/viewer.js
Changed
@@ -1,41 +1,50 @@ /** - * @license - * Copyright (C) 2013 KO GmbH <copyright@kogmbh.com> + * Copyright (C) 2012-2015 KO GmbH <copyright@kogmbh.com> * * @licstart - * The JavaScript code in this page is free software: you can redistribute it - * and/or modify it under the terms of the GNU Affero General Public License - * (GNU AGPL) as published by the Free Software Foundation, either version 3 of - * the License, or (at your option) any later version. The code is distributed - * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU AGPL for more details. + * This file is part of WebODF. * - * As additional permission under GNU AGPL version 3 section 7, you - * may distribute non-source (e.g., minimized or compacted) forms of - * that code without the copy of the GNU GPL normally required by - * section 4, provided you include this license notice and a URL - * through which recipients can access the Corresponding Source. + * WebODF is free software: you can redistribute it and/or modify it + * under the terms of the GNU Affero General Public License (GNU AGPL) + * as published by the Free Software Foundation, either version 3 of + * the License, or (at your option) any later version. * - * As a special exception to the AGPL, any HTML file which merely makes function - * calls to this code, and for that purpose includes it by reference shall be - * deemed a separate work for copyright law purposes. In addition, the copyright - * holders of this code give you permission to combine this code with free - * software libraries that are released under the GNU LGPL. You may copy and - * distribute such a system following the terms of the GNU AGPL for this code - * and the LGPL for the libraries. If you modify this code, you may extend this - * exception to your version of the code, but you are not obligated to do so. - * If you do not wish to do so, delete this exception statement from your - * version. + * WebODF is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. * - * This license applies to this entire compilation. + * You should have received a copy of the GNU Affero General Public License + * along with WebODF. If not, see <http://www.gnu.org/licenses/>. * @licend + * * @source: http://www.webodf.org/ - * @source: http://gitorious.org/webodf/webodf/ + * @source: https://github.com/kogmbh/WebODF/ + */ + +/* + * This file is a derivative from a part of Mozilla's PDF.js project. The + * original license header follows. + */ + +/* Copyright 2012 Mozilla Foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. */ /*global document, window*/ -function Viewer(viewerPlugin, docurl) { +function Viewer(viewerPlugin, parameters) { "use strict"; var self = this, @@ -45,25 +54,88 @@ kDefaultScaleDelta = 1.1, kDefaultScale = 'auto', presentationMode = false, + isFullScreen = false, initialized = false, isSlideshow = false, url, - viewerElement, + viewerElement = document.getElementById('viewer'), canvasContainer = document.getElementById('canvasContainer'), overlayNavigator = document.getElementById('overlayNavigator'), + titlebar = document.getElementById('titlebar'), + toolbar = document.getElementById('toolbarContainer'), pageSwitcher = document.getElementById('toolbarLeft'), zoomWidget = document.getElementById('toolbarMiddleContainer'), scaleSelector = document.getElementById('scaleSelect'), - filename, + dialogOverlay = document.getElementById('dialogOverlay'), + toolbarRight = document.getElementById('toolbarRight'), + aboutDialog, pages = [], currentPage, scaleChangeTimer, - touchTimer; + touchTimer, + toolbarTouchTimer, + /**@const*/ + UI_FADE_DURATION = 5000; + + function isBlankedOut() { + return (blanked.style.display === 'block'); + } + + function initializeAboutInformation() { + var aboutDialogCentererTable, aboutDialogCentererCell, aboutButton, pluginName, pluginVersion, pluginURL; + + if (viewerPlugin) { + pluginName = viewerPlugin.getPluginName(); + pluginVersion = viewerPlugin.getPluginVersion(); + pluginURL = viewerPlugin.getPluginURL(); + } + + // Create dialog + aboutDialogCentererTable = document.createElement('div'); + aboutDialogCentererTable.id = "aboutDialogCentererTable"; + aboutDialogCentererCell = document.createElement('div'); + aboutDialogCentererCell.id = "aboutDialogCentererCell"; + aboutDialog = document.createElement('div'); + aboutDialog.id = "aboutDialog"; + aboutDialog.innerHTML = + "<h1>ViewerJS</h1>" + + "<p>Open Source document viewer for webpages, built with HTML and JavaScript.</p>" + + "<p>Learn more and get your own copy on the <a href=\"http://viewerjs.org/\" target=\"_blank\">ViewerJS website</a>.</p>" + + (viewerPlugin ? ("<p>Using the <a href = \""+ pluginURL + "\" target=\"_blank\">" + pluginName + "</a> " + + "(<span id = \"pluginVersion\">" + pluginVersion + "</span>) " + + "plugin to show you this document.</p>") + : "") + + "<p>Supported by <a href=\"http://nlnet.nl\" target=\"_blank\"><br><img src=\"images\/nlnet.png\" width=\"160\" height=\"60\" alt=\"NLnet Foundation\"></a></p>" + + "<p>Made by <a href=\"http://kogmbh.com\" target=\"_blank\"><br><img src=\"images\/kogmbh.png\" width=\"172\" height=\"40\" alt=\"KO GmbH\"></a></p>" + + "<button id = \"aboutDialogCloseButton\" class = \"toolbarButton textButton\">Close</button>"; + dialogOverlay.appendChild(aboutDialogCentererTable); + aboutDialogCentererTable.appendChild(aboutDialogCentererCell); + aboutDialogCentererCell.appendChild(aboutDialog); + + // Create button to open dialog that says "ViewerJS" + aboutButton = document.createElement('button'); + aboutButton.id = "about"; + aboutButton.className = "toolbarButton textButton about"; + aboutButton.title = "About"; + aboutButton.innerHTML = "ViewerJS" + toolbarRight.appendChild(aboutButton); + + // Attach events to the above + aboutButton.addEventListener('click', function () { + showAboutDialog(); + }); + document.getElementById('aboutDialogCloseButton').addEventListener('click', function () { + hideAboutDialog(); + }); + + } - function isFullScreen() { - // Note that the browser fullscreen (triggered by short keys) might - // be considered different from content fullscreen when expecting a boolean - return document.isFullScreen || document.mozFullScreen || document.webkitIsFullScreen; + function showAboutDialog() { + dialogOverlay.style.display = "block"; + } + + function hideAboutDialog() { + dialogOverlay.style.display = "none"; } function selectScaleOption(value) { @@ -171,18 +243,38 @@ delayedRefresh(300); } - - this.initialize = function (url) { - viewerElement = document.getElementById('viewer'); - filename = url.replace(/^.*[\\\/]/, ''); - document.title = filename; - document.getElementById('documentName').innerHTML = document.title; + function readZoomParameter(zoom) { + var validZoomStrings = ["auto", "page-actual", "page-width"], + number; + + if (validZoomStrings.indexOf(zoom) !== -1) { + return zoom; + } + number = parseFloat(zoom); + if (number && kMinScale <= number && number <= kMaxScale) { + return zoom; + } + return kDefaultScale; + } + + this.initialize = function () { + var initialScale, + element;
View file
roundcubemail-plugins-kolab-3.2.3.tar.gz/plugins/odfviewer/webodf.js -> roundcubemail-plugins-kolab-3.2.4.tar.gz/plugins/odfviewer/webodf.js
Changed
@@ -1,464 +1,30 @@ -// Input 0 /* + This is a generated file. DO NOT EDIT. - Copyright (C) 2012 KO GmbH <copyright@kogmbh.com> + Copyright (C) 2010-2014 KO GmbH <copyright@kogmbh.com> @licstart - The JavaScript code in this page is free software: you can redistribute it - and/or modify it under the terms of the GNU Affero General Public License - (GNU AGPL) as published by the Free Software Foundation, either version 3 of - the License, or (at your option) any later version. The code is distributed - WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - FITNESS FOR A PARTICULAR PURPOSE. See the GNU AGPL for more details. - - As additional permission under GNU AGPL version 3 section 7, you - may distribute non-source (e.g., minimized or compacted) forms of - that code without the copy of the GNU GPL normally required by - section 4, provided you include this license notice and a URL - through which recipients can access the Corresponding Source. - - As a special exception to the AGPL, any HTML file which merely makes function - calls to this code, and for that purpose includes it by reference shall be - deemed a separate work for copyright law purposes. In addition, the copyright - holders of this code give you permission to combine this code with free - software libraries that are released under the GNU LGPL. You may copy and - distribute such a system following the terms of the GNU AGPL for this code - and the LGPL for the libraries. If you modify this code, you may extend this - exception to your version of the code, but you are not obligated to do so. - If you do not wish to do so, delete this exception statement from your - version. - - This license applies to this entire compilation. - @licend - @source: http://www.webodf.org/ - @source: http://gitorious.org/webodf/webodf/ -*/ -var core={},gui={},xmldom={},odf={},ops={}; -// Input 1 -function Runtime(){}Runtime.ByteArray=function(e){};Runtime.prototype.getVariable=function(e){};Runtime.prototype.toJson=function(e){};Runtime.prototype.fromJson=function(e){};Runtime.ByteArray.prototype.slice=function(e,k){};Runtime.ByteArray.prototype.length=0;Runtime.prototype.byteArrayFromArray=function(e){};Runtime.prototype.byteArrayFromString=function(e,k){};Runtime.prototype.byteArrayToString=function(e,k){};Runtime.prototype.concatByteArrays=function(e,k){}; -Runtime.prototype.read=function(e,k,l,p){};Runtime.prototype.readFile=function(e,k,l){};Runtime.prototype.readFileSync=function(e,k){};Runtime.prototype.loadXML=function(e,k){};Runtime.prototype.writeFile=function(e,k,l){};Runtime.prototype.isFile=function(e,k){};Runtime.prototype.getFileSize=function(e,k){};Runtime.prototype.deleteFile=function(e,k){};Runtime.prototype.log=function(e,k){};Runtime.prototype.setTimeout=function(e,k){};Runtime.prototype.libraryPaths=function(){}; -Runtime.prototype.type=function(){};Runtime.prototype.getDOMImplementation=function(){};Runtime.prototype.parseXML=function(e){};Runtime.prototype.getWindow=function(){};Runtime.prototype.assert=function(e,k,l){};var IS_COMPILED_CODE=!0; -Runtime.byteArrayToString=function(e,k){function l(h){var b="",f,d=h.length;for(f=0;f<d;f+=1)b+=String.fromCharCode(h[f]&255);return b}function p(h){var b="",f,d=h.length,a,n,q,g;for(f=0;f<d;f+=1)a=h[f],128>a?b+=String.fromCharCode(a):(f+=1,n=h[f],194<=a&&224>a?b+=String.fromCharCode((a&31)<<6|n&63):(f+=1,q=h[f],224<=a&&240>a?b+=String.fromCharCode((a&15)<<12|(n&63)<<6|q&63):(f+=1,g=h[f],240<=a&&245>a&&(a=(a&7)<<18|(n&63)<<12|(q&63)<<6|g&63,a-=65536,b+=String.fromCharCode((a>>10)+55296,(a&1023)+56320))))); -return b}var r;"utf8"===k?r=p(e):("binary"!==k&&this.log("Unsupported encoding: "+k),r=l(e));return r};Runtime.getVariable=function(e){try{return eval(e)}catch(k){}};Runtime.toJson=function(e){return JSON.stringify(e)};Runtime.fromJson=function(e){return JSON.parse(e)};Runtime.getFunctionName=function(e){return void 0===e.name?(e=/function\s+(\w+)/.exec(e))&&e[1]:e.name}; -function BrowserRuntime(e){function k(h,b){var f,d,a;void 0!==b?a=h:b=h;e?(d=e.ownerDocument,a&&(f=d.createElement("span"),f.className=a,f.appendChild(d.createTextNode(a)),e.appendChild(f),e.appendChild(d.createTextNode(" "))),f=d.createElement("span"),0<b.length&&"<"===b[0]?f.innerHTML=b:f.appendChild(d.createTextNode(b)),e.appendChild(f),e.appendChild(d.createElement("br"))):console&&console.log(b);"alert"===a&&alert(b)}var l=this,p={},r=window.ArrayBuffer&&window.Uint8Array;r&&(Uint8Array.prototype.slice= -function(h,b){void 0===b&&(void 0===h&&(h=0),b=this.length);var f=this.subarray(h,b),d,a;b-=h;d=new Uint8Array(new ArrayBuffer(b));for(a=0;a<b;a+=1)d[a]=f[a];return d});this.ByteArray=r?function(h){return new Uint8Array(new ArrayBuffer(h))}:function(h){var b=[];b.length=h;return b};this.concatByteArrays=r?function(h,b){var f,d=h.length,a=b.length,n=new this.ByteArray(d+a);for(f=0;f<d;f+=1)n[f]=h[f];for(f=0;f<a;f+=1)n[f+d]=b[f];return n}:function(h,b){return h.concat(b)};this.byteArrayFromArray=function(h){return h.slice()}; -this.byteArrayFromString=function(h,b){var f;if("utf8"===b){f=h.length;var d,a,n,q=0;for(a=0;a<f;a+=1)n=h.charCodeAt(a),q+=1+(128<n)+(2048<n);d=new l.ByteArray(q);for(a=q=0;a<f;a+=1)n=h.charCodeAt(a),128>n?(d[q]=n,q+=1):2048>n?(d[q]=192|n>>>6,d[q+1]=128|n&63,q+=2):(d[q]=224|n>>>12&15,d[q+1]=128|n>>>6&63,d[q+2]=128|n&63,q+=3)}else for("binary"!==b&&l.log("unknown encoding: "+b),f=h.length,d=new l.ByteArray(f),a=0;a<f;a+=1)d[a]=h.charCodeAt(a)&255;return f=d};this.byteArrayToString=Runtime.byteArrayToString; -this.getVariable=Runtime.getVariable;this.fromJson=Runtime.fromJson;this.toJson=Runtime.toJson;this.readFile=function(h,b,f){function d(){var q;4===a.readyState&&(0!==a.status||a.responseText?200===a.status||0===a.status?(q="binary"===b?null!==a.responseBody&&"undefined"!==String(typeof VBArray)?(new VBArray(a.responseBody)).toArray():l.byteArrayFromString(a.responseText,"binary"):a.responseText,p[h]=q,f(null,q)):f(a.responseText||a.statusText):f("File "+h+" is empty."))}if(p.hasOwnProperty(h))f(null, -p[h]);else{var a=new XMLHttpRequest;a.open("GET",h,!0);a.onreadystatechange=d;a.overrideMimeType&&("binary"!==b?a.overrideMimeType("text/plain; charset="+b):a.overrideMimeType("text/plain; charset=x-user-defined"));try{a.send(null)}catch(n){f(n.message)}}};this.read=function(h,b,f,d){function a(){var a;4===n.readyState&&(0!==n.status||n.responseText?200===n.status||0===n.status?(n.response?(a=n.response,a=new Uint8Array(a)):a=null!==n.responseBody&&"undefined"!==String(typeof VBArray)?(new VBArray(n.responseBody)).toArray(): -l.byteArrayFromString(n.responseText,"binary"),p[h]=a,d(null,a.slice(b,b+f))):d(n.responseText||n.statusText):d("File "+h+" is empty."))}if(p.hasOwnProperty(h))d(null,p[h].slice(b,b+f));else{var n=new XMLHttpRequest;n.open("GET",h,!0);n.onreadystatechange=a;n.overrideMimeType&&n.overrideMimeType("text/plain; charset=x-user-defined");n.responseType="arraybuffer";try{n.send(null)}catch(q){d(q.message)}}};this.readFileSync=function(h,b){var f=new XMLHttpRequest,d;f.open("GET",h,!1);f.overrideMimeType&& -("binary"!==b?f.overrideMimeType("text/plain; charset="+b):f.overrideMimeType("text/plain; charset=x-user-defined"));try{if(f.send(null),200===f.status||0===f.status)d=f.responseText}catch(a){}return d};this.writeFile=function(h,b,f){p[h]=b;var d=new XMLHttpRequest;d.open("PUT",h,!0);d.onreadystatechange=function(){4===d.readyState&&(0!==d.status||d.responseText?200<=d.status&&300>d.status||0===d.status?f(null):f("Status "+String(d.status)+": "+d.responseText||d.statusText):f("File "+h+" is empty."))}; -b=b.buffer&&!d.sendAsBinary?b.buffer:l.byteArrayToString(b,"binary");try{d.sendAsBinary?d.sendAsBinary(b):d.send(b)}catch(a){l.log("HUH? "+a+" "+b),f(a.message)}};this.deleteFile=function(h,b){delete p[h];var f=new XMLHttpRequest;f.open("DELETE",h,!0);f.onreadystatechange=function(){4===f.readyState&&(200>f.status&&300<=f.status?b(f.responseText):b(null))};f.send(null)};this.loadXML=function(h,b){var f=new XMLHttpRequest;f.open("GET",h,!0);f.overrideMimeType&&f.overrideMimeType("text/xml");f.onreadystatechange= -function(){4===f.readyState&&(0!==f.status||f.responseText?200===f.status||0===f.status?b(null,f.responseXML):b(f.responseText):b("File "+h+" is empty."))};try{f.send(null)}catch(d){b(d.message)}};this.isFile=function(h,b){l.getFileSize(h,function(f){b(-1!==f)})};this.getFileSize=function(h,b){var f=new XMLHttpRequest;f.open("HEAD",h,!0);f.onreadystatechange=function(){if(4===f.readyState){var d=f.getResponseHeader("Content-Length");d?b(parseInt(d,10)):b(-1)}};f.send(null)};this.log=k;this.assert= -function(h,b,f){if(!h)throw k("alert","ASSERTION FAILED:\n"+b),f&&f(),b;};this.setTimeout=function(h,b){setTimeout(function(){h()},b)};this.libraryPaths=function(){return["lib"]};this.setCurrentDirectory=function(h){};this.type=function(){return"BrowserRuntime"};this.getDOMImplementation=function(){return window.document.implementation};this.parseXML=function(h){return(new DOMParser).parseFromString(h,"text/xml")};this.exit=function(h){k("Calling exit with code "+String(h)+", but exit() is not implemented.")}; -this.getWindow=function(){return window};this.getNetwork=function(){var h=this.getVariable("now");return void 0===h?{networkStatus:"unavailable"}:h}} -function NodeJSRuntime(){function e(b,d,a){b=p.resolve(r,b);"binary"!==d?l.readFile(b,d,a):l.readFile(b,null,a)}var k=this,l=require("fs"),p=require("path"),r="",h,b;this.ByteArray=function(b){return new Buffer(b)};this.byteArrayFromArray=function(b){var d=new Buffer(b.length),a,n=b.length;for(a=0;a<n;a+=1)d[a]=b[a];return d};this.concatByteArrays=function(b,d){var a=new Buffer(b.length+d.length);b.copy(a,0,0);d.copy(a,b.length,0);return a};this.byteArrayFromString=function(b,d){return new Buffer(b, -d)};this.byteArrayToString=function(b,d){return b.toString(d)};this.getVariable=Runtime.getVariable;this.fromJson=Runtime.fromJson;this.toJson=Runtime.toJson;this.readFile=e;this.loadXML=function(b,d){e(b,"utf-8",function(a,b){if(a)return d(a);d(null,k.parseXML(b))})};this.writeFile=function(b,d,a){b=p.resolve(r,b);l.writeFile(b,d,"binary",function(b){a(b||null)})};this.deleteFile=function(b,d){b=p.resolve(r,b);l.unlink(b,d)};this.read=function(b,d,a,n){b=p.resolve(r,b);l.open(b,"r+",666,function(b, -g){if(b)n(b);else{var c=new Buffer(a);l.read(g,c,0,a,d,function(a,b){l.close(g);n(a,c)})}})};this.readFileSync=function(b,d){return d?"binary"===d?l.readFileSync(b,null):l.readFileSync(b,d):""};this.isFile=function(b,d){b=p.resolve(r,b);l.stat(b,function(a,b){d(!a&&b.isFile())})};this.getFileSize=function(b,d){b=p.resolve(r,b);l.stat(b,function(a,b){a?d(-1):d(b.size)})};this.log=function(b,d){var a;void 0!==d?a=b:d=b;"alert"===a&&process.stderr.write("\n!!!!! ALERT !!!!!\n");process.stderr.write(d+ -"\n");"alert"===a&&process.stderr.write("!!!!! ALERT !!!!!\n")};this.assert=function(b,d,a){b||(process.stderr.write("ASSERTION FAILED: "+d),a&&a())};this.setTimeout=function(b,d){setTimeout(function(){b()},d)};this.libraryPaths=function(){return[__dirname]};this.setCurrentDirectory=function(b){r=b};this.currentDirectory=function(){return r};this.type=function(){return"NodeJSRuntime"};this.getDOMImplementation=function(){return b};this.parseXML=function(b){return h.parseFromString(b,"text/xml")}; -this.exit=process.exit;this.getWindow=function(){return null};this.getNetwork=function(){return{networkStatus:"unavailable"}};h=new (require("xmldom").DOMParser);b=k.parseXML("<a/>").implementation} -function RhinoRuntime(){function e(b,f){var d;void 0!==f?d=b:f=b;"alert"===d&&print("\n!!!!! ALERT !!!!!");print(f);"alert"===d&&print("!!!!! ALERT !!!!!")}var k=this,l=Packages.javax.xml.parsers.DocumentBuilderFactory.newInstance(),p,r,h="";l.setValidating(!1);l.setNamespaceAware(!0);l.setExpandEntityReferences(!1);l.setSchema(null);r=Packages.org.xml.sax.EntityResolver({resolveEntity:function(b,f){var d=new Packages.java.io.FileReader(f);return new Packages.org.xml.sax.InputSource(d)}});p=l.newDocumentBuilder(); -p.setEntityResolver(r);this.ByteArray=function(b){return[b]};this.byteArrayFromArray=function(b){return b};this.byteArrayFromString=function(b,f){var d=[],a,n=b.length;for(a=0;a<n;a+=1)d[a]=b.charCodeAt(a)&255;return d};this.byteArrayToString=Runtime.byteArrayToString;this.getVariable=Runtime.getVariable;this.fromJson=Runtime.fromJson;this.toJson=Runtime.toJson;this.concatByteArrays=function(b,f){return b.concat(f)};this.loadXML=function(b,f){var d=new Packages.java.io.File(b),a;try{a=p.parse(d)}catch(n){print(n); -f(n);return}f(null,a)};this.readFile=function(b,f,d){h&&(b=h+"/"+b);var a=new Packages.java.io.File(b),n="binary"===f?"latin1":f;a.isFile()?(b=readFile(b,n),"binary"===f&&(b=k.byteArrayFromString(b,"binary")),d(null,b)):d(b+" is not a file.")};this.writeFile=function(b,f,d){h&&(b=h+"/"+b);b=new Packages.java.io.FileOutputStream(b);var a,n=f.length;for(a=0;a<n;a+=1)b.write(f[a]);b.close();d(null)};this.deleteFile=function(b,f){h&&(b=h+"/"+b);(new Packages.java.io.File(b))["delete"]()?f(null):f("Could not delete "+ -b)};this.read=function(b,f,d,a){h&&(b=h+"/"+b);var n;n=b;var q="binary";(new Packages.java.io.File(n)).isFile()?("binary"===q&&(q="latin1"),n=readFile(n,q)):n=null;n?a(null,this.byteArrayFromString(n.substring(f,f+d),"binary")):a("Cannot read "+b)};this.readFileSync=function(b,f){return f?readFile(b,f):""};this.isFile=function(b,f){h&&(b=h+"/"+b);var d=new Packages.java.io.File(b);f(d.isFile())};this.getFileSize=function(b,f){h&&(b=h+"/"+b);var d=new Packages.java.io.File(b);f(d.length())};this.log= -e;this.assert=function(b,f,d){b||(e("alert","ASSERTION FAILED: "+f),d&&d())};this.setTimeout=function(b,f){b()};this.libraryPaths=function(){return["lib"]};this.setCurrentDirectory=function(b){h=b};this.currentDirectory=function(){return h};this.type=function(){return"RhinoRuntime"};this.getDOMImplementation=function(){return p.getDOMImplementation()};this.parseXML=function(b){return p.parse(b)};this.exit=quit;this.getWindow=function(){return null};this.getNetwork=function(){return{networkStatus:"unavailable"}}} -var runtime=function(){return"undefined"!==String(typeof window)?new BrowserRuntime(window.document.getElementById("logoutput")):"undefined"!==String(typeof require)?new NodeJSRuntime:new RhinoRuntime}(); -(function(){function e(e){var k=e[0],h;h=eval("if (typeof "+k+" === 'undefined') {eval('"+k+" = {};');}"+k);for(k=1;k<e.length-1;k+=1)h=h.hasOwnProperty(e[k])?h[e[k]]:h[e[k]]={};return h[e[e.length-1]]}var k={},l={};runtime.loadClass=function(p){function r(b){b=b.replace(/\./g,"/")+".js";var a=runtime.libraryPaths(),n,q,g;runtime.currentDirectory&&a.push(runtime.currentDirectory());for(n=0;n<a.length;n+=1){q=a[n];if(!l.hasOwnProperty(q))try{g=runtime.readFileSync(a[n]+"/manifest.js","utf8"),l[q]= -g&&g.length?eval(g):null}catch(c){l[q]=null,runtime.log("Cannot load manifest for "+q+".")}g=null;if((q=l[q])&&q.indexOf&&-1!==q.indexOf(b))return a[n]+"/"+b}return null}function h(b){var a,n;n=r(b);if(!n)throw b+" is not listed in any manifest.js.";try{a=runtime.readFileSync(n,"utf8")}catch(q){throw runtime.log("Error loading "+b+" "+q),q;}if(void 0===a)throw"Cannot load class "+b;a=a+("\n//# sourceURL="+n)+("\n//@ sourceURL="+n);try{a=eval(b+" = eval(code);")}catch(g){throw runtime.log("Error loading "+ -b+" "+g),g;}return a}if(!IS_COMPILED_CODE&&!k.hasOwnProperty(p)){var b=p.split("."),f;f=e(b);if(!f&&(f=h(p),!f||Runtime.getFunctionName(f)!==b[b.length-1]))throw runtime.log("Loaded code is not for "+b[b.length-1]),"Loaded code is not for "+b[b.length-1];k[p]=!0}}})(); -(function(e){function k(e){if(e.length){var k=e[0];runtime.readFile(k,"utf8",function(r,h){function b(){var a;(a=eval(d))&&runtime.exit(a)}var f="";runtime.libraryPaths();var d=h;-1!==k.indexOf("/")&&(f=k.substring(0,k.indexOf("/")));runtime.setCurrentDirectory(f);r||null===d?(runtime.log(r),runtime.exit(1)):b.apply(null,e)})}}e=e?Array.prototype.slice.call(e):[];"NodeJSRuntime"===runtime.type()?k(process.argv.slice(2)):"RhinoRuntime"===runtime.type()?k(e):k(e.slice(1))})("undefined"!==String(typeof arguments)&& -arguments); -// Input 2 -core.Base64=function(){function e(a){var c=[],b,m=a.length;for(b=0;b<m;b+=1)c[b]=a.charCodeAt(b)&255;return c}function k(a){var c,b="",m,g=a.length-2;for(m=0;m<g;m+=3)c=a[m]<<16|a[m+1]<<8|a[m+2],b+=u[c>>>18],b+=u[c>>>12&63],b+=u[c>>>6&63],b+=u[c&63];m===g+1?(c=a[m]<<4,b+=u[c>>>6],b+=u[c&63],b+="=="):m===g&&(c=a[m]<<10|a[m+1]<<2,b+=u[c>>>12],b+=u[c>>>6&63],b+=u[c&63],b+="=");return b}function l(a){a=a.replace(/[^A-Za-z0-9+\/]+/g,"");var b=[],c=a.length%4,m,g=a.length,q;for(m=0;m<g;m+=4)q=(t[a.charAt(m)]|| -0)<<18|(t[a.charAt(m+1)]||0)<<12|(t[a.charAt(m+2)]||0)<<6|(t[a.charAt(m+3)]||0),b.push(q>>16,q>>8&255,q&255);b.length-=[0,0,2,1][c];return b}function p(a){var b=[],c,m=a.length,g;for(c=0;c<m;c+=1)g=a[c],128>g?b.push(g):2048>g?b.push(192|g>>>6,128|g&63):b.push(224|g>>>12&15,128|g>>>6&63,128|g&63);return b}function r(a){var b=[],c,m=a.length,g,q,s;for(c=0;c<m;c+=1)g=a[c],128>g?b.push(g):(c+=1,q=a[c],224>g?b.push((g&31)<<6|q&63):(c+=1,s=a[c],b.push((g&15)<<12|(q&63)<<6|s&63)));return b}function h(a){return k(e(a))} -function b(a){return String.fromCharCode.apply(String,l(a))}function f(a){return r(e(a))}function d(a){a=r(a);for(var c="",b=0;b<a.length;)c+=String.fromCharCode.apply(String,a.slice(b,b+45E3)),b+=45E3;return c}function a(a,b,c){var m="",g,q,s;for(s=b;s<c;s+=1)b=a.charCodeAt(s)&255,128>b?m+=String.fromCharCode(b):(s+=1,g=a.charCodeAt(s)&255,224>b?m+=String.fromCharCode((b&31)<<6|g&63):(s+=1,q=a.charCodeAt(s)&255,m+=String.fromCharCode((b&15)<<12|(g&63)<<6|q&63)));return m}function n(b,c){function m(){var d= -s+g;d>b.length&&(d=b.length);q+=a(b,s,d);s=d;d=s===b.length;c(q,d)&&!d&&runtime.setTimeout(m,0)}var g=1E5,q="",s=0;b.length<g?c(a(b,0,b.length),!0):("string"!==typeof b&&(b=b.slice()),m())}function q(a){return p(e(a))}function g(a){return String.fromCharCode.apply(String,p(a))}function c(a){return String.fromCharCode.apply(String,p(e(a)))}var u="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";(function(){var a=[],b;for(b=0;26>b;b+=1)a.push(65+b);for(b=0;26>b;b+=1)a.push(97+b);for(b= -0;10>b;b+=1)a.push(48+b);a.push(43);a.push(47);return a})();var t=function(a){var b={},c,m;c=0;for(m=a.length;c<m;c+=1)b[a.charAt(c)]=c;return b}(u),s,m,A=runtime.getWindow(),x,v;A&&A.btoa?(x=function(a){return A.btoa(a)},s=function(a){return x(c(a))}):(x=h,s=function(a){return k(q(a))});A&&A.atob?(v=function(a){return A.atob(a)},m=function(b){b=v(b);return a(b,0,b.length)}):(v=b,m=function(a){return d(l(a))});return function(){this.convertByteArrayToBase64=this.convertUTF8ArrayToBase64=k;this.convertBase64ToByteArray= -this.convertBase64ToUTF8Array=l;this.convertUTF16ArrayToByteArray=this.convertUTF16ArrayToUTF8Array=p;this.convertByteArrayToUTF16Array=this.convertUTF8ArrayToUTF16Array=r;this.convertUTF8StringToBase64=h;this.convertBase64ToUTF8String=b;this.convertUTF8StringToUTF16Array=f;this.convertByteArrayToUTF16String=this.convertUTF8ArrayToUTF16String=d;this.convertUTF8StringToUTF16String=n;this.convertUTF16StringToByteArray=this.convertUTF16StringToUTF8Array=q;this.convertUTF16ArrayToUTF8String=g;this.convertUTF16StringToUTF8String= -c;this.convertUTF16StringToBase64=s;this.convertBase64ToUTF16String=m;this.fromBase64=b;this.toBase64=h;this.atob=v;this.btoa=x;this.utob=c;this.btou=n;this.encode=s;this.encodeURI=function(a){return s(a).replace(/[+\/]/g,function(a){return"+"===a?"-":"_"}).replace(/\\=+$/,"")};this.decode=function(a){return m(a.replace(/[\-_]/g,function(a){return"-"===a?"+":"/"}))}}}(); -// Input 3 -core.RawDeflate=function(){function e(){this.dl=this.fc=0}function k(){this.extra_bits=this.static_tree=this.dyn_tree=null;this.max_code=this.max_length=this.elems=this.extra_base=0}function l(a,b,c,m){this.good_length=a;this.max_lazy=b;this.nice_length=c;this.max_chain=m}function p(){this.next=null;this.len=0;this.ptr=[];this.ptr.length=r;this.off=0}var r=8192,h,b,f,d,a=null,n,q,g,c,u,t,s,m,A,x,v,w,P,B,E,O,y,J,C,D,G,X,Q,F,K,H,U,Z,W,L,I,M,S,T,R,N,V,z,ca,$,Y,da,aa,la,sa,ga,ia,ea,ha,ma,ta,ua=[0,0,0, -0,0,0,0,0,1,1,1,1,2,2,2,2,3,3,3,3,4,4,4,4,5,5,5,5,0],ja=[0,0,0,0,1,1,2,2,3,3,4,4,5,5,6,6,7,7,8,8,9,9,10,10,11,11,12,12,13,13],Ka=[0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,3,7],ya=[16,17,18,0,8,7,9,6,10,5,11,4,12,3,13,2,14,1,15],na;na=[new l(0,0,0,0),new l(4,4,8,4),new l(4,5,16,8),new l(4,6,32,32),new l(4,4,16,16),new l(8,16,32,32),new l(8,16,128,128),new l(8,32,128,256),new l(32,128,258,1024),new l(32,258,258,4096)];var oa=function(c){a[q+n++]=c;if(q+n===r){var m;if(0!==n){null!==h?(c=h,h=h.next):c=new p; -c.next=null;c.len=c.off=0;null===b?b=f=c:f=f.next=c;c.len=n-q;for(m=0;m<c.len;m++)c.ptr[m]=a[q+m];n=q=0}}},pa=function(b){b&=65535;q+n<r-2?(a[q+n++]=b&255,a[q+n++]=b>>>8):(oa(b&255),oa(b>>>8))},qa=function(){v=(v<<5^c[y+3-1]&255)&8191;w=s[32768+v];s[y&32767]=w;s[32768+v]=y},ba=function(a,b){A>16-b?(m|=a<<A,pa(m),m=a>>16-A,A+=b-16):(m|=a<<A,A+=b)},fa=function(a,b){ba(b[a].fc,b[a].dl)},za=function(a,b,c){return a[b].fc<a[c].fc||a[b].fc===a[c].fc&&V[b]<=V[c]},Aa=function(a,b,c){var m;for(m=0;m<c&&ta< -ma.length;m++)a[b+m]=ma.charCodeAt(ta++)&255;return m},va=function(){var a,b,m=65536-D-y;if(-1===m)m--;else if(65274<=y){for(a=0;32768>a;a++)c[a]=c[a+32768];J-=32768;y-=32768;x-=32768;for(a=0;8192>a;a++)b=s[32768+a],s[32768+a]=32768<=b?b-32768:0;for(a=0;32768>a;a++)b=s[a],s[a]=32768<=b?b-32768:0;m+=32768}C||(a=Aa(c,y+D,m),0>=a?C=!0:D+=a)},Ba=function(a){var b=G,m=y,g,q=O,d=32506<y?y-32506:0,t=y+258,n=c[m+q-1],e=c[m+q];O>=F&&(b>>=2);do if(g=a,c[g+q]===e&&c[g+q-1]===n&&c[g]===c[m]&&c[++g]===c[m+1]){m+= -2;g++;do++m;while(c[m]===c[++g]&&c[++m]===c[++g]&&c[++m]===c[++g]&&c[++m]===c[++g]&&c[++m]===c[++g]&&c[++m]===c[++g]&&c[++m]===c[++g]&&c[++m]===c[++g]&&m<t);g=258-(t-m);m=t-258;if(g>q){J=a;q=g;if(258<=g)break;n=c[m+q-1];e=c[m+q]}}while((a=s[a&32767])>d&&0!==--b);return q},ka=function(a,b){t[aa++]=b;0===a?K[b].fc++:(a--,K[z[b]+256+1].fc++,H[(256>a?ca[a]:ca[256+(a>>7)])&255].fc++,u[la++]=a,ga|=ia);ia<<=1;0===(aa&7)&&(da[sa++]=ga,ga=0,ia=1);if(2<Q&&0===(aa&4095)){var c=8*aa,m=y-x,g;for(g=0;30>g;g++)c+= -H[g].fc*(5+ja[g]);c>>=3;if(la<parseInt(aa/2,10)&&c<parseInt(m/2,10))return!0}return 8191===aa||8192===la},wa=function(a,b){for(var c=T[b],m=b<<1;m<=R;){m<R&&za(a,T[m+1],T[m])&&m++;if(za(a,c,T[m]))break;T[b]=T[m];b=m;m<<=1}T[b]=c},Ca=function(a,b){var c=0;do c|=a&1,a>>=1,c<<=1;while(0<--b);return c>>1},Da=function(a,b){var c=[];c.length=16;var m=0,g;for(g=1;15>=g;g++)m=m+S[g-1]<<1,c[g]=m;for(m=0;m<=b;m++)g=a[m].dl,0!==g&&(a[m].fc=Ca(c[g]++,g))},xa=function(a){var b=a.dyn_tree,c=a.static_tree,m=a.elems, -g,q=-1,s=m;R=0;N=573;for(g=0;g<m;g++)0!==b[g].fc?(T[++R]=q=g,V[g]=0):b[g].dl=0;for(;2>R;)g=T[++R]=2>q?++q:0,b[g].fc=1,V[g]=0,ea--,null!==c&&(ha-=c[g].dl);a.max_code=q;for(g=R>>1;1<=g;g--)wa(b,g);do g=T[1],T[1]=T[R--],wa(b,1),c=T[1],T[--N]=g,T[--N]=c,b[s].fc=b[g].fc+b[c].fc,V[s]=V[g]>V[c]+1?V[g]:V[c]+1,b[g].dl=b[c].dl=s,T[1]=s++,wa(b,1);while(2<=R);T[--N]=T[1];s=a.dyn_tree;g=a.extra_bits;var m=a.extra_base,c=a.max_code,d=a.max_length,t=a.static_tree,n,e,f,u,h=0;for(e=0;15>=e;e++)S[e]=0;s[T[N]].dl= -0;for(a=N+1;573>a;a++)n=T[a],e=s[s[n].dl].dl+1,e>d&&(e=d,h++),s[n].dl=e,n>c||(S[e]++,f=0,n>=m&&(f=g[n-m]),u=s[n].fc,ea+=u*(e+f),null!==t&&(ha+=u*(t[n].dl+f)));if(0!==h){do{for(e=d-1;0===S[e];)e--;S[e]--;S[e+1]+=2;S[d]--;h-=2}while(0<h);for(e=d;0!==e;e--)for(n=S[e];0!==n;)g=T[--a],g>c||(s[g].dl!==e&&(ea+=(e-s[g].dl)*s[g].fc,s[g].fc=e),n--)}Da(b,q)},Ea=function(a,b){var c,m=-1,g,q=a[0].dl,s=0,d=7,n=4;0===q&&(d=138,n=3);a[b+1].dl=65535;for(c=0;c<=b;c++)g=q,q=a[c+1].dl,++s<d&&g===q||(s<n?W[g].fc+=s:0!== -g?(g!==m&&W[g].fc++,W[16].fc++):10>=s?W[17].fc++:W[18].fc++,s=0,m=g,0===q?(d=138,n=3):g===q?(d=6,n=3):(d=7,n=4))},Fa=function(){8<A?pa(m):0<A&&oa(m);A=m=0},Ga=function(a,b){var c,m=0,g=0,q=0,s=0,d,n;if(0!==aa){do 0===(m&7)&&(s=da[q++]),c=t[m++]&255,0===(s&1)?fa(c,a):(d=z[c],fa(d+256+1,a),n=ua[d],0!==n&&(c-=$[d],ba(c,n)),c=u[g++],d=(256>c?ca[c]:ca[256+(c>>7)])&255,fa(d,b),n=ja[d],0!==n&&(c-=Y[d],ba(c,n))),s>>=1;while(m<aa)}fa(256,a)},Ha=function(a,b){var c,m=-1,g,q=a[0].dl,s=0,d=7,n=4;0===q&&(d=138, -n=3);for(c=0;c<=b;c++)if(g=q,q=a[c+1].dl,!(++s<d&&g===q)){if(s<n){do fa(g,W);while(0!==--s)}else 0!==g?(g!==m&&(fa(g,W),s--),fa(16,W),ba(s-3,2)):10>=s?(fa(17,W),ba(s-3,3)):(fa(18,W),ba(s-11,7));s=0;m=g;0===q?(d=138,n=3):g===q?(d=6,n=3):(d=7,n=4)}},Ia=function(){var a;for(a=0;286>a;a++)K[a].fc=0;for(a=0;30>a;a++)H[a].fc=0;for(a=0;19>a;a++)W[a].fc=0;K[256].fc=1;ga=aa=la=sa=ea=ha=0;ia=1},ra=function(a){var b,m,g,q;q=y-x;da[sa]=ga;xa(L);xa(I);Ea(K,L.max_code);Ea(H,I.max_code);xa(M);for(g=18;3<=g&&0=== -W[ya[g]].dl;g--);ea+=3*(g+1)+14;b=ea+3+7>>3;m=ha+3+7>>3;m<=b&&(b=m);if(q+4<=b&&0<=x)for(ba(0+a,3),Fa(),pa(q),pa(~q),g=0;g<q;g++)oa(c[x+g]);else if(m===b)ba(2+a,3),Ga(U,Z);else{ba(4+a,3);q=L.max_code+1;b=I.max_code+1;g+=1;ba(q-257,5);ba(b-1,5);ba(g-4,4);for(m=0;m<g;m++)ba(W[ya[m]].dl,3);Ha(K,q-1);Ha(H,b-1);Ga(K,H)}Ia();0!==a&&Fa()},Ja=function(c,m,g){var s,d,t;for(s=0;null!==b&&s<g;){d=g-s;d>b.len&&(d=b.len);for(t=0;t<d;t++)c[m+s+t]=b.ptr[b.off+t];b.off+=d;b.len-=d;s+=d;0===b.len&&(d=b,b=b.next,d.next= -h,h=d)}if(s===g)return s;if(q<n){d=g-s;d>n-q&&(d=n-q);for(t=0;t<d;t++)c[m+s+t]=a[q+t];q+=d;s+=d;n===q&&(n=q=0)}return s},La=function(a,t,e){var f;if(!d){if(!C){A=m=0;var h,u;if(0===Z[0].dl){L.dyn_tree=K;L.static_tree=U;L.extra_bits=ua;L.extra_base=257;L.elems=286;L.max_length=15;L.max_code=0;I.dyn_tree=H;I.static_tree=Z;I.extra_bits=ja;I.extra_base=0;I.elems=30;I.max_length=15;I.max_code=0;M.dyn_tree=W;M.static_tree=null;M.extra_bits=Ka;M.extra_base=0;M.elems=19;M.max_length=7;for(u=h=M.max_code= -0;28>u;u++)for($[u]=h,f=0;f<1<<ua[u];f++)z[h++]=u;z[h-1]=u;for(u=h=0;16>u;u++)for(Y[u]=h,f=0;f<1<<ja[u];f++)ca[h++]=u;for(h>>=7;30>u;u++)for(Y[u]=h<<7,f=0;f<1<<ja[u]-7;f++)ca[256+h++]=u;for(f=0;15>=f;f++)S[f]=0;for(f=0;143>=f;)U[f++].dl=8,S[8]++;for(;255>=f;)U[f++].dl=9,S[9]++;for(;279>=f;)U[f++].dl=7,S[7]++;for(;287>=f;)U[f++].dl=8,S[8]++;Da(U,287);for(f=0;30>f;f++)Z[f].dl=5,Z[f].fc=Ca(f,5);Ia()}for(f=0;8192>f;f++)s[32768+f]=0;X=na[Q].max_lazy;F=na[Q].good_length;G=na[Q].max_chain;x=y=0;D=Aa(c,0, -65536);if(0>=D)C=!0,D=0;else{for(C=!1;262>D&&!C;)va();for(f=v=0;2>f;f++)v=(v<<5^c[f]&255)&8191}b=null;q=n=0;3>=Q?(O=2,E=0):(E=2,B=0);g=!1}d=!0;if(0===D)return g=!0,0}if((f=Ja(a,t,e))===e)return e;if(g)return f;if(3>=Q)for(;0!==D&&null===b;){qa();0!==w&&32506>=y-w&&(E=Ba(w),E>D&&(E=D));if(3<=E)if(u=ka(y-J,E-3),D-=E,E<=X){E--;do y++,qa();while(0!==--E);y++}else y+=E,E=0,v=c[y]&255,v=(v<<5^c[y+1]&255)&8191;else u=ka(0,c[y]&255),D--,y++;u&&(ra(0),x=y);for(;262>D&&!C;)va()}else for(;0!==D&&null===b;){qa(); -O=E;P=J;E=2;0!==w&&(O<X&&32506>=y-w)&&(E=Ba(w),E>D&&(E=D),3===E&&4096<y-J&&E--);if(3<=O&&E<=O){u=ka(y-1-P,O-3);D-=O-1;O-=2;do y++,qa();while(0!==--O);B=0;E=2;y++;u&&(ra(0),x=y)}else 0!==B?ka(0,c[y-1]&255)&&(ra(0),x=y):B=1,y++,D--;for(;262>D&&!C;)va()}0===D&&(0!==B&&ka(0,c[y-1]&255),ra(1),g=!0);return f+Ja(a,f+t,e-f)};this.deflate=function(m,g){var q,n;ma=m;ta=0;"undefined"===String(typeof g)&&(g=6);(q=g)?1>q?q=1:9<q&&(q=9):q=6;Q=q;C=d=!1;if(null===a){h=b=f=null;a=[];a.length=r;c=[];c.length=65536; -u=[];u.length=8192;t=[];t.length=32832;s=[];s.length=65536;K=[];K.length=573;for(q=0;573>q;q++)K[q]=new e;H=[];H.length=61;for(q=0;61>q;q++)H[q]=new e;U=[];U.length=288;for(q=0;288>q;q++)U[q]=new e;Z=[];Z.length=30;for(q=0;30>q;q++)Z[q]=new e;W=[];W.length=39;for(q=0;39>q;q++)W[q]=new e;L=new k;I=new k;M=new k;S=[];S.length=16;T=[];T.length=573;V=[];V.length=573;z=[];z.length=256;ca=[];ca.length=512;$=[];$.length=29;Y=[];Y.length=30;da=[];da.length=1024}for(var l=Array(1024),p=[];0<(q=La(l,0,l.length));){var G= -[];G.length=q;for(n=0;n<q;n++)G[n]=String.fromCharCode(l[n]);p[p.length]=G.join("")}ma=null;return p.join("")}}; -// Input 4 -core.ByteArray=function(e){this.pos=0;this.data=e;this.readUInt32LE=function(){var e=this.data,l=this.pos+=4;return e[--l]<<24|e[--l]<<16|e[--l]<<8|e[--l]};this.readUInt16LE=function(){var e=this.data,l=this.pos+=2;return e[--l]<<8|e[--l]}}; -// Input 5 -core.ByteArrayWriter=function(e){var k=this,l=new runtime.ByteArray(0);this.appendByteArrayWriter=function(e){l=runtime.concatByteArrays(l,e.getByteArray())};this.appendByteArray=function(e){l=runtime.concatByteArrays(l,e)};this.appendArray=function(e){l=runtime.concatByteArrays(l,runtime.byteArrayFromArray(e))};this.appendUInt16LE=function(e){k.appendArray([e&255,e>>8&255])};this.appendUInt32LE=function(e){k.appendArray([e&255,e>>8&255,e>>16&255,e>>24&255])};this.appendString=function(k){l=runtime.concatByteArrays(l, -runtime.byteArrayFromString(k,e))};this.getLength=function(){return l.length};this.getByteArray=function(){return l}}; -// Input 6 -core.RawInflate=function(){var e,k,l=null,p,r,h,b,f,d,a,n,q,g,c,u,t,s,m=[0,1,3,7,15,31,63,127,255,511,1023,2047,4095,8191,16383,32767,65535],A=[3,4,5,6,7,8,9,10,11,13,15,17,19,23,27,31,35,43,51,59,67,83,99,115,131,163,195,227,258,0,0],x=[0,0,0,0,0,0,0,0,1,1,1,1,2,2,2,2,3,3,3,3,4,4,4,4,5,5,5,5,0,99,99],v=[1,2,3,4,5,7,9,13,17,25,33,49,65,97,129,193,257,385,513,769,1025,1537,2049,3073,4097,6145,8193,12289,16385,24577],w=[0,0,0,0,1,1,2,2,3,3,4,4,5,5,6,6,7,7,8,8,9,9,10,10,11,11,12,12,13,13],P=[16,17,18, -0,8,7,9,6,10,5,11,4,12,3,13,2,14,1,15],B=function(){this.list=this.next=null},E=function(){this.n=this.b=this.e=0;this.t=null},O=function(a,b,c,m,g,q){this.BMAX=16;this.N_MAX=288;this.status=0;this.root=null;this.m=0;var s=Array(this.BMAX+1),d,n,t,e,f,u,h,k=Array(this.BMAX+1),l,p,r,G=new E,A=Array(this.BMAX);e=Array(this.N_MAX);var v,x=Array(this.BMAX+1),C,w,X;X=this.root=null;for(f=0;f<s.length;f++)s[f]=0;for(f=0;f<k.length;f++)k[f]=0;for(f=0;f<A.length;f++)A[f]=null;for(f=0;f<e.length;f++)e[f]= -0;for(f=0;f<x.length;f++)x[f]=0;d=256<b?a[256]:this.BMAX;l=a;p=0;f=b;do s[l[p]]++,p++;while(0<--f);if(s[0]==b)this.root=null,this.status=this.m=0;else{for(u=1;u<=this.BMAX&&0==s[u];u++);h=u;q<u&&(q=u);for(f=this.BMAX;0!=f&&0==s[f];f--);t=f;q>f&&(q=f);for(C=1<<u;u<f;u++,C<<=1)if(0>(C-=s[u])){this.status=2;this.m=q;return}if(0>(C-=s[f]))this.status=2,this.m=q;else{s[f]+=C;x[1]=u=0;l=s;p=1;for(r=2;0<--f;)x[r++]=u+=l[p++];l=a;f=p=0;do 0!=(u=l[p++])&&(e[x[u]++]=f);while(++f<b);b=x[t];x[0]=f=0;l=e;p=0; -e=-1;v=k[0]=0;r=null;for(w=0;h<=t;h++)for(a=s[h];0<a--;){for(;h>v+k[1+e];){v+=k[1+e];e++;w=(w=t-v)>q?q:w;if((n=1<<(u=h-v))>a+1)for(n-=a+1,r=h;++u<w&&!((n<<=1)<=s[++r]);)n-=s[r];v+u>d&&v<d&&(u=d-v);w=1<<u;k[1+e]=u;r=Array(w);for(n=0;n<w;n++)r[n]=new E;X=null==X?this.root=new B:X.next=new B;X.next=null;X.list=r;A[e]=r;0<e&&(x[e]=f,G.b=k[e],G.e=16+u,G.t=r,u=(f&(1<<v)-1)>>v-k[e],A[e-1][u].e=G.e,A[e-1][u].b=G.b,A[e-1][u].n=G.n,A[e-1][u].t=G.t)}G.b=h-v;p>=b?G.e=99:l[p]<c?(G.e=256>l[p]?16:15,G.n=l[p++]): -(G.e=g[l[p]-c],G.n=m[l[p++]-c]);n=1<<h-v;for(u=f>>v;u<w;u+=n)r[u].e=G.e,r[u].b=G.b,r[u].n=G.n,r[u].t=G.t;for(u=1<<h-1;0!=(f&u);u>>=1)f^=u;for(f^=u;(f&(1<<v)-1)!=x[e];)v-=k[e],e--}this.m=k[1];this.status=0!=C&&1!=t?1:0}}},y=function(a){for(;b<a;){var c=h,m;m=t.length==s?-1:t[s++];h=c|m<<b;b+=8}},J=function(a){return h&m[a]},C=function(a){h>>=a;b-=a},D=function(b,m,s){var d,t,h;if(0==s)return 0;for(h=0;;){y(c);t=q.list[J(c)];for(d=t.e;16<d;){if(99==d)return-1;C(t.b);d-=16;y(d);t=t.t[J(d)];d=t.e}C(t.b); -if(16==d)k&=32767,b[m+h++]=e[k++]=t.n;else{if(15==d)break;y(d);a=t.n+J(d);C(d);y(u);t=g.list[J(u)];for(d=t.e;16<d;){if(99==d)return-1;C(t.b);d-=16;y(d);t=t.t[J(d)];d=t.e}C(t.b);y(d);n=k-t.n-J(d);for(C(d);0<a&&h<s;)a--,n&=32767,k&=32767,b[m+h++]=e[k++]=e[n++]}if(h==s)return s}f=-1;return h},G,X=function(a,b,m){var s,d,n,t,f,e,h,k=Array(316);for(s=0;s<k.length;s++)k[s]=0;y(5);e=257+J(5);C(5);y(5);h=1+J(5);C(5);y(4);s=4+J(4);C(4);if(286<e||30<h)return-1;for(d=0;d<s;d++)y(3),k[P[d]]=J(3),C(3);for(;19> -d;d++)k[P[d]]=0;c=7;d=new O(k,19,19,null,null,c);if(0!=d.status)return-1;q=d.root;c=d.m;t=e+h;for(s=n=0;s<t;)if(y(c),f=q.list[J(c)],d=f.b,C(d),d=f.n,16>d)k[s++]=n=d;else if(16==d){y(2);d=3+J(2);C(2);if(s+d>t)return-1;for(;0<d--;)k[s++]=n}else{17==d?(y(3),d=3+J(3),C(3)):(y(7),d=11+J(7),C(7));if(s+d>t)return-1;for(;0<d--;)k[s++]=0;n=0}c=9;d=new O(k,e,257,A,x,c);0==c&&(d.status=1);if(0!=d.status)return-1;q=d.root;c=d.m;for(s=0;s<h;s++)k[s]=k[s+e];u=6;d=new O(k,h,0,v,w,u);g=d.root;u=d.m;return 0==u&& -257<e||0!=d.status?-1:D(a,b,m)};this.inflate=function(m,F){null==e&&(e=Array(65536));b=h=k=0;f=-1;d=!1;a=n=0;q=null;t=m;s=0;var P=new runtime.ByteArray(F);a:{var H,B;for(H=0;H<F&&(!d||-1!=f);){if(0<a){if(0!=f)for(;0<a&&H<F;)a--,n&=32767,k&=32767,P[0+H++]=e[k++]=e[n++];else{for(;0<a&&H<F;)a--,k&=32767,y(8),P[0+H++]=e[k++]=J(8),C(8);0==a&&(f=-1)}if(H==F)break}if(-1==f){if(d)break;y(1);0!=J(1)&&(d=!0);C(1);y(2);f=J(2);C(2);q=null;a=0}switch(f){case 0:B=P;var E=0+H,W=F-H,L=void 0,L=b&7;C(L);y(16);L=J(16); -C(16);y(16);if(L!=(~h&65535))B=-1;else{C(16);a=L;for(L=0;0<a&&L<W;)a--,k&=32767,y(8),B[E+L++]=e[k++]=J(8),C(8);0==a&&(f=-1);B=L}break;case 1:if(null!=q)B=D(P,0+H,F-H);else b:{B=P;E=0+H;W=F-H;if(null==l){for(var I=void 0,L=Array(288),I=void 0,I=0;144>I;I++)L[I]=8;for(;256>I;I++)L[I]=9;for(;280>I;I++)L[I]=7;for(;288>I;I++)L[I]=8;r=7;I=new O(L,288,257,A,x,r);if(0!=I.status){alert("HufBuild error: "+I.status);B=-1;break b}l=I.root;r=I.m;for(I=0;30>I;I++)L[I]=5;G=5;I=new O(L,30,0,v,w,G);if(1<I.status){l= -null;alert("HufBuild error: "+I.status);B=-1;break b}p=I.root;G=I.m}q=l;g=p;c=r;u=G;B=D(B,E,W)}break;case 2:B=null!=q?D(P,0+H,F-H):X(P,0+H,F-H);break;default:B=-1}if(-1==B)break a;H+=B}}t=null;return P}}; -// Input 7 -/* - - Copyright (C) 2012 KO GmbH <copyright@kogmbh.com> - - @licstart - The JavaScript code in this page is free software: you can redistribute it - and/or modify it under the terms of the GNU Affero General Public License - (GNU AGPL) as published by the Free Software Foundation, either version 3 of - the License, or (at your option) any later version. The code is distributed - WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - FITNESS FOR A PARTICULAR PURPOSE. See the GNU AGPL for more details. - - As additional permission under GNU AGPL version 3 section 7, you - may distribute non-source (e.g., minimized or compacted) forms of - that code without the copy of the GNU GPL normally required by - section 4, provided you include this license notice and a URL - through which recipients can access the Corresponding Source. - - As a special exception to the AGPL, any HTML file which merely makes function - calls to this code, and for that purpose includes it by reference shall be - deemed a separate work for copyright law purposes. In addition, the copyright - holders of this code give you permission to combine this code with free - software libraries that are released under the GNU LGPL. You may copy and - distribute such a system following the terms of the GNU AGPL for this code - and the LGPL for the libraries. If you modify this code, you may extend this - exception to your version of the code, but you are not obligated to do so. - If you do not wish to do so, delete this exception statement from your - version. - - This license applies to this entire compilation. - @licend - @source: http://www.webodf.org/ - @source: http://gitorious.org/webodf/webodf/ -*/ -core.LoopWatchDog=function(e,k){var l=Date.now(),p=0;this.check=function(){var r;if(e&&(r=Date.now(),r-l>e))throw runtime.log("alert","watchdog timeout"),"timeout!";if(0<k&&(p+=1,p>k))throw runtime.log("alert","watchdog loop overflow"),"loop overflow";}}; -// Input 8 -core.Cursor=function(e,k){function l(b){b.parentNode&&(a.push({prev:b.previousSibling,next:b.nextSibling}),b.parentNode.removeChild(b))}function p(a,b){a.nodeType===Node.TEXT_NODE&&(0===a.length?a.parentNode.removeChild(a):b.nodeType===Node.TEXT_NODE&&(b.insertData(0,a.data),a.parentNode.removeChild(a)))}function r(){a.forEach(function(a){a.prev&&a.prev.nextSibling&&p(a.prev,a.prev.nextSibling);a.next&&a.next.previousSibling&&p(a.next.previousSibling,a.next)});a.length=0}function h(b,c,q){if(c.nodeType=== -Node.TEXT_NODE){runtime.assert(Boolean(c),"putCursorIntoTextNode: invalid container");var d=c.parentNode;runtime.assert(Boolean(d),"putCursorIntoTextNode: container without parent");runtime.assert(0<=q&&q<=c.length,"putCursorIntoTextNode: offset is out of bounds");0===q?d.insertBefore(b,c):(q!==c.length&&c.splitText(q),d.insertBefore(b,c.nextSibling))}else if(c.nodeType===Node.ELEMENT_NODE){runtime.assert(Boolean(c),"putCursorIntoContainer: invalid container");for(d=c.firstChild;null!==d&&0<q;)d= -d.nextSibling,q-=1;c.insertBefore(b,d)}a.push({prev:b.previousSibling,next:b.nextSibling})}var b=e.createElementNS("urn:webodf:names:cursor","cursor"),f=e.createElementNS("urn:webodf:names:cursor","anchor"),d,a=[],n,q;this.getNode=function(){return b};this.getAnchorNode=function(){return f.parentNode?f:b};this.getSelectedRange=function(){q?(n.setStartBefore(b),n.collapse(!0)):(n.setStartAfter(d?f:b),n.setEndBefore(d?b:f));return n};this.setSelectedRange=function(a,c){n&&n!==a&&n.detach();n=a;d=!1!== -c;(q=a.collapsed)?(l(f),l(b),h(b,a.startContainer,a.startOffset)):(l(f),l(b),h(d?b:f,a.endContainer,a.endOffset),h(d?f:b,a.startContainer,a.startOffset));r()};this.remove=function(){l(b);r()};b.setAttributeNS("urn:webodf:names:cursor","memberId",k);f.setAttributeNS("urn:webodf:names:cursor","memberId",k)}; -// Input 9 -/* - - Copyright (C) 2013 KO GmbH <copyright@kogmbh.com> - - @licstart - The JavaScript code in this page is free software: you can redistribute it - and/or modify it under the terms of the GNU Affero General Public License - (GNU AGPL) as published by the Free Software Foundation, either version 3 of - the License, or (at your option) any later version. The code is distributed - WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - FITNESS FOR A PARTICULAR PURPOSE. See the GNU AGPL for more details. - - As additional permission under GNU AGPL version 3 section 7, you - may distribute non-source (e.g., minimized or compacted) forms of - that code without the copy of the GNU GPL normally required by - section 4, provided you include this license notice and a URL - through which recipients can access the Corresponding Source. - - As a special exception to the AGPL, any HTML file which merely makes function - calls to this code, and for that purpose includes it by reference shall be - deemed a separate work for copyright law purposes. In addition, the copyright - holders of this code give you permission to combine this code with free - software libraries that are released under the GNU LGPL. You may copy and - distribute such a system following the terms of the GNU AGPL for this code - and the LGPL for the libraries. If you modify this code, you may extend this - exception to your version of the code, but you are not obligated to do so. - If you do not wish to do so, delete this exception statement from your - version. - - This license applies to this entire compilation. - @licend - @source: http://www.webodf.org/ - @source: http://gitorious.org/webodf/webodf/ -*/ -core.EventNotifier=function(e){var k={};this.emit=function(e,p){var r,h;runtime.assert(k.hasOwnProperty(e),'unknown event fired "'+e+'"');h=k[e];for(r=0;r<h.length;r+=1)h[r](p)};this.subscribe=function(e,p){runtime.assert(k.hasOwnProperty(e),'tried to subscribe to unknown event "'+e+'"');k[e].push(p);runtime.log('event "'+e+'" subscribed.')};this.unsubscribe=function(e,p){var r;runtime.assert(k.hasOwnProperty(e),'tried to unsubscribe from unknown event "'+e+'"');r=k[e].indexOf(p);runtime.assert(-1!== -r,'tried to unsubscribe unknown callback from event "'+e+'"');-1!==r&&k[e].splice(r,1);runtime.log('event "'+e+'" unsubscribed.')};(function(){var l;for(l=0;l<e.length;l+=1)k[e[l]]=[]})()}; -// Input 10 -core.UnitTest=function(){};core.UnitTest.prototype.setUp=function(){};core.UnitTest.prototype.tearDown=function(){};core.UnitTest.prototype.description=function(){};core.UnitTest.prototype.tests=function(){};core.UnitTest.prototype.asyncTests=function(){}; -core.UnitTest.provideTestAreaDiv=function(){var e=runtime.getWindow().document,k=e.getElementById("testarea");runtime.assert(!k,'Unclean test environment, found a div with id "testarea".');k=e.createElement("div");k.setAttribute("id","testarea");e.body.appendChild(k);return k}; -core.UnitTest.cleanupTestAreaDiv=function(){var e=runtime.getWindow().document,k=e.getElementById("testarea");runtime.assert(!!k&&k.parentNode===e.body,'Test environment broken, found no div with id "testarea" below body.');e.body.removeChild(k)}; -core.UnitTestRunner=function(){function e(d){b+=1;runtime.log("fail",d)}function k(b,a){var n;try{if(b.length!==a.length)return e("array of length "+b.length+" should be "+a.length+" long"),!1;for(n=0;n<b.length;n+=1)if(b[n]!==a[n])return e(b[n]+" should be "+a[n]+" at array index "+n),!1}catch(q){return!1}return!0}function l(b,a,n){var q=b.attributes,g=q.length,c,f,t;for(c=0;c<g;c+=1)if(f=q.item(c),"xmlns"!==f.prefix){t=a.getAttributeNS(f.namespaceURI,f.localName);if(!a.hasAttributeNS(f.namespaceURI, -f.localName))return e("Attribute "+f.localName+" with value "+f.value+" was not present"),!1;if(t!==f.value)return e("Attribute "+f.localName+" was "+t+" should be "+f.value),!1}return n?!0:l(a,b,!0)}function p(b,a){if(b.nodeType!==a.nodeType)return e(b.nodeType+" should be "+a.nodeType),!1;if(b.nodeType===Node.TEXT_NODE)return b.data===a.data;runtime.assert(b.nodeType===Node.ELEMENT_NODE,"Only textnodes and elements supported.");if(b.namespaceURI!==a.namespaceURI||b.localName!==a.localName)return e(b.namespaceURI+ -" should be "+a.namespaceURI),!1;if(!l(b,a,!1))return!1;for(var n=b.firstChild,q=a.firstChild;n;){if(!q||!p(n,q))return!1;n=n.nextSibling;q=q.nextSibling}return q?!1:!0}function r(b,a){return 0===a?b===a&&1/b===1/a:b===a?!0:"number"===typeof a&&isNaN(a)?"number"===typeof b&&isNaN(b):Object.prototype.toString.call(a)===Object.prototype.toString.call([])?k(b,a):"object"===typeof a&&"object"===typeof b?a.constructor===Element||a.constructor===Node?p(a,b):f(a,b):!1}function h(b,a,n){"string"===typeof a&&
View file
roundcubemail-plugins-kolab-3.2.3.tar.gz/plugins/tasklist/composer.json -> roundcubemail-plugins-kolab-3.2.4.tar.gz/plugins/tasklist/composer.json
Changed
@@ -21,7 +21,7 @@ "require": { "php": ">=5.3.0", "roundcube/plugin-installer": ">=0.1.3", - "kolab/libcalendaring": ">=3.2.3", + "kolab/libcalendaring": ">=3.2.4", "roundcube/jqueryui": ">=1.10.4" } }
View file
roundcubemail-plugins-kolab-3.2.3.tar.gz/plugins/tasklist/drivers/database/tasklist_database_driver.php -> roundcubemail-plugins-kolab-3.2.4.tar.gz/plugins/tasklist/drivers/database/tasklist_database_driver.php
Changed
@@ -770,7 +770,7 @@ // convert legacy alarms data else if (strlen($alarms)) { list($trigger, $action) = explode(':', $alarms, 2); - if ($trigger = libcalendaring::parse_alaram_value($trigger)) { + if ($trigger = libcalendaring::parse_alarm_value($trigger)) { $valarms = array(array('action' => $action, 'trigger' => $trigger[3] ?: $trigger[0])); } }
View file
roundcubemail-plugins-kolab-3.2.3.tar.gz/plugins/tasklist/skins/larry/tasklist.css -> roundcubemail-plugins-kolab-3.2.4.tar.gz/plugins/tasklist/skins/larry/tasklist.css
Changed
@@ -903,7 +903,7 @@ } #taskedit .edit-attendees-table tbody td { - padding: 4px 7px; + padding: 5px 7px 6px; } #taskedit .edit-attendees-table tbody tr:last-child td { @@ -955,7 +955,15 @@ white-space: nowrap; overflow: hidden; text-overflow: ellipsis; +} + +#taskedit .edit-attendees-table td.name .attendee-name { + display: block; position: relative; + overflow: hidden; + text-overflow: ellipsis; + padding: 5px 7px 6px 4px; + margin: -5px -7px -6px; } #taskedit .edit-attendees-table td.name select {
View file
roundcubemail-plugins-kolab-3.2.3.tar.gz/plugins/tasklist/tasklist.js -> roundcubemail-plugins-kolab-3.2.4.tar.gz/plugins/tasklist/tasklist.js
Changed
@@ -1720,7 +1720,7 @@ rcmail.gettext('expandattendeegroup','libcalendaring') + '</a>'; } - var html = '<td class="name">' + dispname + '</td>' + + var html = '<td class="name"><span class="attendee-name">' + dispname + '</span></td>' + '<td class="confirmstate"><span class="' + String(data.status).toLowerCase() + '" title="' + Q(tooltip) + '">' + Q(data.status || '') + '</span></td>' + (data.cutype != 'RESOURCE' ? '<td class="invite">' + (readonly || !invbox ? '' : invbox) + '</td>' : '') + '<td class="options">' + (readonly ? '' : dellink) + '</td>'; @@ -1736,7 +1736,7 @@ tr.find('a.deletelink').click({ id:(data.email || data.name) }, function(e) { remove_attendee(this, e.data.id); return false; }); tr.find('a.mailtolink').click(task_attendee_click); - tr.find('a.expandlink').click(data, function(e) { me.expand_attendee_group(e, add_attendee, remove_attendee); }); + tr.find('a.expandlink').click(data, function(e) { me.expand_attendee_group(e, add_attendee, remove_attendee); return false; }); tr.find('input.edit-attendee-reply').click(function() { var enabled = $('#edit-attendees-invite:checked').length || $('input.edit-attendee-reply:checked').length; $('#taskeditform .attendees-commentbox')[enabled ? 'show' : 'hide']();
View file
roundcubemail-plugins-kolab.dsc
Changed
@@ -2,7 +2,7 @@ Source: roundcubemail-plugins-kolab Binary: roundcubemail-plugins-kolab Architecture: all -Version: 1:3.2.3-0~kolab3 +Version: 1:3.2.4-0~kolab1 Maintainer: Christoph Wickert <wickert@kolabsys.com> Uploaders: Jeroen van Meeuwen (Kolab Systems) <vanmeeuwen@kolabsys.com>, Paul Klos <kolab@klos2day.nl> Standards-Version: 3.9.3 @@ -10,5 +10,5 @@ Package-List: roundcubemail-plugins-kolab deb web extra Files: - 00000000000000000000000000000000 0 roundcubemail-plugins-kolab-3.2.3.tar.gz + 00000000000000000000000000000000 0 roundcubemail-plugins-kolab-3.2.4.tar.gz 00000000000000000000000000000000 0 debian.tar.gz
Locations
Projects
Search
Status Monitor
Help
Open Build Service
OBS Manuals
API Documentation
OBS Portal
Reporting a Bug
Contact
Mailing List
Forums
Chat (IRC)
Twitter
Open Build Service (OBS)
is an
openSUSE project
.