示例#1
0
 public function eventPreSaveFilter(array $context)
 {
     if (!in_array('xss-fail', $context['event']->eParamFILTERS) && !in_array('validate-xsrf', $context['event']->eParamFILTERS)) {
         return;
     }
     $contains_xss = FALSE;
     // Loop over the fields to check for XSS, this loop will
     // break as soon as XSS is detected
     foreach ($context['fields'] as $field => $value) {
         if (is_array($value)) {
             if (self::detectXSSInArray($value) === FALSE) {
                 continue;
             }
             $contains_xss = TRUE;
             break;
         } else {
             if (self::detectXSS($value) === FALSE) {
                 continue;
             }
             $contains_xss = TRUE;
             break;
         }
     }
     // Detect XSS filter
     if (in_array('xss-fail', $context['event']->eParamFILTERS) && $contains_xss === TRUE) {
         $context['messages'][] = array('xss', FALSE, __("Possible XSS attack detected in submitted data"));
     }
     // Validate XSRF token filter
     if (in_array('validate-xsrf', $context['event']->eParamFILTERS)) {
         if (Symphony::Engine()->isXSRFEnabled() && is_session_empty() === false && XSRF::validateRequest(true) === false) {
             $context['messages'][] = array('xsrf', FALSE, __("Request was rejected for having an invalid cross-site request forgery token."));
         }
     }
 }
 public function __viewEdit($new = false)
 {
     $this->setPageType('form');
     $this->setTitle(sprintf(__("Symphony - Newsletter Recipient Groups - %s", array(), false), ucfirst($this->_context[1])));
     $errors = new XMLElement('errors');
     $context = new XMLElement('context');
     General::array_to_xml($context, $this->_context);
     $this->_XML->appendChild($context);
     // Fix for 2.4 and XSRF
     if (Symphony::Configuration()->get("enable_xsrf", "symphony") == "yes" && class_exists('XSRF')) {
         $xsrf_input = new XMLElement('xsrf_input');
         $xsrf_input->appendChild(XSRF::formToken());
         $this->_XML->appendChild($xsrf_input);
     }
     $section_xml = new XMLElement('sections');
     $sectionManager = new SectionManager($this);
     $sections = $sectionManager->fetch();
     foreach ($sections as $section) {
         $entry = new XMLElement('entry');
         General::array_to_xml($entry, $section->get());
         foreach ($section->fetchFields() as $field) {
             $field_xml = new XMLElement('field');
             General::array_to_xml($field_xml, $field->get());
             $filter_html = new XMLElement('filter_html');
             $field->displayDatasourceFilterPanel($filter_html, NULL, $errors, $section->get('id'));
             $field_xml->appendChild($filter_html);
             $field_elements = new XMLElement('elements');
             General::array_to_xml($field_elements, $field->fetchIncludableElements());
             $field_xml->appendChild($field_elements);
             $entry->appendChild($field_xml);
         }
         $section_xml->appendChild($entry);
     }
     $this->_XML->appendChild($section_xml);
     $title = __('New Group');
     $breadcrumbs = array(Widget::Anchor(__('Email Newsletter Recipients'), SYMPHONY_URL . '/extension/email_newsletter_manager/recipientgroups/'));
     $recipientgroups = new XMLElement('recipientgroups');
     if ($this->_context[2] == 'saved' || $this->_context[3] == 'saved') {
         $this->pageAlert(__(__('Email Recipient updated at %1$s. <a href="%2$s" accesskey="c">Create another?</a> <a href="%3$s" accesskey="a">View all Recipient Groups</a>'), array(Widget::Time()->generate(), SYMPHONY_URL . '/extension/email_newsletter_manager/recipientgroups/new/', SYMPHONY_URL . '/extension/email_newsletter_manager/recipientgroups/')), Alert::SUCCESS);
     }
     if ($new == false) {
         /*
             TODO add POST values to XML
         */
         $group = RecipientgroupManager::create($this->_context[1]);
         if (is_object($group)) {
             $entry = new XMLElement('entry');
             $properties = $group->getProperties();
             $about = $group->about();
             $title = $about['name'];
             General::array_to_xml($entry, $about);
             $source = new XMLElement('source', $properties['source']);
             $entry->appendChild($source);
             // Section Only
             if (is_numeric($properties['source'])) {
                 $fields = new XMLElement('fields');
                 $email = new XMLElement('email', $properties['email']);
                 $fields->appendChild($email);
                 $name = new XMLElement('name');
                 General::array_to_xml($name, $properties['name']);
                 $fields->appendChild($name);
                 $entry->appendChild($fields);
             }
             // Hack to make sure filter data is preserved in the UI when there is an error in the form.
             // For next versions: always do the local/user differentiation in php, rather than xslt.
             // This will make the xslt cleaner and easier to understand and debug.
             if (!empty($_POST['fields'])) {
                 $properties['filters'] = $_POST['fields']['filter'][0];
             }
             if (!empty($properties['filters'])) {
                 $filters = new XMLElement('filters');
                 foreach ($properties['filters'] as $filter => $val) {
                     // Section and Author
                     if ($filter == 'id') {
                         $title = new XMLElement('h4', 'System ID');
                         $label = Widget::Label(__('Value'));
                         $label->appendChild(Widget::Input('fields[filter][' . $properties['source'] . '][id]', General::sanitize($val)));
                         $filter_entry = new XMLElement('entry', NULL, array('id' => 'id', 'data-type' => 'id'));
                         $filter_entry->appendChild($title);
                         $filter_entry->appendChild($label);
                         $filters->appendChild($filter_entry);
                     }
                     if ($filter == 'system:date') {
                         $title = new XMLElement('h4', 'System Date');
                         $label = Widget::Label(__('Value'));
                         $label->appendChild(Widget::Input('fields[filter][' . $properties['source'] . '][system:date]', General::sanitize($val)));
                         $filter_entry = new XMLElement('entry', NULL, array('id' => 'id', 'data-type' => 'system:date'));
                         $filter_entry->appendChild($title);
                         $filter_entry->appendChild($label);
                         $filters->appendChild($filter_entry);
                     }
                     // Section Only
                     if (is_numeric($properties['source'])) {
                         $section = SectionManager::fetch($properties['source']);
                         if (is_object($section)) {
                             $section_fields = $section->fetchFields();
                             foreach ($section_fields as $field) {
                                 $field_ids[] = $field->get('id');
                             }
                             // only add filters to the duplicator if the field id
                             // belongs to the current section
                             if (is_numeric($filter) && in_array($filter, $field_ids)) {
                                 $filter_obj = FieldManager::fetch($filter);
                                 if (is_object($filter_obj)) {
                                     $filter_entry = new XMLElement('entry', NULL, array('id' => $filter, 'data-type' => FieldManager::fetchHandleFromID($filter)));
                                     $filter_obj->displayDatasourceFilterPanel($filter_entry, $val, $errors, is_numeric($properties['source']) ? $properties['source'] : 1);
                                     $filters->appendChild($filter_entry);
                                 }
                             }
                         }
                     }
                     // Author only
                     if ($properties['source'] == 'authors') {
                         $filter_names = array('username' => 'Username', 'first_name' => 'First Name', 'last_name' => 'Last Name', 'email' => 'Email Address', 'user_type' => 'User Type');
                         if (in_array($filter, array_keys($filter_names))) {
                             $title = new XMLElement('h4', $filter_names[$filter]);
                             $label = Widget::Label(__('Value'));
                             $label->appendChild(Widget::Input('fields[filter][' . $properties['source'] . '][username]', General::sanitize($val)));
                             $filter_entry = new XMLElement('entry', NULL, array('id' => 'id', 'data-type' => 'username'));
                             $filter_entry->appendChild($title);
                             $filter_entry->appendChild($label);
                             $filters->appendChild($filter_entry);
                         }
                     }
                 }
                 $entry->appendChild($filters);
                 $title = $about['name'];
             }
             if ($properties['source'] == 'static_recipients') {
                 $entry->appendChild(new XMLElement('static_recipients', '<![CDATA[' . $group->recipients . ']]>'));
             }
             $recipientgroups->appendChild($entry);
             $this->_XML->appendChild($recipientgroups);
         } else {
             Administration::instance()->errorPageNotFound();
         }
     }
     $this->insertBreadcrumbs($breadcrumbs);
     $this->appendSubheading($title);
 }
 public function appendTokensToForms($context)
 {
     if (isset($context["oPage"])) {
         $context["oPage"]->Form->prependChild(XSRF::formToken());
     }
 }
 /**
  * Called by index.php, this function is responsible for rendering the current
  * page on the Frontend. Two delegates are fired, AdminPagePreGenerate and
  * AdminPagePostGenerate. This function runs the Profiler for the page build
  * process.
  *
  * @uses AdminPagePreGenerate
  * @uses AdminPagePostGenerate
  * @see core.Symphony#__buildPage()
  * @see boot.getCurrentPage()
  * @param string $page
  *  The result of getCurrentPage, which returns the $_GET['symphony-page']
  *  variable.
  * @throws Exception
  * @throws SymphonyErrorPage
  * @return string
  *  The HTML of the page to return
  */
 public function display($page)
 {
     Symphony::Profiler()->sample('Page build process started');
     $this->__buildPage($page);
     // Add XSRF token to form's in the backend
     if (self::isXSRFEnabled() && isset($this->Page->Form)) {
         $this->Page->Form->prependChild(XSRF::formToken());
     }
     /**
      * Immediately before generating the admin page. Provided with the page object
      * @delegate AdminPagePreGenerate
      * @param string $context
      *  '/backend/'
      * @param HTMLPage $oPage
      *  An instance of the current page to be rendered, this will usually be a class that
      *  extends HTMLPage. The Symphony backend uses a convention of contentPageName
      *  as the class that extends the HTMLPage
      */
     Symphony::ExtensionManager()->notifyMembers('AdminPagePreGenerate', '/backend/', array('oPage' => &$this->Page));
     $output = $this->Page->generate();
     /**
      * Immediately after generating the admin page. Provided with string containing page source
      * @delegate AdminPagePostGenerate
      * @param string $context
      *  '/backend/'
      * @param string $output
      *  The resulting backend page HTML as a string, passed by reference
      */
     Symphony::ExtensionManager()->notifyMembers('AdminPagePostGenerate', '/backend/', array('output' => &$output));
     Symphony::Profiler()->sample('Page built');
     return $output;
 }
        $xsl = @new SimpleXMLElement($xsl);
        $xsl->registerXPathNamespace("ext", "http://getsymphony.com/schemas/extension/1.0");
        $result = $xsl->xpath("//ext:extension[@id = '" . $e->getAdditional()->name . "']");
        if (!empty($result)) {
            $match = $extension->getFilename();
            break;
        }
    }
}
// If we've found a similar folder
if ($match != "" && $e->getAdditional()->rename_failed !== true) {
    $div->appendChild(new XMLElement('p', __('Often the cause of this error is a misnamed extension folder. You can try renaming %s to %s, or you can uninstall the extension to continue.', array('<code>extensions/' . $match . '</code>', '<code>extensions/' . $e->getAdditional()->name . '</code>'))));
    $form->appendChild(Widget::Input('existing-folder', $match, 'hidden'));
    $form->appendChild(Widget::Input('new-folder', $e->getAdditional()->name, 'hidden'));
    $button = new XMLElement('button', __('Rename folder'));
    $button->setAttributeArray(array('name' => 'action[rename]', 'class' => 'button', 'type' => 'submit', 'accesskey' => 's'));
    $actions->appendChild($button);
} elseif ($e->getAdditional()->rename_failed) {
    $div->appendChild(new XMLElement('p', __('Sorry, but Symphony was unable to rename the folder. You can try renaming %s to %s yourself, or you can uninstall the extension to continue.', array('<code>extensions/' . $match . '</code>', '<code>extensions/' . $e->getAdditional()->name . '</code>'))));
} else {
    $div->appendChild(new XMLElement('p', __('You can try uninstalling the extension to continue, or you might want to ask on the forums')));
}
// Add XSRF token to form's in the backend
if (Symphony::Engine()->isXSRFEnabled()) {
    $form->prependChild(XSRF::formToken());
}
$div->appendChild($form);
$Page->Body->appendChild($div);
$output = $Page->generate();
echo $output;
exit;
 function __viewEdit($new = false)
 {
     $this->setPageType('form');
     if ($this->_context[2] == 'saved' || $this->_context[3] == 'saved') {
         $this->pageAlert(__(__('Email Sender updated at %1$s. <a href="%2$s" accesskey="c">Create another?</a> <a href="%3$s" accesskey="a">View all Senders</a>'), array(Widget::Time()->generate(), SYMPHONY_URL . '/extension/email_newsletter_manager/senders/new/', SYMPHONY_URL . '/extension/email_newsletter_manager/senders/')), Alert::SUCCESS);
     }
     $senders = new XMLElement('senders');
     $title = __('New Sender');
     $breadcrumbs = array(Widget::Anchor(__('Email Newsletter Senders'), SYMPHONY_URL . '/extension/email_newsletter_manager/senders/'));
     // Fix for 2.4 and XSRF
     if (Symphony::Configuration()->get("enable_xsrf", "symphony") == "yes" && class_exists('XSRF')) {
         $xsrf_input = new XMLElement('xsrf_input');
         $xsrf_input->appendChild(XSRF::formToken());
         $this->_XML->appendChild($xsrf_input);
     }
     if (!$new) {
         $sender = SenderManager::create($this->_context[1]);
         // Make sure the POSTED values are always shown when present.
         // This will make sure the form is always up-to-date, even where there are errors.
         if (!empty($_POST['fields']) && !empty($_POST['settings'])) {
             $posted_array = $_POST['fields'];
             $posted_array[$_POST['settings']['gateway']] = $_POST['settings']['email_' . $_POST['settings']['gateway']];
         }
         $about = empty($_POST['fields']) && empty($_POST['settings']) ? (array) $sender->about() : $posted_array;
         $about['handle'] = Lang::createHandle($about['name'], 225, '-');
         $entry = new XMLElement('entry');
         General::array_to_xml($entry, $about);
         $senders->appendChild($entry);
         $title = $about['name'];
         //$breadcrumbs[] = Widget::Anchor('hi', SYMPHONY_URL . '/extension/email_newsletter_manager/senders/edit/' . $sender->getHandle());
     }
     $el_gateways = new XMLElement('gateways');
     $gateways = EmailGatewayManager::listAll();
     foreach ($gateways as $gateway) {
         // to be removed in later versions. Right now only smtp and sendmail are supported.
         if (in_array($gateway['handle'], array('smtp', 'sendmail', 'amazon_ses'))) {
             $gw = EmailGatewayManager::create($gateway['handle']);
             if (!empty($about[$gateway['handle']])) {
                 $config = $about[$gateway['handle']];
                 if ($gateway['handle'] == 'smtp') {
                     $gw->setFrom($config['from_address'], $config['from_name']);
                     $gw->setHost($config['host']);
                     $gw->setSecure($config['secure']);
                     $gw->setPort($config['port']);
                     $gw->setAuth($config['auth']);
                     $gw->setUser($config['username']);
                     $gw->setPass($config['password']);
                 }
                 if ($gateway['handle'] == 'amazon_ses') {
                     $gw->setFrom($config['from_address'], $config['from_name']);
                     $gw->setAwsKey($config['aws_key']);
                     $gw->setAwsSecretKey($config['aws_secret_key']);
                     $gw->setFallback($config['fallback']);
                     $gw->setReturnPath($config['return_path']);
                 }
                 if ($gateway['handle'] == 'sendmail') {
                     $gw->setFrom($config['from_address'], $config['from_name']);
                 }
             }
             $entry = new XMLElement('entry');
             General::array_to_xml($entry, $gateway);
             $config_panel = new XMLElement('config_panel');
             $config_panel->appendChild($gw->getPreferencesPane());
             $entry->appendChild($config_panel);
             $el_gateways->appendChild($entry);
         }
     }
     $senders->appendChild($el_gateways);
     $this->insertBreadcrumbs($breadcrumbs);
     $this->appendSubheading($title);
     $this->_XML->appendChild($senders);
 }
 public function view()
 {
     if (isset($_POST['action']['submit'])) {
         $this->panelErrors = Extension_Dashboard::validatePanelOptions($this->panelType, $this->panelId);
         if (empty($this->panelErrors)) {
             $this->panelId = Extension_Dashboard::savePanel(array('id' => $this->panelId, 'label' => $this->panelLabel, 'placement' => $this->panelPlacement, 'type' => $this->panelType), $this->panelConfig);
         }
     } else {
         if (isset($_POST['action']['delete'])) {
             Extension_Dashboard::deletePanel($this->panelId);
             $this->_Result->setAttribute('id', $this->panelId);
             $this->_Result->setAttribute('placement', $this->panelPlacement);
             return;
         }
     }
     if (isset($this->panelId) && !empty($this->panelId)) {
         $this->panelConfig = Extension_Dashboard::getPanel($this->panelId);
         $this->panelLabel = $this->panelConfig['label'];
         $this->panelPlacement = $this->panelConfig['placement'];
     }
     if (isset($_POST['action']['submit']) && empty($this->panelErrors)) {
         $html = Extension_Dashboard::buildPanelHTML($this->panelConfig);
         $class = $html->getAttribute('class');
         $html->setAttribute('class', $class . ' new-panel');
         $this->_Result->setAttribute('id', $this->panelId);
         $this->_Result->setAttribute('placement', $this->panelPlacement);
         $this->_Result->setValue(sprintf('<![CDATA[%s]]>', $html->generate()));
     } else {
         $this->addHeaderToPage('Content-Type', 'text/html');
         $container = new XMLElement('form');
         $container->setAttribute('id', 'save-panel');
         $container->appendChild(new XMLElement('div', NULL, array('class' => 'top')));
         $heading = new XMLElement('h3', __('Configuration') . ' <span>' . (isset($this->panelLabel) ? $this->panelLabel : __('Untitled Panel')) . '<span>');
         $container->appendChild($heading);
         $config_options = Extension_Dashboard::buildPanelOptions($this->panelType, $this->panelId, $this->panelErrors);
         $primary = new XMLElement('div', NULL, array('class' => 'panel-config'));
         $fieldset = new XMLElement('fieldset', NULL, array('class' => 'settings'));
         $legend = new XMLElement('legend', __('General'));
         $fieldset->appendChild($legend);
         $group = new XMLElement('div', NULL, array('class' => 'group'));
         $group->appendChild(Widget::Label(__('Name'), Widget::Input('label', $this->panelLabel)));
         $group->appendChild(Widget::Label(__('Placement'), Widget::Select('placement', array(array('primary', $this->panelPlacement == 'primary', __('Main content')), array('secondary', $this->panelPlacement == 'secondary', __('Sidebar'))))));
         $fieldset->appendChild($group);
         $primary->appendChild($fieldset);
         if ($config_options) {
             $primary->appendChild($config_options);
         }
         $actions = new XMLElement('div', NULL, array('class' => 'actions'));
         $actions->appendChild(Widget::Input('action[submit]', __('Save Panel'), 'submit', array('class' => 'button create')));
         $actions->appendChild(Widget::Input('action[cancel]', __('Cancel'), 'submit'));
         if ($this->panelId) {
             $actions->appendChild(new XMLElement('button', __('Delete Panel'), array('class' => 'delete', 'name' => 'action[delete]')));
         }
         $primary->appendChild($actions);
         $primary->appendChild(Widget::Input('id', $this->panelId, 'hidden'));
         $primary->appendChild(Widget::Input('type', $this->panelType, 'hidden'));
         $container->appendChild($primary);
         if (Symphony::isXSRFEnabled()) {
             $container->prependChild(XSRF::formToken());
         }
         $this->_Result = $container;
     }
 }
