Index: branches/5.3.x/core/kernel/db/db_tag_processor.php =================================================================== --- branches/5.3.x/core/kernel/db/db_tag_processor.php (revision 16717) +++ branches/5.3.x/core/kernel/db/db_tag_processor.php (revision 16718) @@ -1,3187 +1,3212 @@ getObject($params); return $object->GetID() <= 0; } /** * Returns view menu name for current prefix * * @param Array $params * @return string */ function GetItemName($params) { $item_name = $this->getUnitConfig()->getViewMenuPhrase(); return $this->Application->Phrase($item_name); } function ViewMenu($params) { $block_params = $params; unset($block_params['block']); $block_params['name'] = $params['block']; $list =& $this->GetList($params); $block_params['PrefixSpecial'] = $list->getPrefixSpecial(); return $this->Application->ParseBlock($block_params); } function SearchKeyword($params) { $list =& $this->GetList($params); return $this->Application->RecallVar($list->getPrefixSpecial() . '_search_keyword'); } /** * Draw filter menu content (for ViewMenu) based on filters defined in config * * @param Array $params * @return string */ function DrawFilterMenu($params) { $block_params = $this->prepareTagParams($params); $block_params['name'] = $params['spearator_block']; $separator = $this->Application->ParseBlock($block_params); $filter_menu = $this->getUnitConfig()->getFilterMenu(); if ( !$filter_menu ) { trigger_error('no filters defined for prefix ' . $this->Prefix . ', but DrawFilterMenu tag used', E_USER_NOTICE); return ''; } // Params: label, filter_action, filter_status $block_params['name'] = $params['item_block']; $view_filter = $this->Application->RecallVar($this->getPrefixSpecial() . '_view_filter'); if ( $view_filter === false ) { $this->Application->HandleEvent(new kEvent($this->getPrefixSpecial() . ':OnRemoveFilters')); $view_filter = $this->Application->RecallVar($this->getPrefixSpecial() . '_view_filter'); } $view_filter = unserialize($view_filter); $filters = Array (); $prefix_special = $this->getPrefixSpecial(); foreach ($filter_menu['Filters'] as $filter_key => $filter_params) { $group_params = isset($filter_params['group_id']) ? $filter_menu['Groups'][$filter_params['group_id']] : Array (); if ( !isset($group_params['element_type']) ) { $group_params['element_type'] = 'checkbox'; } if ( !$filter_params ) { $filters[] = $separator; continue; } $block_params['label'] = $filter_params['label']; if ( getArrayValue($view_filter, $filter_key) ) { $submit = 0; if ( isset($params['old_style']) ) { $status = $group_params['element_type'] == 'checkbox' ? 1 : 2; } else { $status = $group_params['element_type'] == 'checkbox' ? '[\'img/check_on.gif\']' : '[\'img/menu_dot.gif\']'; } } else { $submit = 1; $status = 'null'; } $block_params['filter_action'] = 'set_filter("' . $prefix_special . '","' . $filter_key . '","' . $submit . '",' . $params['ajax'] . ');'; $block_params['filter_status'] = $status; // 1 - checkbox, 2 - radio, 0 - no image $filters[] = $this->Application->ParseBlock($block_params); } return implode('', $filters); } /** * Draws auto-refresh submenu in View Menu. * * @param Array $params * @return string */ function DrawAutoRefreshMenu($params) { $refresh_intervals = $this->Application->ConfigValue('AutoRefreshIntervals'); if (!$refresh_intervals) { trigger_error('no refresh intervals defined for prefix '.$this->Prefix.', but DrawAutoRefreshMenu tag used', E_USER_NOTICE); return ''; } $refresh_intervals = explode(',', $refresh_intervals); $view_name = $this->Application->RecallVar($this->getPrefixSpecial().'_current_view'); $current_refresh_interval = $this->Application->RecallPersistentVar($this->getPrefixSpecial().'_refresh_interval.'.$view_name); if ($current_refresh_interval === false) { // if no interval was selected before, then choose 1st interval $current_refresh_interval = $refresh_intervals[0]; } $ret = ''; $block_params = $this->prepareTagParams($params); $block_params['name'] = $params['render_as']; foreach ($refresh_intervals as $refresh_interval) { $block_params['label'] = $this->_formatInterval($refresh_interval); $block_params['refresh_interval'] = $refresh_interval; $block_params['selected'] = $current_refresh_interval == $refresh_interval; $ret .= $this->Application->ParseBlock($block_params); } return $ret; } /** * Tells, that current grid is using auto refresh * * @param Array $params * @return bool */ function UseAutoRefresh($params) { $view_name = $this->Application->RecallVar($this->getPrefixSpecial().'_current_view'); return $this->Application->RecallPersistentVar($this->getPrefixSpecial().'_auto_refresh.'.$view_name); } /** * Returns current grid refresh interval * * @param Array $params * @return bool */ function AutoRefreshInterval($params) { $view_name = $this->Application->RecallVar($this->getPrefixSpecial().'_current_view'); return $this->Application->RecallPersistentVar($this->getPrefixSpecial().'_refresh_interval.'.$view_name); } /** * Formats time interval using given text for hours and minutes * * @param int $interval minutes * @param string $hour_text Text for hours * @param string $min_text Text for minutes * @return string */ function _formatInterval($interval, $hour_text = 'h', $min_text = 'min') { // 65 $minutes = $interval % 60; $hours = ($interval - $minutes) / 60; $ret = ''; if ($hours) { $ret .= $hours.$hour_text.' '; } if ($minutes) { $ret .= $minutes.$min_text; } return $ret; } function IterateGridFields($params) { $mode = $params['mode']; $def_block = isset($params['block']) ? $params['block'] : ''; $force_block = isset($params['force_block']) ? $params['force_block'] : false; $grid = $this->getUnitConfig()->getGridByName($params['grid']); $grid_config = $grid['Fields']; $picker_helper = new kColumnPickerHelper($this->getPrefixSpecial(), $params['grid']); $grid_config = $picker_helper->apply($grid_config); if ( $mode == 'fields' ) { return "'" . join("','", array_keys($grid_config)) . "'"; } $object =& $this->GetList($params); $o = ''; $i = 0; foreach ($grid_config as $field => $options) { $i++; $block_params = $this->prepareTagParams($params); $block_params = array_merge($block_params, $options); $block_params['block_name'] = array_key_exists($mode . '_block', $block_params) ? $block_params[$mode . '_block'] : $def_block; $block_params['name'] = $force_block ? $force_block : $block_params['block_name']; $block_params['field'] = $field; $block_params['sort_field'] = isset($options['sort_field']) ? $options['sort_field'] : $field; $block_params['filter_field'] = isset($options['filter_field']) ? $options['filter_field'] : $field; $w = $picker_helper->getWidth($field); if ( $w ) { // column picker width overrides width from unit config $block_params['width'] = $w; } $field_options = $object->GetFieldOptions($field); if ( array_key_exists('use_phrases', $field_options) ) { $block_params['use_phrases'] = $field_options['use_phrases']; } $block_params['is_last'] = ($i == count($grid_config)); $o .= $this->Application->ParseBlock($block_params, 1); } return $o; } function PickerCRC($params) { $picker_helper = new kColumnPickerHelper($this->getPrefixSpecial(), $params['grid']); return $picker_helper->getData()->getChecksum(); } function FreezerPosition($params) { $picker_helper = new kColumnPickerHelper($this->getPrefixSpecial(), $params['grid']); $data = $picker_helper->getData(); $freezer_pos = $data->getOrder('__FREEZER__'); return $freezer_pos === false || $data->isHidden('__FREEZER__') ? 1 : ++$freezer_pos; } function GridFieldsCount($params) { $grid = $this->getUnitConfig()->getGridByName($params['grid']); return count($grid['Fields']); } /** * Prints list content using block specified * * @param Array $params * @return string * @access public */ function PrintList($params) { $params['no_table'] = 1; return $this->PrintList2($params); } function InitList($params) { $list_name = isset($params['list_name']) ? $params['list_name'] : ''; if ( getArrayValue($this->nameToSpecialMapping, $list_name) === false ) { $list =& $this->GetList($params); } } function BuildListSpecial($params) { return $this->Special; } /** * Returns key, that identifies each list on template (used internally, not tag) * * @param Array $params * @return string */ function getUniqueListKey($params) { $types = array_key_exists('types', $params) ? $params['types'] : ''; $except = array_key_exists('except', $params) ? $params['except'] : ''; $list_name = array_key_exists('list_name', $params) ? $params['list_name'] : ''; if (!$list_name) { $list_name = $this->Application->Parser->GetParam('list_name'); } return $types . $except . $list_name; } /** * Enter description here... * * @param Array $params * @return kDBList */ function &GetList($params) { $list_name = array_key_exists('list_name', $params) ? $params['list_name'] : ''; if ( !$list_name ) { $list_name = $this->Application->Parser->GetParam('list_name'); } $requery = isset($params['requery']) && $params['requery']; $main_list = array_key_exists('main_list', $params) && $params['main_list']; if ( $list_name && !$requery ) { // list with "list_name" parameter if ( !array_key_exists($list_name, $this->nameToSpecialMapping) ) { // special missing -> generate one $special = $main_list ? $this->Special : $this->BuildListSpecial($params); } else { // get special, formed during list initialization $special = $this->nameToSpecialMapping[$list_name]; } } else { // list without "list_name" parameter $special = $main_list ? $this->Special : $this->BuildListSpecial($params); } $prefix_special = rtrim($this->Prefix . '.' . $special, '.'); $params['skip_counting'] = true; /** @var kDBList $list */ $list = $this->Application->recallObject($prefix_special, $this->Prefix . '_List', $params); if ( !array_key_exists('skip_quering', $params) || !$params['skip_quering'] ) { if ( $requery ) { $this->Application->HandleEvent(new kEvent($prefix_special . ':OnListBuild', $params)); } if ( array_key_exists('offset', $params) ) { $list->SetOffset($list->GetOffset() + $params['offset']); // apply custom offset } $list->Query($requery); if ( array_key_exists('offset', $params) ) { $list->SetOffset($list->GetOffset() - $params['offset']); // remove custom offset } } $this->Init($this->Prefix, $special); if ( $list_name ) { $this->nameToSpecialMapping[$list_name] = $special; } return $list; } function ListMarker($params) { $list =& $this->GetList($params); $ret = $list->getPrefixSpecial(); if (array_key_exists('as_preg', $params) && $params['as_preg']) { $ret = preg_quote($ret, '/'); } return $ret; } function CombinedSortingDropDownName($params) { $list =& $this->GetList($params); return $list->getPrefixSpecial() . '_CombinedSorting'; } /** * Prepares name for field with event in it (used only on front-end) * * @param Array $params * @return string */ function SubmitName($params) { $list =& $this->GetList($params); $prefix_special = $list->getPrefixSpecial(); return 'events[' . $prefix_special . '][' . $params['event'] . ']'; } /** * Prints list content using block specified * * @param Array $params * @return string * @access public */ function PrintList2($params) { $per_page = $this->SelectParam($params, 'per_page,max_items'); if ( $per_page !== false ) { $params['per_page'] = $per_page; } $list =& $this->GetList($params); $o = ''; $direction = (isset($params['direction']) && $params['direction'] == "H") ? "H" : "V"; $columns = (isset($params['columns'])) ? $params['columns'] : 1; $config = $this->getUnitConfig(); $id_field = (isset($params['id_field'])) ? $params['id_field'] : $config->getIDField(); if ( $columns > 1 && $direction == 'V' ) { $records_left = array_splice($list->Records, $list->GetSelectedCount()); // because we have 1 more record for "More..." link detection (don't need to sort it) $list->Records = $this->LinearToVertical($list->Records, $columns, $list->GetPerPage()); $list->Records = array_merge($list->Records, $records_left); } $list->GoFirst(); $block_params = $this->prepareTagParams($params); $block_params['name'] = $this->SelectParam($params, 'render_as,block'); $block_params['pass_params'] = 'true'; $block_params['column_width'] = $params['column_width'] = 100 / $columns; $block_start_row_params = $this->prepareTagParams($params); $block_start_row_params['name'] = $this->SelectParam($params, 'row_start_render_as,block_row_start,row_start_block'); $block_end_row_params = $this->prepareTagParams($params); $block_end_row_params['name'] = $this->SelectParam($params, 'row_end_render_as,block_row_end,row_end_block'); $block_empty_cell_params = $this->prepareTagParams($params); $block_empty_cell_params['name'] = $this->SelectParam($params, 'empty_cell_render_as,block_empty_cell,empty_cell_block'); $i = 0; $backup_id = $this->Application->GetVar($this->Prefix . '_id'); $displayed = Array (); $column_number = 1; $cache_mod_rw = $config->getCacheModRewrite() && $this->Application->RewriteURLs() && !$this->Application->isCachingType(CACHING_TYPE_MEMORY); $limit = isset($params['limit']) ? $params['limit'] : false; while (!$list->EOL() && (!$limit || $i<$limit)) { $this->Application->SetVar($this->getPrefixSpecial() . '_id', $list->GetDBField($id_field)); // for edit/delete links using GET $this->Application->SetVar($this->Prefix . '_id', $list->GetDBField($id_field)); $block_params['is_last'] = ($i == $list->GetSelectedCount() - 1); $block_params['last_row'] = ($i + (($i + 1) % $columns) >= $list->GetSelectedCount() - 1); $block_params['not_last'] = !$block_params['is_last']; // for front-end if ( $cache_mod_rw ) { $serial_name = $this->Application->incrementCacheSerial($this->Prefix, $list->GetDBField($id_field), false); if ( $this->Prefix == 'c' ) { // for listing subcategories in category $this->Application->setCache('filenames[%' . $serial_name . '%]', $list->GetDBField('NamedParentPath')); $this->Application->setCache('category_tree[%CIDSerial:' . $list->GetDBField($id_field) . '%]', $list->GetDBField('TreeLeft') . ';' . $list->GetDBField('TreeRight')); } else { // for listing items in category $this->Application->setCache('filenames[%' . $serial_name . '%]', $list->GetDBField('Filename')); $serial_name = $this->Application->incrementCacheSerial('c', $list->GetDBField('CategoryId'), false); $this->Application->setCache('filenames[%' . $serial_name . '%]', $list->GetDBField('CategoryFilename')); } } if ( $i % $columns == 0 ) { // record in this iteration is first in row, then open row $column_number = 1; $o .= $block_start_row_params['name'] ? $this->Application->ParseBlock($block_start_row_params) : (!isset($params['no_table']) ? '' : ''); } else { $column_number++; } $block_params['first_col'] = $column_number == 1 ? 1 : 0; $block_params['last_col'] = $column_number == $columns ? 1 : 0; $block_params['column_number'] = $column_number; $block_params['num'] = ($i + 1); $this->PrepareListElementParams($list, $block_params); // new, no need to rewrite PrintList $o .= $this->Application->ParseBlock($block_params); array_push($displayed, $list->GetDBField($id_field)); if ( $direction == 'V' && $list->GetSelectedCount() % $columns > 0 && $column_number == ($columns - 1) && ceil(($i + 1) / $columns) > $list->GetSelectedCount() % ceil($list->GetSelectedCount() / $columns) ) { // if vertical output, then draw empty cells vertically, not horizontally $o .= $block_empty_cell_params['name'] ? $this->Application->ParseBlock($block_empty_cell_params) : ' '; $i++; } if ( ($i + 1) % $columns == 0 ) { // record in next iteration is first in row too, then close this row $o .= $block_end_row_params['name'] ? $this->Application->ParseBlock($block_end_row_params) : (!isset($params['no_table']) ? '' : ''); } if ( $this->Special && $this->Application->hasObject($this->Prefix) ) { // object, produced by "kDBList::linkToParent" method, that otherwise would keep it's id /** @var kDBBase $item */ $item = $this->Application->recallObject($this->Prefix); if ( $item instanceof kDBItem ) { $this->Application->removeObject($this->Prefix); } } $list->GoNext(); $i++; } // append empty cells in place of missing cells in last row while ($i % $columns != 0) { // until next cell will be in new row append empty cells $o .= $block_empty_cell_params['name'] ? $this->Application->ParseBlock($block_empty_cell_params) : ' '; if ( ($i + 1) % $columns == 0 ) { // record in next iteration is first in row too, then close this row $o .= $block_end_row_params['name'] ? $this->Application->ParseBlock($block_end_row_params) : ''; } $i++; } $cur_displayed = $this->Application->GetVar($this->Prefix . '_displayed_ids'); if ( !$cur_displayed ) { $cur_displayed = Array (); } else { $cur_displayed = explode(',', $cur_displayed); } $displayed = array_unique(array_merge($displayed, $cur_displayed)); $this->Application->SetVar($this->Prefix . '_displayed_ids', implode(',', $displayed)); $this->Application->SetVar($this->Prefix . '_id', $backup_id); $this->Application->SetVar($this->getPrefixSpecial() . '_id', ''); if ( isset($params['more_link_render_as']) ) { $block_params = $params; $params['render_as'] = $params['more_link_render_as']; $o .= $this->MoreLink($params); } return $o; } /** * Returns ID of previous record (related to current) in list. * Use only on item detail pages. * * @param Array $params * @return int * @access protected */ protected function PreviousResource($params) { /** @var kDBItem $object */ $object = $this->getObject($params); /** @var ListHelper $list_helper */ $list_helper = $this->Application->recallObject('ListHelper'); $select_clause = $object->getUnitConfig()->getNavigationSelectClause(null); return $list_helper->getNavigationResource($object, $params['list'], false, $select_clause); } /** * Returns ID of next record (related to current) in list. * Use only on item detail pages. * * @param Array $params * @return int * @access protected */ protected function NextResource($params) { /** @var kDBItem $object */ $object = $this->getObject($params); /** @var ListHelper $list_helper */ $list_helper = $this->Application->recallObject('ListHelper'); $select_clause = $object->getUnitConfig()->getNavigationSelectClause(null); return $list_helper->getNavigationResource($object, $params['list'], true, $select_clause); } /** * Allows to modify block params & current list record before PrintList parses record * * @param kDBList $object * @param Array $block_params * @return void * @access protected */ protected function PrepareListElementParams(&$object, &$block_params) { // $fields_hash =& $object->getCurrentRecord(); } /** * Renders given block name, when there there is more data in list, then are displayed right now * * @param Array $params * @return string * @access protected */ protected function MoreLink($params) { $per_page = $this->SelectParam($params, 'per_page,max_items'); if ( $per_page !== false ) { $params['per_page'] = $per_page; } $list =& $this->GetList($params); if ( $list->isCounted() ) { $has_next_page = $list->GetPage() < $list->GetTotalPages(); } else { // selected more, then on the page -> has more $has_next_page = $list->GetPerPage() < $list->GetRecordsCount(); } if ( $has_next_page ) { $block_params = Array ('name' => $this->SelectParam($params, 'render_as,block')); return $this->Application->ParseBlock($block_params); } return ''; } function PageLink($params) { static $default_per_page = Array (); /** @var kDBList $object */ $object =& $this->GetList($params); // process sorting if ($object->isMainList()) { if (!array_key_exists('sort_by', $params)) { $sort_by = $this->Application->GetVar('sort_by'); if ($sort_by !== false) { $params['sort_by'] = $sort_by; } } } $prefix_special = $this->getPrefixSpecial(); // process page $page = array_key_exists('page', $params) ? $params['page'] : $this->Application->GetVar($prefix_special . '_Page'); if (!$page) { // ensure, that page is always present if ($object->isMainList()) { $params[$prefix_special . '_Page'] = $this->Application->GetVar('page', 1); } else { $params[$prefix_special . '_Page'] = 1; } } if (array_key_exists('page', $params)) { $params[$prefix_special . '_Page'] = $params['page']; unset($params['page']); } // process per-page $per_page = array_key_exists('per_page', $params) ? $params['per_page'] : $this->Application->GetVar($prefix_special . '_PerPage'); if (!$per_page) { // ensure, that per-page is always present list ($prefix, ) = explode('.', $prefix_special); if (!array_key_exists($prefix, $default_per_page)) { /** @var ListHelper $list_helper */ $list_helper = $this->Application->recallObject('ListHelper'); $default_per_page[$prefix] = $list_helper->getDefaultPerPage($prefix); } if ($object->isMainList()) { $params[$prefix_special . '_PerPage'] = $this->Application->GetVar('per_page', $default_per_page[$prefix]); } else { $params[$prefix_special . '_PerPage'] = $default_per_page[$prefix]; } } if (array_key_exists('per_page', $params)) { $params[$prefix_special . '_PerPage'] = $params['per_page']; unset($params['per_page']); } if (!array_key_exists('pass', $params)) { $params['pass'] = 'm,' . $prefix_special; } // process template $t = array_key_exists('template', $params) ? $params['template'] : ''; unset($params['template']); if (!$t) { $t = $this->Application->GetVar('t'); } return $this->Application->HREF($t, '', $params); } /** * Deprecated * * @param array $params * @return int * @deprecated Parameter "column_width" of "PrintList" tag does that */ function ColumnWidth($params) { $columns = $this->Application->Parser->GetParam('columns'); return round(100/$columns).'%'; } /** * Append prefix and special to tag * params (get them from tagname) like * they were really passed as params * * @param Array $tag_params * @return Array * @access protected */ function prepareTagParams($tag_params = Array()) { $ret = $tag_params; $ret['Prefix'] = $this->Prefix; $ret['Special'] = $this->Special; $ret['PrefixSpecial'] = $this->getPrefixSpecial(); return $ret; } function GetISO($currency, $field_currency = '') { if ( $currency == 'selected' ) { return $this->Application->RecallVar('curr_iso'); } if ( $currency == 'primary' || $currency == '' ) { return $this->Application->GetPrimaryCurrency(); } // explicit currency return $currency == 'field' && $field_currency ? $field_currency : $currency; } /** * Convert primary currency to selected (if they are the same, converter will just return) * * @param float $value * @param string $target_iso * @param string $source_iso * @return float */ function ConvertCurrency($value, $target_iso, $source_iso = 'PRIMARY') { /** @var CurrencyRates $converter */ $converter = $this->Application->recallObject('CurrencyRates'); return $converter->Convert($value, $source_iso, $target_iso); } function AddCurrencySymbol($value, $iso, $decimal_tag = '') { /** @var CurrencyRates $converter */ $converter = $this->Application->recallObject('CurrencyRates'); return $converter->AddCurrencySymbol($value, $iso, $decimal_tag); } /** * Get's requested field value * * @param Array $params * @return string * @access public */ function Field($params) { $field = $this->SelectParam($params, 'name,field'); if (!$this->Application->isAdmin) { // don't apply kUtil::escape() on any field value on Front-End $params['no_special'] = 'no_special'; } /** @var kDBItem $object */ $object = $this->getObject($params); if (array_key_exists('db', $params) && $params['db']) { $value = $object->GetDBField($field); } else { if (array_key_exists('currency', $params) && $params['currency']) { $source_iso = isset($params['currency_field']) ? $object->GetDBField($params['currency_field']) : 'PRIMARY'; $target_iso = $this->GetISO($params['currency'], $source_iso); $original = $object->GetDBField($field); $value = $this->ConvertCurrency($original, $target_iso, $source_iso); $object->SetDBField($field, $value); $object->SetFieldOption($field, 'converted', true); } $format = array_key_exists('format', $params) ? $params['format'] : false; if (!$format || $format == '$format') { $format = NULL; } $value = $object->GetField($field, $format); if (array_key_exists('negative', $params) && $params['negative']) { if (strpos($value, '-') === 0) { $value = substr($value, 1); } else { $value = '-' . $value; } } if (array_key_exists('currency', $params) && $params['currency']) { $decimal_tag = isset($params['decimal_tag']) ? $params['decimal_tag'] : ''; $value = $this->AddCurrencySymbol($value, $target_iso, $decimal_tag); $params['no_special'] = 1; } } if (!array_key_exists('no_special', $params) || !$params['no_special']) { $value = kUtil::escape($value); } if (array_key_exists('checked', $params) && $params['checked']) { $value = ($value == ( isset($params['value']) ? $params['value'] : 1)) ? 'checked' : ''; } if (array_key_exists('plus_or_as_label', $params) && $params['plus_or_as_label']) { $value = substr($value, 0,1) == '+' ? substr($value, 1) : $this->Application->Phrase($value); } elseif (array_key_exists('as_label', $params) && $params['as_label']) { $value = $this->Application->Phrase($value); } $first_chars = $this->SelectParam($params,'first_chars,cut_first'); if ($first_chars) { $stripped_value = strip_tags($value, $this->SelectParam($params, 'allowed_tags')); if ( mb_strlen($stripped_value) > $first_chars ) { $value = preg_replace('/\s+?(\S+)?$/', '', mb_substr($stripped_value, 0, $first_chars + 1)) . ' ...'; } } if (array_key_exists('nl2br', $params) && $params['nl2br']) { $value = nl2br($value); } if ($value != '') { $this->Application->Parser->DataExists = true; } if (array_key_exists('currency', $params) && $params['currency']) { // restoring value in original currency, for other Field tags to work properly $object->SetDBField($field, $original); } return $value; } function FieldHintLabel($params) { if ( isset($params['direct_label']) && $params['direct_label'] ) { $label = $params['direct_label']; $hint = $this->Application->Phrase($label, false); } else { $label = $params['title_label']; $hint = $this->Application->Phrase('hint:' . $label, false); } return $hint != strtoupper('!' . $label . '!') ? $hint : ''; // $hint } /** * Returns formatted date + time on current language * * @param $params */ function DateField($params) { $field = $this->SelectParam($params, 'name,field'); if ($field) { /** @var kDBItem $object */ $object = $this->getObject($params); $timestamp = $object->GetDBField($field); } else { $timestamp = $params['value']; } $date = $timestamp; // prepare phrase replacements $replacements = Array ( 'l' => 'la_WeekDay', 'D' => 'la_WeekDay', 'M' => 'la_Month', 'F' => 'la_Month', ); // cases allow to append phrase suffix based on requested case (e.g. Genitive) $case_suffixes = array_key_exists('case_suffixes', $params) ? $params['case_suffixes'] : false; if ($case_suffixes) { // apply case suffixes (for russian language only) $case_suffixes = explode(',', $case_suffixes); foreach ($case_suffixes as $case_suffux) { list ($replacement_name, $case_suffix_value) = explode('=', $case_suffux, 2); $replacements[$replacement_name] .= $case_suffix_value; } } $format = array_key_exists('format', $params) ? $params['format'] : false; if (preg_match('/_regional_(.*)/', $format, $regs)) { /** @var kDBItem $language */ $language = $this->Application->recallObject('lang.current'); $format = $language->GetDBField($regs[1]); } elseif (!$format) { $format = null; } // escape formats, that are resolved to words by `date` foreach ($replacements as $format_char => $phrase_prefix) { if (strpos($format, $format_char) === false) { unset($replacements[$format_char]); continue; } $replacements[$format_char] = $this->Application->Phrase($phrase_prefix . date($format_char, $date)); $format = str_replace($format_char, '#' . ord($format_char) . '#', $format); } $date_formatted = date($format, $date); // unescape formats, that are resolved to words by `date` foreach ($replacements as $format_char => $format_replacement) { $date_formatted = str_replace('#' . ord($format_char) . '#', $format_replacement, $date_formatted); } return $date_formatted; } function SetField($params) { // /** @var kDBItem $object */ $object = $this->getObject($params); $dst_field = $this->SelectParam($params, 'name,field'); list($prefix_special, $src_field) = explode(':', $params['src']); /** @var kDBItem $src_object */ $src_object = $this->Application->recallObject($prefix_special); $object->SetDBField($dst_field, $src_object->GetDBField($src_field)); } /** * Depricated * * @param Array $params * @return string * @deprecated parameter "as_label" of "Field" tag does the same */ function PhraseField($params) { $field_label = $this->Field($params); $translation = $this->Application->Phrase( $field_label ); return $translation; } function Error($params) { /** @var kDBItem $object */ $object = $this->getObject($params); $field = $this->SelectParam($params, 'name,field'); return $object->GetErrorMsg($field, false); } function HasError($params) { if ($params['field'] == 'any') { /** @var kDBItem $object */ $object = $this->getObject($params); $skip_fields = array_key_exists('except', $params) ? $params['except'] : false; $skip_fields = $skip_fields ? explode(',', $skip_fields) : Array(); return $object->HasErrors($skip_fields); } else { $res = false; $fields = explode(',', $this->SelectParam($params, 'field,fields')); foreach ($fields as $field) { // call kDBTagProcessor::Error instead of kDBItem::GetErrorPseudo to have ability to override Error tag $params['field'] = $field; $res = $res || ($this->Error($params) != ''); } return $res; } } /** * Renders error message block, when there are errors on a form * * @param Array $params * @return string * @access protected */ protected function ErrorWarning($params) { if ( !isset($params['field']) ) { $params['field'] = 'any'; } if ( $this->HasError($params) ) { $params['prefix'] = $this->getPrefixSpecial(); return $this->Application->ParseBlock($params); } return ''; } function IsRequired($params) { /** @var kDBItem $object */ $object = $this->getObject($params); $field = $params['field']; $formatter_class = $object->GetFieldOption($field, 'formatter'); if ( $formatter_class == 'kMultiLanguage' ) { /** @var kMultiLanguage $formatter */ $formatter = $this->Application->recallObject($formatter_class); $field = $formatter->LangFieldName($field); } return $object->isRequired($field); } function FieldOption($params) { $object = $this->getObject($params);; $options = $object->GetFieldOptions($params['field']); $ret = isset($options[$params['option']]) ? $options[$params['option']] : ''; if (isset($params['as_label']) && $params['as_label']) $ret = $this->Application->ReplaceLanguageTags($ret); return $ret; } /** * Prints list a all possible field options * * @param Array $params * @return string * @access protected */ protected function PredefinedOptions($params) { /** @var kDBList $object */ $object = $this->getObject($params); $field = $params['field']; $value = array_key_exists('value', $params) ? $params['value'] : $object->GetDBField($field); $field_options = $object->GetFieldOptions($field); if (!array_key_exists('options', $field_options) || !is_array($field_options['options'])) { trigger_error('Options not defined for '.$object->Prefix.' field '.$field.'', E_USER_WARNING); return ''; } $options = $field_options['options']; if ( array_key_exists('has_empty', $params) && $params['has_empty'] ) { $empty_value = array_key_exists('empty_value', $params) ? $params['empty_value'] : ''; $empty_label = isset($params['empty_label']) ? $params['empty_label'] : ''; if ( $empty_label ) { if ( mb_substr($empty_label, 0, 1) == '+' ) { // using plain text instead of phrase label $empty_label = mb_substr($empty_label, 1); } else { $empty_label = $this->Application->Phrase($empty_label, false); } } // don't use other array merge function, because they will reset keys !!! $options = kUtil::array_merge_recursive(Array ($empty_value => $empty_label), $options); } $block_params = $this->prepareTagParams($params); $block_params['name'] = $this->SelectParam($params, 'render_as,block'); $block_params['pass_params'] = 'true'; if (method_exists($object, 'EOL') && count($object->Records) == 0) { // for drawing grid column filter $block_params['field_name'] = ''; } else { // deprecated (produces warning when used as grid filter), but used in Front-End (submission create), admin (submission view) $block_params['field_name'] = $this->InputName($params); } $selected_html = isset($params['selected']) ? $params['selected'] : 'selected'; $selected_param_name = array_key_exists('selected_param', $params) ? $params['selected_param'] : false; if (!$selected_param_name) { $selected_param_name = $selected_html; } $o = ''; if (array_key_exists('no_empty', $params) && $params['no_empty'] && !getArrayValue($options, '')) { // removes empty option, when present (needed?) array_shift($options); } $selected_option_keys = $this->getSelectedOptionKeys($value); if ( isset($params['selected_only']) && $params['selected_only'] ) { $options = $this->getSelectedOptions($options, $selected_option_keys); } + elseif ( isset($params['unselected_only']) && $params['unselected_only'] ) { + $options = $this->getUnselectedOptions($options, $selected_option_keys); + } $column_changed = false; $option_number = $column_number = 1; $option_count = count($options); $column_count = isset($params['columns']) ? $params['columns'] : 1; $options_per_column = ceil($option_count / $column_count); $block_params['option_count'] = $option_count; foreach ( $options as $option_key => $option_title ) { $block_params['key'] = $option_key; $block_params['option'] = $option_title; $block_params[$selected_param_name] = $this->isOptionSelected($option_key, $selected_option_keys) ? ' ' . $selected_html : ''; $block_params['column_number'] = $column_number; $block_params['column_changed'] = $column_changed; $block_params['option_number'] = $option_number; $block_params['is_last'] = $option_number == $option_count; $o .= $this->Application->ParseBlock($block_params); $column_changed = false; $option_number++; if ( $option_number > $column_number * $options_per_column ) { $column_number++; $column_changed = true; } } return $o; } /** * Returns unified representation of selected options based on field value. * * @param mixed $field_value Field value. * * @return array */ protected function getSelectedOptionKeys($field_value) { if ( strpos($field_value, '|') !== false ) { // multiple checkboxes OR multiselect return explode('|', trim($field_value, '|')); } // single selection radio OR checkboxes OR dropdown return array("$field_value"); } /** * Returns only options, that have been selected. * * @param array $options All options. * @param array $selected_option_keys Selected options. * * @return array */ protected function getSelectedOptions(array $options, array $selected_option_keys) { $ret = array(); foreach ( $options as $option_key => $option_title ) { if ( $this->isOptionSelected($option_key, $selected_option_keys) ) { $ret[$option_key] = $option_title; } } return $ret; } /** + * Returns only options, that have not been selected. + * + * @param array $options All options. + * @param array $selected_option_keys Selected options. + * + * @return array + */ + protected function getUnselectedOptions(array $options, array $selected_option_keys) + { + $ret = array(); + + foreach ( $options as $option_key => $option_title ) { + if ( !$this->isOptionSelected($option_key, $selected_option_keys) ) { + $ret[$option_key] = $option_title; + } + } + + return $ret; + } + + /** * Determines if given option is among selected ones. * * @param mixed $option_key Option key. * @param array $selected_option_keys Selected options. * * @return boolean */ protected function isOptionSelected($option_key, array $selected_option_keys) { return in_array("$option_key", $selected_option_keys, true); } function PredefinedSearchOptions($params) { /** @var kDBList $object */ $object =& $this->GetList($params); $params['value'] = $this->SearchField($params); return $this->PredefinedOptions($params); } function Format($params, $object = null) { $field = $this->SelectParam($params, 'name,field'); if ( !isset($object) ) { /** @var kDBItem $object */ $object = $this->getObject($params); } $options = $object->GetFieldOptions($field); $format = $options[$this->SelectParam($params, 'input_format') ? 'input_format' : 'format']; $formatter_class = array_key_exists('formatter', $options) ? $options['formatter'] : false; if ( $formatter_class ) { /** @var kFormatter $formatter */ $formatter = $this->Application->recallObject($formatter_class); $human_format = array_key_exists('human', $params) ? $params['human'] : false; $edit_size = array_key_exists('edit_size', $params) ? $params['edit_size'] : false; $sample = array_key_exists('sample', $params) ? $params['sample'] : false; if ( $sample ) { return $formatter->GetSample($field, $options, $object); } elseif ( $human_format || $edit_size ) { $format = $formatter->HumanFormat($format); return $edit_size ? strlen($format) : $format; } } return $format; } /** * Returns grid padination information * Can return links to pages * * @param Array $params * @return mixed */ function PageInfo($params) { /** @var kDBList $object */ $object =& $this->GetList($params); $type = $params['type']; unset($params['type']); // remove parameters used only by current tag $ret = ''; switch ($type) { case 'current': $ret = $object->GetPage(); break; case 'total': $ret = $object->GetTotalPages(); break; case 'prev': $ret = $object->GetPage() > 1 ? $object->GetPage() - 1 : false; break; case 'next': $ret = $object->GetPage() < $object->GetTotalPages() ? $object->GetPage() + 1 : false; break; } if ($ret && isset($params['as_link']) && $params['as_link']) { unset($params['as_link']); // remove parameters used only by current tag $params['page'] = $ret; $current_page = $object->GetPage(); // backup current page $ret = $this->PageLink($params); $this->Application->SetVar($object->getPrefixSpecial().'_Page', $current_page); // restore page } return $ret; } /** * Print grid pagination using * block names specified * * @param Array $params * @return string * @access public */ function PrintPages($params) { $list =& $this->GetList($params); $prefix_special = $list->getPrefixSpecial(); $total_pages = $list->GetTotalPages(); if ( $total_pages > 1 ) { $this->Application->Parser->DataExists = true; } if ( $total_pages == 0 ) { // display 1st page as selected in case if we have no pages at all $total_pages = 1; } $o = ''; // what are these 2 lines for? $this->Application->SetVar($prefix_special . '_event', ''); $this->Application->SetVar($prefix_special . '_id', ''); $current_page = $list->GetPage(); // $this->Application->RecallVar($prefix_special.'_Page'); $block_params = $this->prepareTagParams($params); $split = (isset($params['split']) ? $params['split'] : 10); $split_start = $current_page - ceil($split / 2); if ( $split_start < 1 ) { $split_start = 1; } $split_end = $split_start + $split - 1; if ( $split_end > $total_pages ) { $split_end = $total_pages; $split_start = max($split_end - $split + 1, 1); } if ( $current_page > 1 ) { $prev_block_params = $this->prepareTagParams($params); if ( $total_pages > $split ) { $prev_block_params['page'] = max($current_page - $split, 1); $prev_block_params['name'] = $this->SelectParam($params, 'prev_page_split_render_as,prev_page_split_block'); if ( $prev_block_params['name'] ) { $this->Application->SetVar($this->getPrefixSpecial() . '_Page', $prev_block_params['page']); $o .= $this->Application->ParseBlock($prev_block_params); } } $prev_block_params['name'] = 'page'; $prev_block_params['page'] = $current_page - 1; $prev_block_params['name'] = $this->SelectParam($params, 'prev_page_render_as,block_prev_page,prev_page_block'); if ( $prev_block_params['name'] ) { $this->Application->SetVar($this->getPrefixSpecial() . '_Page', $prev_block_params['page']); $o .= $this->Application->ParseBlock($prev_block_params); } } else { $no_prev_page_block = $this->SelectParam($params, 'no_prev_page_render_as,block_no_prev_page'); if ( $no_prev_page_block ) { $block_params['name'] = $no_prev_page_block; $o .= $this->Application->ParseBlock($block_params); } } $total_records = $list->GetRecordsCount(); $separator_params['name'] = $this->SelectParam($params, 'separator_render_as,block_separator'); for ($i = $split_start; $i <= $split_end; $i++) { $from_record = ($i - 1) * $list->GetPerPage(); $to_record = $from_record + $list->GetPerPage(); if ( $to_record > $total_records ) { $to_record = $total_records; } $block_params['from_record'] = $from_record + 1; $block_params['to_record'] = $to_record; if ( $i == $current_page ) { $block = $this->SelectParam($params, 'current_render_as,active_render_as,block_current,active_block'); } else { $block = $this->SelectParam($params, 'link_render_as,inactive_render_as,block_link,inactive_block'); } $block_params['name'] = $block; $block_params['page'] = $i; $this->Application->SetVar($this->getPrefixSpecial() . '_Page', $block_params['page']); $o .= $this->Application->ParseBlock($block_params); if ( $this->SelectParam($params, 'separator_render_as,block_separator') && $i < $split_end ) { $o .= $this->Application->ParseBlock($separator_params); } } if ( $current_page < $total_pages ) { $next_block_params = $this->prepareTagParams($params); $next_block_params['page'] = $current_page + 1; $next_block_params['name'] = $this->SelectParam($params, 'next_page_render_as,block_next_page,next_page_block'); if ( $next_block_params['name'] ) { $this->Application->SetVar($this->getPrefixSpecial() . '_Page', $next_block_params['page']); $o .= $this->Application->ParseBlock($next_block_params); } if ( $total_pages > $split ) { $next_block_params['page'] = min($current_page + $split, $total_pages); $next_block_params['name'] = $this->SelectParam($params, 'next_page_split_render_as,next_page_split_block'); if ( $next_block_params['name'] ) { $this->Application->SetVar($this->getPrefixSpecial() . '_Page', $next_block_params['page']); $o .= $this->Application->ParseBlock($next_block_params); } } } else { $no_next_page_block = $this->SelectParam($params, 'no_next_page_render_as,block_no_next_page'); if ( $no_next_page_block ) { $block_params['name'] = $no_next_page_block; $o .= $this->Application->ParseBlock($block_params); } } $this->Application->SetVar($this->getPrefixSpecial() . '_Page', $current_page); return $o; } /** * Print grid pagination using * block names specified * * @param Array $params * @return string * @access public */ function PaginationBar($params) { return $this->PrintPages($params); } function PerPageBar($params) { $object =& $this->GetList($params); $ret = ''; $per_pages = explode(';', $params['per_pages']); $block_params = $this->prepareTagParams($params); $block_params['name'] = $params['render_as']; foreach ($per_pages as $per_page) { $block_params['per_page'] = $per_page; $this->Application->SetVar($this->getPrefixSpecial() . '_PerPage', $per_page); $block_params['selected'] = $per_page == $object->GetPerPage(); $ret .= $this->Application->ParseBlock($block_params, 1); } $this->Application->SetVar($this->getPrefixSpecial() . '_PerPage', $object->GetPerPage()); return $ret; } /** * Returns field name (processed by kMultiLanguage formatter * if required) and item's id from it's IDField or field required * * @param Array $params * @return Array (id,field) * @access private */ function prepareInputName($params) { /** @var kDBItem $object */ $object = $this->getObject($params); $field = $this->SelectParam($params, 'name,field'); $formatter_class = $object->GetFieldOption($field, 'formatter'); if ($formatter_class == 'kMultiLanguage') { /** @var kMultiLanguage $formatter */ $formatter = $this->Application->recallObject($formatter_class); $force_primary = $object->GetFieldOption($field, 'force_primary'); $field = $formatter->LangFieldName($field, $force_primary); } if (array_key_exists('force_id', $params)) { $id = $params['force_id']; } else { $id_field = array_key_exists('IdField', $params) ? $params['IdField'] : false; $id = $id_field ? $object->GetDBField($id_field) : $object->GetID(); } return Array($id, $field); } /** * Returns input field name to * be placed on form (for correct * event processing) * * @param Array $params * @return string * @access public */ function InputName($params) { list($id, $field) = $this->prepareInputName($params); $ret = $this->getPrefixSpecial().'['.$id.']['.$field.']'; if (array_key_exists('as_preg', $params) && $params['as_preg']) { $ret = preg_quote($ret, '/'); } return $ret; } /** * Allows to override various field options through hidden fields with specific names in submit. * This tag generates this special names * * @param Array $params * @return string * @author Alex */ function FieldModifier($params) { list($id, $field) = $this->prepareInputName($params); $ret = 'field_modifiers['.$this->getPrefixSpecial().']['.$field.']['.$params['type'].']'; if (array_key_exists('as_preg', $params) && $params['as_preg']) { $ret = preg_quote($ret, '/'); } if (isset($params['value'])) { $object = $this->getObject($params); $field_modifiers[$field][$params['type']] = $params['value']; $object->ApplyFieldModifiers($field_modifiers); } return $ret; } /** * Returns index where 1st changeable sorting field begins * * @return int * @access private */ function getUserSortIndex() { $list_sortings = $this->getUnitConfig()->getListSortingsBySpecial($this, Array ()); $user_sorting_start = 0; $forced_sorting = getArrayValue($list_sortings, 'ForcedSorting'); return $forced_sorting ? count($forced_sorting) : $user_sorting_start; } /** * Returns order direction for given field * * * * @param Array $params * @return string * @access public */ function Order($params) { $field = $params['field']; $user_sorting_start = $this->getUserSortIndex(); $list =& $this->GetList($params); if ($list->GetOrderField($user_sorting_start) == $field) { return strtolower($list->GetOrderDirection($user_sorting_start)); } elseif($this->Application->ConfigValue('UseDoubleSorting') && $list->GetOrderField($user_sorting_start+1) == $field) { return '2_'.strtolower($list->GetOrderDirection($user_sorting_start+1)); } else { return 'no'; } } /** * Detects, that current sorting is not default * * @param Array $params * @return bool */ function OrderChanged($params) { $list =& $this->GetList($params); /** @var ListHelper $list_helper */ $list_helper = $this->Application->recallObject('ListHelper'); return $list_helper->hasUserSorting($list); } /** * Gets information of sorting field at "pos" position, * like sorting field name (type="field") or sorting direction (type="direction") * * @param Array $params * @return string * @access protected */ protected function OrderInfo($params) { $user_sorting_start = $this->getUserSortIndex() + --$params['pos']; $list =& $this->GetList($params); if ( $params['type'] == 'field' ) { return $list->GetOrderField($user_sorting_start); } if ( $params['type'] == 'direction' ) { return $list->GetOrderDirection($user_sorting_start); } return ''; } /** * Checks if sorting field/direction matches passed field/direction parameter * * @param Array $params * @return bool * @access protected */ protected function IsOrder($params) { $params['type'] = isset($params['field']) ? 'field' : 'direction'; $value = $this->OrderInfo($params); if ( isset($params['field']) ) { return $params['field'] == $value; } elseif ( isset($params['direction']) ) { return $params['direction'] == $value; } return false; } /** * Returns list per-page * * @param Array $params * @return int */ function PerPage($params) { $object =& $this->GetList($params); return $object->GetPerPage(); } /** * Checks if list perpage matches value specified * * @param Array $params * @return bool */ function PerPageEquals($params) { $object =& $this->GetList($params); return $object->GetPerPage() == $params['value']; } function SaveEvent($params) { // SaveEvent is set during OnItemBuild, but we may need it before any other tag calls OnItemBuild $object = $this->getObject($params); return $this->Application->GetVar($this->getPrefixSpecial().'_SaveEvent'); } function NextId($params) { $object = $this->getObject($params); $wid = $this->Application->GetTopmostWid($this->Prefix); $session_name = rtrim($this->getPrefixSpecial().'_selected_ids_'.$wid, '_'); $ids = explode(',', $this->Application->RecallVar($session_name)); $cur_id = $object->GetID(); $i = array_search($cur_id, $ids); if ($i !== false) { return $i < count($ids) - 1 ? $ids[$i + 1] : ''; } return ''; } function PrevId($params) { $object = $this->getObject($params); $wid = $this->Application->GetTopmostWid($this->Prefix); $session_name = rtrim($this->getPrefixSpecial().'_selected_ids_'.$wid, '_'); $ids = explode(',', $this->Application->RecallVar($session_name)); $cur_id = $object->GetID(); $i = array_search($cur_id, $ids); if ($i !== false) { return $i > 0 ? $ids[$i - 1] : ''; } return ''; } function IsSingle($params) { return ($this->NextId($params) === '' && $this->PrevId($params) === ''); } function IsLast($params) { return ($this->NextId($params) === ''); } function IsFirst($params) { return ($this->PrevId($params) === ''); } /** * Checks if field value is equal to proposed one * * @param Array $params * @return bool * @deprecated */ function FieldEquals($params) { /** @var kDBItem $object */ $object = $this->getObject($params); return $object->GetDBField( $this->SelectParam($params, 'name,field') ) == $params['value']; } /** * Checks, that grid has icons defined and they should be shown * * @param Array $params * @return bool */ function UseItemIcons($params) { return array_key_exists('Icons', $this->getUnitConfig()->getGridByName($params['grid'])); } /** * Returns corresponding to grid layout selector column width * * @param Array $params * @return int */ function GridSelectorColumnWidth($params) { $width = 0; if ($params['selector']) { $width += $params['selector_width']; } if ($this->UseItemIcons($params)) { $width += $params['icon_width']; } return $width; } /** * Returns grids item selection mode (checkbox, radio, ) * * @param Array $params * @return string */ function GridSelector($params) { $grid = $this->getUnitConfig()->getGridByName($params['grid']); return array_key_exists('Selector', $grid) ? $grid['Selector'] : $params['default']; } function ItemIcon($params) { $config = $this->getUnitConfig(); $grid = $config->getGridByName($params['grid']); if ( !isset($grid['Icons']) ) { return ''; } $icons = $grid['Icons']; if ( isset($params['name']) ) { $icon_name = $params['name']; return isset($icons[$icon_name]) ? $icons[$icon_name] : ''; } $status_fields = $config->getStatusField(false, Array ()); if ( !$status_fields ) { return $icons['default']; } /** @var kDBList $object */ $object = $this->getObject($params); $icon = ''; foreach ($status_fields as $status_field) { $icon .= $object->GetDBField($status_field) . '_'; } $icon = rtrim($icon, '_'); return isset($icons[$icon]) ? $icons[$icon] : $icons['default']; } /** * Generates bluebar title + initializes prefixes used on page * * @param Array $params * @return string */ function SectionTitle($params) { $config = $this->getUnitConfig(); $preset_name = kUtil::replaceModuleSection($params['title_preset']); $title_info = $config->getTitlePresetByName($preset_name); if ( $title_info === false ) { $title = str_replace('#preset_name#', $preset_name, $params['title']); if ( $this->Application->ConfigValue('UseSmallHeader') && isset($params['group_title']) && $params['group_title'] ) { $title .= ' - ' . $params['group_title']; } return $title; } $default_title_preset = $config->getTitlePresetByName('default'); if ( $default_title_preset ) { // use default labels + custom labels specified in preset used $title_info = kUtil::array_merge_recursive($default_title_preset, $title_info); } $title = $title_info['format']; // 1. get objects in use for title construction $objects = Array (); $object_status = Array (); $status_labels = Array (); $prefixes = array_key_exists('prefixes', $title_info) ? $title_info['prefixes'] : false; $all_tag_params = array_key_exists('tag_params', $title_info) ? $title_info['tag_params'] : false; /** @var Array $prefixes */ if ( $prefixes ) { // extract tag_params passed directly to SectionTitle tag for specific prefix foreach ($params as $tp_name => $tp_value) { if ( preg_match('/(.*)\[(.*)\]/', $tp_name, $regs) ) { $all_tag_params[$regs[1]][$regs[2]] = $tp_value; unset($params[$tp_name]); } } $tag_params = Array (); foreach ($prefixes as $prefix_special) { $prefix_data = $this->Application->processPrefix($prefix_special); $prefix_data['prefix_special'] = rtrim($prefix_data['prefix_special'], '.'); if ( $all_tag_params ) { $tag_params = getArrayValue($all_tag_params, $prefix_data['prefix_special']); if ( !$tag_params ) { $tag_params = Array (); } } $tag_params = array_merge($params, $tag_params); $objects[$prefix_data['prefix_special']] = $this->Application->recallObject($prefix_data['prefix_special'], $prefix_data['prefix'], $tag_params); $object_status[$prefix_data['prefix_special']] = $objects[$prefix_data['prefix_special']]->IsNewItem() ? 'new' : 'edit'; // a. set object's status field (adding item/editing item) for each object in title if ( getArrayValue($title_info[$object_status[$prefix_data['prefix_special']] . '_status_labels'], $prefix_data['prefix_special']) ) { $status_labels[$prefix_data['prefix_special']] = $title_info[$object_status[$prefix_data['prefix_special']] . '_status_labels'][$prefix_data['prefix_special']]; $title = str_replace('#' . $prefix_data['prefix_special'] . '_status#', $status_labels[$prefix_data['prefix_special']], $title); } // b. setting object's titlefield value (in titlebar ONLY) to default in case if object beeing created with no titlefield filled in if ( $object_status[$prefix_data['prefix_special']] == 'new' ) { $new_value = $this->getInfo($objects[$prefix_data['prefix_special']], 'titlefield'); if ( !$new_value && getArrayValue($title_info['new_titlefield'], $prefix_data['prefix_special']) ) { $new_value = $this->Application->Phrase($title_info['new_titlefield'][$prefix_data['prefix_special']]); } $title = str_replace('#' . $prefix_data['prefix_special'] . '_titlefield#', $new_value, $title); } } } // replace to section title $section = array_key_exists('section', $params) ? $params['section'] : false; if ( $section ) { /** @var kSectionsHelper $sections_helper */ $sections_helper = $this->Application->recallObject('SectionsHelper'); $section_data =& $sections_helper->getSectionData($section); $title = str_replace('#section_label#', '!' . $section_data['label'] . '!', $title); } // 2. replace phrases if any found in format string $title = $this->Application->ReplaceLanguageTags($title, false); // 3. find and replace any replacement vars preg_match_all('/#(.*_.*)#/Uis', $title, $rets); if ( $rets[1] ) { $replacement_vars = array_keys(array_flip($rets[1])); foreach ($replacement_vars as $replacement_var) { $var_info = explode('_', $replacement_var, 2); $object =& $objects[$var_info[0]]; $new_value = $this->getInfo($object, $var_info[1]); $title = str_replace('#' . $replacement_var . '#', $new_value, $title); } } // replace trailing spaces inside title preset + '' occurrences into single space $title = preg_replace('/[ ]*\'\'[ ]*/', ' ', $title); if ( $this->Application->ConfigValue('UseSmallHeader') && isset($params['group_title']) && $params['group_title'] ) { $title .= ' - ' . $params['group_title']; } $first_chars = $this->SelectParam($params, 'first_chars,cut_first'); if ( $first_chars && !preg_match('/(.*)<\/a>/', $title) ) { // don't cut titles, that contain phrase translation links $stripped_title = strip_tags($title, $this->SelectParam($params, 'allowed_tags')); if ( mb_strlen($stripped_title) > $first_chars ) { $title = mb_substr($stripped_title, 0, $first_chars) . ' ...'; } } return $title; } /** * Returns information about list * * @param kDBList $object * @param string $info_type * @return string * @access protected */ protected function getInfo(&$object, $info_type) { switch ( $info_type ) { case 'titlefield': $field = $object->getUnitConfig()->getTitleField(); return $field !== false ? $object->GetField($field) : 'TitleField Missing'; break; case 'recordcount': if ( $object->GetRecordsCount(false) != $object->GetRecordsCount() ) { $of_phrase = $this->Application->Phrase('lc_of'); return $object->GetRecordsCount() . ' ' . $of_phrase . ' ' . $object->GetRecordsCount(false); } return $object->GetRecordsCount(); break; } return $object->GetField($info_type); } function GridInfo($params) { /** @var kDBList $object */ $object =& $this->GetList($params); switch ( $params['type'] ) { case 'filtered': return $object->GetRecordsCount(); case 'total': return $object->GetRecordsCount(false); case 'selected': return $object->GetSelectedCount(); case 'from': return $object->GetRecordsCount() ? $object->GetOffset() + 1 : 0; //0-based case 'to': $record_count = $object->GetRecordsCount(); return $object->GetPerPage(true) != -1 ? min($object->GetOffset() + $object->GetPerPage(), $record_count) : $record_count; case 'total_pages': return $object->GetTotalPages(); case 'needs_pagination': return ($object->GetPerPage(true) != -1) && (($object->GetRecordsCount() > $object->GetPerPage()) || ($object->GetPage() > 1)); } return false; } /** * Parses block depending on its element type. * For radio and select elements values are taken from 'value_list_field' in key1=value1,key2=value2 * format. key=value can be substituted by SELECT f1 AS OptionName, f2 AS OptionValue... FROM TableName * where prefix is TABLE_PREFIX * * @param Array $params * @return string */ function ConfigFormElement($params) { /** @var kDBItem $object */ $object = $this->getObject($params); $field = $params['field']; /** @var InpCustomFieldsHelper $helper */ $helper = $this->Application->recallObject('InpCustomFieldsHelper'); $element_type = $object->GetDBField($params['element_type_field']); if ($element_type == 'label') { $element_type = 'text'; } $formatter_class = $object->GetFieldOption($field, 'formatter'); switch ($element_type) { case 'select': case 'multiselect': case 'radio': + case 'picker': if ($object->GetDBField('DirectOptions')) { // used for custom fields $options = $object->GetDBField('DirectOptions'); } else { // used for configuration $options = $helper->GetValuesHash( $object->GetDBField($params['value_list_field']) ); } $object->SetFieldOption($field, 'formatter', 'kOptionsFormatter'); $object->SetFieldOption($field, 'options', $options); break; case 'text': case 'textarea': case 'upload': $params['field_params'] = $helper->ParseConfigSQL($object->GetDBField($params['value_list_field'])); break; case 'password': case 'checkbox': default: break; } if (!$element_type) { throw new Exception('Element type missing for "' . $object->GetDBField('VariableName') . '" configuration variable'); } $params['name'] = $params['blocks_prefix'] . $element_type; // use $pass_params to pass 'SourcePrefix' parameter from PrintList to CustomInputName tag $ret = $this->Application->ParseBlock($params, 1); $object->SetFieldOption($field, 'formatter', $formatter_class); return $ret; } /** * Get's requested custom field value * * @param Array $params * @return string * @access public */ function CustomField($params) { $params['name'] = 'cust_'.$this->SelectParam($params, 'name,field'); return $this->Field($params); } function CustomFieldLabel($params) { $object = $this->getObject($params); $field = $this->SelectParam($params, 'name,field'); $sql = 'SELECT FieldLabel FROM ' . $this->Application->getUnitConfig('cf')->getTableName() . ' WHERE FieldName = ' . $this->Conn->qstr($field); return $this->Application->Phrase($this->Conn->GetOne($sql)); } /** * transposes 1-dimensional array elements for vertical alignment according to given columns and per_page parameters * * @param array $arr * @param int $columns * @param int $per_page * @return array */ function LinearToVertical(&$arr, $columns, $per_page) { $rows = $columns; // in case if after applying per_page limit record count less then // can fill requrested column count, then fill as much as we can $cols = min(ceil($per_page / $columns), ceil(count($arr) / $columns)); $imatrix = array(); for ($row = 0; $row < $rows; $row++) { for ($col = 0; $col < $cols; $col++) { $source_index = $row * $cols + $col; if (!isset($arr[$source_index])) { // in case if source array element count is less then element count in one row continue; } $imatrix[$col * $rows + $row] = $arr[$source_index]; } } ksort($imatrix); return array_values($imatrix); } /** * If data was modified & is in TempTables mode, then parse block with name passed; * remove modification mark if not in TempTables mode * * @param Array $params * @return string * @access protected */ protected function SaveWarning($params) { $main_prefix = array_key_exists('main_prefix', $params) ? $params['main_prefix'] : false; if ( $main_prefix ) { $top_prefix = $main_prefix; } else { $top_prefix = $this->Application->GetTopmostPrefix($this->Prefix); } $temp_tables = substr($this->Application->GetVar($top_prefix . '_mode'), 0, 1) == 't'; $modified = $this->Application->RecallVar($top_prefix . '_modified'); if ( $temp_tables && $modified ) { $block_params = $this->prepareTagParams($params); $block_params['name'] = $this->SelectParam($params, 'render_as,name'); $block_params['edit_mode'] = $temp_tables ? 1 : 0; return $this->Application->ParseBlock($block_params); } $this->Application->RemoveVar($top_prefix . '_modified'); return ''; } /** * Returns list record count queries (on all pages) * * @param Array $params * @return int */ function TotalRecords($params) { $list =& $this->GetList($params); return $list->GetRecordsCount(); } /** * Returns selected records count. * * @param array $params Tag params. * * @return string */ protected function SelectedRecords(array $params) { $list =& $this->GetList($params); return $list->GetSelectedCount(); } /** * Range filter field name * * @param Array $params * @return string */ function SearchInputName($params) { $field = $this->SelectParam($params, 'field,name'); $ret = 'custom_filters['.$this->getPrefixSpecial().']['.$params['grid'].']['.$field.']['.$params['filter_type'].']'; if (isset($params['type'])) { $ret .= '['.$params['type'].']'; } if (array_key_exists('as_preg', $params) && $params['as_preg']) { $ret = preg_quote($ret, '/'); } return $ret; } /** * Return range filter field value * * @param Array $params * @return string * @access protected */ protected function SearchField($params) // RangeValue { $field = $this->SelectParam($params, 'field,name'); $view_name = $this->Application->RecallVar($this->getPrefixSpecial() . '_current_view'); $custom_filter = $this->Application->RecallPersistentVar($this->getPrefixSpecial() . '_custom_filter.' . $view_name /*, ALLOW_DEFAULT_SETTINGS*/); $custom_filter = $custom_filter ? unserialize($custom_filter) : Array (); if ( isset($custom_filter[$params['grid']][$field]) ) { $ret = $custom_filter[$params['grid']][$field][$params['filter_type']]['submit_value']; if ( isset($params['type']) ) { $ret = $ret[$params['type']]; } if ( array_key_exists('formatted', $params) && $params['formatted'] ) { $object =& $this->GetList($params); $formatter_class = $object->GetFieldOption($field, 'formatter'); if ( $formatter_class ) { /** @var kFormatter $formatter */ $formatter = $this->Application->recallObject($formatter_class); $ret = $formatter->Format($ret, $field, $object); } } if ( !array_key_exists('no_special', $params) || !$params['no_special'] ) { $ret = kUtil::escape($ret); } return $ret; } return ''; } /** * Tells, that at least one of search filters is used by now * * @param Array $params * @return bool */ function SearchActive($params) { if ($this->Application->RecallVar($this->getPrefixSpecial() . '_search_keyword')) { // simple search filter is used return true; } $view_name = $this->Application->RecallVar($this->getPrefixSpecial().'_current_view'); $custom_filter = $this->Application->RecallPersistentVar($this->getPrefixSpecial().'_custom_filter.'.$view_name/*, ALLOW_DEFAULT_SETTINGS*/); $custom_filter = $custom_filter ? unserialize($custom_filter) : Array(); return array_key_exists($params['grid'], $custom_filter); } function SearchFormat($params) { $object =& $this->GetList($params); return $this->Format($params, $object); } /** * Returns error of range field * * @param Array $params * @return string * @access protected */ protected function SearchError($params) { $field = $this->SelectParam($params, 'field,name'); $error_var_name = $this->getPrefixSpecial() . '_' . $field . '_error'; $pseudo = $this->Application->RecallVar($error_var_name); if ( $pseudo ) { $this->Application->RemoveVar($error_var_name); } /** @var kDBItem $object */ $object = $this->Application->recallObject($this->Prefix . '.' . $this->Special . '-item', null, Array ('skip_autoload' => true)); $object->SetError($field, $pseudo); return $object->GetErrorMsg($field, false); } /** * Returns object used in tag processor * * @param Array $params * @access public * @return kDBItem|kDBList */ function getObject($params = Array()) { /** @var kDBItem $object */ $object = $this->Application->recallObject($this->getPrefixSpecial(), $this->Prefix, $params); if ( isset($params['requery']) && $params['requery'] ) { $this->Application->HandleEvent(new kEvent($this->getPrefixSpecial() . ':LoadItem', $params)); } return $object; } /** * Checks if object propery value matches value passed * * @param Array $params * @return bool */ function PropertyEquals($params) { $object = $this->getObject($params); $property_name = $this->SelectParam($params, 'name,var,property'); return $object->$property_name == $params['value']; } function DisplayOriginal($params) { return false; } /*function MultipleEditing($params) { $wid = $this->Application->GetTopmostWid($this->Prefix); $session_name = rtrim($this->getPrefixSpecial().'_selected_ids_'.$wid, '_'); $selected_ids = explode(',', $this->Application->RecallVar($session_name)); $ret = ''; if ($selected_ids) { $selected_ids = explode(',', $selected_ids); $object = $this->getObject( kUtil::array_merge_recursive($params, Array('skip_autoload' => true)) ); $params['name'] = $params['render_as']; foreach ($selected_ids as $id) { $object->Load($id); $ret .= $this->Application->ParseBlock($params); } } return $ret; }*/ /** * Returns import/export process percent * * @param Array $params * @return int * @deprecated Please convert to event-model, not tag based */ function ExportStatus($params) { /** @var kCatDBItemExportHelper $export_object */ $export_object = $this->Application->recallObject('CatItemExportHelper'); $event = new kEvent($this->getPrefixSpecial().':OnDummy'); $action_method = 'perform'.ucfirst($this->Special); $field_values = $export_object->$action_method($event); // finish code is done from JS now if ($field_values['start_from'] >= $field_values['total_records']) { if ($this->Special == 'import') { // this is used? $this->Application->StoreVar('PermCache_UpdateRequired', 1); $this->Application->Redirect('categories/cache_updater', Array('m_opener' => 'r', 'pass' => 'm', 'continue' => 1)); } elseif ($this->Special == 'export') { // used for orders export in In-Commerce $finish_t = $this->Application->RecallVar('export_finish_t'); $this->Application->Redirect($finish_t, Array('pass' => 'all')); $this->Application->RemoveVar('export_finish_t'); } } $export_options = $export_object->loadOptions($event); return $export_options['start_from'] * 100 / $export_options['total_records']; } /** * Returns path where exported category items should be saved * * @param Array $params * @return string * @access protected */ protected function ExportPath($params) { $export_options = unserialize($this->Application->RecallVar($this->getPrefixSpecial() . '_options')); $extension = $export_options['ExportFormat'] == 1 ? 'csv' : 'xml'; $filename = preg_replace('/(.*)\.' . $extension . '$/', '\1', $export_options['ExportFilename']) . '.' . $extension; $path = EXPORT_PATH . '/'; if ( array_key_exists('as_url', $params) && $params['as_url'] ) { $path = str_replace(FULL_PATH . '/', $this->Application->BaseURL(), $path); } return $path . $filename; } function FieldTotal($params) { $list =& $this->GetList($params); $field = $this->SelectParam($params, 'field,name'); $total_function = array_key_exists('function', $params) ? $params['function'] : $list->getTotalFunction($field); if (array_key_exists('function_only', $params) && $params['function_only']) { return $total_function; } if (array_key_exists('currency', $params) && $params['currency']) { $iso = $this->GetISO($params['currency']); $original = $list->getTotal($field, $total_function); $value = $this->ConvertCurrency($original, $iso); $list->setTotal($field, $total_function, $value); } $value = $list->GetFormattedTotal($field, $total_function); if (array_key_exists('currency', $params) && $params['currency']) { $value = $this->AddCurrencySymbol($value, $iso); } return $value; } function FCKEditor($params) { $editor_name = array_key_exists('name', $params) ? $params['name'] : $this->InputName($params); /** @var fckFCKHelper $fck_helper */ $fck_helper = $this->Application->recallObject('FCKHelper'); if ( isset($params['mode']) && $params['mode'] == 'inline' ) { return $fck_helper->CKEditorInlineTag($editor_name, $params); } return $fck_helper->CKEditorTag($editor_name, $this->CKEditorValue($params), $params); } /** * Returns value, used by FCKEditor tag * * @param array $params * * @return string */ protected function CKEditorValue($params) { $params['no_special'] = 1; $params['format'] = array_key_exists('format', $params) ? $params['format'] . ';fck_ready' : 'fck_ready'; return $this->Field($params); } function IsNewItem($params) { $object = $this->getObject($params); return $object->IsNewItem(); } /** * Creates link to an item including only it's id * * @param Array $params * @return string * @access protected */ protected function ItemLink($params) { /** @var kDBItem $object */ $object = $this->getObject($params); if ( !isset($params['pass']) ) { $params['pass'] = 'm'; } $params[ $object->getPrefixSpecial() . '_id' ] = $object->GetID(); return $this->Application->ProcessParsedTag('m', 'T', $params); } /** * Creates a button for editing item in Admin Console * * @param Array $params * @return string * @access protected * @throws InvalidArgumentException */ protected function AdminEditButton($params) { if ( EDITING_MODE != EDITING_MODE_CONTENT ) { return ''; } /** @var kDBItem $object */ $object = $this->getObject($params); $item_prefix = isset($params['item_prefix']) ? $params['item_prefix'] : $this->Prefix; if ( isset($params['template']) ) { $template = $params['template']; } else { $item_config = $this->Application->getUnitConfig($item_prefix); $admin_template_prefix = $item_config->getAdminTemplatePrefix(); $template = $item_config->getAdminTemplatePath() . '/' . $admin_template_prefix . 'edit'; if ( !$admin_template_prefix ) { throw new InvalidArgumentException('Automatic admin editing template detection failed because of missing "AdminTemplatePrefix" unit config option in "' . $this->Prefix . '" unit config'); } } $form_name = 'kf_' . str_replace('-', '_', $item_prefix) . '_' . $object->GetID(); $form_name .= '_' . kUtil::crc32(json_encode($params)); $button_icon = isset($params['button_icon']) ? $params['button_icon'] : 'content_mode.png'; $button_class = isset($params['button_class']) ? $params['button_class'] : 'admin-edit-btn'; $button_title = isset($params['button_title']) ? $params['button_title'] : 'la_btn_AdminEditItem'; if ( substr($button_title, 0, 1) == '+' ) { $button_title = substr($button_title, 1); } else { $button_title = $this->Application->Phrase($button_title, false, true); } if ( !isset($params['pass']) ) { $params['pass'] = 'm,' . $item_prefix; } $edit_prefix = $item_prefix; list($parent_prefix, $parent_id) = $this->getParentPrefixAndId($object); if ( $parent_prefix !== false ) { $edit_prefix = $parent_prefix; $params[$parent_prefix . '_id'] = $parent_id; $params['pass'] = $parent_prefix . ',' . $params['pass']; } $icon_url = $this->Application->BaseURL() . 'core/admin_templates/img/top_frame/icons/' . $button_icon; if ( !isset($params['temp_mode']) || (isset($params['temp_mode']) && $params['temp_mode']) ) { $edit_function = 'std_edit_item'; } else { $edit_function = 'std_edit_temp_item'; } $button_onclick = '$form_name = ' . json_encode($form_name) . '; ' . $edit_function . '(' . json_encode($edit_prefix) . ', ' . json_encode($template) . '); return false;'; $button_code = ''; $params['m_opener'] = 'd'; $params[$item_prefix . '_id'] = $object->GetID(); $params['front'] = 1; // to make opener stack work properly $params['__NO_REWRITE__'] = 1; // since admin link unset($params['button_icon'], $params['button_class'], $params['button_title'], $params['template'], $params['item_prefix'], $params['temp_mode']); // link from Front-End to Admin, don't remove "index.php" $form_name_escaped = kUtil::escape($form_name, kUtil::ESCAPE_HTML); $edit_url = kUtil::escape($this->Application->HREF($template, ADMIN_DIRECTORY, $params, 'index.php'), kUtil::ESCAPE_HTML); $edit_form = '
'; if ( isset($params['forms_later']) && $params['forms_later'] ) { $all_forms = $this->Application->GetVar('all_forms'); $this->Application->SetVar('all_forms', $all_forms . $edit_form); } else { $button_code .= $edit_form; } return $button_code; } /** * Returns parent record ID. * * @param kDBBase $object Object. * * @return array */ protected function getParentPrefixAndId(kDBBase $object) { static $parent_mapping = array(); $unit_config = $object->getUnitConfig(); $parent_prefix = $unit_config->getParentPrefix(); if ( $parent_prefix === false ) { return array(false, null); } $foreign_key = $unit_config->getForeignKey($parent_prefix); $parent_table_key = $unit_config->getParentTableKey($parent_prefix); $parent_unit_config = $this->Application->getUnitConfig($parent_prefix); $parent_id_field = $parent_unit_config->getIDField(); $parent_id = $object->GetDBField($foreign_key); if ( $parent_table_key != $parent_id_field ) { $cache_key = $object->getPrefixSpecial(); if ( !isset($parent_mapping[$cache_key]) ) { $foreign_key_values = array_unique($object->GetCol($foreign_key)); $sql = 'SELECT ' . $parent_id_field . ', ' . $parent_table_key . ' FROM ' . $parent_unit_config->getTableName() . ' WHERE ' . $parent_table_key . ' IN (' . implode(',', $foreign_key_values) . ')'; $parent_mapping[$cache_key] = $this->Conn->GetCol($sql, $parent_table_key); } // Parent record was deleted, but child record is still referencing it. if ( !isset($parent_mapping[$cache_key][$parent_id]) ) { return array(false, null); } $parent_id = $parent_mapping[$cache_key][$parent_id]; } return array($parent_prefix, $parent_id); } /** * Calls OnNew event from template, when no other event submitted * * @param Array $params */ function PresetFormFields($params) { $prefix = $this->getPrefixSpecial(); if ( !$this->Application->GetVar($prefix . '_event') ) { $this->Application->HandleEvent(new kEvent($prefix . ':OnNew')); } } function PrintSerializedFields($params) { /** @var kDBItem $object */ $object = $this->getObject($params); $field = $this->SelectParam($params, 'field'); $data = unserialize($object->GetDBField($field)); $o = ''; $std_params['name'] = $params['render_as']; $std_params['field'] = $params['field']; $std_params['pass_params'] = true; foreach ($data as $key => $row) { $block_params = array_merge($std_params, $row, array('key'=>$key)); $o .= $this->Application->ParseBlock($block_params); } return $o; } /** * Checks if current prefix is main item * * @param Array $params * @return bool */ function IsTopmostPrefix($params) { return $this->Prefix == $this->Application->GetTopmostPrefix($this->Prefix); } function PermSection($params) { $section = $this->SelectParam($params, 'section,name'); return $this->getUnitConfig()->getPermSectionByName($section, ''); } function PerPageSelected($params) { $list =& $this->GetList($params); return $list->GetPerPage(true) == $params['per_page'] ? $params['selected'] : ''; } /** * Returns prefix + generated sepcial + any word * * @param Array $params * @return string */ function VarName($params) { $list =& $this->GetList($params); return $list->getPrefixSpecial() . '_' . $params['type']; } /** * Returns edit tabs by specified preset name or false in case of error * * @param string $preset_name * @return mixed */ function getEditTabs($preset_name) { $presets = $this->getUnitConfig()->getEditTabPresets(); if ( !$presets || !isset($presets[$preset_name]) || count($presets[$preset_name]) == 0 ) { return false; } return count($presets[$preset_name]) > 1 ? $presets[$preset_name] : false; } /** * Detects if specified preset has tabs in it * * @param Array $params * @return bool */ function HasEditTabs($params) { return $this->getEditTabs($params['preset_name']) ? true : false; } /** * Sorts edit tabs based on their priority * * @param Array $tab_a * @param Array $tab_b * @return int */ function sortEditTabs($tab_a, $tab_b) { if ($tab_a['priority'] == $tab_b['priority']) { return 0; } return $tab_a['priority'] < $tab_b['priority'] ? -1 : 1; } /** * Prints edit tabs based on preset name specified * * @param Array $params * @return string * @access protected */ protected function PrintEditTabs($params) { $edit_tabs = $this->getEditTabs($params['preset_name']); if ( !$edit_tabs ) { return ''; } usort($edit_tabs, Array (&$this, 'sortEditTabs')); $ret = ''; $block_params = $this->prepareTagParams($params); $block_params['name'] = $params['render_as']; foreach ($edit_tabs as $tab_info) { $block_params['title'] = $tab_info['title']; $block_params['template'] = $tab_info['t']; $ret .= $this->Application->ParseBlock($block_params); } return $ret; } /** * Performs image resize to required dimensions and returns resulting url (cached resized image) * * @param Array $params * @return string */ function ImageSrc($params) { $max_width = isset($params['MaxWidth']) ? $params['MaxWidth'] : false; $max_height = isset($params['MaxHeight']) ? $params['MaxHeight'] : false; $logo_filename = isset($params['LogoFilename']) ? $params['LogoFilename'] : false; $logo_h_margin = isset($params['LogoHMargin']) ? $params['LogoHMargin'] : false; $logo_v_margin = isset($params['LogoVMargin']) ? $params['LogoVMargin'] : false; $object = $this->getObject($params); $field = $this->SelectParam($params, 'name,field'); return $object->GetField($field, 'resize:'.$max_width.'x'.$max_height.';wm:'.$logo_filename.'|'.$logo_h_margin.'|'.$logo_v_margin); } /** * Allows to retrieve given setting from unit config * * @param Array $params * @return mixed */ function UnitOption($params) { return $this->getUnitConfig()->getSetting($params['name']); } /** * Returns list of allowed toolbar buttons or false, when all is allowed * * @param Array $params * @return string */ function VisibleToolbarButtons($params) { $preset_name = kUtil::replaceModuleSection($params['title_preset']); $preset_info = $this->getUnitConfig()->getTitlePresetByName($preset_name); if ( !$preset_info ) { trigger_error('Title preset not specified or missing (in tag "' . $this->getPrefixSpecial() . ':' . __METHOD__ . '")', E_USER_NOTICE); return false; } if ( !array_key_exists('toolbar_buttons', $preset_info) || !is_array($preset_info['toolbar_buttons']) ) { return false; } // always add search buttons array_push($preset_info['toolbar_buttons'], 'search', 'search_reset_alt'); $toolbar_buttons = array_values($preset_info['toolbar_buttons']); // reset index return $toolbar_buttons ? trim(json_encode($toolbar_buttons), '[]') : 'false'; } /** * Checks, that "To" part of at least one of range filters is used * * @param Array $params * @return bool */ function RangeFiltersUsed($params) { /** @var kSearchHelper $search_helper */ $search_helper = $this->Application->recallObject('SearchHelper'); return $search_helper->rangeFiltersUsed($this->getPrefixSpecial(), $params['grid']); } /** * This is abstract tag, used to modify unit config data based on template, where it's used. * Tag is called from "combined_header" block in admin only. * * @param Array $params */ function ModifyUnitConfig($params) { } /** * Checks, that field is visible on edit form * * @param Array $params * @return bool */ function FieldVisible($params) { $check_field = $params['field']; $field_options = $this->_getFieldDefinition($check_field); if ( !$field_options ) { $params['field'] = 'Password'; return $check_field == 'VerifyPassword' ? $this->FieldVisible($params) : true; } $show_mode = array_key_exists('show_mode', $field_options) ? $field_options['show_mode'] : true; if ( $show_mode === smDEBUG ) { return defined('DEBUG_MODE') && DEBUG_MODE; } return $show_mode; } /** * Checks, that there area visible fields in given section on edit form * * @param Array $params * @return bool */ function FieldsVisible($params) { if ( !$params['fields'] ) { return true; } $check_fields = explode(',', $params['fields']); foreach ($check_fields as $check_field) { // when at least one field in subsection is visible, then subsection is visible too $field_options = $this->_getFieldDefinition($check_field); if ( $field_options ) { $show_mode = array_key_exists('show_mode', $field_options) ? $field_options['show_mode'] : true; } else { $show_mode = true; } if ( ($show_mode === true) || (($show_mode === smDEBUG) && (defined('DEBUG_MODE') && DEBUG_MODE)) ) { // field is visible return true; } } return false; } /** * Returns field definition * * @param string $field_name * @return Array * @access protected */ protected function _getFieldDefinition($field_name) { $config = $this->getUnitConfig(); $ret = $config->getFieldByName($field_name); if ( !$ret ) { $ret = $config->getVirtualFieldByName($field_name); } return $ret; } /** * Checks, that requested option is checked inside field value. * * @param array $params Tag params. * * @return boolean */ protected function Selected(array $params) { /** @var kDBItem $object */ $object = $this->getObject($params); $field = $this->SelectParam($params, 'name,field'); $value = $object->GetDBField($field); if ( strpos($value, '|') !== false ) { $selected_values = explode('|', substr($value, 1, -1)); } else { $selected_values = array((string)$value); } return in_array((string)$params['value'], $selected_values, true); } /** * Displays option name by it's value * * @param Array $params * @return string * @access protected */ protected function OptionValue($params) { /** @var kDBItem $object */ $object = $this->getObject($params); $value = $params['value']; $field = $this->SelectParam($params, 'name,field'); $field_options = $object->GetFieldOptions($field); if ( isset($field_options['options'][$value]) ) { $value = $field_options['options'][$value]; $use_phrases = isset($field_options['use_phrases']) ? $field_options['use_phrases'] : false; return $use_phrases ? $this->Application->Phrase($value) : $value; } return ''; } /** * Returns/sets form name for current object * * @param Array $params * @return string */ function FormName($params) { $form_name = $this->SelectParam($params, 'name,form,form_name'); if ( $form_name ) { $prefix = $this->getPrefixSpecial(); if ( $this->Application->hasObject( $this->getPrefixSpecial() ) ) { /** @var kDBItem $object */ $object = $this->getObject($params); if ( $object->getFormName() != $form_name ) { trigger_error('Setting form to "' . $form_name . '" failed, since object "' . $this->getPrefixSpecial() . '" is created before FormName tag (e.g. in event or another tag).', E_USER_WARNING); } } else { $forms = $this->Application->GetVar('forms', Array ()); $forms[ $this->getPrefixSpecial() ] = $form_name; $this->Application->SetVar('forms', $forms); } return ''; } /** @var kDBItem $object */ $object = $this->getObject($params); return $object->getFormName(); } /** * Just reloads the object using given parameters * * @param Array $params * @return string * @access protected */ protected function ReloadItem($params) { $params['requery'] = 1; /** @var kDBItem $object */ $object = $this->getObject($params); return ''; } } Index: branches/5.3.x/core/units/configuration/configuration_config.php =================================================================== --- branches/5.3.x/core/units/configuration/configuration_config.php (revision 16717) +++ branches/5.3.x/core/units/configuration/configuration_config.php (revision 16718) @@ -1,126 +1,126 @@ 'conf', 'ItemClass' => Array ('class' => 'ConfigurationItem', 'file' => 'configuration.php', 'build_event' => 'OnItemBuild'), 'ListClass' => Array ('class' => 'kDBList', 'file' => '', 'build_event' => 'OnListBuild'), 'EventHandlerClass' => Array ('class' => 'ConfigurationEventHandler', 'file' => 'configuration_event_handler.php', 'build_event' => 'OnBuild'), 'TagProcessorClass' => Array ('class' => 'ConfigurationTagProcessor', 'file' => 'configuration_tag_processor.php', 'build_event' => 'OnBuild'), 'ValidatorClass' => 'ConfigurationValidator', 'AutoLoad' => true, 'RegisterClasses' => Array ( Array ('pseudo' => 'ConfigurationValidator', 'class' => 'ConfigurationValidator', 'file' => 'configuration_validator.php', 'build_event' => ''), ), 'QueryString' => Array ( 1 => 'id', 2 => 'Page', 3 => 'PerPage', 4 => 'event', 5 => 'mode', ), 'IDField' => 'VariableId', 'TitleField' => 'VariableName', 'TitlePresets' => Array ( 'default' => Array ('tag_params' => Array ('conf' => Array ('per_page' => -1))), 'config_list_general' => Array ('prefixes' => Array ('conf_List'), 'format' => "!la_updating_config!"), 'config_list_output' => Array ('prefixes' => Array ('conf_List'), 'format' => "!la_updating_config!"), 'config_list_contacts' => Array ('prefixes' => Array ('conf_List'), 'format' => "!la_updating_config!"), 'config_list_categories' => Array ('prefixes' => Array ('conf_List'), 'format' => "!la_updating_config!"), 'config_list_users' => Array ('prefixes' => Array ('conf_List'), 'format' => "!la_updating_config!"), 'section_label' => Array ('prefixes' => Array ('conf_List'), 'format' => "#section_label#"), 'config_edit' => Array ( 'new_status_labels' => Array ('conf' => '!la_title_AddingSystemSetting!'), 'edit_status_labels' => Array ('conf' => '!la_title_EditingSystemSetting!'), 'prefixes' => Array ('conf'), 'format' => "#conf_status# '#conf_titlefield#'", ), ), 'TableName' => TABLE_PREFIX . 'SystemSettings', 'ListSQLs' => Array ( '' => ' SELECT %1$s.* %2$s FROM %1$s' ), 'ListSortings' => Array ( '' => Array ( 'Sorting' => Array ('DisplayOrder' => 'asc', 'GroupDisplayOrder' => 'asc'), ) ), 'Fields' => Array ( 'VariableId' => Array ('type' => 'int', 'not_null' => 1, 'default' => 0), 'VariableName' => Array ( 'type' => 'string', 'formatter' => 'kFormatter', 'regexp' => '/^[a-z0-9_]+$/i', 'not_null' => 1, 'required' => 1, 'default' => '' ), 'VariableValue' => Array ('type' => 'string', 'default' => NULL), 'ModuleOwner' => Array ( 'type' => 'string', 'formatter' => 'kOptionsFormatter', 'options' => Array (), 'required' => 1, 'default' => 'In-Portal' ), 'Section' => Array ( 'type' => 'string', 'error_msgs' => Array ('unknown_section' => '!la_error_UnknownSection!'), 'not_null' => 1, 'required' => 1, 'default' => '' ), 'Heading' => Array ( 'type' => 'string', 'formatter' => 'kFormatter', 'regexp' => '/^la_section_[A-Z\d:_\-\.]+$/i', 'not_null' => 1, 'required' => 1, 'default' => '' ), 'Prompt' => Array ( 'type' => 'string', 'formatter' => 'kFormatter', 'regexp' => '/^la_config_[A-Z\d:_\-\.]+$/i', 'not_null' => 1, 'required' => 1, 'default' => '' ), 'ElementType' => Array ( 'type' => 'string', - 'formatter' => 'kOptionsFormatter', 'options' => Array ('text' => 'la_type_text', 'select' => 'la_type_select', 'multiselect' => 'la_type_multiselect', 'radio' => 'la_type_radio', 'checkbox' => 'la_type_checkbox', 'password' => 'la_type_password', 'textarea' => 'la_type_textarea'), 'use_phrases' => 1, + 'formatter' => 'kOptionsFormatter', 'options' => Array ('text' => 'la_type_text', 'select' => 'la_type_select', 'multiselect' => 'la_type_multiselect', 'radio' => 'la_type_radio', 'checkbox' => 'la_type_checkbox', 'password' => 'la_type_password', 'textarea' => 'la_type_textarea', 'picker' => 'la_type_picker'), 'use_phrases' => 1, 'not_null' => 1, 'required' => 1, 'default' => '' ), 'Validation' => Array ('type' => 'string', 'default' => NULL), 'ValueList' => Array ('type' => 'string', 'default' => NULL), 'DisplayOrder' => Array ( 'type' => 'float', 'unique' => Array ('ModuleOwner', 'Section', 'GroupDisplayOrder'), 'not_null' => 1, 'required' => 1, 'default' => 0 ), 'GroupDisplayOrder' => Array ( 'type' => 'float', 'unique' => Array ('ModuleOwner', 'Section', 'DisplayOrder'), 'not_null' => 1, 'required' => 1, 'default' => 0 ), 'Install' => Array ('type' => 'int', 'not_null' => 1, 'default' => 1), 'HintLabel' => Array ('type' => 'string', 'max_len' => 255, 'default' => NULL), ), 'VirtualFields' => Array ( 'DirectOptions' => Array ('type' => 'string', 'default' => ''), ), -); \ No newline at end of file +); Index: branches/5.3.x/core/admin_templates/incs/config_blocks.tpl =================================================================== --- branches/5.3.x/core/admin_templates/incs/config_blocks.tpl (revision 16717) +++ branches/5.3.x/core/admin_templates/incs/config_blocks.tpl (revision 16718) @@ -1,131 +1,171 @@ style="width:100%"/>  "> + + + + + + + + + + + + + + + + +
+ + + +   + + + +
+ + + +
+
+ +
+ +
+
+ class="" onclick="update_checkbox(this, document.getElementById(''))"> name="" id="_" value="">   *: <inp2:Field name='HintLabel' as_label='1' html_escape='1'/>
[] [
', this.href);">] ');" id="toggle_mark[]" title="Collapse/Expand Section">[-] _" header_label="">   ');" id="toggle_mark[]" title="Collapse/Expand Section">[-] _" header_label="">  
Index: branches/5.3.x/core/install/english.lang =================================================================== --- branches/5.3.x/core/install/english.lang (revision 16717) +++ branches/5.3.x/core/install/english.lang (revision 16718) @@ -1,2257 +1,2258 @@ JGJvZHkNCjxici8+PGJyLz4NCg0KU2luY2VyZWx5LDxici8+PGJyLz4NCg0KV2Vic2l0ZSBhZG1pbmlzdHJhdGlvbi4NCg0KPCEtLSMjIDxpbnAyOmVtYWlsLWxvZ19JdGVtTGluayB0ZW1wbGF0ZT0icGxhdGZvcm0vbXlfYWNjb3VudC9lbWFpbCIvPiAjIy0tPg== QWN0aXZl QWRk QWRkIFRv QWRtaW5pc3RyYXRpdmUgQ29uc29sZQ== YWxsb3cgY2hhbmdpbmc= QWxsb3cgZGVsZXRpbmcgTW9kdWxlIFJvb3QgU2VjdGlvbg== VmlldyBpbiBCcm93c2UgTW9kZQ== R28gSW5zaWRl QWx3YXlz YW5k QXV0bw== QXV0b21hdGlj QXZhaWxhYmxlIENvbHVtbnM= QXZhaWxhYmxlIEl0ZW1z QmFja2dyb3VuZA== Qm9yZGVycw== QWRk RWRpdCBJdGVt QnJvd3NlIE1vZGU= Q2FuY2Vs Q2hhbmdl Q2xlYXI= Q29udGVudCBNb2Rl RGVsZXRl RGVsZXRl ZGVsZXRlIHJldmlldw== RGVwbG95 RGVzaWduIE1vZGU= RG93bg== RHVtcA== RWRpdA== RWRpdCBCbG9jaw== RWRpdCBDb250ZW50 RWRpdCBEZXNpZ24= R2VuZXJhdGU= R2VuZXJhdGUgUGFnZQ== R2V0IFZhbHVl TG9jYXRl TW92ZSBEb3du TW92ZSBVcA== UHVibGlzaGluZyBUb29scw== UmVidWlsZA== UmVjb21waWxl UmVmcmVzaA== UmVzZXQ= UmVzZXQgJmFtcDsgVmFsaWRhdGUgQ29uZmlnIEZpbGVz UmVzZXQgInJvb3QiIHBhc3N3b3Jk U2F2ZQ== U2F2ZSBDaGFuZ2Vz U2VjdGlvbiBQcm9wZXJ0aWVz U2VjdGlvbiBUZW1wbGF0ZQ== U2VsZWN0IEFsbA== U2V0IFZhbHVl U2hvdyBTdHJ1Y3R1cmU= U3luY2hyb25pemU= VW5zZWxlY3Q= VXA= VXNl Ynk= Q2FuY2Vs U2VjdGlvbg== TnVtYmVyIG9mIGRheXMgZm9yIGEgY2F0LiB0byBiZSBORVc= RGVmYXVsdCBNRVRBIGRlc2NyaXB0aW9u RGVmYXVsdCBNRVRBIEtleXdvcmRz TnVtYmVyIG9mIHNlY3Rpb25zIHBlciBwYWdl U2VjdGlvbnMgUGVyIFBhZ2UgKFNob3J0bGlzdCk= RGlzcGxheSBlZGl0b3IgUElDS3MgYWJvdmUgcmVndWxhciBzZWN0aW9ucw== QW5kIHRoZW4gYnk= T3JkZXIgc2VjdGlvbnMgYnk= Q2xvc2U= QWNjZXNz QWRkaXRpb25hbA== QWZmZWN0ZWQgSXRlbXM= QWx0IFZhbHVl QnVpbGQgRGF0ZQ== U2VjdGlvbiBOYW1l Q29sdW1uIFBocmFzZQ== RWZmZWN0aXZl RS1tYWlsIFRlbXBsYXRlcw== RW5hYmxlIEUtbWFpbCBDb21tdW5pY2F0aW9u Jm5ic3A7 RXZlbnQgRGVzY3JpcHRpb24= RXZlbnQgUGFyYW1z SGludCBQaHJhc2U= U3RhdHVz SW1hZ2U= VVJM SW5oZXJpdGVk SW5oZXJpdGVkIEZyb20= SW4gTWVudQ== SVAgQWRkcmVzcw== UG9wdWxhcg== VXNlciBQcmltYXJ5 S2V5d29yZA== TGFiZWw= TGFuZ3VhZ2UgUGFjayBJbnN0YWxsZWQ= TGFzdCBDaGFuZ2Vk TGFzdCBDb21waWxlZA== TGFzdCBBdHRlbXB0 TGluayBVUkw= TWFpbGluZyBMaXN0 TWVtYmVyc2hpcCBFeHBpcmVz TWVzc2FnZSBIZWFkZXJz SFRNTA== T3JpZ2luYWwgVmFsdWU= UGF0aA== QWRk RGVsZXRl RWRpdA== UGVybWlzc2lvbiBOYW1l QWNjZXNz Vmlldw== UGhyYXNlcw== VXNlciBJRA== UHJldmlldw== UHJpbWFyeSBHcm91cA== UHJpbWFyeSBWYWx1ZQ== RmllbGQgUHJvbXB0 UXVldWVk UmVmZXJlcg== UmVzZXQgdG8gZGVmYXVsdA== Q29tbWVudHM= Q3JlYXRlZCBieQ== U2NoZWR1bGUgRnJvbSBEYXRl U2NoZWR1bGUgVG8gRGF0ZQ== QXR0ZW1wdHMg U2Vzc2lvbiBFbmQ= U2Vzc2lvbiBTdGFydA== U29ydCBieQ== VHlwZQ== U3lzdGVtIFBhdGg= SXRlbSBUeXBl VXNlcnM= TGFzdG5hbWUgRmlyc3RuYW1l RmllbGQgVmFsdWU= VmlzaWJsZQ== VmlzaXQgRGF0ZQ== QXNjZW5kaW5n RGVzY2VuZGluZw== QWRtaW4gQ29uc29sZSBJbnRlcmZhY2U= U1NMIERvbWFpbiBmb3IgQWRtaW5pc3RyYXRpdmUgQ29uc29sZSAod3d3LmRvbWFpbi5jb20p QWxsb3cgdG8gc2VsZWN0IG1lbWJlcnNoaXAgZ3JvdXAgb24gRnJvbnQtZW5k TGlzdCBhdXRvbWF0aWMgcmVmcmVzaCBpbnRlcnZhbHMgKGluIG1pbnV0ZXMp QmFja3VwIFBhdGg= U3dpdGNoIENhdGFsb2cgdGFicyBiYXNlZCBvbiBNb2R1bGU= U2VjdGlvbiBQZXJtaXNzaW9uIFJlYnVpbGQgTW9kZQ== Q2hlY2sgU3RvcCBXb3Jkcw== RW5hYmxlICJWaWV3IFBlcm1pc3Npb25zIiBDaGVjayBpbiBDYXRhbG9n Q0tGaW5kZXIgTGljZW5zZSBLZXk= Q0tGaW5kZXIgTGljZW5zZSBOYW1l RGVmYXVsdCBDU1YgRXhwb3J0IERlbGltaXRlcg== RGVmYXVsdCBDU1YgRXhwb3J0IEVuY2xvc3VyZSBDaGFyYWN0ZXI= RGVmYXVsdCBDU1YgRXhwb3J0IEVuY29kaW5n RGVmYXVsdCBDU1YgRXhwb3J0IE5ldyBMaW5lIFNlcGFyYXRvcg== U2hvdyAiRm9ybXMgRWRpdG9yIiBpbiBERUJVRyBtb2RlIG9ubHk= U2hvdyAiUHJvbW8gQmxvY2sgR3JvdXBzIEVkaXRvciIgaW4gREVCVUcgbW9kZSBvbmx5 RGVmYXVsdCBEZXNpZ24gVGVtcGxhdGU= RGVmYXVsdCBFLW1haWwgUmVjaXBpZW50cw== RGVmYXVsdCAiUGVyIFBhZ2UiIHNldHRpbmcgaW4gR3JpZHM= RGVmYXVsdCBSZWdpc3RyYXRpb24gQ291bnRyeQ== RGVmYXVsdCBBbmFseXRpY3MgVHJhY2tpbmcgQ29kZQ== RW1haWwgRGVsaXZlcnk= S2VlcCAiRS1tYWlsIExvZyIgZm9y RW5hYmxlICJFLW1haWwgTG9nIg== RW5hYmxlIFJldmlzaW9uIENvbnRyb2wgZm9yIFNlY3Rpb24gQ29udGVudA== VGVtcGxhdGUgZm9yICJGaWxlIG5vdCBmb3VuZCAoNDA0KSIgRXJyb3I= RXhjbHVkZSB0ZW1wbGF0ZSBiYXNlZCBTZWN0aW9ucyBmcm9tIFNlYXJjaCBSZXN1bHRzIChpZS4gVXNlciBSZWdpc3RyYXRpb24p RmlsZW5hbWUgU3BlY2lhbCBDaGFyIFJlcGxhY2VtZW50 Rmlyc3QgRGF5IE9mIFdlZWs= Rm9yY2UgQ2Fub25pY2FsIFVSTHM= QWx3YXlzIHVzZSBJbWFnZU1hZ2ljayB0byByZXNpemUgaW1hZ2Vz Rm9yY2UgUmVkaXJlY3QgdG8gU2VsZWN0ZWQgVVJMIEVuZGluZw== UmVkaXJlY3QgdG8gSFRUUCB3aGVuIFNTTCBpcyBub3QgcmVxdWlyZWQ= RnVsbCBpbWFnZSBIZWlnaHQ= RnVsbCBpbWFnZSBXaWR0aA== VGVtcGxhdGUgZm9yIEhhcmQgTWFpbnRlbmFuY2U= QnlwYXNzIEhUVFAgQXV0aGVudGljYXRpb24gZnJvbSBJUHMgKHNlcGFyYXRlZCBieSBzZW1pY29sb25zKQ== UGFzc3dvcmQgZm9yIEhUVFAgQXV0aGVudGljYXRpb24= VXNlcm5hbWUgZm9yIEhUVFAgQXV0aGVudGljYXRpb24= S2VlcCBTZXNzaW9uIGFsaXZlIG9uIEJyb3dzZXIgY2xvc2U= TWFpbCBGdW5jdGlvbiBIZWFkZXIgU2VwYXJhdG9y TWFpbGluZyBMaXN0IFF1ZXVlIFBlciBTdGVw TWFpbGluZyBMaXN0IFNlbmQgUGVyIFN0ZXA= TWFpbnRlbmFuY2UgTWVzc2FnZSBmb3IgQWRtaW4= TWFpbnRlbmFuY2UgTWVzc2FnZSBmb3IgRnJvbnQgRW5k TWF4aW11bSBudW1iZXIgb2YgaW1hZ2Vz RGVmYXVsdCBVUkwgRW5kaW5nIGluIFNFTy1mcmllbmRseSBtb2Rl VGVtcGxhdGUgZm9yICJJbnN1ZmZpY2llbnQgUGVybWlzc2lvbnMiIEVycm9y R1pJUCBjb21wcmVzc2lvbiBsZXZlbCAwLTk= UGF0aCB0byBXZWJzaXRl UGVyZm9ybSBFeGFjdCBTZWFyY2g= Q29tbWVudHMgcGVyIHBhZ2U= UGxhaW4gVGV4dCBDb29raWVz UmFuZG9tIFN0cmluZw== IlJlY3ljbGUgQmluIiBTZWN0aW9uSWQ= VXNlcm5hbWUgUmVxdWlyZWQgRHVyaW5nIFJlZ2lzdHJhdGlvbg== UmVzdG9yZSBsYXN0IHZpc2l0ZWQgQWRtaW4gU2VjdGlvbiBhZnRlciBMb2dpbg== UmVxdWlyZSBTU0wgZm9yIEFkbWluaXN0cmF0aXZlIENvbnNvbGU= UmVxdWlyZSBTU0wgZm9yIGxvZ2luICYgY2hlY2tvdXQ= RnJhbWVzIGluIGFkbWluaXN0cmF0aXZlIGNvbnNvbGUgYXJlIHJlc2l6YWJsZQ== TWluaW1hbCBTZWFyY2ggS2V5d29yZCBMZW5ndGg= U2Vzc2lvbiBTZWN1cml0eSBDaGVjayBiYXNlZCBvbiBCcm93c2VyIFNpZ25hdHVyZQ== U2Vzc2lvbiBDb29raWUgRG9tYWlucyAoc2luZ2xlIGRvbWFpbiBwZXIgbGluZSk= U2Vzc2lvbiBTZWN1cml0eSBDaGVjayBiYXNlZCBvbiBJUA== S2VlcCAiU2Vzc2lvbiBMb2ciIGZvcg== V2Vic2l0ZSBTdWJ0aXRsZQ== VGltZSB6b25lIG9mIHRoZSBzaXRl VGVtcGxhdGUgZm9yIFNvZnQgTWFpbnRlbmFuY2U= U1NMIERvbWFpbiAod3d3LmRvbWFpbi5jb20p VXNlIFN0aWNreSBHcmlkIFNlbGVjdGlvbg== U2VuZCBVc2VyLWRlZmluZWQgIlN5c3RlbSBMb2ciIG1lc3NhZ2VzIHRv S2VlcCAiU3lzdGVtIExvZyIgZm9y VGh1bWJuYWlsIEhlaWdodA== VGh1bWJuYWlsIFdpZHRo VHJpbSBSZXF1aXJlZCBGaWVsZHM= VHlwZUtpdCBJRA== VXBkYXRlIGNvdW50ZXJzIChpbiBvdGhlciBmaWx0ZXJzKSBvbiBmaWx0ZXIgY2hhbmdl VHJhY2sgZGF0YWJhc2UgY2hhbmdlcyB0byBjaGFuZ2UgbG9n VXNlIENvbHVtbiBGcmVlemVy QXV0by1kZXRlY3QgVXNlcidzIGxhbmd1YWdlIGJhc2VkIG9uIGl0J3MgQnJvd3NlciBzZXR0aW5ncw== VXNlIERvdWJsZSBTb3J0aW5n RW5hYmxlIEhUVFAgQXV0aGVudGljYXRpb24= RW5hYmxlIEhUTUwgR1pJUCBjb21wcmVzc2lvbg== VXNlIFBhZ2VIaXQgY291bnRlcg== RWRpdGluZyBXaW5kb3cgU3R5bGU= RW1haWwgYWN0aXZhdGlvbiBleHBpcmF0aW9uIHRpbWVvdXQgKGluIG1pbnV0ZXMp VXNlIFNtYWxsIFNlY3Rpb24gSGVhZGVycw== VXNlIFRvb2xiYXIgTGFiZWxz VXNlIFZpc2l0b3IgVHJhY2tpbmc= VXNlIEphdmFTY3JpcHQgcmVkaXJlY3Rpb24gYWZ0ZXIgbG9naW4vbG9nb3V0IChmb3IgSUlTKQ== RW5hYmxlIFNFTy1mcmllbmRseSBVUkxzIG1vZGUgKE1PRC1SRVdSSVRFKQ== RW5hYmxlIE1PRF9SRVdSSVRFIGZvciBTU0w= V2Vic2l0ZSBuYW1l WWFob28gQXBwbGljYXRpb25JZA== QXJlIHlvdSBzdXJlIHlvdSB3YW50IHRvIGRlbGV0ZSBzZWxlY3RlZCBFeHBvcnQgUHJlc2V0Pw== VGhlIHNlY3Rpb24gdHJlZSBtdXN0IGJlIHVwZGF0ZWQgdG8gcmVmbGVjdCB0aGUgbGF0ZXN0IGNoYW5nZXM= Q3VycmVudCBUaGVtZQ== RGF0YSBHcmlkcw== RGF0YSBHcmlkcyAy ZGF5cw== QXJlIHlvdSBzdXJlIHlvdSB3YW50IHRvIGRlbGV0ZSB0aGUgaXRlbShzKT8gVGhpcyBhY3Rpb24gY2Fubm90IGJlIHVuZG9uZS4= VGhpcyBzZWN0aW9uIGFsbG93cyB5b3UgdG8gbWFuYWdlIHNlY3Rpb25zIGFuZCBpdGVtcyBhY3Jvc3MgYWxsIHNlY3Rpb25z VGhpcyBzZWN0aW9uIGFsbG93cyB5b3UgdG8gYnJvd3NlIHRoZSBjYXRhbG9nIGFuZCBtYW5hZ2Ugc2VjdGlvbnMgYW5kIGl0ZW1z TWFuYWdlIHRoZSBzdHJ1Y3R1cmUgb2YgeW91ciBzaXRlLCBpbmNsdWRpbmcgc2VjdGlvbnMsIGl0ZW1zIGFuZCBzZWN0aW9uIHNldHRpbmdzLg== RGlzYWJsZWQ= RG91YmxlLVF1b3Rlcw== RG93bmxvYWQgQ1NW RG93bmxvYWQgRXhwb3J0IEZpbGU= RG93bmxvYWQgTGFuZ3VhZ2UgRXhwb3J0 RHJhZnQ= RHJhZnQgQXZhaWxhYmxl ZHJhZnQgc2F2ZWQgYXQgJXM= Q29udGVudCBFZGl0b3I= WW91IGhhdmUgbm90IHNhdmVkIGNoYW5nZXMgdG8gdGhlIGl0ZW0geW91IGFyZSBlZGl0aW5nITxiciAvPkNsaWNrIE9LIHRvIGxvb3NlIGNoYW5nZXMgYW5kIGdvIHRvIHRoZSBzZWxlY3RlZCBzZWN0aW9uPGJyIC8+b3IgQ2FuY2VsIHRvIHN0YXkgaW4gdGhlIGN1cnJlbnQgc2VjdGlvbi4= RGVmYXVsdCB0ZXh0 RmlsZSBpcyBlbXB0eQ== RmlsZSBpcyBlbXB0eQ== RW5hYmxlZA== Q2FuJ3QgZGVsZXRlIHN5c3RlbSBwZXJtaXNzaW9u Q2FuJ3Qgb3BlbiB0aGUgZmlsZQ== Q2FuJ3Qgc2F2ZSBhIGZpbGU= Q29ubmVjdGlvbiBGYWlsZWQ= RXJyb3IgY29weWluZyBzdWJzZWN0aW9ucw== Q3VzdG9tIGZpZWxkIHdpdGggaWRlbnRpY2FsIG5hbWUgYWxyZWFkeSBleGlzdHM= RW1haWwgRGVzaWduIFRlbXBsYXRlIHNob3VsZCBjb250YWluIGF0IGxlYXN0ICIkYm9keSIgdGFnIGluIGl0Lg== RmlsZSBub3QgZm91bmQ= RmlsZSBpcyB0b28gbGFyZ2U= VGhpcyBVUkwgaXMgY29uZmxpY3Rpbmcgd2l0aCBleGlzdGluZyBVUkwgYW5kIGNhbid0IGJlIHVzZWQ= Z3JvdXAgbm90IGZvdW5k RmllbGQgZG9lc24ndCBleGlzdCBpbiAiJXMiIHVuaXQgY29uZmln SW52YWxpZCBGaWxlIEZvcm1hdA== VW5pdCBjb25maWcgcHJlZml4IG5vdCBmb3VuZA== aW52YWxpZCBvcHRpb24= VGhlIHVzZXJuYW1lIGNhbiBjb250YWluIG9ubHk6IGxldHRlcnMsIG51bWJlcnMsIHVuZGVyc2NvcmVzLCBkYXNoZXMgYW5kIGRvdHM= TG9naW4gRmFpbGVk UmVjZWl2aW5nIGxpc3Qgb2YgbWVzc2FnZXMgZnJvbSB0aGUgU2VydmVyIGhhcyBmYWlsZWQ= RXJyb3IgbW92aW5nIHN1YnNlY3Rpb24= Q2FuJ3QgaW5oZXJpdCB0ZW1wbGF0ZSBmcm9tIHRvcCBjYXRlZ29yeQ== Tm8gbWF0Y2hpbmcgY29sdW1ucyBhcmUgZm91bmQ= VGhpcyBvcGVyYXRpb24gaXMgbm90IGFsbG93ZWQh VmFsaWRhdGlvbiBlcnJvciwgcGxlYXNlIGRvdWJsZS1jaGVjayBJbi1Qb3J0YWwgdGFncw== UGFzc3dvcmRzIGRvIG5vdCBtYXRjaCE= Q2FuJ3QgRGVsZXRlIE5vbi1FbXB0eSBQcm9tbyBCbG9jayBHcm91cA== UmVxdWlyZWQgZmllbGQoLXMpIG5vdCBmaWxsZWQ= cmVxdWlyZWQgY29sdW1ucyBtaXNzaW5n Um9vdCBzZWN0aW9uIG9mIHRoZSBtb2R1bGUocykgY2FuIG5vdCBiZSBkZWxldGVkIQ== U2VsZWN0IGF0IGxlYXN0IG9uZSBpdGVtIHRvIG1vdmU= VGVtcGxhdGUgZmlsZSBpcyBtaXNzaW5n Q29weWluZyBvcGVyYXRpb24gaW4gVGVtcG9yYXJ5IHRhYmxlcyBoYXMgZmFpbGVkLiBQbGVhc2UgY29udGFjdCB3ZWJzaXRlIGFkbWluaXN0cmF0b3Iu UmVjb3JkIGlzIG5vdCB1bmlxdWU= U2VjdGlvbiBmaWVsZCBub3QgdW5pcXVl VW5rbm93biBzZWN0aW9u VW5rbm93biBzZWN0aW9u VXNlciBCYW5uZWQ= dXNlciBub3QgZm91bmQ= IlNjaGVkdWxlZCBUbyIgZGF0ZS90aW1lIG11c3QgYmUgYmVmb3JlICJTY2hlZHVsZWQgRnJvbSI= WW91IG11c3Qgc2VsZWN0IG9ubHkgb25lIHVzZXI= SW5jb3JyZWN0IGRhdGUgZm9ybWF0LCBwbGVhc2UgdXNlICh7Zm9ybWF0fSkgZXguICh7c2FtcGxlfSk= SW5jb3JyZWN0IGRhdGEgZm9ybWF0LCBwbGVhc2UgdXNlIHt0eXBlfQ== SW52YWxpZCBGb3JtYXQ= RmllbGQgdmFsdWUgbGVuZ3RoIGlzIG91dCBvZiByYW5nZSwgcG9zc2libGUgdmFsdWUgbGVuZ3RoIGZyb20ge21pbl9sZW5ndGh9IHRvIHttYXhfbGVuZ3RofQ== UHJpbWFyeSBMYW5nLiB2YWx1ZSBSZXF1aXJlZA== RmllbGQgaXMgcmVxdWlyZWQ= RmllbGQgdmFsdWUgbXVzdCBiZSB1bmlxdWU= RmllbGQgdmFsdWUgaXMgb3V0IG9mIHJhbmdlLCBwb3NzaWJsZSB2YWx1ZXMgZnJvbSB7bWluX3ZhbHVlfSB0byB7bWF4X3ZhbHVlfQ== RXhwb3J0IGZvbGRlciBpcyBub3Qgd3JpdGFibGU= RXJyb3IgY3JlYXRpbmcgZm9sZGVyLiBFcnJvciBudW1iZXI6 UGxlYXNlIG5hbWUgeW91ciBmaWxlcyB0byBiZSB3ZWItZnJpZW5kbHkuIFdlIHJlY29tbWVuZCB1c2luZyBvbmx5IHRoZXNlIGNoYXJhY3RlcnMgaW4gZmlsZSBuYW1lczogDQpMZXR0ZXJzIGEteiwgQS1aLCBOdW1iZXJzIDAtOSwgIl8iICh1bmRlcnNjb3JlKSwgIi0iIChkYXNoKSwgIiAiIChzcGFjZSksICIuIiAocGVyaW9kKQ0KUGxlYXNlIGF2b2lkIHVzaW5nIGFueSBvdGhlciBjaGFyYWN0ZXJzIGxpa2UgcXVvdGVzLCBicmFja2V0cywgcXVvdGF0aW9uIG1hcmtzLCAiPyIsICIhIiwgIj0iLCBmb3JlaWduIHN5bWJvbHMsIGV0Yy4= RXJyb3Igb24gZmlsZSB1cGxvYWQuIEVycm9yIG51bWJlcjo= QSBmaWxlIHdpdGggdGhlIHNhbWUgbmFtZSBpcyBhbHJlYWR5IGF2YWlsYWJsZQ== RGF0ZQ== RmlsZSBOYW1l U2l6ZQ== Rm9sZGVyIGFscmVhZHkgZXhpc3Rz SW52YWxpZCBmaWxlIHR5cGUgZm9yIHRoaXMgZm9kZXI= SW52YWxpZCBmb2xkZXIgbmFtZQ== WW91IGhhdmUgbm8gcGVybWlzc2lvbnMgdG8gY3JlYXRlIHRoZSBmb2xkZXI= UGxlYXNlIHR5cGUgdGhlIGZvbGRlciBuYW1l VHlwZSB0aGUgbmFtZSBvZiB0aGUgbmV3IGZvbGRlcjo= VW5rbm93biBlcnJvciBjcmVhdGluZyBmb2xkZXI= RmllbGQ= RGlzcGxheSBPcmRlcg== T3JkZXI= QWN0aW9u QWRkcmVzcyBMaW5lIDE= QWRkcmVzcyBMaW5lIDI= TWVzc2FnZXMgZnJvbSBTaXRlIEFkbWluIGFyZSBmcm9t QWRtaW4gUHJpbWFyeQ== TGFuZ3VhZ2U= QWR2YW5jZWQgQ1NT QWR2YW5jZWQgU2VhcmNo QWxsb3cgQ2hhbmdpbmcgIlRvIiBSZWNpcGllbnQ= QWxsb3cgQ2hhbmdpbmcgU2VuZGVy QWx0IFZhbHVl QW5zd2Vy QXNzaWduZWQgdG8gU2VjdGlvbnM= QXR0YWNobWVudA== QXV0byBDcmVhdGUgRmlsZSBOYW1l QXV0b21hdGljIEZpbGVuYW1l QXZhaWxhYmxlIENvbHVtbnM= QmFja2dyb3VuZA== QmFja2dyb3VuZCBBdHRhY2htZW50 QmFja2dyb3VuZCBDb2xvcg== QmFja2dyb3VuZCBJbWFnZQ== QmFja2dyb3VuZCBQb3NpdGlvbg== QmFja2dyb3VuZCBSZXBlYXQ= QmNj QmluZCB0byBTeXN0ZW0gRXZlbnQ= RWxlbWVudCBQb3NpdGlvbg== Qm9yZGVyIEJvdHRvbQ== Qm9yZGVyIExlZnQ= Qm9yZGVyIFJpZ2h0 Qm9yZGVycw== Qm9yZGVyIFRvcA== Qm91bmNlIERhdGU= Qm91bmNlIEVtYWls Qm91bmNlIEluZm8= QnV0dG9uIFRleHQ= U2VjdGlvbg== U2VjdGlvbiBGb3JtYXQ= U2VjdGlvbiBJRA== U2VjdGlvbiBzZXBhcmF0b3I= U2VjdGlvbiBUZW1wbGF0ZQ== Q2M= Q2hhbmdlcw== Q2hhcnNldA== Q2hlY2sgRHVwbGljYXRlcyBieQ== Q2l0eQ== Q29sdW1uIFBocmFzZQ== Q29tbWVudHM= Q29tcGFueQ== Q29uZmlndXJhdGlvbiBIZWFkZXIgTGFiZWw= Q29udGVudCBCbG9jaw== Q1RSLCAl Q29weSBMYWJlbHMgZnJvbSB0aGlzIExhbmd1YWdl Q291bnRyeQ== Q3JlYXRlZCBCeQ== Q3JlYXRlZCBPbg== Q29tbW9uIFNldHRpbmdz RGF5 SG91cg== TWludXRl TW9udGg= V2Vla2RheQ== Q1NTIFRlbXBsYXRl Q1NTIENsYXNzIE5hbWU= Q3Vyc29y Q3VzdG9tIERldGFpbHMgVGVtcGxhdGU= U2VuZCBFbWFpbCBUbw== U2VuZCBFbWFpbCBGcm9t DQoNCg0KDQoNCg0KDQoNCg0KDQoNCg0KDQoNCg0KDQoNCg0KDQoNCg0KDQoNCg0KDQoNCg0KRGV0YWlscyBUZW1wbGF0ZQ== RGF0ZSBGb3JtYXQ= RGVjaW1hbCBQb2ludA== RGVzY3JpcHRpb24= QWNjZXNzIHdpdGggTGluaw== RGlzcGxheQ== RGlzcGxheSBpbiBHcmlk RmllbGQgTGFiZWw= RGlzcGxheSBzaXRlIG5hbWUgaW4gSGVhZGVy RGlzcGxheSBUbyBQdWJsaWM= UmFuZ2Ugb2YgSVBz RG9tYWluIE5hbWU= QXMgUGxhaW4gVGV4dA== RHVyYXRpb24= RWRpdG9ycyBQaWNr RWxhcHNlZCBUaW1l RS1tYWls RS1tYWlsIENvbW11bmljYXRpb24gUm9sZQ== RS1tYWlsIG9yIFVzZXJuYW1l RS1tYWlsICI8c3Ryb25nPntwYXNzd29yZH08L3N0cm9uZz4iIHBhc3N3b3JkIHRvIHVzZXI= RW1haWxzIGluIFF1ZXVl RW1haWxzIFNlbnQ= RW1haWxzIFRvdGFs RS1tYWlsIFRlbXBsYXRlIE5hbWU= RW1haWwgVmVyaWZpZWQ= RW5hYmxl RW5hYmxlZA== RW5hYmxlIENhY2hpbmcgZm9yIHRoaXMgU2VjdGlvbg== RXJyb3IgTWVzc2FnZQ== RXJyb3IgVGFn RXN0aW1hdGVkIFRpbWU= RXZlbnQ= RXhwaXJl RXhwb3J0IGNvbHVtbnM= RXhwb3J0IFNwZWNpZmllZCBDb3VudHJpZXM= RGF0YSBUeXBlcyB0byBFeHBvcnQ= RXhwb3J0IFNwZWNpZmllZCBFLW1haWwgVGVtcGxhdGVz RXhwb3J0IEZpbGVuYW1l RXhwb3J0IGZvcm1hdA== RXhwb3J0IE1vZHVsZXM= RXhwb3J0IFNwZWNpZmllZCBQaHJhc2Vz RXhwb3J0IFBocmFzZSBUeXBlcw== RXhwb3J0IFByZXNldCBUaXRsZQ== RXhwb3J0IFByZXNldA== U2F2ZS9VcGRhdGUgRXhwb3J0IFByZXNldA== RXh0ZXJuYWwgTGluaw== RXh0ZXJuYWwgVVJM RXh0cmEgSGVhZGVycw== RmF4 TWF0Y2ggVHlwZQ== RmllbGQgTmFtZQ== RmllbGRzIGVuY2xvc2VkIGJ5 RmllbGRzIHNlcGFyYXRlZCBieQ== RmllbGQgVGl0bGVz RmllbGQgVHlwZQ== TWF0Y2ggVmFsdWU= RmlsZSBDb250ZW50cw== RmlsZW5hbWU= RmlsZW5hbWUgUmVwbGFjZW1lbnRz UGF0aA== RmlsdGVyIEZpZWxk RmlsdGVyIFR5cGU= Rmlyc3QgTmFtZQ== Rm9udA== Rm9udCBDb2xvcg== Rm9udCBGYW1pbHk= Rm9udCBTaXpl Rm9udCBTdHlsZQ== Rm9udCBXZWlnaHQ= T25saW5lIEZvcm0= T25saW5lIEZvcm0gU3VibWl0dGVkIFRlbXBsYXRl U2hvcnQgVVJM RnJvbSBFbWFpbA== RnJvbnQtRW5kIE9ubHk= TGFuZ3VhZ2U= QWxsb3cgUmVnaXN0cmF0aW9uIG9uIEZyb250LWVuZA== RnVsbCBOYW1l VXNlciBHcm91cA== R3JvdXAgRGlzcGxheSBPcmRlcg== SUQ= R3JvdXAgTmFtZQ== SGVpZ2h0 UmV2aWV3IFdhcyBIZWxwZnVs SGludCBQaHJhc2U= SGl0cw== SG90 SFRNTCBWZXJzaW9u SFRNTCBWZXJzaW9u SWNvbiBVUkwgKGRpc2FibGVkKQ== SWNvbiBVUkw= SUQ= SW1hZ2U= SW1wb3J0IFNlY3Rpb24= SW1wb3J0IENvbHVtbnM= SW1wb3J0IEZpbGU= SW1wb3J0IEZpbGVuYW1l T3ZlcndyaXRlIEV4aXN0aW5nIFBocmFzZXM= SW1wb3J0IE5ldyBQaHJhc2VzIGFzIFN5bmNlZA== SW5jbHVkZSBmaWVsZCB0aXRsZXM= SW5jbHVkZSBTdWJsZXZlbHM= SW5wdXQgRGF0ZSBGb3JtYXQ= SW5wdXQgVGltZSBGb3JtYXQ= SW5zdGFsbCBNb2R1bGVz SW5zdGFsbCBQaHJhc2UgVHlwZXM= SVAgQWRkcmVzcw== SVAgUmVzdHJpY3Rpb25z VXNlIGN1cnJlbnQgc2VjdGlvbiBhcyByb290IGZvciB0aGUgZXhwb3J0 SVNPIENvZGU= UHJpbWFyeQ== UmVxdWlyZWQ= SXMgU3lzdGVt U3lzdGVtIFRlbXBsYXRl VXNlciBGaWVsZA== SXRlbSBJRA== SXRlbSBOYW1l SXRlbSBQcmVmaXg= SXRlbSBUZW1wbGF0ZQ== TGFuZ3VhZ2U= TGFuZ3VhZ2UgRmlsZQ== TGFuZ3VhZ2UgSUQ= TGFuZ3VhZ2Vz TGFzdCBOYW1l TGFzdCBSdW4gT24= TGFzdCBSdW4gU3RhdHVz TGFzdCBUaW1lb3V0IE9u TGFzdCBVcGRhdGVkIE9u TGVmdA== TGluZSBlbmRpbmdz TGluZSBFbmRpbmdzIEluc2lkZSBGaWVsZHM= TGluayBUeXBl SUQ= TGlzdGluZyBUeXBl TG9jYWxl TG9jYWwgTmFtZQ== TG9jYXRpb24= QmFja3RyYWNl Q29kZQ== RXZlbnQgTmFtZQ== SG9zdG5hbWU= TG9naW4= SW50ZXJmYWNl TG9nIExldmVs TWVtb3J5IFVzZWQ= TWVzc2FnZQ== Tm90aWZpY2F0aW9uIFN0YXR1cw== TG9nbyBpbWFnZQ== Qm90dG9tIExvZ28gSW1hZ2U= TG9nbyBMb2dpbg== UHJvY2VzcyBJRA== UmVxdWVzdCBEYXRh UmVxdWVzdCBTb3VyY2U= UmVxdWVzdCBVUkk= U2Vzc2lvbiBEYXRh U2Vzc2lvbiBLZXk= U291cmNlIEZpbGUgTGluZQ== U291cmNlIEZpbGVuYW1l VGltZXN0YW1w VHlwZQ== VXNlciBEYXRh TWFyZ2luIEJvdHRvbQ== TWFyZ2luIExlZnQ= TWFyZ2luIFJpZ2h0 TWFyZ2lucw== TWFyZ2luIFRvcA== TWFzdGVyIElE TWFzdGVyIFByZWZpeA== TWF4aW11bSBudW1iZXIgb2YgU2VjdGlvbnMgb24gSXRlbSBjYW4gYmUgYWRkZWQgdG8= Q3VzdG9tIE1lbnUgSWNvbiAoaWUuIGltZy9tZW51X3Byb2R1Y3RzLmdpZik= TWVudSBTdGF0dXM= TWVyZ2UgdG8gU3VibWlzc2lvbg== TWVzc2FnZQ== TWVzc2FnZSBCb2R5 UGxhaW4gVGV4dCBWZXJzaW9u TWVzc2FnZSBUeXBl TWV0YSBEZXNjcmlwdGlvbg== TWV0YSBLZXl3b3Jkcw== TWlzc3BlbGxlZCBXb3Jk TW9kZQ== TW9kaWZpZWQ= TW9kdWxl TW9kdWxl TXVsdGlsaW5ndWFs TmFtZQ== TmV3 TmV4dCBSdW4gT24= Tm90ZXM= UmV2aWV3IFdhc24ndCBIZWxwZnVs TnVtYmVyIE9mIENsaWNrcw== TnVtYmVyIE9mIFZpZXdz T2NjdXJlZCBPbg== T3BlbiBJbiBOZXcgV2luZG93 T3B0aW9ucw== T3B0aW9uIFRpdGxl T3JkZXI= T3RoZXIgUmVjaXBpZW50cw== T3V0cHV0 T3ZlcndyaXRlIERlZmF1bHQgQ2FjaGluZyBLZXk= UGFjayBOYW1l UGFkZGluZyBCb3R0b20= UGFkZGluZyBMZWZ0 UGFkZGluZyBSaWdodA== UGFkZGluZ3M= UGFkZGluZyBUb3A= Q3VzdG9tIENhY2hpbmcgS2V5 Jmx0O1RJVExFJmd0OyBUYWc= Q2FjaGUgRXhwaXJhdGlvbiBpbiBzZWNvbmRz VGl0bGUgKE1lbnUgSXRlbSk= U2VjdGlvbiBUaXRsZQ== UGFyZW50IEl0ZW0gSUQ= UGFyZW50IEl0ZW0gTmFtZQ== UGFyZW50IFNlY3Rpb24= UGFzc3dvcmQ= UGVyY2VudHMgQ29tcGxldGVk UGhvbmU= TGFiZWw= UGhyYXNlIFR5cGU= UG9w UG9wdWxhcg== UG9ydA== UG9zaXRpb24= UHJlZml4 UHJpbWFyeQ== UHJpbWFyeSBTZWN0aW9u UHJpbWFyeQ== UHJpbWFyeSBMYW5ndWFnZSBQaHJhc2U= T3JkZXI= Q29udmVydCB1bm1hdGNoZWQgZS1tYWlscyBpbnRvIG5ldyBzdWJtaXNzaW9ucw== UHJvbW8gQmxvY2sgR3JvdXA= UHJvdGVjdGVk UXVhbnRpdHk= UmFuZ2UgQ291bnQ= UmF0aW5n UmVjaXBpZW50 UmVjaXBpZW50J3MgQWRkcmVzcw== UmVjaXBpZW50J3MgQWRkcmVzcyBUeXBl UmVjaXBpZW50J3MgTmFtZQ== UmVjaXBpZW50cw== UmVjaXBpZW50IFR5cGU= UmVjaXBpZW50IFVzZXI= Rm9yY2UgUmVkaXJlY3QgKHdoZW4gdXNlcidzIElQIG1hdGNoZXMp UmVmZXJyZXIgVVJM S2V5d29yZA== VHlwZQ== UmVtb3RlIFVSTA== UmVwbGFjZSBEdXBsaWNhdGVz UmVwbGFjZW1lbnQ= UmVwbGFjZW1lbnQgVGFncw== UmVwbGllZCBPbg== UmVwbHkgQmNj UmVwbHkgQ2M= UmVwbHkgRnJvbSBFLW1haWw= UmVwbHkgRnJvbSBOYW1l UmVwbHkgTWVzc2FnZSBTaWduYXR1cmU= UmVwbGllZA== UmVwb3J0ZWQgQnk= UmVwb3J0ZWQgT24= UmVxdWlyZWQ= UmVxdWlyZSBMb2dpbg== UmVxdWlyZSBTU0w= Q29tbWVudA== UmV2aXNpb24gTnVtYmVy UmV2aXNpb24gVGl0bGU= UHJvbW8gUm90YXRpb24gRGVsYXkgKHNlY29uZHMp UnVsZSBUeXBl UnVuIFNjaGVkdWxl UnVuIFRpbWU= U2FtZSBBcyBUaHVtYg== U2NoZWR1bGUgRnJvbQ== U2NoZWR1bGUgVG8= U2VhcmNoIFRlcm0= U2VuZGVy U2VuZGVyJ3MgQWRkcmVzcw== U2VuZGVyJ3MgTmFtZQ== U2VudCBPbg== U2VudA== U2VydmVy U2Vzc2lvbiBMb2cgSUQ= U2V0dGluZ3M= U2hvcnQgRGF0ZSBGb3JtYXQ= U2hvcnQgSVNPIENvZGU= U2hvcnQgVGltZSBGb3JtYXQ= U2ltcGxlIFNlYXJjaA== U2l0ZSBEb21haW4gTGltaXRhdGlvbg== TmFtZQ== U2tpcCBGaXJzdCBSb3c= U29ydCBWYWx1ZXM= U291cmNlIENvbHVtbiBQaHJhc2UgKGZyb20gJXMp U291cmNlIEhpbnQgUGhyYXNlIChmcm9tICVzKQ== U291cmNlIEhUTUwgVmVyc2lvbiAoZnJvbSAlcyk= U291cmNlIFRleHQgVmVyc2lvbiAoZnJvbSAlcyk= U291cmNlIFN1YmplY3QgKGZyb20gJXMp U291cmNlIFBocmFzZSAoZnJvbSAlcyk= U1NMIERvbWFpbiBOYW1l U3RhcnQgRGF0ZQ== U3RhdGU= U3RhdGUgQ291bnRyeQ== U3RhdHVz U3RpY2t5 U3RvcCBXb3Jk U3R5bGVzaGVldCBGaWxl U3ViamVjdA== U3VibWl0dGVkIE9u U3VibWlzc2lvbiBOb3RpZmljYXRpb24gRW1haWw= U3Vic2NyaWJlZCBPbg== U3VnZ2VzdGVkIENvcnJlY3Rpb24= UG9pbnRzIHRvIFNlY3Rpb24= U3luY2hyb25pemUgTGFuZ3VhZ2U= U3lzdGVtIEV2ZW50 U2V0dGluZyBIaW50IExhYmVs U2V0dGluZyBOYW1l U2VjdGlvbg== VmFsaWRhdGlvbiBMb2dpYw== U2V0dGluZyBWYWx1ZQ== VGFibGUgTmFtZSBpbiBEYXRhYmFzZSA= VGFn SXRlbQ== VGVtcGxhdGUgRmlsZQ== VGVtcGxhdGUgTmFtZQ== VGVtcGxhdGU= VGV4dA== VGV4dCBBbGlnbg== VGV4dCBEZWNvcmF0aW9u VGV4dCBWZXJzaW9u VGV4dCBWZXJzaW9u VGhlbWU= VGhlbWVz VGhlc2F1cnVzIFRlcm0= VGhlc2F1cnVzIFR5cGU= VGhvdXNhbmRzIFNlcGFyYXRvcg== VGltZSBGb3JtYXQ= VGltZW91dA== VGltZSBab25l VGl0bGU= VG8= VG8gRS1tYWls VG9w QW5hbHl0aWNzIFRyYWNraW5nIENvZGU= UHJvbW8gVHJhbnNpdGlvbiBDb250cm9scw== UHJvbW8gVHJhbnNpdGlvbiBFZmZlY3Q= UHJvbW8gVHJhbnNpdGlvbiBFZmZlY3QgKGN1c3RvbSk= VHJhbnNpdGlvbiBEZWxheSAoc2Vjb25kcyk= VHJhbnNsYXRlIEZyb20gTGFuZ2F1Z2U= UGhyYXNl VHJhbnNsYXRpb24gaW4gU3luYw== VHlwZQ== TWVhc3VyZXMgU3lzdGVt VXBsb2FkIEZpbGUgRnJvbSBMb2NhbCBQQw== QWxsb3dlZCBGaWxlIEV4dGVuc2lvbnM= TWF4aW11bSBGaWxlIFNpemU= VVJM TGluayB0byBFeHRlcm5hbCBVUkw= VXNlIEN1c3RvbSBNZW51IEljb24= VXNlciBEb2N1bWVudGF0aW9uIFVSTA== VXNlciBHcm91cHM= VXNlcm5hbWU= VXNlIFNlY3VyaXR5IEltYWdl UmUtZW50ZXIgUGFzc3dvcmQ= VmVyc2lvbg== VmlzaWJpbGl0eQ== Vm90ZXM= V2lkdGg= Wi1JbmRleA== WklQ Rm9udCBQcm9wZXJ0aWVz RG8geW91IHdhbnQgdG8gc2F2ZSB0aGUgY2hhbmdlcz8= QXJlIHlvdSBzdXJlIHlvdSB3b3VsZCBsaWtlIHRvIGRpc2NhcmQgdGhlIGNoYW5nZXM/ RnJvbQ== RnJvbSBEYXRl R2VuZXJhbCBTZWN0aW9ucw== SGVhZCBGcmFtZQ== SGlkZQ== QWxsIEZpbGVz Q2xpY2sgdG8gZWRpdA== Q1NWIEZpbGVz SW1hZ2UgRmlsZXM= UE9QMyBTZXJ2ZXIgUG9ydC4gRm9yIGV4LiAiMTEwIiBmb3IgcmVndWxhciBjb25uZWN0aW9uLCAiOTk1IiBmb3Igc2VjdXJlIGNvbm5lY3Rpb24u UE9QMyBTZXJ2ZXIgQWRkcmVzcy4gRm9yIGV4LiB1c2UgInNzbDovL3BvcC5nbWFpbC5jb20iIGZvciBHbWFpbCwgInBvcC5tYWlsLnlhaG9vLmNvbSIgZm9yIFlhaG9vLg== Q2FjaGUgS2V5KHMp ZGF0YWJhc2UgY2FjaGU= bWVtb3J5IGNhY2hl VXNpbmcgUmVndWxhciBFeHByZXNzaW9u SG90 SFRNTA== SUQgRmllbGQ= SW52YWxpZCBFLU1haWw= SW5jb3JyZWN0IGRhdGEgZm9ybWF0LCBwbGVhc2UgdXNlIGludGVnZXI= TWlzc2luZyBvciBpbnZhbGlkIEluLVBvcnRhbCBMaWNlbnNl SW5jb3JyZWN0IFVzZXJuYW1lIG9yIFBhc3N3b3Jk SW52YWxpZCBzdGF0ZQ== U2VjdGlvbnM= PCAxIHNlYy4= RGlzcGxheSBlZGl0b3IgUElDS3MgYWJvdmUgcmVndWxhciBsaW5rcw== TnVtYmVyIG9mIGRheXMgZm9yIGEgbGluayB0byBiZSBORVc= TnVtYmVyIG9mIGxpbmtzIHBlciBwYWdl TnVtYmVyIG9mIGxpbmtzIHBlciBwYWdlIG9uIGEgc2hvcnQgbGlzdGluZw== QW5kIHRoZW4gYnk= T3JkZXIgbGlua3MgYnk= TGludXg= TG9jYWw= TG9jYWwgSW1hZ2U= RnVuY3Rpb24= TG9nZ2VkIGluIGFz TG9naW4= TG9nb3V0 KEdNVCk= KEdNVCAtMDE6MDAp KEdNVCAtMTA6MDAp KEdNVCAtMTE6MDAp KEdNVCAtMTI6MDAp KEdNVCAtMDI6MDAp KEdNVCAtMDM6MDAp KEdNVCAtMDQ6MDAp KEdNVCAtMDU6MDAp KEdNVCAtMDY6MDAp KEdNVCAtMDc6MDAp KEdNVCAtMDg6MDAp KEdNVCAtMDk6MDAp TWFyZ2lucw== R3JvdXAgTWVtYmVyc2hpcCBFeHBpcmF0aW9uIFJlbWluZGVyIChkYXlzKQ== TWV0cmlj U2VjdGlvbiBwYXRoIGluIG9uZSBmaWVsZA== TW9kdWxlIG5vdCBsaWNlbnNlZA== TW9uZGF5 Q2hhbmdlIGxvZyBpcyBjdXJyZW50bHkgZGlzYWJsZWQuIFR1cm4gb24gIiVzIiBzZXR0aW5nIHRvIGVuYWJsZSBpdC4= RW5hYmxlIHRyYWNraW5nIGRhdGFiYXNlIGNoYW5nZXMgdG8gY2hhbmdlIGxvZz8= TGFzdCBvcGVyYXRpb24gaGFzIGJlZW4gc3VjY2Vzc2Z1bGx5IGNvbXBsZXRlZCE= QXBwbHkgdG8gYWxsIFN1Yi1zZWN0aW9ucz8= WW91ciAicm9vdCIgcGFzc3dvcmQgaGFzIGJlZW4gcmVzZXQuIFBsZWFzZSByZW1vdmUgREJHX1JFU0VUX1JPT1QgY29uc3RhbnQgYW5kIGNoZWNrIHlvdXIgZS1tYWlsIGFkZHJlc3Mu WW91ciBjaGFuZ2VzIHdlcmUgc3VjY2Vzc2Z1bGx5IHNhdmVkIQ== TmV2ZXI= TmV2ZXIgRXhwaXJlcw== TmV3 TmV4dCBzZWN0aW9u Tm8= Tm9uZQ== Tm8gUGVybWlzc2lvbnM= bmQ= cmQ= c3Q= dGg= T2Zm T24= T25lIFdheQ== b24gbGluZQ== Y3JlYXRlZA== ZGVsZXRlZA== dXBkYXRlZA== QWN0aXZl QWRkcmVzcw== QWZ0ZXI= QWxsb3c= Q3VzdG9t RmFkZQ== U2xpZGU= QXByaWw= QXVndXN0 QXV0by1EZXRlY3Q= QXV0b21hdGlj QmVmb3Jl Qm91bmNlZA== Q2FuY2VsZWQ= Q2l0eQ== Q29sb24= Q29tbWE= Q29tbWVudCBUZXh0 Q29va2llcw== Q291bnRyaWVz Q291bnRyeQ== Q3JlYXRlZCBPbg== LS0gQ29tbW9uIFNldHRpbmdzIC0t LS0gRGF5cyAtLQ== RXZlcnkgZGF5 RXZlcnkgMTUgbWludXRlcw== RXZlcnkgNSBtaW51dGVz RXZlcnkgNCBob3Vycw== RXZlcnkgaG91cg== RXZlcnkgbWludXRl RXZlcnkgbW9udGg= RXZlcnkgb3RoZXIgZGF5 RXZlcnkgb3RoZXIgaG91cg== RXZlcnkgb3RoZXIgbWludXRl RXZlcnkgb3RoZXIgbW9udGg= RXZlcnkgNiBob3Vycw== RXZlcnkgNiBtb250aHM= RXZlcnkgMTAgbWludXRlcw== RXZlcnkgMzAgbWludXRlcw== RXZlcnkgMyBob3Vycw== RXZlcnkgMyBtb250aHM= RXZlcnkgMTIgaG91cnM= RXZlcnkgd2Vla2RheQ== LS0gSG91cnMgLS0= LS0gTWludXRlcyAtLQ== TW9uIHRocnUgRnJp TW9uLCBXZWQsIEZyaQ== LS0gTW9udGhzIC0t T25jZSBhIGRheQ== T25jZSBhIG1vbnRo T25jZSBhbiBob3Vy T25jZSBhIHdlZWs= T25jZSBhIHllYXI= U2F0IGFuZCBTdW4= VHVlcywgVGh1cnM= VHdpY2UgYSBkYXk= MXN0IGFuZCAxNXRo VHdpY2UgYW4gaG91cg== LS0gV2Vla2RheXMgLS0= Q3VycmVudCBEb21haW4= Q3VzdG9tICJUbyIgUmVjaXBpZW50KC1zKQ== Q3VzdG9tIFNlbmRlcg== ZGF5KHMp RGVjZW1iZXI= RGVjbGluZWQ= RGVmYXVsdCBXZWJzaXRlIGFkZHJlc3M= RGVueQ== RGVzY3JpcHRpb24= RGlzYWJsZWQ= RG9lc24ndCBtYXRjaA== RWRpdG9yJ3MgUGljaw== RS1tYWls RS1tYWlsIEJvZHk= SW1tZWRpYXRl RW1haWwgUXVldWU= Rm9yZXZlciAobmV2ZXIgZGVsZXRlZCBhdXRvbWF0aWNhbGx5KQ== RS1tYWlsIFN1YmplY3Q= RS1tYWlsIFRlbXBsYXRlcw== RXJyb3I= RXZlcnlvbmU= RXhhY3Q= RXhwaXJlZA== RXh0ZXJuYWw= RXh0ZXJuYWwgVXJs RmFpbGVk RmVicnVhcnk= Rmlyc3QgTmFtZQ== NSB5ZWFycw== RnJpZGF5 R3JvdXA= R3Vlc3RzIE9ubHk= aG91cihzKQ== SW5oZXJpdCBmcm9tIFBhcmVudA== SW50ZXJuYWw= SW52YWxpZA== SVAgQWRkcmVzcw== SXMgdW5pcXVl SmFudWFyeQ== SnVseQ== SnVuZQ== TGFzdCBOYW1l TG9nZ2VkIE91dA== RGlzYWJsZWQ= UGVuZGluZw== U2VudA== RGF0YWJhc2U= T3RoZXI= UEhQ TWFudWFs TWFyY2g= TWF5 bWludXRlKHMp TW9kYWwgV2luZG93 TW9uZGF5 bW9udGgocyk= TmV3IEUtbWFpbA== Tm90IGVtcHR5 Tm90IGxpa2U= Tm90IFByb2Nlc3NlZA== Tm90IFJlcGxpZWQ= Tm92ZW1iZXI= T2N0b2Jlcg== MSBkYXk= MSBtb250aA== MSB3ZWVr MSB5ZWFy UGFydGlhbGx5IFByb2Nlc3NlZA== UGVuZGluZw== UGhvbmU= TGFiZWxz UG9wdXAgV2luZG93 UHJvY2Vzc2Vk UHVibGlzaGVk UXVlcnkgU3RyaW5nIChTSUQp UmF0aW5n UmVjaXBpZW50IEUtbWFpbA== UmVjaXBpZW50IE5hbWU= UmVwbGllZA== UnVubmluZw== U2FtZSBXaW5kb3c= U2F0dXJkYXk= c2Vjb25kKHMp U2VtaS1jb2xvbg== U2VudA== U2VwdGVtYmVy U2lsZW50 U2tpcHBlZA== U3BhY2U= U3RhdGU= U3ViLW1hdGNo U3VjY2Vzcw== U3VuZGF5 RnJvbSBvdGhlcnM= VG8gb3RoZXJz U3lzdGVt Rm9yZXZlciAobmV2ZXIgZGVsZXRlZCBhdXRvbWF0aWNhbGx5KQ== VGFi VGVtcGxhdGU= MyBtb250aHM= MyB5ZWFycw== VGh1cnNkYXk= VGl0bGU= VHVlc2RheQ== MiB3ZWVrcw== MiB5ZWFycw== VXNlcg== RW1haWwgQWN0aXZhdGlvbg== SW1tZWRpYXRlIA== VXNlcm5hbWU= Tm90IEFsbG93ZWQ= VXBvbiBBcHByb3ZhbA== VmlydHVhbA== V2VkbmVzZGF5 d2VlayhzKQ== eWVhcihzKQ== Wmlw T3RoZXIgRmllbGRz b3V0IG9m KEdNVCArMDE6MDAp KEdNVCArMTA6MDAp KEdNVCArMTE6MDAp KEdNVCArMTI6MDAp KEdNVCArMTM6MDAp KEdNVCArMDI6MDAp KEdNVCArMDM6MDAp KEdNVCArMDQ6MDAp KEdNVCArMDU6MDAp KEdNVCArMDY6MDAp KEdNVCArMDc6MDAp KEdNVCArMDg6MDAp KEdNVCArMDk6MDAp UGFkZGluZ3M= UGFnZQ== QXR0ZW50aW9uOiAlcyBpcyBjdXJyZW50bHkgZWRpdGluZyB0aGlzIHNlY3Rpb24h QXR0ZW50aW9uOiAlcyBhcmUgY3VycmVudGx5IGVkaXRpbmcgdGhpcyBzZWN0aW9uISA= QXR0ZW50aW9uOiAlcyBhcmUgY3VycmVudGx5IGVkaXRpbmcgdGhpcyBzZWN0aW9uIQ== UGFzc3dvcmRzIGRvIG5vdCBtYXRjaA== UGFzc3dvcmQgaXMgdG9vIHNob3J0LCBwbGVhc2UgZW50ZXIgYXQgbGVhc3QgJXMgY2hhcmFjdGVycw== UGVuZGluZw== UGVyZm9ybWluZyBCYWNrdXA= UGVyZm9ybWluZyBJbXBvcnQ= UGVyZm9ybWluZyBSZXN0b3Jl RXhwb3J0IExhbmd1YWdlIHBhY2s= SW1wb3J0IExhbmd1YWdlIHBhY2s= U2V0IFByaW1hcnkgTGFuZ3VhZ2U= RW5hYmxlIE1vZHVsZXM= RGlzYWJsZSBNb2R1bGVz TWFuYWdlIFBlcm1pc3Npb25z U2VuZCBFLW1haWwgdG8gR3JvdXBzIGluIEFkbWlu QmFuIFVzZXJz U2VuZCBFLW1haWwgdG8gVXNlcnMgaW4gQWRtaW4= QWRtaW4gTG9naW4= QWRkIFBlbmRpbmcgQ2F0ZWdvcnk= QWRkIENhdGVnb3J5 RGVsZXRlIENhdGVnb3J5 TW9kaWZ5IENhdGVnb3J5 QWxsb3cgQWRkaW5nIFBlbmRpbmcgQ29udGVudCBSZXZpc2lvbnM= QWxsb3cgQWRkaW5nIENvbnRlbnQgUmV2aXNpb25z QWxsb3cgUmVzdG9yaW5nIENvbnRlbnQgUmV2aXNpb25zIGZyb20gSGlzdG9yeQ== QWxsb3cgVmlld2luZyBIaXN0b3J5IG9mIENvbnRlbnQgUmV2aXNpb25z QWxsb3cgTW9kZXJhdGluZyAoQXBwcm92ZS9EZWNsaW5lKSBDb250ZW50IFJldmlzaW9ucw== VmlldyBDYXRlZ29yeQ== QXBwZW5kIHBocGluZm8gdG8gYWxsIHBhZ2VzIChEZWJ1Zyk= RGlzcGxheSBJdGVtIFF1ZXJpZXMgKERlYnVnKQ== RGlzcGxheSBJdGVtIExpc3QgUXVlcmllcyAoRGVidWcp QWxsb3cgZmF2b3JpdGVz QWxsb3cgTG9naW4= Q2hhbmdlIFVzZXIgUHJvZmlsZXM= U2hvdyBMYW5ndWFnZSBUYWdz UmVhZC1Pbmx5IEFjY2VzcyBUbyBEYXRhYmFzZQ== Tm90IFRyYW5zbGF0ZWQ= VHJhbnNsYXRlZA== QWRtaW4= Qm90aA== RnJvbnQ= UGljaw== U2VsZWN0ZWQgQ29sdW1ucw== UG9wdWxhcg== UG9zaXRpb24gQW5kIFZpc2liaWxpdHk= UHJldmlvdXMgc2VjdGlvbg== UHJpbWFyeQ== QWN0aXZlIFNlY3Rpb25z QWN0aXZlIFVzZXJz U2VudCBUbw== TWVzc2FnZXMgZnJvbSBTaXRlIEFkbWluIGFyZSBmcm9t QWR2YW5jZWQgU2VhcmNo QWR2YW5jZWQgVXNlciBNYW5hZ2VtZW50 QWxsb3cgcGFzc3dvcmQgcmVzZXQgYWZ0ZXI= R2VuZXJhdGUgZnJvbSB0aGUgYXJ0aWNsZSBib2R5 RGF0ZSBvZiBCYWNrdXA6 QmFja3VwIFBhdGg= QmFja3VwIHN0YXR1cw== QmFubmVkIFVzZXJz RGF0ZSBvZiBCaXJ0aA== RWRpdG9yJ3MgUGljayBTZWN0aW9ucw== Q3VycmVudCBTZXNzaW9ucw== VG90YWwgU2l6ZSBvZiB0aGUgRGF0YWJhc2U= RGVmYXVsdA== VXNlciBJRCBmb3IgRGVmYXVsdCBQZXJzaXN0ZW50IFNldHRpbmdz RGVmYXVsdCBWYWx1ZQ== RGlzYWJsZWQgU2VjdGlvbnM= RGlzcGxheSBpbiBHcmlk RGlzcGxheSBPcmRlcg== QWxsb3cgRHVwbGljYXRlIFJhdGluZyBWb3Rlcw== QWxsb3cgRHVwbGljYXRlIFJldmlld3M= RWRpdG9yJ3MgUGljaw== VHlwZQ== VGhlIEVtYWlsIE1lc3NhZ2UgaGFzIGJlZW4gc2VudA== RXhwb3J0IENvbXBsZXRlIQ== RmllbGQgSWQ= RmllbGQgTGFiZWw= RmllbGQgTmFtZQ== RmllbGQgUHJvbXB0 RnJlcXVlbmN5 SGVhZGluZw== KE1pbmltdW0gNCk= SW1wb3J0IFNvdXJjZQ== SW5wdXQgVHlwZQ== S2VlcCBTZXNzaW9uIFdoZW4gQnJvc3dlciBJcyBDbG9zZWQ= TGFuZ3VhZ2UgQ2FjaGUgVGltZW91dA== TGFzdCBTZWN0aW9uIFVwZGF0ZQ== TGFzdCBVcGRhdGVkIExpbms= U2VydmVyIFJlcXVpcmVzIEF1dGhlbnRpY2F0aW9u UG9ydCAoZS5nLiBwb3J0IDI1KQ== TWFpbCBTZXJ2ZXIgQWRkcmVzcw== TWF4aW1hbCBpbXBvcnRlZCBzZWN0aW9uIGxldmVs TWVtYmVyc2hpcCBFeHBpcmVz TGVmdCBNZW51IChUcmVlKSBXaWR0aA== TW92ZSBkb3du TW92ZSB1cA== U2hvdyBtdWx0aXBsZQ== TmV3IFNlY3Rpb25z TmV3ZXN0IFNlY3Rpb24gRGF0ZQ== TmV3ZXN0IExpbmsgRGF0ZQ== TmV3ZXN0IFVzZXIgRGF0ZQ== Q3VycmVudGx5IEFjdGl2ZSBVc2VyIFNlc3Npb25z UGVuZGluZyBTZWN0aW9ucw== UGVuZGluZyBJdGVtcw== UGVyZm9ybSB0aGlzIG9wZXJhdGlvbiBub3c/ UGVyIFBhZ2U= UGVyc29uYWwgSW5mb3JtYXRpb24= UHJpbWFyeSBHcm91cA== UHJpb3JpdHk= UmF0aW5n KE1pbmltdW0gMCwgTWF4aW11bSA1KQ== TnVtYmVyIG9mIERhdGFiYXNlIFJlY29yZHM= TnVtYmVyIG9mIFJlZ2lvbiBQYWNrcw== U2VhcmNoIFJlbGV2YW5jZSBkZXBlbmRzIG9u U2VhcmNoIFJlbGV2ZW5jZSBTZXR0aW5ncw== UmVxdWlyZWQ= SW5jcmVhc2UgaW1wb3J0YW5jZSBpZiBmaWVsZCBjb250YWlucyBhIHJlcXVpcmVkIGtleXdvcmQgYnk= UmVzdG9yZSBoYXMgZmFpbGVkIGFuIGVycm9yIG9jY3VyZWQ6 Q2hvb3NlIG9uZSBvZiB0aGUgZm9sbG93aW5nIGJhY2t1cCBkYXRlcyB0byByZXN0b3JlIG9yIGRlbGV0ZQ== UmVzdG9yZSBTdGF0dXM= UmVzdG9yZSBoYXMgYmVlbiBjb21wbGV0ZWQgc3VjY2Vzc2Z1bGx5 U2VsZWN0IE1vZHVsZSBSb290IFNlY3Rpb246 Um9vdCBQYXNzd29yZA== U2VhcmNoIFR5cGU= U2VsZWN0IFNvdXJjZSBMYW5ndWFnZQ== U2VudCBPbg== U2Vzc2lvbiBDb29raWUgTmFtZQ== U2Vzc2lvbiBNYW5hZ2VtZW50IE1ldGhvZA== U2Vzc2lvbiBJbmFjdGl2aXR5IFRpbWVvdXQgKHNlY29uZHMp U2hvdyBvbiB0aGUgZ2VuZXJhbCB0YWI= U2ltcGxlIFNlYXJjaA== QWRkaXRpb25hbCBNZXNzYWdlIEhlYWRlcnM= TWFpbCBTZXJ2ZXIgUGFzc3dvcmQ= TWFpbCBTZXJ2ZXIgVXNlcm5hbWU= VXNlIG5vbi1ibG9ja2luZyBzb2NrZXQgbW9kZQ== U1FMIFF1ZXJ5Og== UGVyZm9ybSBTUUwgUXVlcnk= U3RlcCBPbmU= U3VibWl0dGVkIE9u RW5hYmxlIFRhZyBDYWNoaW5n VG90YWwgU2l6ZSBvZiBTeXN0ZW0gRmlsZXM= TnVtYmVyIG9mIERhdGFiYXNlIFRhYmxlcw== TnVtYmVyIG9mIFRoZW1lcw== VG90YWwgU2VjdGlvbnM= VG90YWwgVXNlciBHcm91cHM= QWN0aXZlIFVzZXJz RGlzYWJsZWQgVXNlcnM= UGVuZGluZyBVc2Vycw== TnVtYmVyIG9mIFVuaXF1ZSBDb3VudHJpZXMgb2YgVXNlcnM= TnVtYmVyIG9mIFVuaXF1ZSBTdGF0ZXMgb2YgVXNlcnM= VmFsaWRhdGlvbg== TGlzdCBvZiBWYWx1ZXM= KE1pbmltdW0gMSk= V2FybmluZyE= V2VpZ2h0 U2luZ2xlLVF1b3RlcyAoaWUuICcp UmVjaXByb2NhbA== UmVjb3Jkcw== VGhpcyByZWNvcmQgaXMgYmVpbmcgZWRpdGVkIGJ5IHRoZSBmb2xsb3dpbmcgdXNlcnM6DQolcw== VXNlIENhcHRjaGEgY29kZSBvbiBSZWdpc3RyYXRpb24= UmVndWxhcg== UmVtb3ZlIEZyb20= Tm90IGFsbCByZXF1aXJlZCBmaWVsZHMgYXJlIGZpbGxlZC4gUGxlYXNlIGZpbGwgdGhlbSBmaXJzdC4= Q29tbWVudHMgcGVyIFBhZ2U= Q29tbWVudHMgcGVyIFBhZ2UgKHNob3J0LWxpc3Qp UmV2aXNpb24gIyVz SG9tZQ== U2FtcGxlIFRleHQ= c2F2ZWQgYXQgJXM= U2F2ZSBVc2VybmFtZSBvbiBUaGlzIENvbXB1dGVy U2VhcmNo QmFzaWMgUGVybWlzc2lvbnM= U2VjdGlvbg== Q29uZmlnIEZpbGVz Q291bnRlcnM= Q3VzdG9tIEZpZWxkcw== U3VibWlzc2lvbiBEYXRh RS1tYWlsIERlc2lnbiBUZW1wbGF0ZXM= RmlsZQ== RnJvbnQtZW5k RnVsbCBTaXplIEltYWdl R2VuZXJhbA== SW1hZ2U= SW1hZ2UgU2V0dGluZ3M= SW1wb3J0IENvbXBsZXRlZA== VXNlciBJdGVtcw== TWVtb3J5IENhY2hl TWVzc2FnZQ== U2VjdGlvbiBPdmVydmlldw== U2VjdGlvbiBQcm9wZXJ0aWVz U2VjdGlvbiBDYWNoaW5n UHJvamVjdCBEZXBsb3ltZW50 UHJvcGVydGllcw== UXVpY2sgTGlua3M= UmVjaXBpZW50cyBJbmZvcm1hdGlvbg== UmVsYXRpb24= UmVwbGFjZW1lbnQgVGFncw== U2VuZGVyIEluZm9ybWF0aW9u U2V0dGluZ3M= M3JkIFBhcnR5IEFQSSBTZXR0aW5ncw== QWRtaW4gQ29uc29sZSBTZXR0aW5ncw== Q1NWIEV4cG9ydCBTZXR0aW5ncw== TG9ncyBTZXR0aW5ncw== TWFpbGluZyBTZXR0aW5ncw== TWFpbnRlbmFuY2UgU2V0dGluZ3M= U2Vzc2lvbiBTZXR0aW5ncw== U1NMIFNldHRpbmdz U3lzdGVtIFNldHRpbmdz V2Vic2l0ZSBTZXR0aW5ncw== U3VibWlzc2lvbiBOb3Rlcw== VGVtcGxhdGVz VGh1bWJuYWlsIEltYWdl VHJhbnNsYXRpb24= U2VhcmNoIFVzZXJz VmFsdWVz U2VsZWN0IENvbHVtbnM= U2VsZWN0ZWQgSXRlbXM= U2VsZWN0aW5nIFNlY3Rpb25z T25lIGZpZWxkIGZvciBlYWNoIHNlY3Rpb24gbGV2ZWw= Q2xvbmU= Q2xvbmU= Q29udGludWU= RWRpdA== RXhwb3J0 R28gVXA= SW1wb3J0 RG93bg== VXA= TmV3 UmVidWlsZA== UmVzY2FuIFRoZW1lcw== UmVzZXQ= UHJpbWFyeQ== U3luY2hyb25pemU= Vmlldw== U2hvdw== QWZmZWN0ZWQgcm93cw== RXhlY3V0ZWQgaW46 U3RlcA== RGVmaW5pdGlvbg== UHJldmlldw== U3VuZGF5 U3lzdGVt QWRtaW5pc3RyYXRpb24gUGFuZWwgVUk= QWR2YW5jZWQgVmlldw== QmFja3Vw QmFuIFJ1bGVz QmFzZSBTdHlsZXM= QmxvY2sgU3R5bGVz Q2F0YWxvZw== QnJvd3NlIFdlYnNpdGU= U2VjdGlvbnM= Q2hhbmdlcyBMb2c= Rm9ybXM= VXNlciBNYW5hZ2VtZW50 Q3VzdG9tIEZpZWxkcw== RS1tYWlsIEV2ZW50cw== R2VuZXJhbCBTZXR0aW5ncw== T3V0cHV0 U2VhcmNo R2VuZXJhbA== Q3VzdG9t RS1tYWlsIENvbW11bmljYXRpb24= RS1tYWlsIExvZw== RW1haWwgUXVldWU= RS1tYWlsIFRlbXBsYXRlcw== RmllbGRz RmlsZXM= Rm9ybXMgQ29uZmlndXJhdGlvbg== R2VuZXJhbA== R2VuZXJhbA== R3JvdXBz SGVscA== SW1hZ2Vz SW1wb3J0IERhdGE= SXRlbXM= TGFiZWxz TG9ncyAmIFJlcG9ydHM= TWVzc2FnZXM= UGFja2FnZSBDb250ZW50 UGVybWlzc2lvbnM= UGVybWlzc2lvbiBUeXBlcw== UHJvbW8gQmxvY2tz UHJvcGVydGllcw== UXVlcnkgRGF0YWJhc2U= UmVnaW9uYWw= UmVsYXRlZCBTZWFyY2hlcw== UmVsYXRpb25z UmVzdG9yZQ== Q29tbWVudHM= U2VhcmNo U2VhcmNoIExvZw== UEhQIEluZm9ybWF0aW9u U3lzdGVtIFRvb2xz U2Vzc2lvbiBMb2c= U2Vzc2lvbiBMb2c= U2V0dGluZ3M= U2hvdyBBbGw= U2hvdyBTdHJ1Y3R1cmU= V2Vic2l0ZSAmIENvbnRlbnQ= QWRtaW4gU2tpbnM= U3VtbWFyeQ== U3lzdGVtIExvZw== Q29uZmlndXJhdGlvbg== VGFnIGxpYnJhcnk= VGhlbWVz VG9vbHM= VXNlcnM= R3JvdXBz VXNlcnM= VmlzaXRvciBMb2c= VmlzaXRz dGV4dA== QWRtaW4= QWR2YW5jZWQ= QWxs QXV0by1SZWZyZXNo QmFjayB1cCBoYXMgYmVlbiBjb21wbGV0ZWQuIFRoZSBiYWNrdXAgZmlsZSBpczo= SW4tUG9ydGFsIGRvZXMgbm90IGhhdmUgYWNjZXNzIHRvIHdyaXRlIHRvIHRoaXMgZGlyZWN0b3J5 VGhpcyB1dGlsaXR5IGFsbG93cyB5b3UgdG8gYmFja3VwIHlvdXIgSW4tUG9ydGFsIGRhdGFiYXNlIHNvIGl0IGNhbiBiZSByZXN0b3JlZCBhdCBsYXRlciBpbiBuZWVkZWQu Ynl0ZXM= Q2F0YWxvZw== U2VjdGlvbnM= U2VjdGlvbg== WW91IGFyZSBhYm91dCB0byBjbGVhciBjbGlwYm9hcmQgY29udGVudCENClByZXNzIE9LIHRvIGNvbnRpbnVlIG9yIENhbmNlbCB0byByZXR1cm4gdG8gcHJldmlvdXMgc2NyZWVuLg== Q3VzdG9tIEZpZWxkcw== c2VjdGlvbnM= RGF0ZS9UaW1lIFNldHRpbmdz UnVubmluZyB0aGlzIHV0aWxpdHkgd2lsbCBhZmZlY3QgeW91ciBkYXRhYmFzZS4gUGxlYXNlIGJlIGFkdmlzZWQgdGhhdCB5b3UgY2FuIHVzZSB0aGlzIHV0aWxpdHkgYXQgeW91ciBvd24gcmlzay4gSW4tUG9ydGFsIG9yIGl0J3MgZGV2ZWxvcGVycyBjYW4gbm90IGJlIGhlbGQgbGlhYmxlIGZvciBhbnkgY29ycnVwdCBkYXRhIG9yIGRhdGEgbG9zcy4= RGVmYXVsdA== RGVsZXRl RGlzYWJsZQ== UnVubmluZyB0aGlzIHV0aWxpdHkgd2lsbCBhZmZlY3QgeW91ciBkYXRhYmFzZS4gUGxlYXNlIGJlIGFkdmlzZWQgdGhhdCB5b3UgY2FuIHVzZSB0aGlzIHV0aWxpdHkgYXQgeW91ciBvd24gcmlzay4gSW4tUG9ydGFsIG9yIGl0J3MgZGV2ZWxvcGVycyBjYW4gbm90IGJlIGhlbGQgbGlhYmxlIGZvciBhbnkgY29ycnVwdCBkYXRhIG9yIGRhdGEgbG9zcy4= UGxlYXNlIG1ha2Ugc3VyZSB0byBCQUNLVVAgeW91ciBkYXRhYmFzZShzKSBiZWZvcmUgcnVubmluZyB0aGlzIHV0aWxpdHkh RWRpdA== RW1haWw= Rm9sbG93aW5nIGxpbmVzIHdlcmUgTk9UIGltcG9ydGVk RnJvbnQtRW5kIE9ubHk= R2VuZXJhbA== SG90 SSBhZ3JlZSB0byB0aGUgdGVybXMgYW5kIGNvbmRpdGlvbnM= SW1wb3J0IFJlc3VsdHM= SW4gRGV2ZWxvcG1lbnQ= SW52ZXJ0 S2V5d29yZA== TGluaw== RGVmYXVsdCBNRVRBIGtleXdvcmRz TWluaW11bSBwYXNzd29yZCBsZW5ndGg= VXNlciBuYW1lIGxlbmd0aCAobWluIC0gbWF4KQ== U2hvdyBtdWx0aXBsZQ== TmV3 Tm9uZQ== Tm8gUGVybWlzc2lvbg== b3I= UGhvbmU= UG9wdWxhcg== UG9wdWxhcml0eQ== UmVhZHkgdG8gSW5zdGFsbA== cmVjb3JkcyBhZGRlZA== cmVjb3JkcyB1cGRhdGVk UmVxdWlyZWQgZmllbGRz SGVyZSB5b3UgY2FuIHJlc3RvcmUgeW91ciBkYXRhYmFzZSBmcm9tIGEgcHJldmlvdXNseSBiYWNrZWQgdXAgc25hcHNob3QuIFJlc3RvcmluZyB5b3VyIGRhdGFiYXNlIHdpbGwgZGVsZXRlIGFsbCBvZiB5b3VyIGN1cnJlbnQgZGF0YSBhbmQgbG9nIHlvdSBvdXQgb2YgdGhlIHN5c3RlbS4= Q29tbWVudA== Q29tbWVudHM= TW9kdWxlIFJvb3QgU2VjdGlvbg== U2F2ZQ== U2VsZWN0 U2Vzc2lvbiBFeHBpcmVk U2ltcGxl U29ydA== VW5zZWxlY3Q= VXNlcg== VXNlcnM= VmVyc2lvbg== Vmlldw== QWRkaW5nIEFkbWluaXN0cmF0b3I= QWRkaW5nIEJhbiBSdWxl QWRkaW5nIENvdW50cnkvU3RhdGU= QWRkaW5nIEN1c3RvbSBGaWVsZA== QWRkaW5nIEUtbWFpbCBUZW1wbGF0ZQ== QWRkaW5nIEZpbGU= QWRkaW5nIEl0ZW0gRmlsdGVy QWRkaW5nIE1haWxpbmcgTGlzdA== QWRkaW5nIFBlcm1pc3Npb24gVHlwZQ== QWRkaW5nIFByb21vIEJsb2Nr QWRkaW5nIFByb21vIEJsb2NrIEdyb3Vw QWRkaW5nIFNjaGVkdWxlZCBUYXNr QWRkaW5nIFNpdGUgRG9tYWlu QWRkaW5nIFNraW4= QWRkaW5nIFNwZWxsaW5nIERpY3Rpb25hcnk= QWRkaW5nIFN0b3AgV29yZA== QWRkaW5nIFN5c3RlbSBFdmVudCBTdWJzY3JpcHRpb24= QWRkaW5nIFN5c3RlbSBTZXR0aW5n QWRkaW5nIFRoZW1lIFRlbXBsYXRl QWRkaW5nIFRoZXNhdXJ1cw== QWRkaW5nIEJhc2UgU3R5bGU= QWRkaW5nIEJsb2NrIFN0eWxl QWRkaW5nIFNlY3Rpb24= QWRkaW5nIFNlYXJjaCBGaWVsZA== QWRkaW5nIENNUyBCbG9jaw== QWRkaW5nIEZvcm0= QWRkaW5nIEZvcm0gRmllbGQ= QWRkaW5nIEdyb3Vw QWRkaW5nIEltYWdl QWRkaW5nIExhbmd1YWdl QWRkaW5nIFBocmFzZQ== QWRkaW5nIEtleXdvcmQ= QWRkaW5nIFJlbGF0aW9uc2hpcA== QWRkaW5nIENvbW1lbnQ= QWRkaW5nIFRoZW1l QWRkaW5nIFVzZXI= QWRkaXRpb25hbCBQZXJtaXNzaW9ucw== QWRtaW5pc3RyYXRvcnM= QWR2YW5jZWQ= U2hvd2luZyBhbGwgcmVnYXJkbGVzcyBvZiBTdHJ1Y3R1cmU= QmFzZSBTdHlsZXM= QmxvY2sgU3R5bGVz Qm91bmNlIFBPUDMgU2VydmVyIFNldHRpbmdz U2VjdGlvbnM= U2VsZWN0IHNlY3Rpb24= Q29sdW1uIFBpY2tlcg== Q29uZmlndXJhdGlvbg== Q29udGFjdCBJbmZvcm1hdGlvbg== Q291bnRyaWVzICYgU3RhdGVz Q1NWIEV4cG9ydA== Q1NWIEltcG9ydA== Q3VzdG9t Q3VzdG9tIEZpZWxkcw== RGVwbG95bWVudA== RWRpdGluZyBBZG1pbmlzdHJhdG9y RWRpdGluZyBCYW4gUnVsZQ== RWRpdGluZyBDaGFuZ2VzIExvZw== Q29udGVudCBFZGl0b3IgLSBBdXRvLXNhdmVkIGF0ICVz RWRpdGluZyBDb3VudHJ5L1N0YXRl RWRpdGluZyBEcmFmdCAoJTIkcyk= RWRpdGluZyBFLW1haWwgVGVtcGxhdGU= RWRpdGluZyBGaWxl RWRpdGluZyBJdGVtIEZpbHRlcg== RWRpdGluZyBNZW1iZXJzaGlw RWRpdGluZyBQZXJtaXNzaW9uIFR5cGU= RWRpdGluZyBQcm9tbyBCbG9jaw== RWRpdGluZyBQcm9tbyBCbG9jayBHcm91cA== RWRpdGluZyBTY2hlZHVsZWQgVGFzaw== RWRpdGluZyBTaXRlIERvbWFpbg== RWRpdGluZyBTa2lu RWRpdGluZyBTUEFNIFJlcG9ydA== RWRpdGluZyBTcGVsbGluZyBEaWN0aW9uYXJ5 RWRpdGluZyBTdG9wIFdvcmQ= RWRpdGluZyBTdHlsZQ== RWRpdGluZyBTeXN0ZW0gRXZlbnQgU3Vic2NyaXB0aW9u RWRpdGluZyBTeXN0ZW0gU2V0dGluZw== RWRpdGluZyBUaGVtZSBGaWxl RWRpdGluZyBUaGVzYXVydXM= RWRpdGluZyBUcmFuc2xhdGlvbg== RWRpdGluZyBCYXNlIFN0eWxl RWRpdGluZyBCbG9jayBTdHlsZQ== RWRpdGluZyBTZWN0aW9u RWRpdGluZyBDTVMgQmxvY2s= RWRpdGluZyBDdXN0b20gRmllbGQ= RWRpdGluZyBGb3Jt RWRpdGluZyBGb3JtIEZpZWxk RWRpdGluZyBHcm91cA== RWRpdGluZyBJbWFnZQ== RWRpdGluZyBMYW5ndWFnZQ== RWRpdGluZyBQaHJhc2U= RWRpdGluZyBLZXl3b3Jk RWRpdGluZyBSZWxhdGlvbnNoaXA= RWRpdGluZyBDb21tZW50 RWRpdGluZyBUaGVtZQ== RWRpdGluZyBVc2Vy RS1tYWlsIENvbW11bmljYXRpb24= RS1tYWlsIFNldHRpbmdz RS1tYWlsIFRlbXBsYXRlcw== RXhwb3J0IExhbmd1YWdlIFBhY2sgLSBSZXN1bHRz RXhwb3J0IExhbmd1YWdlIFBhY2sgLSBTdGVwMQ== RmllbGRz RmlsZXM= Rm9ybXM= Rm9ybSBTdWJtaXNzaW9ucw== R2VuZXJhbA== R3JvdXBz SW1hZ2Vz SW5zdGFsbCBMYW5ndWFnZSBQYWNrIC0gU3RlcCAx SW5zdGFsbCBMYW5ndWFnZSBQYWNrIC0gU3RlcCAy SXRlbSBGaWx0ZXJz SXRlbXM= TGFiZWxz TGFuZy4gTWFuYWdlbWVudA== TGFuZ3VhZ2UgUGFja3M= TGFuZ3VhZ2VzIE1hbmFnZW1lbnQ= TG9hZGluZyAuLi4= T3RoZXI= UmVxdWVzdA== U2Vzc2lvbg== U291cmNl TWFpbGluZ3M= TWVzc2FnZXM= TW9kdWxlIERlcGxveW1lbnQgTG9n TW9kdWxlcw== TmV3IEUtbWFpbCBUZW1wbGF0ZQ== TmV3IEZpbGU= TmV3IFJlcGx5 TmV3IFNjaGVkdWxlZCBUYXNr TmV3IFRoZW1l TmV3IFRoZW1lIFRlbXBsYXRl TmV3IEJhc2UgU3R5bGU= TmV3IEJsb2NrIFN0eWxl TmV3IFNlY3Rpb24= TmV3IEZpZWxk TmV3IEltYWdl TmV3IFJlbGF0aW9uc2hpcA== TmV3IENvbW1lbnQ= Tm8gUGVybWlzc2lvbnM= UGVybWlzc2lvbnM= TGFiZWxzICYgUGhyYXNlcw== UGxlYXNlIFdhaXQ= UHJvbW8gQmxvY2sgR3JvdXBz UHJvbW8gQmxvY2tz UHJvcGVydGllcw== UmVsYXRlZCBTZWFyY2hlcw== UmVsYXRpb25z UmVwbHkgUE9QMyBTZXJ2ZXIgU2V0dGluZ3M= Q29tbWVudHM= UnVuIFNjaGVkdWxl UnVuIFNldHRpbmdz U2NoZWR1bGVkIFRhc2tz U2VsZWN0IEdyb3VwKHMp U2VsZWN0IFVzZXI= U2VuZCBFLW1haWw= U2VuZGluZyBQcmVwYXJlZCBFLW1haWxz TWFpbCBoYXMgYmVlbiBzZW50IFN1Y2Nlc3NmdWxseQ== U2l0ZSBEb21haW5z U1BBTSBSZXBvcnRz U3BlbGxpbmcgRGljdGlvbmFyeQ== U3RvcCBXb3Jkcw== U3RydWN0dXJlICYgRGF0YQ== U3lzdGVtIEN1c3RvbSBGaWVsZHM= VXNlciBTdWJzY3JpcHRpb25z U3lzdGVtIFRvb2xz Q2xlYXIgVGVtcGxhdGVzIENhY2hl Q29tbW9ubHkgVXNlZCBLZXlz RGVwbG95IENoYW5nZXM= RHVtcCBBc3NldHM= S2V5IE5hbWU= S2V5IFZhbHVl TG9jYXRlIFVuaXQgQ29uZmlnIEZpbGU= UmVidWlsZCBNdWx0aWxpbmd1YWwgRmllbGRz UmVjb21waWxlIFRlbXBsYXRlcw== UmVmcmVzaCBUaGVtZSBGaWxlcw== UmVzZXQgQWRtaW4gQ29uc29sZSBTZWN0aW9ucw== UmVzZXQgQWxsIEtleXM= UmVzZXQgQ29uZmlncyBGaWxlcyBDYWNoZSBhbmQgUGFyc2VkIFN5c3RlbSBEYXRh UmVzZXQgTW9kUmV3cml0ZSBDYWNoZQ== UmVzZXQgUGFyc2VkIGFuZCBDYWNoZWQgU3lzdGVtIERhdGE= UmVzZXQgU01TIE1lbnUgQ2FjaGU= U2hvdyBEYXRhYmFzZSBUYWJsZSBTdHJ1Y3R1cmU= U3luY2hyb25pemUgRGF0YWJhc2UgUmV2aXNpb25z VGhlbWUgRmlsZXM= VGhlc2F1cnVz VXBkYXRpbmcgU2VjdGlvbnM= VXNlcnM= Vmlld2luZyBFbWFpbCBMb2c= Vmlld2luZyBmb3JtIHN1Ym1pc3Npb24= Vmlld2luZyBNYWlsaW5nIExpc3Q= Vmlld2luZyBNb2R1bGUgRGVwbG95bWVudCBMb2c= Vmlld2luZyBSZXBseQ== Vmlld2luZyBSZXZpc2lvbiAjJXMgKCVzKQ== Vmlld2luZyBTeXN0ZW0gTG9n VmlzaXRz V2Vic2l0ZQ== dG8= Q3Vyci4gU2VjdGlvbg== RG93bg== VXA= QWRk QWRkIFVzZXIgdG8gR3JvdXA= QWRkIFVzZXIgVG8gR3JvdXA= QXBwcm92ZQ== QmFjaw== Q2FuY2Vs Q2xlYXIgQ2xpcGJvYXJk Q2xvbmU= Q2xvbmUgVXNlcnM= Q2xvc2U= Q29weQ== Q3V0 RGVjbGluZQ== RGVsZXRl RGVsZXRlIEFsbA== RGVsZXRlIFJldmlldw== RGVsZXRlIFJlcG9ydCBPbmx5 RGVueQ== RGV0YWlscw== RGlzYWJsZQ== RGlzY2FyZA== RWRpdA== RWRpdCBDdXJyZW50IFNlY3Rpb24= RnJvbnQtRW5kIE9ubHk= RW5hYmxl RXhwb3J0 RXhwb3J0IExhbmd1YWdl SGlkZSBNZW51 SGlzdG9yeQ== SG9tZQ== SW1wb3J0 SW1wb3J0IExhbmd1YWdl TG9naW4gQXM= TW92ZSBEb3du TW92ZSBVcA== TmV3IEJhc2UgU3R5bGU= TmV3IEJsb2NrIFN0eWxl TmV3IENvdW50cnkvU3RhdGU= TmV3IEdyb3Vw TmV3IGxhYmVs TmV3IExhbmd1YWdl TmV3IFBlcm1pc3Npb24= TmV3IFBocmFzZQ== TmV3IENvbW1lbnQ= TmV3IFNjaGVkdWxlZCBUYXNr TmV3IFNlYXJjaCBGaWVsZA== TmV3IFNpdGUgRG9tYWlu TmV3IFN0b3AgV29yZA== TmV3IFN5c3RlbSBTZXR0aW5n TmV3IFRlcm0= TmV3IFRoZW1l TmV3IFVzZXI= TmV3IFNlY3Rpb24= TmV3IEN1c3RvbSBGaWVsZA== TmV3IEZvcm0= TmV3IEZvcm0gRmllbGQ= TmV3IEltYWdlcw== QWRkIEtleXdvcmQ= TmV3IFJlbGF0aW9u TmV3IFRlbXBsYXRl TmV4dA== UGFzdGU= UHJldmlvdXM= UHJldmlldw== U2V0IFByaW1hcnkgR3JvdXA= UHJpbnQ= UHJvY2VzcyBRdWV1ZQ== UHVibGlzaA== UmVidWlsZCBTZWN0aW9uIENhY2hl UmVjYWxjdWxhdGUgUHJpb3JpdGllcw== UmVmcmVzaA== UmVwbHk= UmVzY2FuIFRoZW1lcw== UmVzZW5k UmVzZXQ= UmVzZXQgQ291bnRlcnM= UmVzZXQgUGVyc2lzdGVudCBTZXR0aW5ncw== UmVzZXQgVG8gQmFzZQ== UnVu UnVuIFNRTA== U2F2ZQ== U2F2ZSBhcyBEcmFmdA== U2VhcmNo UmVzZXQ= U2VsZWN0IFVzZXI= U2VuZA== U2VuZCBFLW1haWw= U2VuZCBFLW1haWw= U2V0IFByaW1hcnk= U2V0IFByaW1hcnkgU2VjdGlvbg== U2V0IFByaW1hcnkgTGFuZ3VhZ2U= VXNlIGFzIFByaW1hcnk= U2V0IFN0aWNreQ== U2V0dGluZ3M= U2hvdyBNZW51 U3luY2hyb25pemUgTGFuZ3VhZ2Vz VG9vbHM= VXAgYSBTZWN0aW9u VmFsaWRhdGU= Vmlldw== VmlldyBEZXRhaWxz Vmlldw== VG8gRGF0ZQ== VHJhbnNsYXRl VHJhbnNsYXRlZA== VHJlZQ== Q2hlY2tib3hlcw== RGF0ZQ== RGF0ZSAmIFRpbWU= TGFiZWw= TXVsdGlwbGUgU2VsZWN0 UGFzc3dvcmQgZmllbGQ= + UGlja2Vy UmFkaW8gYnV0dG9ucw== UmFuZ2UgU2xpZGVy RHJvcCBkb3duIGZpZWxk Q2hlY2tib3g= VGV4dCBmaWVsZA== VGV4dCBhcmVh RmlsZSBVcGxvYWQ= VW5jaGFuZ2Vk VW5pY29kZQ== VXBkYXRpbmcgQ29uZmlndXJhdGlvbg== VXBsb2Fk VXNlIENyb24gdG8gcnVuIFNjaGVkdWxlZCBUYXNrcw== QXNzaWduIGFkbWluaXN0cmF0b3JzIHRvIGdyb3Vw QWxsb3cgbmV3IHVzZXIgcmVnaXN0cmF0aW9u QXNzaWduIEFsbCBVc2VycyBUbyBHcm91cA== QXNzaWduIHVzZXJzIG5vdCBsb2dnZWQgaW4gdG8gZ3JvdXA= QXNzaWduIHJlZ2lzdGVyZWQgdXNlcnMgdG8gZ3JvdXA= QXNzaWduIHBhc3N3b3JkIGF1dG9tYXRpY2FsbHk= QXNzaWduIG1haWxpbmcgbGlzdCBzdWJzY3JpYmVycyB0byBncm91cA== VVMvVUs= RS1tYWlsIGFkZHJlc3M= VmFsdWU= RGlyZWN0IGFjY2VzcyBvciBib29rbWFyaw== V2FybmluZzogRW5hYmxpbmcgSFRNTCBpcyBhIHNlY3VyaXR5IHJpc2sgYW5kIGNvdWxkIGRhbWFnZSB0aGUgc3lzdGVtIGlmIHVzZWQgaW1wcm9wZXJseSE= QSBzZWFyY2ggb3IgYSBmaWx0ZXIgaXMgaW4gZWZmZWN0LiBZb3UgbWF5IG5vdCBiZSBzZWVpbmcgYWxsIG9mIHRoZSBkYXRhLg== T25lIG9yIG1vcmUgZmllbGRzIG9uIHRoaXMgZm9ybSBoYXMgYW4gZXJyb3IuPGJyLz4NCjxzbWFsbD5QbGVhc2UgbW92ZSB5b3VyIG1vdXNlIG92ZXIgdGhlIGZpZWxkcyBtYXJrZWQgd2l0aCByZWQgdG8gc2VlIHRoZSBlcnJvciBkZXRhaWxzLjwvc21hbGw+ TW9kaWZpY2F0aW9ucyB3aWxsIG5vdCB0YWtlIGVmZmVjdCB1bnRpbCB5b3UgY2xpY2sgdGhlIFNhdmUgYnV0dG9uIQ== d2Vlaw== V2luZG93cw== eWVhcg== WWVz U3ViLXNlY3Rpb25zIFF1YW50aXR5 TmF2aWdhdGlvbiBCYXI= UmF0aW5n TnVtYmVyIG9mIFJldmlld3M= TnVtYmVyIG9mIFJhdGluZyBWb3Rlcw== U2VjdGlvbiBJRA== Q3JlYXRlZCBCeSBVc2VyIElE RGF0ZSBDcmVhdGVk RGVzY3JpcHRpb24= RWRpdG9ycyBQaWNr SGl0cw== SXRlbSBJcyBIb3Q= TGluayBJRA== TWV0YSBEZXNjcmlwdGlvbg== TWV0YSBLZXl3b3Jkcw== TGFzdCBNb2RpZmllZCBEYXRl TW9kaWZpZWQgQnkgVXNlciBJRA== TmFtZQ== SXRlbSBJcyBOZXc= Tm90aWZ5IE93bmVyIG9mIENoYW5nZXM= T3JpZ2luYWwgSXRlbSBJRA== T3duZXIgVXNlciBJRA== UGFyZW50IElE UGFyZW50IFBhdGg= SXRlbSBJcyBQb3B1bGFy UHJpb3JpdHk= UXR5IFNvbGQ= UmVzb3VyY2UgSUQ= U3RhdHVz SXRlbSBJcyBhIFRvcCBTZWxsZXI= VVJM b2Y= SW52YWxpZA== Tm90IFZhbGlkYXRlZA== VmFsaWQ= TmV3IENhdGVnb3J5ICI8aW5wMjpjX0ZpZWxkIG5hbWU9Ik5hbWUiLz4iIC0gQWRkZWQ= WW91ciBzdWdnZXN0ZWQgY2F0ZWdvcnkgIjxpbnAyOmNfRmllbGQgbmFtZT0iTmFtZSIvPiIgaGFzIGJlZW4gYWRkZWQu TmV3IENhdGVnb3J5ICI8aW5wMjpjX0ZpZWxkIG5hbWU9Ik5hbWUiLz4iIFN1Ym1pdHRlZCBieSBVc2Vycw== QSBjYXRlZ29yeSAiPGlucDI6Y19GaWVsZCBuYW1lPSJOYW1lIi8+IiBoYXMgYmVlbiBhZGRlZC4= U3VnZ2VzdGVkIENhdGVnb3J5ICI8aW5wMjpjX0ZpZWxkIG5hbWU9Ik5hbWUiLz4iIGlzIFBlbmRpbmc= VGhlIGNhdGVnb3J5IHlvdSBzdWdnZXN0ZWQgIjxpbnAyOmNfRmllbGQgbmFtZT0iTmFtZSIvPiIgaXMgcGVuZGluZyBmb3IgYWRtaW5pc3RyYXRpdmUgYXBwcm92YWwuDQoNClRoYW5rIHlvdSE= U3VnZ2VzdGVkIENhdGVnb3J5ICI8aW5wMjpjX0ZpZWxkIG5hbWU9Ik5hbWUiLz4iIGlzIFBlbmRpbmc= QSBjYXRlZ29yeSAiPGlucDI6Y19GaWVsZCBuYW1lPSJOYW1lIi8+IiBoYXMgYmVlbiBhZGRlZCwgcGVuZGluZyB5b3VyIGNvbmZpcm1hdGlvbi4gIFBsZWFzZSByZXZpZXcgdGhlIGNhdGVnb3J5IGFuZCBhcHByb3ZlIG9yIGRlbnkgaXQu QSBjYXRlZ29yeSBoYXMgYmVlbiBhcHByb3ZlZA== WW91ciBzdWdnZXN0ZWQgY2F0ZWdvcnkgIjxpbnAyOmNfRmllbGQgbmFtZT0iTmFtZSIvPiIgaGFzIGJlZW4gYXBwcm92ZWQu WW91ciBDYXRlZ29yeSAiPGlucDI6Y19GaWVsZCBuYW1lPSJOYW1lIi8+IiBoYXMgYmVlbiBEZW5pZWQ= WW91ciBjYXRlZ29yeSBzdWdnZXN0aW9uICI8aW5wMjpjX0ZpZWxkIG5hbWU9Ik5hbWUiLz4iIGhhcyBiZWVuIGRlbmllZC4= TmV3IEVtYWlsIFJFUExZIFJlY2VpdmVkIGluICJGZWVkYmFjayBNYW5hZ2VyIiAoPGlucDI6Zm9ybXN1YnMuLWl0ZW1fRmllbGQgbmFtZT0iRm9ybVN1Ym1pc3Npb25JZCIvPik= TmV3IEVtYWlsIFJFUExZIFJlY2VpdmVkIGluICZxdW90O0ZlZWRiYWNrIE1hbmFnZXImcXVvdDsuPGJyIC8+DQo8YnIgLz4NCk9yaWdpbmFsIEZlZWRiYWNrSWQ6IDxpbnAyOmZvcm1zdWJzLi1pdGVtX0ZpZWxkIG5hbWU9IkZvcm1TdWJtaXNzaW9uSWQiLz4gPGJyIC8+DQpPcmlnaW5hbCBTdWJqZWN0OiA8aW5wMjpmb3Jtc3Vicy4taXRlbV9Gb3JtRmllbGQgcm9sZT0ic3ViamVjdCIvPiA8YnIgLz4NCjxiciAvPg0KUGxlYXNlIHByb2NlZWQgdG8gdGhlIEFkbWluIENvbnNvbGUgaW4gb3JkZXIgdG8gcmV2aWV3IGFuZCByZXBseSB0byB0aGUgdXNlci4= TmV3IEVtYWlsIC0gRGVsaXZlcnkgRmFpbHVyZSBSZWNlaXZlZCBpbiAiRmVlZGJhY2sgTWFuYWdlciIgKDxpbnAyOmZvcm1zdWJzLi1pdGVtX0ZpZWxkIG5hbWU9IkZvcm1TdWJtaXNzaW9uSWQiLz4p TmV3IEVtYWlsIERlbGl2ZXJ5IEZhaWx1cmUgUmVjZWl2ZWQgaW4gJnF1b3Q7RmVlZGJhY2sgTWFuYWdlciZxdW90Oy48YnIgLz4NCjxiciAvPg0KT3JpZ2luYWwgRmVlZGJhY2tJZDogPGlucDI6Zm9ybXN1YnMuLWl0ZW1fRmllbGQgbmFtZT0iRm9ybVN1Ym1pc3Npb25JZCIvPiA8YnIgLz4NCk9yaWdpbmFsIFN1YmplY3Q6IDxpbnAyOmZvcm1zdWJzLi1pdGVtX0Zvcm1GaWVsZCByb2xlPSJzdWJqZWN0Ii8+IDxiciAvPg0KPGJyIC8+DQpQbGVhc2UgcHJvY2VlZCB0byB0aGUgQWRtaW4gQ29uc29sZSBpbiBvcmRlciB0byByZXZpZXcgYW5kIHJlcGx5IHRvIHRoZSB1c2VyLg== PGlucDI6bV9QYXJhbSBuYW1lPSJzdWJqZWN0Ii8+ICN2ZXJpZnk8aW5wMjpzdWJtaXNzaW9uLWxvZ19GaWVsZCBuYW1lPSJWZXJpZnlDb2RlIi8+ PGlucDI6bV9QYXJhbSBuYW1lPSJtZXNzYWdlIi8+ VGhhbmsgWW91IGZvciBDb250YWN0aW5nIFVzIQ== PHA+VGhhbmsgeW91IGZvciBjb250YWN0aW5nIHVzLiBXZSdsbCBiZSBpbiB0b3VjaCB3aXRoIHlvdSBzaG9ydGx5ITwvcD4= TmV3IGZvcm0gc3VibWlzc2lvbg== PHA+Rm9ybSBoYXMgYmVlbiBzdWJtaXR0ZWQuIFBsZWFzZSBwcm9jZWVkIHRvIHRoZSBBZG1pbiBDb25zb2xlIHRvIHJldmlldyB0aGUgc3VibWlzc2lvbiE8L3A+ Um9vdCBSZXNldCBQYXNzd29yZA== WW91ciBuZXcgcGFzc3dvcmQgaXM6IDxpbnAyOm1fUGFyYW0gbmFtZT0icGFzc3dvcmQiLz4= U3lzdGVtIExvZyBOb3RpZmljYXRpb25zICg8aW5wMjpzeXN0ZW0tbG9nLmVtYWlsX1RvdGFsUmVjb3Jkcy8+KQ== PGlucDI6bV9EZWZpbmVFbGVtZW50IG5hbWU9ImJhY2t0cmFjZV9lbGVtZW50Ij4NCgk8bGk+PGlucDI6bV9QaHJhc2UgbmFtZT0ibGFfTG9nQmFja3RyYWNlRnVuY3Rpb24iLz46IDxpbnAyOm1fUGFyYW0gbmFtZT0iZmlsZV9pbmZvIi8+PC9saT4NCjwvaW5wMjptX0RlZmluZUVsZW1lbnQ+DQoNCjxpbnAyOm1fRGVmaW5lRWxlbWVudCBuYW1lPSJzeXN0ZW1fbG9nX2VsZW1lbnQiPg0KCTxoND48aW5wMjpGaWVsZCBuYW1lPSJMb2dUaW1lc3RhbXAiIGZvcm1hdD0iTSBkIEg6aTpzIi8+IDxpbnAyOkZpZWxkIG5hbWU9IkxvZ0hvc3RuYW1lIi8+IDxpbnAyOlJlcXVlc3RVUkkgaHRtbF9lc2NhcGU9IjEiLz5bUElEPTxpbnAyOkZpZWxkIG5hbWU9IkxvZ1Byb2Nlc3NJZCIvPixVSUQ9PGlucDI6RmllbGQgbmFtZT0iTG9nVW5pcXVlSWQiLz5dPC9oND4NCglbPGlucDI6RmllbGQgbmFtZT0iTG9nTGV2ZWwiLz5dICM8aW5wMjpGaWVsZCBuYW1lPSJMb2dDb2RlIi8+OiA8aW5wMjpGaWVsZCBuYW1lPSJMb2dNZXNzYWdlIiBub19zcGVjaWFsPSIxIi8+IGluIDxpbnAyOkZpbGVuYW1lLz4gb24gbGluZSA8aW5wMjpGaWVsZCBuYW1lPSJMb2dTb3VyY2VGaWxlTGluZSIvPjxici8+DQoNCgk8aW5wMjptX2lmIGNoZWNrPSJGaWVsZCIgbmFtZT0iTG9nQmFja3RyYWNlIiBkYj0iZGIiPg0KCQk8YnIvPkJhY2t0cmFjZToNCg0KCQk8b2wgc3R5bGU9Im1hcmdpbjogMDsgcGFkZGluZy1sZWZ0OiAyNXB4OyBmb250LXNpemU6IDEycHg7Ij4NCgkJCTxpbnAyOlByaW50QmFja3RyYWNlIHJlbmRlcl9hcz0iYmFja3RyYWNlX2VsZW1lbnQiLz4NCgkJPC9vbD4NCgk8L2lucDI6bV9pZj4NCg0KCTxpbnAyOm1faWZub3QgY2hlY2s9Im1fUGFyYW0iIG5hbWU9ImlzX2xhc3QiPjxoci8+PC9pbnAyOm1faWZub3Q+DQo8L2lucDI6bV9EZWZpbmVFbGVtZW50Pg0KDQo8aW5wMjpzeXN0ZW0tbG9nLmVtYWlsX1ByaW50TGlzdCByZW5kZXJfYXM9InN5c3RlbV9sb2dfZWxlbWVudCIvPg== PGlucDI6bV9EZWZpbmVFbGVtZW50IG5hbWU9ImJhY2t0cmFjZV9wbGFpbl9lbGVtZW50Ij4NCjxpbnAyOkJhY2t0cmFjZUluZGV4Lz4uIDxpbnAyOm1fUGhyYXNlIG5hbWU9ImxhX0xvZ0JhY2t0cmFjZUZ1bmN0aW9uIi8+OiA8aW5wMjptX1BhcmFtIG5hbWU9ImZpbGVfaW5mbyIvPg0KPGlucDI6bV9pZm5vdCBjaGVjaz0ibV9QYXJhbSIgbmFtZT0iaXNfbGFzdCI+DQoNCjwvaW5wMjptX2lmbm90Pg0KPC9pbnAyOm1fRGVmaW5lRWxlbWVudD4NCjxpbnAyOm1fRGVmaW5lRWxlbWVudCBuYW1lPSJzeXN0ZW1fbG9nX3BsYWluX2VsZW1lbnQiPg0KPGlucDI6RmllbGQgbmFtZT0iTG9nVGltZXN0YW1wIiBmb3JtYXQ9Ik0gZCBIOmk6cyIvPiA8aW5wMjpGaWVsZCBuYW1lPSJMb2dIb3N0bmFtZSIvPiA8aW5wMjpSZXF1ZXN0VVJJLz5bUElEPTxpbnAyOkZpZWxkIG5hbWU9IkxvZ1Byb2Nlc3NJZCIvPixVSUQ9PGlucDI6RmllbGQgbmFtZT0iTG9nVW5pcXVlSWQiLz5dDQpbPGlucDI6RmllbGQgbmFtZT0iTG9nTGV2ZWwiLz5dICM8aW5wMjpGaWVsZCBuYW1lPSJMb2dDb2RlIi8+OiA8aW5wMjpGaWVsZCBuYW1lPSJMb2dNZXNzYWdlIiBub19zcGVjaWFsPSIxIi8+IGluIDxpbnAyOkZpbGVuYW1lLz4gb24gbGluZSA8aW5wMjpGaWVsZCBuYW1lPSJMb2dTb3VyY2VGaWxlTGluZSIvPg0KPGlucDI6bV9pZiBjaGVjaz0iRmllbGQiIG5hbWU9IkxvZ0JhY2t0cmFjZSIgZGI9ImRiIj4NCg0KQmFja3RyYWNlOg0KPGlucDI6UHJpbnRCYWNrdHJhY2UgcmVuZGVyX2FzPSJiYWNrdHJhY2VfcGxhaW5fZWxlbWVudCIgc3RyaXBfdGFncz0iMSIvPjwvaW5wMjptX2lmPg0KPGlucDI6bV9pZm5vdCBjaGVjaz0ibV9QYXJhbSIgbmFtZT0iaXNfbGFzdCI+DQotLS0tLS0tLS0tLS0tDQoNCjwvaW5wMjptX2lmbm90Pg0KPC9pbnAyOm1fRGVmaW5lRWxlbWVudD4NCjxpbnAyOnN5c3RlbS1sb2cuZW1haWxfUHJpbnRMaXN0IHJlbmRlcl9hcz0ic3lzdGVtX2xvZ19wbGFpbl9lbGVtZW50Ii8+ SW4tcG9ydGFsIHJlZ2lzdHJhdGlvbg== RGVhciA8aW5wMjp1LnJlZ2lzdGVyX0ZpZWxkIG5hbWU9IkZpcnN0TmFtZSIgLz4gPGlucDI6dS5yZWdpc3Rlcl9GaWVsZCBuYW1lPSJMYXN0TmFtZSIgLz4sDQoNClRoYW5rIHlvdSBmb3IgcmVnaXN0ZXJpbmcgb24gPGlucDI6bV9MaW5rIHRlbXBsYXRlPSJpbmRleCIvPi4gWW91ciByZWdpc3RyYXRpb24gaXMgbm93IGFjdGl2ZS4NCjxpbnAyOm1faWYgY2hlY2s9InUucmVnaXN0ZXJfRmllbGQiIG5hbWU9IkVtYWlsIj4NCjxici8+PGJyLz4NClBsZWFzZSBjbGljayBoZXJlIHRvIHZlcmlmeSB5b3VyIEUtbWFpbCBhZGRyZXNzOg0KPGEgaHJlZj0iPGlucDI6dS5yZWdpc3Rlcl9Db25maXJtUGFzc3dvcmRMaW5rIHQ9InBsYXRmb3JtL215X2FjY291bnQvdmVyaWZ5X2VtYWlsIiBub19hbXA9IjEiLz4iPjxpbnAyOnUucmVnaXN0ZXJfQ29uZmlybVBhc3N3b3JkTGluayB0PSJwbGF0Zm9ybS9teV9hY2NvdW50L3ZlcmlmeV9lbWFpbCIgbm9fYW1wPSIxIi8+PC9hPjxici8+PGJyLz4NCjwvaW5wMjptX2lmPg== TmV3IFVzZXIgUmVnaXN0cmF0aW9uICg8aW5wMjp1LnJlZ2lzdGVyX1VzZXJUaXRsZS8+KQ== QSBuZXcgdXNlciAiPGlucDI6dS5yZWdpc3Rlcl9Vc2VyVGl0bGUvPiIgaGFzIGJlZW4gYWRkZWQu TmV3IHVzZXIgaGFzIGJlZW4gY3JlYXRlZA== RGVhciA8aW5wMjp1X0ZpZWxkIG5hbWU9IkZpcnN0TmFtZSIvPiwNCg0KQSBuZXcgdXNlciBoYXMgYmVlbiBjcmVhdGVkIGFuZCBhc3NpZ25lZCB0byB5b3UNCg0KTm93IHlvdSBjYW4gbG9naW4gdXNpbmcgdGhlIGZvbGxvd2luZyBjcmVkZW50aWFsczoNCg0KPGlucDI6bV9pZiBjaGVjaz0idV9GaWVsZCIgbmFtZT0iVXNlcm5hbWUiPlVzZXJuYW1lOiA8aW5wMjp1X0ZpZWxkIG5hbWU9IlVzZXJuYW1lIi8+PGlucDI6bV9lbHNlLz5FLW1haWw6IDxpbnAyOnVfRmllbGQgbmFtZT0iRW1haWwiLz48L2lucDI6bV9pZj4gDQpQYXNzd29yZDogPGlucDI6dV9GaWVsZCBuYW1lPSJQYXNzd29yZF9wbGFpbiIvPiANCg== TmV3IFVzZXIgUmVnaXN0cmF0aW9uICg8aW5wMjp1LnJlZ2lzdGVyX1VzZXJUaXRsZS8+PGlucDI6bV9pZiBjaGVjaz0ibV9HZXRDb25maWciIG5hbWU9IlVzZXJfQWxsb3dfTmV3IiBlcXVhbHNfdG89IjQiPiAtIEFjdGl2YXRpb24gRW1haWw8L2lucDI6bV9pZj4p RGVhciA8aW5wMjp1LnJlZ2lzdGVyX0ZpZWxkIG5hbWU9IkZpcnN0TmFtZSIgLz4gPGlucDI6dS5yZWdpc3Rlcl9GaWVsZCBuYW1lPSJMYXN0TmFtZSIgLz4sPGJyIC8+DQo8YnIgLz4NCjxpbnAyOm1faWYgY2hlY2s9Im1fR2V0Q29uZmlnIiBuYW1lPSJVc2VyX0FsbG93X05ldyIgZXF1YWxzX3RvPSI0Ij4NCglUaGFuayB5b3UgZm9yIHJlZ2lzdGVyaW5nIG9uIDxpbnAyOm1fTGluayB0ZW1wbGF0ZT0iaW5kZXgiLz4gd2Vic2l0ZS4gVG8gYWN0aXZhdGUgeW91ciByZWdpc3RyYXRpb24gcGxlYXNlIGZvbGxvdyBsaW5rIGJlbG93LiA8aW5wMjp1LnJlZ2lzdGVyX0FjdGl2YXRpb25MaW5rIHRlbXBsYXRlPSJwbGF0Zm9ybS9sb2dpbi9hY3RpdmF0ZV9jb25maXJtIi8+DQo8aW5wMjptX2Vsc2UvPg0KCVRoYW5rIHlvdSBmb3IgcmVnaXN0ZXJpbmcgb24gPGlucDI6bV9MaW5rIHRlbXBsYXRlPSJpbmRleCIvPiB3ZWJzaXRlLiBZb3VyIHJlZ2lzdHJhdGlvbiB3aWxsIGJlIGFjdGl2ZSBhZnRlciBhcHByb3ZhbC4gDQoJDQoJPGlucDI6bV9pZiBjaGVjaz0idS5yZWdpc3Rlcl9GaWVsZCIgbmFtZT0iRW1haWwiPg0KCQk8YnIvPjxici8+DQoJCVBsZWFzZSBjbGljayBoZXJlIHRvIHZlcmlmeSB5b3VyIEUtbWFpbCBhZGRyZXNzOg0KCQk8YSBocmVmPSI8aW5wMjp1LnJlZ2lzdGVyX0NvbmZpcm1QYXNzd29yZExpbmsgdD0icGxhdGZvcm0vbXlfYWNjb3VudC92ZXJpZnlfZW1haWwiIG5vX2FtcD0iMSIvPiI+PGlucDI6dS5yZWdpc3Rlcl9Db25maXJtUGFzc3dvcmRMaW5rIHQ9InBsYXRmb3JtL215X2FjY291bnQvdmVyaWZ5X2VtYWlsIiBub19hbXA9IjEiLz48L2E+PGJyLz48YnIvPg0KCTwvaW5wMjptX2lmPg0KPC9pbnAyOm1faWY+ TmV3IFVzZXIgUmVnaXN0ZXJlZA== QSBuZXcgdXNlciAiPGlucDI6dS5yZWdpc3Rlcl9Vc2VyVGl0bGUvPiIgaGFzIHJlZ2lzdGVyZWQgYW5kIGlzIHBlbmRpbmcgYWRtaW5pc3RyYXRpdmUgYXBwcm92YWwu WW91ciBBY2NvdW50IGlzIEFjdGl2ZQ== V2VsY29tZSB0byA8aW5wMjptX0xpbmsgdGVtcGxhdGU9ImluZGV4Ii8+IQ0KDQpZb3VyIHVzZXIgcmVnaXN0cmF0aW9uIGhhcyBiZWVuIGFwcHJvdmVkLiBZb3VyIHVzZXIgbmFtZSBpczogIjxpbnAyOnVfVXNlclRpdGxlLz4iLg== TmV3IFVzZXIgQWNjb3VudCAiPGlucDI6dV9Vc2VyVGl0bGUvPiIgd2FzIEFwcHJvdmVk VXNlciAiPGlucDI6dV9Vc2VyVGl0bGUvPiIgaGFzIGJlZW4gYXBwcm92ZWQu WW91ciBSZWdpc3RyYXRpb24gaGFzIGJlZW4gRGVuaWVk WW91ciByZWdpc3RyYXRpb24gb24gPGEgaHJlZj0iPGlucDI6bV9MaW5rIHRlbXBsYXRlPSJpbmRleCIvPiI+PGlucDI6bV9MaW5rIHRlbXBsYXRlPSJpbmRleCIvPjwvYT4gd2Vic2l0ZSBoYXMgYmVlbiBkZW5pZWQu VXNlciBSZWdpc3RyYXRpb24gZm9yICAiPGlucDI6dV9Vc2VyVGl0bGUvPiIgaGFzIGJlZW4gRGVuaWVk VXNlciAiPGlucDI6dV9Vc2VyVGl0bGUvPiIgaGFzIGJlZW4gZGVuaWVkLg== Q2hhbmdlZCBFLW1haWwgUm9sbGJhY2s= SGVsbG8sPGJyLz48YnIvPg0KDQpJdCBzZWVtcyB0aGF0IHlvdSBoYXZlIGNoYW5nZWQgZS1tYWlsIGluIHlvdXIgSW4tcG9ydGFsIGFjY291bnQuIFlvdSBtYXkgdW5kbyB0aGlzIGNoYW5nZSBieSBjbGlja2luZyBvbiB0aGUgbGluayBiZWxvdzo8YnIvPjxici8+DQoNCjxhIGhyZWY9IjxpbnAyOnVfVW5kb0VtYWlsQ2hhbmdlTGluayB0ZW1wbGF0ZT0icGxhdGZvcm0vbXlfYWNjb3VudC9yZXN0b3JlX2VtYWlsIi8+Ij48aW5wMjp1X1VuZG9FbWFpbENoYW5nZUxpbmsgdGVtcGxhdGU9InBsYXRmb3JtL215X2FjY291bnQvcmVzdG9yZV9lbWFpbCIvPjwvYT48YnIvPjxici8+DQoNCklmIHlvdSBiZWxpZXZlIHlvdSBoYXZlIHJlY2VpdmVkIHRoaXMgZW1haWwgaW4gZXJyb3IsIHBsZWFzZSBpZ25vcmUgdGhpcyBlbWFpbC4gWW91ciBhY2NvdW50IHdpbGwgYmUgbGlua2VkIHRvIGFub3RoZXIgZS1tYWlsIHVubGVzcyB5b3UgaGF2ZSBjbGlja2VkIG9uIHRoZSBhYm92ZSBsaW5rLg== Q2hhbmdlZCBFLW1haWwgVmVyaWZpY2F0aW9u SGVsbG8sPGJyLz48YnIvPg0KDQpJdCBzZWVtcyB0aGF0IHlvdSBoYXZlIGNoYW5nZWQgZS1tYWlsIGluIHlvdXIgSW4tcG9ydGFsIGFjY291bnQuIFBsZWFzZSB2ZXJpZnkgdGhpcyBuZXcgZS1tYWlsIGJ5IGNsaWNraW5nIG9uIHRoZSBsaW5rIGJlbG93Ojxici8+PGJyLz4NCg0KPGEgaHJlZj0iPGlucDI6dV9Db25maXJtUGFzc3dvcmRMaW5rIHQ9InBsYXRmb3JtL215X2FjY291bnQvdmVyaWZ5X2VtYWlsIiBub19hbXA9IjEiLz4iPjxpbnAyOnVfQ29uZmlybVBhc3N3b3JkTGluayB0PSJwbGF0Zm9ybS9teV9hY2NvdW50L3ZlcmlmeV9lbWFpbCIgbm9fYW1wPSIxIi8+PC9hPjxici8+PGJyLz4NCg0KSWYgeW91IGJlbGlldmUgeW91IGhhdmUgcmVjZWl2ZWQgdGhpcyBlbWFpbCBpbiBlcnJvciwgcGxlYXNlIGlnbm9yZSB0aGlzIGVtYWlsLiBZb3VyIGVtYWlsIHdpbGwgbm90IGdldCB2ZXJpZmllZCBzdGF0dXMgdW5sZXNzIHlvdSBoYXZlIGNsaWNrZWQgb24gdGhlIGFib3ZlIGxpbmsuDQo= TWVtYmVyc2hpcCBFeHBpcmF0aW9uIE5vdGljZQ== WW91ciBtZW1iZXJzaGlwIG9uIDxpbnAyOm1fTGluayB0ZW1wbGF0ZT0iaW5kZXgiLz4gd2Vic2l0ZSB3aWxsIHNvb24gZXhwaXJlLg== TWVtYmVyc2hpcCBFeHBpcmF0aW9uIE5vdGljZSBmb3IgIjxpbnAyOlVzZXJUaXRsZS8+IiBTZW50 VXNlciA8aW5wMjpVc2VyVGl0bGUvPiBtZW1iZXJzaGlwIHdpbGwgZXhwaXJlIHNvb24u WW91ciBNZW1iZXJzaGlwIEV4cGlyZWQ= WW91ciBtZW1iZXJzaGlwIG9uIDxpbnAyOm1fTGluayB0ZW1wbGF0ZT0iaW5kZXgiLz4gd2Vic2l0ZSBoYXMgZXhwaXJlZC4= VXNlcidzIE1lbWJlcnNoaXAgRXhwaXJlZCAoIDxpbnAyOlVzZXJUaXRsZS8+KQ== VXNlcidzICg8aW5wMjpVc2VyVGl0bGUvPikgbWVtYmVyc2hpcCBvbiA8aW5wMjptX0xpbmsgdGVtcGxhdGU9ImluZGV4Ii8+IHdlYnNpdGUgaGFzIGV4cGlyZWQu TmV3IHBhc3N3b3JkIGdlbmVyYXRlZA== RGVhciA8aW5wMjp1X0ZpZWxkIG5hbWU9IkZpcnN0TmFtZSIvPiwNCg0KQSBuZXcgcGFzc3dvcmQgaGFzIGJlZW4gZ2VuZXJhdGVkIGZvciB5b3VyIHVzZXIuDQoNCk5vdyB5b3UgY2FuIGxvZ2luIHVzaW5nIHRoZSBmb2xsb3dpbmcgY3JlZGVudGlhbHM6DQoNCjxpbnAyOm1faWYgY2hlY2s9InVfRmllbGQiIG5hbWU9IlVzZXJuYW1lIj5Vc2VybmFtZTogPGlucDI6dV9GaWVsZCBuYW1lPSJVc2VybmFtZSIvPjxpbnAyOm1fZWxzZS8+RS1tYWlsOiA8aW5wMjp1X0ZpZWxkIG5hbWU9IkVtYWlsIi8+PC9pbnAyOm1faWY+IA0KUGFzc3dvcmQ6IDxpbnAyOnVfRmllbGQgbmFtZT0iUGFzc3dvcmRfcGxhaW4iLz4g UmVzZXQgUGFzc3dvcmQgQ29uZmlybWF0aW9u SGVsbG8sPGJyLz48YnIvPg0KDQpJdCBzZWVtcyB0aGF0IHlvdSBoYXZlIHJlcXVlc3RlZCBhIHBhc3N3b3JkIHJlc2V0IGZvciB5b3VyIEluLXBvcnRhbCBhY2NvdW50LiBJZiB5b3Ugd291bGQgbGlrZSB0byBwcm9jZWVkIGFuZCBjaGFuZ2UgdGhlIHBhc3N3b3JkLCBwbGVhc2UgY2xpY2sgb24gdGhlIGxpbmsgYmVsb3c6PGJyLz48YnIvPg0KDQo8YSBocmVmPSI8aW5wMjp1X0NvbmZpcm1QYXNzd29yZExpbmsgbm9fYW1wPSIxIi8+Ij48aW5wMjp1X0NvbmZpcm1QYXNzd29yZExpbmsgbm9fYW1wPSIxIi8+PC9hPjxici8+PGJyLz4NCg0KWW91IHdpbGwgcmVjZWl2ZSBhIHNlY29uZCBlbWFpbCB3aXRoIHlvdXIgbmV3IHBhc3N3b3JkIHNob3J0bHkuPGJyLz48YnIvPg0KDQpJZiB5b3UgYmVsaWV2ZSB5b3UgaGF2ZSByZWNlaXZlZCB0aGlzIGVtYWlsIGluIGVycm9yLCBwbGVhc2UgaWdub3JlIHRoaXMgZW1haWwuIFlvdXIgcGFzc3dvcmQgd2lsbCBub3QgYmUgY2hhbmdlZCB1bmxlc3MgeW91IGhhdmUgY2xpY2tlZCBvbiB0aGUgYWJvdmUgbGluay4NCg== U3Vic2NyaWJlZCB0byBhIE1haWxpbmcgTGlzdCBvbiA8aW5wMjptX0xpbmsgdGVtcGxhdGU9ImluZGV4Ii8+ WW91IGhhdmUgc3Vic2NyaWJlZCB0byBhIG1haWxpbmcgbGlzdCBvbiA8aW5wMjptX0xpbmsgdGVtcGxhdGU9ImluZGV4Ii8+IHdlYnNpdGUu TmV3IFVzZXIgaGFzIFN1YnNjcmliZWQgdG8gYSBNYWxsaW5nIExpc3Q= TmV3IHVzZXIgPGlucDI6RmllbGQgbmFtZT0iRW1haWwiLz4gaGFzIHN1YnNjcmliZWQgdG8gYSBtYWlsaW5nIGxpc3Qgb24gPGEgaHJlZj0iPGlucDI6bV9MaW5rIHRlbXBsYXRlPSJpbmRleCIvPiI+PGlucDI6bV9MaW5rIHRlbXBsYXRlPSJpbmRleCIvPjwvYT4gd2Vic2l0ZS4= Q2hlY2sgb3V0IHRoaXMgV2Vic2l0ZQ== SGVsbG8sPC9icj48L2JyPg0KDQpUaGlzIG1lc3NhZ2UgaGFzIGJlZW4gc2VudCB0byB5b3UgZnJvbSBvbmUgb2YgeW91ciBmcmllbmRzLjwvYnI+PC9icj4NCkNoZWNrIG91dCB0aGlzIHNpdGU6IDxhIGhyZWY9IjxpbnAyOm1fTGluayB0ZW1wbGF0ZT0iaW5kZXgiLz4iPjxpbnAyOm1fTGluayB0ZW1wbGF0ZT0iaW5kZXgiLz48L2E+IQ== V2Vic2l0ZSBTdWdnZXN0ZWQgdG8gYSBGcmllbmQ= QSB2aXNpdG9yIHN1Z2dlc3RlZCA8YSBocmVmPSI8aW5wMjptX0xpbmsgdGVtcGxhdGU9ImluZGV4Ii8+Ij48aW5wMjptX0xpbmsgdGVtcGxhdGU9ImluZGV4Ii8+PC9hPiB3ZWJzaXRlIHRvIGEgZnJpZW5kLg== WW91IGhhdmUgYmVlbiB1bnN1YnNjcmliZWQ= WW91IGhhdmUgc3VjY2Vzc2Z1bGx5IHVuc3Vic2NyaWJlZCBmcm9tIHRoZSBtYWlsaW5nIGxpc3Qgb24gPGEgaHJlZj0iPGlucDI6bV9CYXNlVXJsIC8+Ij48aW5wMjptX0Jhc2VVcmwgLz48L2E+IHdlYnNpdGUu VXNlciBVbnN1YnNyaWJlZCBmcm9tIE1haWxpbmcgTGlzdA== QSB1c2VyICI8aW5wMjpGaWVsZCBuYW1lPSJFbWFpbCIvPiIgaGFzIHVuc3Vic2NyaWJlZCBmcm9tIHRoZSBtYWlsaW5nIGxpc3Qgb24gPGEgaHJlZj0iPGlucDI6bV9MaW5rIHRlbXBsYXRlPSJpbmRleCIvPiI+PGlucDI6bV9MaW5rIHRlbXBsYXRlPSJpbmRleCIvPjwvYT4u VXNlciBSZWdpc3RyYXRpb24gaXMgVmFsaWRhdGVk V2VsY29tZSB0byBJbi1wb3J0YWwhPGJyLz48YnIvPg0KDQpZb3VyIHVzZXIgcmVnaXN0cmF0aW9uIGhhcyBiZWVuIGFwcHJvdmVkLiBZb3UgY2FuIGxvZ2luIG5vdyA8YSBocmVmPSI8aW5wMjptX0xpbmsgdGVtcGxhdGU9ImluZGV4Ii8+Ij48aW5wMjptX0xpbmsgdGVtcGxhdGU9ImluZGV4Ii8+PC9hPiB1c2luZyB0aGUgZm9sbG93aW5nIGluZm9ybWF0aW9uOjxici8+PGJyLz4NCg0KPT09PT09PT09PT09PT09PT09PGJyLz4NClVzZXJuYW1lOiAiPGlucDI6dV9Vc2VyVGl0bGUvPiI8YnIvPg0KUGFzc3dvcmQ6ICI8aW5wMjp1X0ZpZWxkIG5hbWU9IlBhc3N3b3JkX3BsYWluIi8+Ijxici8+DQo9PT09PT09PT09PT09PT09PT08YnIvPjxici8+DQo= TmV3IFVzZXIgUmVnaXN0cmF0aW9uIGlzIFZhbGlkYXRlZA== VXNlciAiPGlucDI6dV9Vc2VyVGl0bGUvPiIgaGFzIGJlZW4gdmFsaWRhdGVkLg==