/** * This callback function adds a box below the message content * if there is a vcard attachment available */ function html_output($p) { $attach_script = false; $icon = 'plugins/vcard_attachments/' . $this->local_skin_path() . '/vcard_add_contact.png'; foreach ($this->vcard_parts as $part) { $vcards = rcube_vcard::import($this->message->get_part_content($part, null, true)); // successfully parsed vcards? if (empty($vcards)) { continue; } // remove part's body if (in_array($part, $this->vcard_bodies)) { $p['content'] = ''; } foreach ($vcards as $idx => $vcard) { // skip invalid vCards if (empty($vcard->email) || empty($vcard->email[0])) { continue; } $display = $vcard->displayname . ' <' . $vcard->email[0] . '>'; // add box below message body $p['content'] .= html::p(array('class' => 'vcardattachment'), html::a(array('href' => "#", 'onclick' => "return plugin_vcard_save_contact('" . JQ($part . ':' . $idx) . "')", 'title' => $this->gettext('addvcardmsg')), html::span(null, Q($display)))); } $attach_script = true; } if ($attach_script) { $this->include_script('vcardattach.js'); $this->include_stylesheet($this->local_skin_path() . '/style.css'); } return $p; }
/** * This callback function adds a box below the message content * if there is a vcard attachment available */ function html_output($p) { $attach_script = false; $icon = 'plugins/vcard_attachments/' . $this->local_skin_path() . '/vcard_add_contact.png'; foreach ($this->vcard_parts as $part) { $vcards = rcube_vcard::import($this->message->get_part_content($part)); // successfully parsed vcards? if (empty($vcards)) { continue; } // remove part's body if (in_array($part, $this->vcard_bodies)) { $p['content'] = ''; } $style = 'margin:0.5em 1em; padding:0.2em 0.5em; border:1px solid #999; ' . 'border-radius:4px; -moz-border-radius:4px; -webkit-border-radius:4px; width: auto'; foreach ($vcards as $idx => $vcard) { $display = $vcard->displayname; if ($vcard->email[0]) { $display .= ' <' . $vcard->email[0] . '>'; } // add box below messsage body $p['content'] .= html::p(array('style' => $style), html::a(array('href' => "#", 'onclick' => "return plugin_vcard_save_contact('" . JQ($part . ':' . $idx) . "')", 'title' => $this->gettext('addvcardmsg')), html::img(array('src' => $icon, 'style' => "vertical-align:middle"))) . ' ' . html::span(null, Q($display))); } $attach_script = true; } if ($attach_script) { $this->include_script('vcardattach.js'); } return $p; }
/** * This callback function adds a box below the message content * if there is a vcard attachment available */ function html_output($p) { if ($this->vcard_part) { $vcard = new rcube_vcard($this->message->get_part_content($this->vcard_part)); // successfully parsed vcard if ($vcard->displayname) { $display = $vcard->displayname; if ($vcard->email[0]) { $display .= ' <' . $vcard->email[0] . '>'; } // add box below messsage body $p['content'] .= html::p(array('style' => "margin:1em; padding:0.5em; border:1px solid #999; border-radius:4px; -moz-border-radius:4px; -webkit-border-radius:4px; width: auto;"), html::a(array('href' => "#", 'onclick' => "return plugin_vcard_save_contact('" . JQ($this->vcard_part) . "')", 'title' => $this->gettext('addvardmsg')), html::img(array('src' => $this->url('vcard_add_contact.png'), 'align' => "middle"))) . ' ' . html::span(null, Q($display))); $this->include_script('vcardattach.js'); } } return $p; }
/** * Callback function used to build mailto: links around e-mail strings * * @param array Matches result from preg_replace_callback * @return int Index of saved string value */ public function mailto_callback($matches) { $href = $matches[1]; $suffix = $this->parse_url_brackets($href); $i = $this->add(html::a(array('href' => 'mailto:' . $href, 'onclick' => "return " . JS_OBJECT_NAME . ".command('compose','" . JQ($href) . "',this)"), Q($href)) . $suffix); return $i >= 0 ? $this->get_replacement($i) : ''; }
/** * Callback function used to build mailto: links around e-mail strings * * @param array Matches result from preg_replace_callback * @return int Index of saved string value */ public function mailto_callback($matches) { $i = $this->add(html::a(array('href' => 'mailto:' . $matches[1], 'onclick' => "return " . JS_OBJECT_NAME . ".command('compose','" . JQ($matches[1]) . "',this)"), Q($matches[1]))); return $i >= 0 ? $this->get_replacement($i) : ''; }
/** * Add UI element to copy event invitations or updates to the calendar */ public function mail_messagebody_html($p) { // load iCalendar functions (if necessary) if (!empty($this->ics_parts)) { $this->get_ical(); } $html = ''; foreach ($this->ics_parts as $mime_id) { $part = $this->message->mime_parts[$mime_id]; $charset = $part->ctype_parameters['charset'] ? $part->ctype_parameters['charset'] : RCMAIL_CHARSET; $events = $this->ical->import($this->message->get_part_content($mime_id), $charset); $title = $this->gettext('title'); $date = rcube_utils::anytodatetime($this->message->headers->date); // successfully parsed events? if (empty($events)) { continue; } // show a box for every event in the file foreach ($events as $idx => $event) { // Begin mod by Rosali (Google sends the ics inline and attached -> avoid duplicates with same UID - https://issues.kolab.org/show_bug.cgi?id=3585) $uid = $event['uid'] ? $event['uid'] : md5(serialize($event)); if (isset($this->ics_parts_filtered[$uid])) { continue; } $this->ics_parts_filtered[$uid] = 1; // End mod by Rosali if ($event['_type'] != 'event' && $event['_type'] != 'task') { // skip non-event objects (#2928) // Mod by Rosali (don't skip tasks) continue; } // define buttons according to method if ($this->ical->method == 'REPLY') { $driver = $this->get_default_driver(); $existing = $driver->get_event($event['uid']); $calendar_saveto = new html_hiddenfield(array('class' => 'calendar-saveto', 'value' => $existing['calendar'])); // Mod by Rosali (always pass calendar to GUI) if ($calendar_saveto) { $title = $this->gettext('itipreply'); $buttons = html::tag('input', array('type' => 'button', 'class' => 'button', 'onclick' => "rcube_calendar.add_event_from_mail('" . JQ($mime_id . ':' . $idx) . "', this)", 'value' => $this->gettext('updateattendeestatus'))) . $calendar_saveto->show(); } } else { if ($this->ical->method == 'REQUEST') { $emails = $this->get_user_emails(); $title = $event['sequence'] > 0 ? $this->gettext('itipupdate') : $this->gettext('itipinvitation'); // add (hidden) buttons and activate them from asyncronous request foreach (array('accepted', 'tentative', 'declined') as $method) { $rsvp_buttons .= html::tag('input', array('type' => 'button', 'class' => "button {$method}", 'onclick' => "rcube_calendar.add_event_from_mail('" . JQ($mime_id . ':' . $idx) . "', this, '{$method}')", 'value' => $this->gettext('itip' . $method))); } $import_button = html::tag('input', array('type' => 'button', 'class' => 'button', 'onclick' => "rcube_calendar.add_event_from_mail('" . JQ($mime_id . ':' . $idx) . "', this)", 'value' => $this->gettext('importtocalendar'))); // check my status $status = 'unknown'; foreach ($event['attendees'] as $attendee) { if ($attendee['email'] && in_array(strtolower($attendee['email']), $emails)) { $status = !empty($attendee['status']) ? strtoupper($attendee['status']) : 'NEEDS-ACTION'; break; } } $dom_id = asciiwords($event['uid'], true); $buttons = html::div(array('id' => 'rsvp-' . $dom_id, 'style' => 'display:none'), $rsvp_buttons); $buttons .= html::div(array('id' => 'import-' . $dom_id, 'style' => 'display:none'), $import_button); $buttons_pre = html::div(array('id' => 'loading-' . $dom_id, 'class' => 'rsvp-status loading'), $this->gettext('loading')); $changed = is_object($event['changed']) ? $event['changed'] : $date; $script = json_serialize(array('uid' => $event['uid'], 'changed' => $changed ? $changed->format('U') : 0, 'sequence' => intval($event['sequence']), 'fallback' => $status)); $this->rc->output->add_script("rcube_calendar.fetch_event_rsvp_status({$script})", 'docready'); } else { if ($this->ical->method == 'CANCEL') { $title = $this->gettext('itipcancellation'); // create buttons to be activated from async request checking existence of this event in local calendars $button_import = html::tag('input', array('type' => 'button', 'class' => 'button', 'onclick' => "rcube_calendar.add_event_from_mail('" . JQ($mime_id . ':' . $idx) . "', this)", 'value' => $this->gettext('importtocalendar'))); $button_remove = html::tag('input', array('type' => 'button', 'class' => 'button', 'onclick' => "rcube_calendar.remove_event_from_mail('" . JQ($event['uid']) . "', '" . JQ($event['title']) . "')", 'value' => $this->gettext('removefromcalendar'))); $dom_id = asciiwords($event['uid'], true); $buttons = html::div(array('id' => 'rsvp-' . $dom_id, 'style' => 'display:none'), $button_remove); $buttons .= html::div(array('id' => 'import-' . $dom_id, 'style' => 'display:none'), $button_import); $buttons_pre = html::div(array('id' => 'loading-' . $dom_id, 'class' => 'rsvp-status loading'), $this->gettext('loading')); $changed = is_object($event['changed']) ? $event['changed'] : $date; $script = json_serialize(array('uid' => $event['uid'], 'changed' => $changed ? $changed->format('U') : 0, 'sequence' => intval($event['sequence']), 'fallback' => 'CANCELLED')); $this->rc->output->add_script("rcube_calendar.fetch_event_rsvp_status({$script})", 'docready'); } else { // get a list of writeable calendars // Begin mod by Rosali (https://gitlab.awesome-it.de/kolab/roundcube-plugins/issues/33) $driver = $this->get_default_driver(); $calendars = $driver->list_calendars(false, true); $calendar_select = new html_select(array('name' => 'calendar', 'class' => 'calendar-saveto', 'is_escaped' => true)); // Mod by Rosali (calendar selector can exist multiple times - can't be referenced by ID) $numcals = 0; foreach ($calendars as $calendar) { $driver = $this->get_driver_by_cal($calendar['calendar_id']); if ($driver->readonly !== true) { $calendar_select->add($calendar['name'], $calendar['id']); $numcals++; } } } } } if ($numcals > 0) { $buttons = html::tag('input', array('type' => 'button', 'class' => 'button', 'onclick' => "rcube_calendar.add_event_from_mail('" . JQ($mime_id . ':' . $idx) . "', this)", 'value' => $this->gettext('importtocalendar'))) . $calendar_select->show($this->rc->config->get('calendar_default_calendar')); } // show event details with buttons if ($buttons) { $html .= html::div('calendar-invitebox', $this->ui->event_details_table($event, $title) . $buttons_pre . html::div('rsvp-buttons', $buttons)); } // Emd mod by Rosli // limit listing if ($idx >= 3) { break; } } } // prepend event boxes to message body if ($html) { $this->ui->init(); $p['content'] = $html . $p['content']; $this->rc->output->add_label('calendar.savingdata', 'calendar.deleteventconfirm', 'calendar.declinedeleteconfirm'); } return $p; }
private function _gen_addressbooks_list($arrBooks, $command) { $rcmail = rcmail::get_instance(); $groupTotal = 0; $maxlength = 35; $maxlength_grp = 33; $out = ''; // address books foreach ($arrBooks as $j => $source) { $title = null; $id = $source['id'] ? $source['id'] : $j; $bookname = !empty($source['name']) ? Q($source['name']) : Q($id); // shorten the address book name to a given length if ($maxlength && $maxlength > 1) { $bname = abbreviate_string($bookname, $maxlength); if ($bname != $bookname) { $title = $bookname; } $bookname = $bname; } if ($source['readonly']) { $out .= html::tag('li', array('id' => 'rcm_contextaddr_' . $id, 'class' => 'addressbook disabled'), html::a(array('href' => $command, 'id' => 'rcm_contextgrps_' . JQ($id), 'onclick' => "rcm_set_dest_book('" . JQ($id) . "', '" . JQ($id) . "', null)", 'class' => 'active', 'title' => $title), Q($bookname))); } else { $out .= html::tag('li', array('id' => 'rcm_contextaddr_' . $id, 'class' => 'addressbook'), html::a(array('href' => $command, 'id' => 'rcm_contextgrps_' . JQ($id), 'onclick' => "rcm_set_dest_book('" . JQ($id) . "', '" . JQ($id) . "', null)", 'class' => 'active', 'title' => $title), Q($bookname))); } // contact groups if ($source['groups']) { $groups = $rcmail->get_address_book($source['id'])->list_groups(); foreach ($groups as $group) { $title = null; $gid = 'G' . $id . $group['ID']; $groupname = !empty($group['name']) ? Q($group['name']) : Q($gid); // shorten the address book name to a given length if ($maxlength_grp && $maxlength_grp > 1) { $gname = abbreviate_string($groupname, $maxlength_grp); if ($gname != $groupname) { $title = $groupname; } $groupname = $gname; } if ($source['readonly']) { $out .= html::tag('li', array('class' => 'contactgroup disabled'), html::a(array('href' => $command, 'id' => 'rcm_contextgrps_' . JQ($gid), 'onclick' => "rcm_set_dest_book('" . JQ($gid) . "', '" . JQ($id) . "', '" . JQ($group['ID']) . "')", 'class' => 'active', 'title' => $title), Q(' ' . $groupname))); } else { $out .= html::tag('li', array('class' => 'contactgroup'), html::a(array('href' => $command, 'id' => 'rcm_contextgrps_' . JQ($gid), 'onclick' => "rcm_set_dest_book('" . JQ($gid) . "', '" . JQ($id) . "', '" . JQ($group['ID']) . "')", 'class' => 'active', 'title' => $title), Q(' ' . $groupname))); } $groupTotal++; } } $groupTotal++; } if ($groupTotal > 5) { $out = html::tag('ul', array('id' => 'rcm_contextgrps', 'class' => 'toolbarmenu folders scrollable'), $out); $out = html::tag('div', array('class' => 'scroll_up_pas'), '') . $out . html::tag('div', array('class' => 'scroll_down_act'), ''); $out = html::tag('div', array('class' => 'popupmenu'), $out); } else { $out = html::tag('ul', array('id' => 'rcm_contextgrps', 'class' => 'popupmenu toolbarmenu folders'), $out); } return $out; }
/** * Build inline UI elements for iTip messages */ public function mail_itip_inline_ui($event, $method, $mime_id, $task, $message_date = null, $preview_url = null) { $buttons = array(); $dom_id = asciiwords($event['uid'], true); $rsvp_status = 'unknown'; // pass some metadata about the event and trigger the asynchronous status check $changed = is_object($event['changed']) ? $event['changed'] : $message_date; $metadata = array('uid' => $event['uid'], 'changed' => $changed ? $changed->format('U') : 0, 'sequence' => intval($event['sequence']), 'method' => $method, 'task' => $task); // create buttons to be activated from async request checking existence of this event in local calendars $buttons[] = html::div(array('id' => 'loading-' . $dom_id, 'class' => 'rsvp-status loading'), $this->gettext('loading')); // on iTip REPLY we have two options: if ($method == 'REPLY') { $title = $this->gettext('itipreply'); foreach ($event['attendees'] as $attendee) { if (!empty($attendee['email']) && $attendee['role'] != 'ORGANIZER' && (empty($event['_sender']) || ($attendee['email'] == $event['_sender'] || $attendee['email'] == $event['_sender_utf']))) { $metadata['attendee'] = $attendee['email']; $rsvp_status = strtoupper($attendee['status']); if ($attendee['delegated-to']) { $metadata['delegated-to'] = $attendee['delegated-to']; } break; } } // 1. update the attendee status on our copy $update_button = html::tag('input', array('type' => 'button', 'class' => 'button', 'onclick' => "rcube_libcalendaring.add_from_itip_mail('" . JQ($mime_id) . "', '{$task}')", 'value' => $this->gettext('updateattendeestatus'))); // 2. accept or decline a new or delegate attendee $accept_buttons = html::tag('input', array('type' => 'button', 'class' => "button accept", 'onclick' => "rcube_libcalendaring.add_from_itip_mail('" . JQ($mime_id) . "', '{$task}')", 'value' => $this->gettext('acceptattendee'))); $accept_buttons .= html::tag('input', array('type' => 'button', 'class' => "button decline", 'onclick' => "rcube_libcalendaring.decline_attendee_reply('" . JQ($mime_id) . "', '{$task}')", 'value' => $this->gettext('declineattendee'))); $buttons[] = html::div(array('id' => 'update-' . $dom_id, 'style' => 'display:none'), $update_button); $buttons[] = html::div(array('id' => 'accept-' . $dom_id, 'style' => 'display:none'), $accept_buttons); } else { if ($method == 'REQUEST') { $emails = $this->lib->get_user_emails(); $title = $event['sequence'] > 0 ? $this->gettext('itipupdate') : $this->gettext('itipinvitation'); $metadata['rsvp'] = true; $metadata['sensitivity'] = $event['sensitivity']; if (is_object($event['start'])) { $metadata['date'] = $event['start']->format('U'); } // check for X-KOLAB-INVITATIONTYPE property and only show accept/decline buttons if (self::get_custom_property($event, 'X-KOLAB-INVITATIONTYPE') == 'CONFIRMATION') { $this->rsvp_actions = array('accepted', 'declined'); $metadata['nosave'] = true; } // 1. display RSVP buttons (if the user was invited) foreach ($this->rsvp_actions as $method) { $rsvp_buttons .= html::tag('input', array('type' => 'button', 'class' => "button {$method}", 'onclick' => "rcube_libcalendaring.add_from_itip_mail('" . JQ($mime_id) . "', '{$task}', '{$method}', '{$dom_id}')", 'value' => $this->gettext('itip' . $method))); } // add button to open calendar/preview if (!empty($preview_url)) { $msgref = $this->lib->ical_message->folder . '/' . $this->lib->ical_message->uid . '#' . $mime_id; $rsvp_buttons .= html::tag('input', array('type' => 'button', 'class' => "button preview", 'onclick' => "rcube_libcalendaring.open_itip_preview('" . JQ($preview_url) . "', '" . JQ($msgref) . "')", 'value' => $this->gettext('openpreview'))); } // 2. update the local copy with minor changes $update_button = html::tag('input', array('type' => 'button', 'class' => 'button', 'onclick' => "rcube_libcalendaring.add_from_itip_mail('" . JQ($mime_id) . "', '{$task}')", 'value' => $this->gettext('updatemycopy'))); // 3. Simply import the event without replying $import_button = html::tag('input', array('type' => 'button', 'class' => 'button', 'onclick' => "rcube_libcalendaring.add_from_itip_mail('" . JQ($mime_id) . "', '{$task}')", 'value' => $this->gettext('importtocalendar'))); // check my status foreach ($event['attendees'] as $attendee) { if ($attendee['email'] && in_array(strtolower($attendee['email']), $emails)) { $metadata['attendee'] = $attendee['email']; $metadata['rsvp'] = $attendee['rsvp'] || $attendee['role'] != 'NON-PARTICIPANT'; $rsvp_status = !empty($attendee['status']) ? strtoupper($attendee['status']) : 'NEEDS-ACTION'; break; } } // add itip reply message controls $rsvp_buttons .= html::div('itip-reply-controls', $this->itip_rsvp_options_ui($dom_id, $metadata['nosave'])); $buttons[] = html::div(array('id' => 'rsvp-' . $dom_id, 'class' => 'rsvp-buttons', 'style' => 'display:none'), $rsvp_buttons); $buttons[] = html::div(array('id' => 'update-' . $dom_id, 'style' => 'display:none'), $update_button); // prepare autocompletion for delegation dialog if (in_array('delegated', $this->rsvp_actions)) { $this->rc->autocomplete_init(); } } else { if ($method == 'CANCEL') { $title = $this->gettext('itipcancellation'); // 1. remove the event from our calendar $button_remove = html::tag('input', array('type' => 'button', 'class' => 'button', 'onclick' => "rcube_libcalendaring.remove_from_itip('" . JQ($event['uid']) . "', '{$task}', '" . JQ($event['title']) . "')", 'value' => $this->gettext('removefromcalendar'))); // 2. update our copy with status=cancelled $button_update = html::tag('input', array('type' => 'button', 'class' => 'button', 'onclick' => "rcube_libcalendaring.add_from_itip_mail('" . JQ($mime_id) . "', '{$task}')", 'value' => $this->gettext('updatemycopy'))); $buttons[] = html::div(array('id' => 'rsvp-' . $dom_id, 'style' => 'display:none'), $button_remove . $button_update); $rsvp_status = 'CANCELLED'; $metadata['rsvp'] = true; } } } // append generic import button if ($import_button) { $buttons[] = html::div(array('id' => 'import-' . $dom_id, 'style' => 'display:none'), $import_button); } // pass some metadata about the event and trigger the asynchronous status check $metadata['fallback'] = $rsvp_status; $metadata['rsvp'] = intval($metadata['rsvp']); $this->rc->output->add_script("rcube_libcalendaring.fetch_itip_object_status(" . json_serialize($metadata) . ")", 'docready'); // get localized texts from the right domain foreach (array('savingdata', 'deleteobjectconfirm', 'declinedeleteconfirm', 'declineattendee', 'cancel', 'itipdelegated', 'declineattendeeconfirm', 'itipcomment', 'delegateinvitation', 'delegateto', 'delegatersvpme', 'delegateinvalidaddress') as $label) { $this->rc->output->command('add_label', "itip.{$label}", $this->gettext($label)); } // show event details with buttons return $this->itip_object_details_table($event, $title) . html::div(array('class' => 'itip-buttons', 'id' => 'itip-buttons-' . asciiwords($metadata['uid'], true)), join('', $buttons)); }
/** * Handler for template_object_messagebody hook. * This callback function adds a box below the message content * if there is a key/cert attachment available */ function message_output($p) { $attach_script = false; foreach ($this->keys_parts as $part) { // remove part's body if (in_array($part, $this->keys_bodies)) { $p['content'] = ''; } $style = "margin:0 1em; padding:0.2em 0.5em; border:1px solid #999; width: auto" . " border-radius:4px; -moz-border-radius:4px; -webkit-border-radius:4px"; // add box below messsage body $p['content'] .= html::p(array('style' => $style), html::a(array('href' => "#", 'onclick' => "return " . JS_OBJECT_NAME . ".enigma_import_attachment('" . JQ($part) . "')", 'title' => $this->gettext('keyattimport')), html::img(array('src' => $this->url('skins/default/key_add.png'), 'style' => "vertical-align:middle"))) . ' ' . html::span(null, $this->gettext('keyattfound'))); $attach_script = true; } if ($attach_script) { $this->include_script('enigma.js'); } return $p; }
/** * Return executable javascript code for all registered commands * * @return string $out */ private function get_js_commands() { $out = ''; if (sizeof($this->env)) { $out .= 'this.set_env(' . json_serialize($this->env) . ");\n"; } foreach ($this->texts as $name => $text) { $out .= sprintf("this.add_label('%s', '%s');\n", $name, JQ($text)); } foreach ($this->commands as $i => $args) { $method = array_shift($args); foreach ($args as $i => $arg) { $args[$i] = json_serialize($arg); } $out .= sprintf("this.%s(%s);\n", preg_replace('/^parent\\./', '', $method), implode(',', $args)); } return $out; }
/** * Callback function for parsing an xml command tag * and turn it into real html content * * @param array Matches array of preg_replace_callback * @return string Tag/Object content */ private function xml_command($matches) { $command = strtolower($matches[1]); $attrib = parse_attrib_string($matches[2]); // empty output if required condition is not met if (!empty($attrib['condition']) && !$this->check_condition($attrib['condition'])) { return ''; } // execute command switch ($command) { // return a button case 'button': if ($attrib['name'] || $attrib['command']) { return $this->button($attrib); } break; // show a label // show a label case 'label': if ($attrib['name'] || $attrib['command']) { $vars = $attrib + array('product' => $this->config['product_name']); unset($vars['name'], $vars['command']); $label = rcube_label($attrib + array('vars' => $vars)); $quoting = !empty($attrib['quoting']) ? strtolower($attrib['quoting']) : (get_boolean((string) $attrib['html']) ? 'no' : ''); switch ($quoting) { case 'no': case 'raw': break; case 'javascript': case 'js': $label = JQ($label); break; default: $label = Q($label); break; } return !$attrib['noshow'] ? $label : ''; } break; // include a file // include a file case 'include': if (!$this->plugin_skin_path || !is_file($path = realpath($this->plugin_skin_path . $attrib['file']))) { $path = realpath(($attrib['skin_path'] ? $attrib['skin_path'] : $this->config['skin_path']) . $attrib['file']); } if (is_readable($path)) { if ($this->config['skin_include_php']) { $incl = $this->include_php($path); } else { $incl = file_get_contents($path); } $incl = $this->parse_conditions($incl); return $this->parse_xml($incl); } break; case 'plugin.include': $hook = $this->app->plugins->exec_hook("template_plugin_include", $attrib); return $hook['content']; break; // define a container block // define a container block case 'container': if ($attrib['name'] && $attrib['id']) { $this->command('gui_container', $attrib['name'], $attrib['id']); // let plugins insert some content here $hook = $this->app->plugins->exec_hook("template_container", $attrib); return $hook['content']; } break; // return code for a specific application object // return code for a specific application object case 'object': $object = strtolower($attrib['name']); $content = ''; // we are calling a class/method if (($handler = $this->object_handlers[$object]) && is_array($handler)) { if (is_object($handler[0]) && method_exists($handler[0], $handler[1]) || is_string($handler[0]) && class_exists($handler[0])) { $content = call_user_func($handler, $attrib); } } else { if (function_exists($handler)) { $content = call_user_func($handler, $attrib); } else { if ($object == 'doctype') { $content = html::doctype($attrib['value']); } else { if ($object == 'logo') { $attrib += array('alt' => $this->xml_command(array('', 'object', 'name="productname"'))); if ($this->config['skin_logo']) { $attrib['src'] = $this->config['skin_logo']; } $content = html::img($attrib); } else { if ($object == 'productname') { $name = !empty($this->config['product_name']) ? $this->config['product_name'] : 'Roundcube Webmail'; $content = Q($name); } else { if ($object == 'version') { $ver = (string) RCMAIL_VERSION; if (is_file(INSTALL_PATH . '.svn/entries')) { if (preg_match('/Revision:\\s(\\d+)/', @shell_exec('svn info'), $regs)) { $ver .= ' [SVN r' . $regs[1] . ']'; } } else { if (is_file(INSTALL_PATH . '.git/index')) { if (preg_match('/Date:\\s+([^\\n]+)/', @shell_exec('git log -1'), $regs)) { if ($date = date('Ymd.Hi', strtotime($regs[1]))) { $ver .= ' [GIT ' . $date . ']'; } } } } $content = Q($ver); } else { if ($object == 'steptitle') { $content = Q($this->get_pagetitle()); } else { if ($object == 'pagetitle') { if (!empty($this->config['devel_mode']) && !empty($_SESSION['username'])) { $title = $_SESSION['username'] . ' :: '; } else { if (!empty($this->config['product_name'])) { $title = $this->config['product_name'] . ' :: '; } else { $title = ''; } } $title .= $this->get_pagetitle(); $content = Q($title); } } } } } } } } // exec plugin hooks for this template object $hook = $this->app->plugins->exec_hook("template_object_{$object}", $attrib + array('content' => $content)); return $hook['content']; // return code for a specified eval expression // return code for a specified eval expression case 'exp': $value = $this->parse_expression($attrib['expression']); return eval("return Q({$value});"); // return variable // return variable case 'var': $var = explode(':', $attrib['name']); $name = $var[1]; $value = ''; switch ($var[0]) { case 'env': $value = $this->env[$name]; break; case 'config': $value = $this->config[$name]; if (is_array($value) && $value[$_SESSION['storage_host']]) { $value = $value[$_SESSION['storage_host']]; } break; case 'request': $value = get_input_value($name, RCUBE_INPUT_GPC); break; case 'session': $value = $_SESSION[$name]; break; case 'cookie': $value = htmlspecialchars($_COOKIE[$name]); break; case 'browser': $value = $this->browser->{$name}; break; } if (is_array($value)) { $value = implode(', ', $value); } return Q($value); break; } return ''; }