示例#8
0
 public function view()
 {
     // Start building the page
     $this->setPageType('index');
     $this->setTitle(__('%1$s &ndash; %2$s', array(__('Symphony'), __('Tracker Activity'))));
     // Add a button to clear all activity
     $clearform = Widget::Form(Symphony::Engine()->getCurrentPageURL(), 'post');
     $button = new XMLElement('button', __('Clear All'));
     $button->setAttributeArray(array('name' => 'action[clear-all]', 'class' => 'button confirm delete', 'title' => __('Clear all activity'), 'accesskey' => 'd', 'data-message' => __('Are you sure you want to clear all activity?')));
     $clearform->appendChild($button);
     if (Symphony::Engine()->isXSRFEnabled()) {
         $clearform->prependChild(XSRF::formToken());
     }
     $this->appendSubheading(__('Tracker Activity'), $clearform);
     // Build pagination, sorting, and limiting info
     $current_page = isset($_REQUEST['pg']) && is_numeric($_REQUEST['pg']) ? max(1, intval($_REQUEST['pg'])) : 1;
     $start = (max(1, $current_page) - 1) * Symphony::Configuration()->get('pagination_maximum_rows', 'symphony');
     $limit = Symphony::Configuration()->get('pagination_maximum_rows', 'symphony');
     // Build filter info
     $filters = array();
     if (isset($_REQUEST['filter'])) {
         list($column, $value) = explode(':', $_REQUEST['filter'], 2);
         $values = explode(',', $value);
         $filters[$column] = array();
         foreach ($values as $value) {
             $filters[$column][] = rawurldecode($value);
         }
     }
     // Fetch activity logs
     $logs = Tracker::fetchActivities($filters, $limit, $start);
     // Build the table
     $thead = array(array(__('Activity'), 'col'), array(__('Date'), 'col'), array(__('Time'), 'col'));
     $tbody = array();
     // If there are no logs, display default message
     if (!is_array($logs) or empty($logs)) {
         $tbody = array(Widget::TableRow(array(Widget::TableData(__('No data available.'), 'inactive', null, count($thead)))));
     } else {
         foreach ($logs as $activity) {
             // Format the date and time
             $date = DateTimeObj::get(__SYM_DATE_FORMAT__, strtotime($activity['timestamp'] . ' GMT'));
             $time = DateTimeObj::get(__SYM_TIME_FORMAT__, strtotime($activity['timestamp'] . ' GMT'));
             $description = Tracker::getDescription($activity);
             $description_class = '';
             // Row class
             $row_class = null;
             if ($activity['action_type'] === 'created') {
                 $row_class = 'status-ok';
             } elseif ($activity['action_type'] === 'deleted') {
                 $row_class = 'status-error';
             }
             if (is_null($description)) {
                 if (!empty($activity['fallback_description'])) {
                     $description = $activity['fallback_description'];
                 } else {
                     $description = __('None found.');
                     $description_class = 'inactive';
                 }
             }
             // Assemble the columns
             $col_date = Widget::TableData($date);
             $col_time = Widget::TableData($time);
             $col_desc = Widget::TableData($description, $description_class);
             $col_desc->appendChild(Widget::Input("items[{$activity['id']}]", null, 'checkbox'));
             // Insert the row
             $tbody[] = Widget::TableRow(array($col_desc, $col_date, $col_time), $row_class, 'activity-' . $activity['id']);
         }
     }
     // Assemble the table
     $table = Widget::Table(Widget::TableHead($thead), null, Widget::TableBody($tbody), 'selectable', null, array('role' => 'directory', 'aria-labelledby' => 'symphony-subheading', 'data-interactive' => 'data-interactive'));
     $this->Form->appendChild($table);
     // Append table actions
     $options = array(array(null, false, __('With Selected...')), array('delete', false, __('Delete')));
     $tableActions = new XMLElement('div');
     $tableActions->setAttribute('class', 'actions');
     $tableActions->appendChild(Widget::Apply($options));
     $this->Form->appendChild($tableActions);
     // Append pagination
     $filter_sql = Tracker::buildFilterSQL($filters);
     $sql = '
         SELECT count(id) as `count`
         FROM `tbl_tracker_activity`' . $filter_sql;
     $per_page = Symphony::Configuration()->get('pagination_maximum_rows', 'symphony');
     $total_entries = Symphony::Database()->fetchVar('count', 0, $sql);
     $remaining_entries = max(0, $total_entries - ($start + $per_page));
     $total_pages = max(1, ceil($total_entries * (1 / $per_page)));
     $remaining_pages = max(0, $total - pages - $current_page);
     if ($total_pages > 1) {
         $ul = new XMLElement('ul');
         $ul->setAttribute('class', 'page');
         // First
         $li = new XMLElement('li');
         if ($current_page > 1) {
             $li->appendChild(Widget::Anchor(__('First'), Administration::instance()->getCurrentPageURL() . '?pg=1'));
         } else {
             $li->setValue(__('First'));
         }
         $ul->appendChild($li);
         // Previous
         $li = new XMLElement('li');
         if ($current_page > 1) {
             $li->appendChild(Widget::Anchor(__('&larr; Previous'), Administration::instance()->getCurrentPageURL() . '?pg=' . ($current_page - 1)));
         } else {
             $li->setValue(__('&larr; Previous'));
         }
         $ul->appendChild($li);
         // Summary
         $li = new XMLElement('li', __('Page %1$s of %2$s', array($current_page, max($current_page, $total_pages))));
         $li->setAttribute('title', __('Viewing %1$s - %2$s of %3$s entries', array($start, $current_page != $total_pages ? $current_page * Symphony::Configuration()->get('pagination_maximum_rows', 'symphony') : $total_entries, $total_entries)));
         $ul->appendChild($li);
         // Next
         $li = new XMLElement('li');
         if ($current_page < $total_pages) {
             $li->appendChild(Widget::Anchor(__('Next &rarr;'), Administration::instance()->getCurrentPageURL() . '?pg=' . ($current_page + 1)));
         } else {
             $li->setValue(__('Next &rarr;'));
         }
         $ul->appendChild($li);
         // Last
         $li = new XMLElement('li');
         if ($current_page < $total_pages) {
             $li->appendChild(Widget::Anchor(__('Last'), Administration::instance()->getCurrentPageURL() . '?pg=' . $total_pages));
         } else {
             $li->setValue(__('Last'));
         }
         $ul->appendChild($li);
         $this->Form->appendChild($ul);
     }
 }