Index: branches/5.2.x/core/kernel/db/cat_event_handler.php
===================================================================
--- branches/5.2.x/core/kernel/db/cat_event_handler.php (revision 16673)
+++ branches/5.2.x/core/kernel/db/cat_event_handler.php (revision 16674)
@@ -1,3117 +1,3117 @@
Array ('self' => 'add|edit|advanced:import'),
'OnResetSettings' => Array ('self' => 'add|edit|advanced:import'),
'OnBeforeDeleteOriginal' => Array ('self' => 'edit|advanced:approve'),
'OnAfterDeleteOriginal' => Array ('self' => 'edit|advanced:approve'),
'OnCopy' => Array ('self' => true),
'OnDownloadFile' => Array ('self' => 'view'),
'OnCancelAction' => Array ('self' => true),
'OnItemBuild' => Array ('self' => true),
'OnMakeVote' => Array ('self' => true),
'OnReviewHelpful' => Array ('self' => true),
);
$this->permMapping = array_merge($this->permMapping, $permissions);
}
/**
* Load item if id is available
*
* @param kEvent $event
* @return void
* @access protected
*/
protected function LoadItem(kEvent $event)
{
/** @var kDBItem $object */
$object = $event->getObject();
$id = $this->getPassedID($event);
if ( $object->Load($id) ) {
/** @var Params $actions */
$actions = $this->Application->recallObject('kActions');
$actions->Set($event->getPrefixSpecial() . '_id', $object->GetID());
$use_pending_editing = $this->Application->getUnitOption($event->Prefix, 'UsePendingEditing');
if ( $use_pending_editing && $event->Special != 'original' ) {
$this->Application->SetVar($event->Prefix . '.original_id', $object->GetDBField('OrgId'));
}
}
else {
$object->setID($id);
}
}
/**
* Checks user permission to execute given $event
*
* @param kEvent $event
* @return bool
* @access public
*/
public function CheckPermission(kEvent $event)
{
if ( !$this->Application->isAdmin ) {
if ( $event->Name == 'OnSetSortingDirect' ) {
// allow sorting on front event without view permission
return true;
}
}
if ( $event->Name == 'OnExport' ) {
// save category_id before doing export
$this->Application->LinkVar('m_cat_id');
}
if ( in_array($event->Name, $this->_getMassPermissionEvents()) ) {
$items = $this->_getPermissionCheckInfo($event);
/** @var kPermissionsHelper $perm_helper */
$perm_helper = $this->Application->recallObject('PermissionsHelper');
if ( ($event->Name == 'OnSave') && array_key_exists(0, $items) ) {
// adding new item (ID = 0)
$perm_value = $perm_helper->AddCheckPermission($items[0]['CategoryId'], $event->Prefix) > 0;
}
else {
// leave only items, that can be edited
$ids = Array ();
$check_method = in_array($event->Name, Array ('OnMassDelete', 'OnCut')) ? 'DeleteCheckPermission' : 'ModifyCheckPermission';
foreach ($items as $item_id => $item_data) {
if ( $perm_helper->$check_method($item_data['CreatedById'], $item_data['CategoryId'], $event->Prefix) > 0 ) {
$ids[] = $item_id;
}
}
if ( !$ids ) {
// no items left for editing -> no permission
return $perm_helper->finalizePermissionCheck($event, false);
}
$perm_value = true;
$event->setEventParam('ids', $ids); // will be used later by "kDBEventHandler::StoreSelectedIDs" method
}
return $perm_helper->finalizePermissionCheck($event, $perm_value);
}
$export_events = array('OnSaveSettings', 'OnResetSettings', 'OnExportBegin');
if ( in_array($event->Name, $export_events) || ($event->Special == 'export' && $event->Name == 'OnNew') ) {
/** @var kPermissionsHelper $perm_helper */
$perm_helper = $this->Application->recallObject('PermissionsHelper');
$perm_value = $this->Application->CheckPermission('in-portal:main_import.view');
return $perm_helper->finalizePermissionCheck($event, $perm_value);
}
if ( $event->Name == 'OnProcessSelected' ) {
if ( $this->Application->RecallVar('dst_field') == 'ImportCategory' ) {
// when selecting target import category
return $this->Application->CheckPermission('in-portal:main_import.view');
}
}
return parent::CheckPermission($event);
}
/**
* Returns events, that require item-based (not just event-name based) permission check
*
* @return Array
*/
function _getMassPermissionEvents()
{
return array(
'OnStoreSelected', 'OnEdit', 'OnSave', 'OnMassDelete', 'OnMassApprove',
'OnMassDecline', 'OnMassMoveUp', 'OnMassMoveDown',
'OnCut',
);
}
/**
* Returns category item IDs, that require permission checking
*
* @param kEvent $event
* @return string
*/
function _getPermissionCheckIDs($event)
{
if ($event->Name == 'OnSave') {
$selected_ids = implode(',', $this->getSelectedIDs($event, true));
if (!$selected_ids) {
$selected_ids = 0; // when saving newly created item (OnPreCreate -> OnPreSave -> OnSave)
}
}
else {
// OnEdit, OnMassDelete events, when items are checked in grid
$selected_ids = implode(',', $this->StoreSelectedIDs($event));
}
return $selected_ids;
}
/**
* Returns information used in permission checking
*
* @param kEvent $event
* @return Array
*/
function _getPermissionCheckInfo($event)
{
/** @var kPermissionsHelper $perm_helper */
$perm_helper = $this->Application->recallObject('PermissionsHelper');
// when saving data from temp table to live table check by data from temp table
$item_ids = $this->_getPermissionCheckIDs($event);
$items = $perm_helper->GetCategoryItemData($event->Prefix, $item_ids, $event->Name == 'OnSave');
if (!$items) {
// when item not present in temp table, then permission is not checked, because there are no data in db to check
$items_info = $this->Application->GetVar( $event->getPrefixSpecial(true) );
list ($id, $fields_hash) = each($items_info);
if (array_key_exists('CategoryId', $fields_hash)) {
$item_category = $fields_hash['CategoryId'];
}
else {
$item_category = $this->Application->GetVar('m_cat_id');
}
$items[$id] = Array (
'CreatedById' => $this->Application->RecallVar('use_id'),
'CategoryId' => $item_category,
);
}
return $items;
}
/**
* Add selected items to clipboard with mode = COPY (CLONE)
*
* @param kEvent $event
* @return void
* @access protected
*/
protected function OnCopy($event)
{
$this->Application->RemoveVar('clipboard');
/** @var kClipboardHelper $clipboard_helper */
$clipboard_helper = $this->Application->recallObject('ClipboardHelper');
$clipboard_helper->setClipboard($event, 'copy', $this->StoreSelectedIDs($event));
$this->clearSelectedIDs($event);
}
/**
* Add selected items to clipboard with mode = CUT
*
* @param kEvent $event
* @return void
* @access protected
*/
protected function OnCut($event)
{
$this->Application->RemoveVar('clipboard');
/** @var kClipboardHelper $clipboard_helper */
$clipboard_helper = $this->Application->recallObject('ClipboardHelper');
$clipboard_helper->setClipboard($event, 'cut', $this->StoreSelectedIDs($event));
$this->clearSelectedIDs($event);
}
/**
* Checks permission for OnPaste event
*
* @param kEvent $event
* @return bool
*/
function _checkPastePermission($event)
{
/** @var kPermissionsHelper $perm_helper */
$perm_helper = $this->Application->recallObject('PermissionsHelper');
$category_id = $this->Application->GetVar('m_cat_id');
if ($perm_helper->AddCheckPermission($category_id, $event->Prefix) == 0) {
// no items left for editing -> no permission
return $perm_helper->finalizePermissionCheck($event, false);
}
return true;
}
/**
* Performs category item paste
*
* @param kEvent $event
* @return void
* @access protected
*/
protected function OnPaste($event)
{
if ( $this->Application->CheckPermission('SYSTEM_ACCESS.READONLY', 1) || !$this->_checkPastePermission($event) ) {
$event->status = kEvent::erFAIL;
return;
}
$clipboard_data = $event->getEventParam('clipboard_data');
if ( !$clipboard_data['cut'] && !$clipboard_data['copy'] ) {
return;
}
if ( $clipboard_data['copy'] ) {
/** @var kTempTablesHandler $temp */
$temp = $this->Application->recallObject($event->getPrefixSpecial() . '_TempHandler', 'kTempTablesHandler');
$this->Application->SetVar('ResetCatBeforeClone', 1); // used in "kCatDBEventHandler::OnBeforeClone"
$temp->CloneItems($event->Prefix, $event->Special, $clipboard_data['copy']);
}
if ( $clipboard_data['cut'] ) {
/** @var kCatDBItem $object */
$object = $this->Application->recallObject($event->getPrefixSpecial() . '.item', $event->Prefix, Array ('skip_autoload' => true));
foreach ($clipboard_data['cut'] as $id) {
$object->Load($id);
$object->MoveToCat();
}
}
}
/**
* Deletes all selected items.
* Automatically recurse into sub-items using temp handler, and deletes sub-items
* by calling its Delete method if sub-item has AutoDelete set to true in its config file
*
* @param kEvent $event
* @return void
* @access protected
*/
protected function OnMassDelete(kEvent $event)
{
if ( $this->Application->CheckPermission('SYSTEM_ACCESS.READONLY', 1) ) {
$event->status = kEvent::erFAIL;
return;
}
$ids = $this->StoreSelectedIDs($event);
$to_delete = Array ();
$recycle_bin = $this->Application->ConfigValue('RecycleBinFolder');
if ( $recycle_bin ) {
/** @var CategoriesItem $rb */
$rb = $this->Application->recallObject('c.recycle', NULL, array ('skip_autoload' => true));
$rb->Load($recycle_bin);
/** @var kCatDBItem $object */
$object = $this->Application->recallObject($event->Prefix . '.recycleitem', NULL, Array ('skip_autoload' => true));
foreach ($ids as $id) {
$object->Load($id);
if ( preg_match('/^' . preg_quote($rb->GetDBField('ParentPath'), '/') . '/', $object->GetDBField('ParentPath')) ) {
$to_delete[] = $id;
continue;
}
$object->MoveToCat($recycle_bin);
}
$ids = $to_delete;
}
/** @var kTempTablesHandler $temp_handler */
$temp_handler = $this->Application->recallObject($event->getPrefixSpecial() . '_TempHandler', 'kTempTablesHandler');
$event->setEventParam('ids', $ids);
$this->customProcessing($event, 'before');
$ids = $event->getEventParam('ids');
if ( $ids ) {
$temp_handler->DeleteItems($event->Prefix, $event->Special, $ids);
}
$this->clearSelectedIDs($event);
}
/**
* Return type clauses for list bulding on front
*
* @param kEvent $event
* @return Array
*/
function getTypeClauses($event)
{
$types = $event->getEventParam('types');
$types = $types ? explode(',', $types) : Array ();
$except_types = $event->getEventParam('except');
$except_types = $except_types ? explode(',', $except_types) : Array ();
$type_clauses = Array();
$user_id = $this->Application->RecallVar('user_id');
$owner_field = $this->getOwnerField($event->Prefix);
$type_clauses['my_items']['include'] = '%1$s.'.$owner_field.' = '.$user_id;
$type_clauses['my_items']['except'] = '%1$s.'.$owner_field.' <> '.$user_id;
$type_clauses['my_items']['having_filter'] = false;
$type_clauses['pick']['include'] = '%1$s.EditorsPick = 1 AND '.TABLE_PREFIX.'CategoryItems.PrimaryCat = 1';
$type_clauses['pick']['except'] = '%1$s.EditorsPick! = 1 AND '.TABLE_PREFIX.'CategoryItems.PrimaryCat = 1';
$type_clauses['pick']['having_filter'] = false;
$type_clauses['hot']['include'] = '`IsHot` = 1 AND PrimaryCat = 1';
$type_clauses['hot']['except'] = '`IsHot`! = 1 AND PrimaryCat = 1';
$type_clauses['hot']['having_filter'] = true;
$type_clauses['pop']['include'] = '`IsPop` = 1 AND PrimaryCat = 1';
$type_clauses['pop']['except'] = '`IsPop`! = 1 AND PrimaryCat = 1';
$type_clauses['pop']['having_filter'] = true;
$type_clauses['new']['include'] = '`IsNew` = 1 AND PrimaryCat = 1';
$type_clauses['new']['except'] = '`IsNew`! = 1 AND PrimaryCat = 1';
$type_clauses['new']['having_filter'] = true;
$type_clauses['displayed']['include'] = '';
$displayed = $this->Application->GetVar($event->Prefix.'_displayed_ids');
if ($displayed) {
$id_field = $this->Application->getUnitOption($event->Prefix, 'IDField');
$type_clauses['displayed']['except'] = '%1$s.'.$id_field.' NOT IN ('.$displayed.')';
}
else {
$type_clauses['displayed']['except'] = '';
}
$type_clauses['displayed']['having_filter'] = false;
$item_type = (int)$this->Application->getUnitOption($event->Prefix, 'ItemType');
if (in_array('search', $types) || in_array('search', $except_types)) {
$event_mapping = Array (
'simple' => 'OnSimpleSearch',
'subsearch' => 'OnSubSearch',
'advanced' => 'OnAdvancedSearch'
);
$keywords = $event->getEventParam('keyword_string');
$type = $this->Application->GetVar('search_type', 'simple');
if ( $keywords ) {
// processing keyword_string param of ListProducts tag
$this->Application->SetVar('keywords', $keywords);
$type = 'simple';
}
$search_event = $event_mapping[$type];
$this->$search_event($event);
/** @var kDBList $object */
$object = $event->getObject();
/** @var kSearchHelper $search_helper */
$search_helper = $this->Application->recallObject('SearchHelper');
$search_sql = ' FROM ' . $search_helper->getSearchTable() . ' search_result
JOIN %1$s
ON %1$s.ResourceId = search_result.ResourceId
AND search_result.ItemType = ' . $item_type;
$sql = str_replace('FROM %1$s', $search_sql, $object->GetPlainSelectSQL());
$object->SetSelectSQL($sql);
$object->addCalculatedField('Relevance', 'search_result.Relevance');
$type_clauses['search']['include'] = 'PrimaryCat = 1 AND ('.TABLE_PREFIX.'Categories.Status = '.STATUS_ACTIVE.')';
$type_clauses['search']['except'] = 'PrimaryCat = 1 AND ('.TABLE_PREFIX.'Categories.Status = '.STATUS_ACTIVE.')';
$type_clauses['search']['having_filter'] = false;
}
if (in_array('related', $types) || in_array('related', $except_types)) {
$related_to = $event->getEventParam('related_to');
if (!$related_to) {
$related_prefix = $event->Prefix;
}
else {
$sql = 'SELECT Prefix
FROM '.TABLE_PREFIX.'ItemTypes
WHERE ItemName = '.$this->Conn->qstr($related_to);
$related_prefix = $this->Conn->GetOne($sql);
}
$rel_table = $this->Application->getUnitOption('rel', 'TableName');
if ($item_type == 0) {
trigger_error('ItemType not defined for prefix ' . $event->Prefix . '', E_USER_WARNING);
}
// process case, then this list is called inside another list
$prefix_special = $event->getEventParam('PrefixSpecial');
if (!$prefix_special) {
$prefix_special = $this->Application->Parser->GetParam('PrefixSpecial');
}
$id = false;
if ($prefix_special !== false) {
$processed_prefix = $this->Application->processPrefix($prefix_special);
if ($processed_prefix['prefix'] == $related_prefix) {
// printing related categories within list of items (not on details page)
/** @var kDBList $list */
$list = $this->Application->recallObject($prefix_special);
$id = $list->GetID();
}
}
if ($id === false) {
// printing related categories for single item (possibly on details page)
if ($related_prefix == 'c') {
$id = $this->Application->GetVar('m_cat_id');
}
else {
$id = $this->Application->GetVar($related_prefix . '_id');
}
}
/** @var kCatDBItem $p_item */
$p_item = $this->Application->recallObject($related_prefix.'.current', NULL, Array('skip_autoload' => true));
$p_item->Load( (int)$id );
$p_resource_id = $p_item->GetDBField('ResourceId');
$sql = 'SELECT SourceId, TargetId FROM '.$rel_table.'
WHERE
(Enabled = 1)
AND (
(Type = 0 AND SourceId = '.$p_resource_id.' AND TargetType = '.$item_type.')
OR
(Type = 1
AND (
(SourceId = '.$p_resource_id.' AND TargetType = '.$item_type.')
OR
(TargetId = '.$p_resource_id.' AND SourceType = '.$item_type.')
)
)
)';
$related_ids_array = $this->Conn->Query($sql);
$related_ids = Array();
foreach ($related_ids_array as $record) {
$related_ids[] = $record[ $record['SourceId'] == $p_resource_id ? 'TargetId' : 'SourceId' ];
}
if (count($related_ids) > 0) {
$type_clauses['related']['include'] = '%1$s.ResourceId IN ('.implode(',', $related_ids).') AND PrimaryCat = 1';
$type_clauses['related']['except'] = '%1$s.ResourceId NOT IN ('.implode(',', $related_ids).') AND PrimaryCat = 1';
}
else {
$type_clauses['related']['include'] = '0';
$type_clauses['related']['except'] = '1';
}
$type_clauses['related']['having_filter'] = false;
}
if (in_array('favorites', $types) || in_array('favorites', $except_types)) {
$sql = 'SELECT ResourceId
FROM '.$this->Application->getUnitOption('fav', 'TableName').'
WHERE PortalUserId = '.$this->Application->RecallVar('user_id');
$favorite_ids = $this->Conn->GetCol($sql);
if ($favorite_ids) {
$type_clauses['favorites']['include'] = '%1$s.ResourceId IN ('.implode(',', $favorite_ids).') AND PrimaryCat = 1';
$type_clauses['favorites']['except'] = '%1$s.ResourceId NOT IN ('.implode(',', $favorite_ids).') AND PrimaryCat = 1';
}
else {
$type_clauses['favorites']['include'] = 0;
$type_clauses['favorites']['except'] = 1;
}
$type_clauses['favorites']['having_filter'] = false;
}
return $type_clauses;
}
/**
* Returns SQL clause, that will help to select only data from specified category & it's children
*
* @param int $category_id
* @return string
*/
function getCategoryLimitClause($category_id)
{
if (!$category_id) {
return false;
}
$tree_indexes = $this->Application->getTreeIndex($category_id);
if (!$tree_indexes) {
// id of non-existing category was given
return 'FALSE';
}
return TABLE_PREFIX.'Categories.TreeLeft BETWEEN '.$tree_indexes['TreeLeft'].' AND '.$tree_indexes['TreeRight'];
}
/**
* Apply any custom changes to list's sql query
*
* @param kEvent $event
* @return void
* @access protected
* @see kDBEventHandler::OnListBuild()
*/
protected function SetCustomQuery(kEvent $event)
{
parent::SetCustomQuery($event);
/** @var kCatDBList $object */
$object = $event->getObject();
// add category filter if needed
if ($event->Special != 'showall' && $event->Special != 'user') {
if ( (string)$event->getEventParam('parent_cat_id') !== '' ) {
$parent_cat_id = $event->getEventParam('parent_cat_id');
}
else {
$parent_cat_id = $this->Application->GetVar('c_id');
if (!$parent_cat_id) {
$parent_cat_id = $this->Application->GetVar('m_cat_id');
}
if (!$parent_cat_id) {
$parent_cat_id = 0;
}
}
if ("$parent_cat_id" == '0') {
// replace "0" category with "Content" category id (this way template
$parent_cat_id = $this->Application->getBaseCategory();
}
if ((string)$parent_cat_id != 'any') {
if ($event->getEventParam('recursive')) {
$filter_clause = $this->getCategoryLimitClause($parent_cat_id);
if ($filter_clause !== false) {
$object->addFilter('category_filter', $filter_clause);
}
$object->addFilter('primary_filter', 'PrimaryCat = 1');
}
else {
$object->addFilter('category_filter', TABLE_PREFIX.'CategoryItems.CategoryId = '.$parent_cat_id );
}
}
else {
$object->addFilter('primary_filter', 'PrimaryCat = 1');
}
}
else {
$object->addFilter('primary_filter', 'PrimaryCat = 1');
// if using recycle bin don't show items from there
$recycle_bin = $this->Application->ConfigValue('RecycleBinFolder');
if ($recycle_bin) {
$object->addFilter('recyclebin_filter', TABLE_PREFIX.'CategoryItems.CategoryId <> '.$recycle_bin);
}
}
if ($event->Special == 'user') {
$editable_user = $this->Application->GetVar('u_id');
$object->addFilter('owner_filter', '%1$s.'.$this->getOwnerField($event->Prefix).' = '.$editable_user);
}
$this->applyViewPermissionFilter($object);
$types = $event->getEventParam('types');
$this->applyItemStatusFilter($object, $types);
$except_types = $event->getEventParam('except');
$type_clauses = $this->getTypeClauses($event);
/** @var kSearchHelper $search_helper */
$search_helper = $this->Application->recallObject('SearchHelper');
$search_helper->SetComplexFilter($event, $type_clauses, $types, $except_types);
}
/**
* Adds filter, that uses *.VIEW permissions to determine if an item should be shown to a user.
*
* @param kCatDBList $object Object.
*
* @return void
* @access protected
*/
protected function applyViewPermissionFilter(kCatDBList $object)
{
if ( !$this->Application->ConfigValue('CheckViewPermissionsInCatalog') ) {
return;
}
if ( $this->Application->RecallVar('user_id') == USER_ROOT ) {
// for "root" CATEGORY.VIEW permission is checked for items lists too
$view_perm = 1;
}
else {
// for any real user item list view permission is checked instead of CATEGORY.VIEW
/** @var kCountHelper $count_helper */
$count_helper = $this->Application->recallObject('CountHelper');
list ($view_perm, $view_filter) = $count_helper->GetPermissionClause($object->Prefix, 'perm');
$object->addFilter('perm_filter2', $view_filter);
}
$object->addFilter('perm_filter', 'perm.PermId = ' . $view_perm);
}
/**
* Adds filter that filters out items with non-required statuses
*
* @param kDBList $object
* @param string $types
*/
function applyItemStatusFilter(&$object, $types)
{
// Link1 (before modifications) [Status = 1, OrgId = NULL], Link2 (after modifications) [Status = -2, OrgId = Link1_ID]
$pending_editing = $this->Application->getUnitOption($object->Prefix, 'UsePendingEditing');
if (!$this->Application->isAdminUser) {
$types = explode(',', $types);
if (in_array('my_items', $types)) {
$allow_statuses = Array (STATUS_ACTIVE, STATUS_PENDING, STATUS_PENDING_EDITING);
$object->addFilter('status_filter', '%1$s.Status IN ('.implode(',', $allow_statuses).')');
if ($pending_editing) {
$user_id = $this->Application->RecallVar('user_id');
$this->applyPendingEditingFilter($object, $user_id);
}
}
else {
$object->addFilter('status_filter', '(%1$s.Status = ' . STATUS_ACTIVE . ') AND (' . TABLE_PREFIX . 'Categories.Status = ' . STATUS_ACTIVE . ')');
if ($pending_editing) {
// if category item uses pending editing abilities, then in no cases show pending copies on front
$object->addFilter('original_filter', '%1$s.OrgId = 0 OR %1$s.OrgId IS NULL');
}
}
}
else {
if ($pending_editing) {
$this->applyPendingEditingFilter($object);
}
}
}
/**
* Adds filter, that removes live items if they have pending editing copies
*
* @param kDBList $object
* @param int $user_id
*/
function applyPendingEditingFilter(&$object, $user_id = NULL)
{
$sql = 'SELECT OrgId
FROM '.$object->TableName.'
WHERE Status = '.STATUS_PENDING_EDITING.' AND OrgId IS NOT NULL';
if (isset($user_id)) {
$owner_field = $this->getOwnerField($object->Prefix);
$sql .= ' AND '.$owner_field.' = '.$user_id;
}
$pending_ids = $this->Conn->GetCol($sql);
if ($pending_ids) {
$object->addFilter('no_original_filter', '%1$s.'.$object->IDField.' NOT IN ('.implode(',', $pending_ids).')');
}
}
/**
* Adds calculates fields for item statuses
*
* @param kDBItem|kDBList $object
* @param kEvent $event
* @return void
* @access protected
*/
protected function prepareObject(&$object, kEvent $event)
{
$this->prepareItemStatuses($event);
$object->addCalculatedField(
'CachedNavbar',
TABLE_PREFIX . 'Categories.l' . $this->Application->GetVar('m_lang') . '_CachedNavbar'
);
if ( $event->Special == 'export' || $event->Special == 'import' ) {
/** @var kCatDBItemExportHelper $export_helper */
$export_helper = $this->Application->recallObject('CatItemExportHelper');
$export_helper->prepareExportColumns($event);
}
}
/**
* Creates calculated fields for all item statuses based on config settings
*
* @param kEvent $event
*/
function prepareItemStatuses($event)
{
$object = $event->getObject( Array('skip_autoload' => true) );
$property_map = $this->Application->getUnitOption($event->Prefix, 'ItemPropertyMappings');
if (!$property_map) {
return ;
}
// new items
$object->addCalculatedField('IsNew', ' IF(%1$s.NewItem = 2,
IF(%1$s.CreatedOn >= (UNIX_TIMESTAMP() - '.
$this->Application->ConfigValue($property_map['NewDays']).
'*3600*24), 1, 0),
%1$s.NewItem
)');
// hot items (cache updated every hour)
if ($this->Application->isCachingType(CACHING_TYPE_MEMORY)) {
$serial_name = $this->Application->incrementCacheSerial($event->Prefix, NULL, false);
$hot_limit = $this->Application->getCache($property_map['HotLimit'] . '[%' . $serial_name . '%]');
}
else {
$hot_limit = $this->Application->getDBCache($property_map['HotLimit']);
}
if ($hot_limit === false) {
$hot_limit = $this->CalculateHotLimit($event);
}
$object->addCalculatedField('IsHot', ' IF(%1$s.HotItem = 2,
IF(%1$s.'.$property_map['ClickField'].' >= '.$hot_limit.', 1, 0),
%1$s.HotItem
)');
// popular items
$object->addCalculatedField('IsPop', ' IF(%1$s.PopItem = 2,
IF(%1$s.CachedVotesQty >= '.
$this->Application->ConfigValue($property_map['MinPopVotes']).
' AND %1$s.CachedRating >= '.
$this->Application->ConfigValue($property_map['MinPopRating']).
', 1, 0),
%1$s.PopItem)');
}
/**
* Calculates hot limit for current item's table
*
* @param kEvent $event
* @return float
* @access protected
*/
protected function CalculateHotLimit($event)
{
$property_map = $this->Application->getUnitOption($event->Prefix, 'ItemPropertyMappings');
if ( !$property_map ) {
return 0.00;
}
$click_field = $property_map['ClickField'];
$last_hot = $this->Application->ConfigValue($property_map['MaxHotNumber']) - 1;
$sql = 'SELECT ' . $click_field . '
FROM ' . $this->Application->getUnitOption($event->Prefix, 'TableName') . '
ORDER BY ' . $click_field . ' DESC
LIMIT ' . $last_hot . ', 1';
$res = $this->Conn->GetCol($sql);
$hot_limit = (double)array_shift($res);
if ( $this->Application->isCachingType(CACHING_TYPE_MEMORY) ) {
$serial_name = $this->Application->incrementCacheSerial($event->Prefix, NULL, false);
$this->Application->setCache($property_map['HotLimit'] . '[%' . $serial_name . '%]', $hot_limit);
}
else {
$this->Application->setDBCache($property_map['HotLimit'], $hot_limit, 3600);
}
return $hot_limit;
}
/**
* Moves item to preferred category, updates item hits
*
* @param kEvent $event
* @return void
* @access protected
*/
protected function OnBeforeItemUpdate(kEvent $event)
{
parent::OnBeforeItemUpdate($event);
/** @var kCatDBItem $object */
$object = $event->getObject();
// update hits field
$property_map = $this->Application->getUnitOption($event->Prefix, 'ItemPropertyMappings');
if ( $property_map ) {
$click_field = $property_map['ClickField'];
if ( $this->Application->isAdminUser && ($this->Application->GetVar($click_field . '_original') !== false) && floor($this->Application->GetVar($click_field . '_original')) != $object->GetDBField($click_field) ) {
$sql = 'SELECT MAX(' . $click_field . ')
FROM ' . $this->Application->getUnitOption($event->Prefix, 'TableName') . '
WHERE FLOOR(' . $click_field . ') = ' . $object->GetDBField($click_field);
$hits = ($res = $this->Conn->GetOne($sql)) ? $res + 0.000001 : $object->GetDBField($click_field);
$object->SetDBField($click_field, $hits);
}
}
// change category
$target_category = $object->GetDBField('CategoryId');
if ( $object->GetOriginalField('CategoryId') != $target_category ) {
$object->MoveToCat($target_category);
}
+
+ if ( $object->GetChangedFields() ) {
+ $now = adodb_mktime();
+ $object->SetDBField('Modified_date', $now);
+ $object->SetDBField('Modified_time', $now);
+ $object->SetDBField('ModifiedById', $this->Application->RecallVar('user_id'));
+ }
}
/**
* Occurs after loading item, 'id' parameter
* allows to get id of item that was loaded
*
* @param kEvent $event
* @return void
* @access protected
*/
protected function OnAfterItemLoad(kEvent $event)
{
parent::OnAfterItemLoad($event);
$special = substr($event->Special, -6);
/** @var kCatDBItem $object */
$object = $event->getObject();
if ( $special == 'import' || $special == 'export' ) {
$image_data = $object->getPrimaryImageData();
if ( $image_data ) {
$thumbnail_image = $image_data[$image_data['LocalThumb'] ? 'ThumbPath' : 'ThumbUrl'];
if ( $image_data['SameImages'] ) {
$full_image = '';
}
else {
$full_image = $image_data[$image_data['LocalImage'] ? 'LocalPath' : 'Url'];
}
$object->SetDBField('ThumbnailImage', $thumbnail_image);
$object->SetDBField('FullImage', $full_image);
$object->SetDBField('ImageAlt', $image_data['AltName']);
}
}
// substituting pending status value for pending editing
if ( $object->HasField('OrgId') && $object->GetDBField('OrgId') > 0 && $object->GetDBField('Status') == -2 ) {
$new_options = Array ();
$options = $object->GetFieldOption('Status', 'options', false, Array ());
foreach ($options as $key => $val) {
if ( $key == 2 ) {
$key = -2;
}
$new_options[$key] = $val;
}
$object->SetFieldOption('Status', 'options', $new_options);
}
if ( !$this->Application->isAdmin ) {
// linking existing images for item with virtual fields
/** @var ImageHelper $image_helper */
$image_helper = $this->Application->recallObject('ImageHelper');
$image_helper->LoadItemImages($object);
// linking existing files for item with virtual fields
/** @var FileHelper $file_helper */
$file_helper = $this->Application->recallObject('FileHelper');
$file_helper->LoadItemFiles($object);
}
if ( $object->isVirtualField('MoreCategories') ) {
// set item's additional categories to virtual field (used in editing)
$item_categories = $this->getItemCategories($object->GetDBField('ResourceId'));
$object->SetDBField('MoreCategories', $item_categories ? '|' . implode('|', $item_categories) . '|' : '');
}
}
/**
* Occurs after updating item
*
* @param kEvent $event
* @return void
* @access protected
*/
protected function OnAfterItemUpdate(kEvent $event)
{
parent::OnAfterItemUpdate($event);
$this->CalculateHotLimit($event);
if ( substr($event->Special, -6) == 'import' ) {
$this->setCustomExportColumns($event);
}
/** @var kCatDBItem $object */
$object = $event->getObject();
if ( !$this->Application->isAdmin ) {
/** @var ImageHelper $image_helper */
$image_helper = $this->Application->recallObject('ImageHelper');
// process image upload in virtual fields
$image_helper->SaveItemImages($object);
/** @var FileHelper $file_helper */
$file_helper = $this->Application->recallObject('FileHelper');
// process file upload in virtual fields
$file_helper->SaveItemFiles($object);
if ( $event->Special != '-item' ) {
// don't touch categories during cloning
$this->processAdditionalCategories($object, 'update');
}
}
$recycle_bin = $this->Application->ConfigValue('RecycleBinFolder');
if ( $this->Application->isAdminUser && $recycle_bin ) {
$sql = 'SELECT CategoryId
FROM ' . $this->Application->getUnitOption('ci', 'TableName') . '
WHERE ItemResourceId = ' . $object->GetDBField('ResourceId') . ' AND PrimaryCat = 1';
$primary_category = $this->Conn->GetOne($sql);
if ( $primary_category == $recycle_bin ) {
$event->CallSubEvent('OnAfterItemDelete');
}
}
-
- if ( $object->GetChangedFields() ) {
- $now = adodb_mktime();
- $object->SetDBField('Modified_date', $now);
- $object->SetDBField('Modified_time', $now);
- $object->SetDBField('ModifiedById', $this->Application->RecallVar('user_id'));
- }
}
/**
* Sets values for import process
*
* @param kEvent $event
* @return void
* @access protected
*/
protected function OnAfterItemCreate(kEvent $event)
{
parent::OnAfterItemCreate($event);
/** @var kCatDBItem $object */
$object = $event->getObject();
if ( substr($event->Special, -6) == 'import' ) {
$this->setCustomExportColumns($event);
}
$object->assignPrimaryCategory();
if ( !$this->Application->isAdmin ) {
/** @var ImageHelper $image_helper */
$image_helper = $this->Application->recallObject('ImageHelper');
// process image upload in virtual fields
$image_helper->SaveItemImages($object);
/** @var FileHelper $file_helper */
$file_helper = $this->Application->recallObject('FileHelper');
// process file upload in virtual fields
$file_helper->SaveItemFiles($object);
if ( $event->Special != '-item' ) {
// don't touch categories during cloning
$this->processAdditionalCategories($object, 'create');
}
}
}
/**
* Make record to search log
*
* @param string $keywords
* @param int $search_type 0 - simple search, 1 - advanced search
*/
function saveToSearchLog($keywords, $search_type = 0)
{
// don't save keywords for each module separately, just one time
// static variable can't help here, because each module uses it's own class instance !
if (!$this->Application->GetVar('search_logged')) {
$sql = 'UPDATE '.TABLE_PREFIX.'SearchLogs
SET Indices = Indices + 1
WHERE Keyword = '.$this->Conn->qstr($keywords).' AND SearchType = '.$search_type; // 0 - simple search, 1 - advanced search
$this->Conn->Query($sql);
if ($this->Conn->getAffectedRows() == 0) {
$fields_hash = Array('Keyword' => $keywords, 'Indices' => 1, 'SearchType' => $search_type);
$this->Conn->doInsert($fields_hash, TABLE_PREFIX.'SearchLogs');
}
$this->Application->SetVar('search_logged', 1);
}
}
/**
* Makes simple search for category items
* based on keywords string
*
* @param kEvent $event
*/
function OnSimpleSearch($event)
{
$event->redirect = false;
$keywords = $this->Application->unescapeRequestVariable(trim($this->Application->GetVar('keywords')));
/** @var kHTTPQuery $query_object */
$query_object = $this->Application->recallObject('HTTPQuery');
/** @var kSearchHelper $search_helper */
$search_helper = $this->Application->recallObject('SearchHelper');
$search_table = $search_helper->getSearchTable();
$sql = 'SHOW TABLES LIKE "'.$search_table.'"';
if(!isset($query_object->Get['keywords']) &&
!isset($query_object->Post['keywords']) &&
$this->Conn->Query($sql))
{
return; // used when navigating by pages or changing sorting in search results
}
if(!$keywords || strlen($keywords) < $this->Application->ConfigValue('Search_MinKeyword_Length'))
{
$search_helper->ensureEmptySearchTable();
$this->Application->SetVar('keywords_too_short', 1);
return; // if no or too short keyword entered, doing nothing
}
$this->Application->StoreVar('keywords', $keywords);
$this->saveToSearchLog($keywords, 0); // 0 - simple search, 1 - advanced search
$event->setPseudoClass('_List');
/** @var kDBList $object */
$object = $event->getObject();
$this->Application->SetVar($event->getPrefixSpecial().'_Page', 1);
$lang = $this->Application->GetVar('m_lang');
$items_table = $this->Application->getUnitOption($event->Prefix, 'TableName');
$module_name = $this->Application->findModule('Var', $event->Prefix, 'Name');
$sql = 'SELECT *
FROM ' . $this->Application->getUnitOption('confs', 'TableName') . '
WHERE ModuleName = ' . $this->Conn->qstr($module_name) . ' AND SimpleSearch = 1';
$search_config = $this->Conn->Query($sql, 'FieldName');
$field_list = array_keys($search_config);
$join_clauses = Array();
// field processing
$weight_sum = 0;
$alias_counter = 0;
$custom_fields = $this->Application->getUnitOption($event->Prefix, 'CustomFields');
if ($custom_fields) {
$custom_table = $this->Application->getUnitOption($event->Prefix.'-cdata', 'TableName');
$join_clauses[] = ' LEFT JOIN '.$custom_table.' custom_data ON '.$items_table.'.ResourceId = custom_data.ResourceId';
}
// what field in search config becomes what field in sql (key - new field, value - old field (from searchconfig table))
$search_config_map = Array();
foreach ($field_list as $key => $field) {
$local_table = TABLE_PREFIX.$search_config[$field]['TableName'];
$weight_sum += $search_config[$field]['Priority']; // counting weight sum; used when making relevance clause
// processing multilingual fields
if ( !$search_config[$field]['CustomFieldId'] && $object->GetFieldOption($field, 'formatter') == 'kMultiLanguage' ) {
$field_list[$key.'_primary'] = 'l'.$this->Application->GetDefaultLanguageId().'_'.$field;
$field_list[$key] = 'l'.$lang.'_'.$field;
if (!isset($search_config[$field]['ForeignField'])) {
$field_list[$key.'_primary'] = $local_table.'.'.$field_list[$key.'_primary'];
$search_config_map[ $field_list[$key.'_primary'] ] = $field;
}
}
// processing fields from other tables
$foreign_field = $search_config[$field]['ForeignField'];
if ( $foreign_field ) {
$exploded = explode(':', $foreign_field, 2);
if ($exploded[0] == 'CALC') {
// ignoring having type clauses in simple search
unset($field_list[$key]);
continue;
}
else {
$multi_lingual = false;
if ($exploded[0] == 'MULTI') {
$multi_lingual = true;
$foreign_field = $exploded[1];
}
$exploded = explode('.', $foreign_field); // format: table.field_name
$foreign_table = TABLE_PREFIX.$exploded[0];
$alias_counter++;
$alias = 't'.$alias_counter;
if ($multi_lingual) {
$field_list[$key] = $alias.'.'.'l'.$lang.'_'.$exploded[1];
$field_list[$key.'_primary'] = 'l'.$this->Application->GetDefaultLanguageId().'_'.$field;
$search_config_map[ $field_list[$key] ] = $field;
$search_config_map[ $field_list[$key.'_primary'] ] = $field;
}
else {
$field_list[$key] = $alias.'.'.$exploded[1];
$search_config_map[ $field_list[$key] ] = $field;
}
$join_clause = str_replace('{ForeignTable}', $alias, $search_config[$field]['JoinClause']);
$join_clause = str_replace('{LocalTable}', $items_table, $join_clause);
$join_clauses[] = ' LEFT JOIN '.$foreign_table.' '.$alias.'
ON '.$join_clause;
}
}
else {
// processing fields from local table
if ($search_config[$field]['CustomFieldId']) {
$local_table = 'custom_data';
// search by custom field value on current language
$custom_field_id = array_search($field_list[$key], $custom_fields);
$field_list[$key] = 'l'.$lang.'_cust_'.$custom_field_id;
// search by custom field value on primary language
$field_list[$key.'_primary'] = $local_table.'.l'.$this->Application->GetDefaultLanguageId().'_cust_'.$custom_field_id;
$search_config_map[ $field_list[$key.'_primary'] ] = $field;
}
$field_list[$key] = $local_table.'.'.$field_list[$key];
$search_config_map[ $field_list[$key] ] = $field;
}
}
// Keyword string processing.
$where_clause = Array ();
foreach ($field_list as $field) {
if (preg_match('/^' . preg_quote($items_table, '/') . '\.(.*)/', $field, $regs)) {
// local real field
$filter_data = $search_helper->getSearchClause($object, $regs[1], $keywords, false);
if ($filter_data) {
$where_clause[] = $filter_data['value'];
}
}
elseif (preg_match('/^custom_data\.(.*)/', $field, $regs)) {
$custom_field_name = 'cust_' . $search_config_map[$field];
$filter_data = $search_helper->getSearchClause($object, $custom_field_name, $keywords, false);
if ($filter_data) {
$where_clause[] = str_replace('`' . $custom_field_name . '`', $field, $filter_data['value']);
}
}
else {
$where_clause[] = $search_helper->buildWhereClause($keywords, Array ($field));
}
}
$where_clause = '((' . implode(') OR (', $where_clause) . '))'; // 2 braces for next clauses, see below!
$search_scope = $this->Application->GetVar('search_scope');
if ($search_scope == 'category') {
$category_id = $this->Application->GetVar('m_cat_id');
$category_filter = $this->getCategoryLimitClause($category_id);
if ($category_filter !== false) {
$join_clauses[] = ' LEFT JOIN '.TABLE_PREFIX.'CategoryItems ON '.TABLE_PREFIX.'CategoryItems.ItemResourceId = '.$items_table.'.ResourceId';
$join_clauses[] = ' LEFT JOIN '.TABLE_PREFIX.'Categories ON '.TABLE_PREFIX.'Categories.CategoryId = '.TABLE_PREFIX.'CategoryItems.CategoryId';
$where_clause = '('.$this->getCategoryLimitClause($category_id).') AND '.$where_clause;
}
}
$where_clause = $where_clause . ' AND (' . $items_table . '.Status = ' . STATUS_ACTIVE . ')';
if ($event->MasterEvent && $event->MasterEvent->Name == 'OnListBuild') {
$sub_search_ids = $event->MasterEvent->getEventParam('ResultIds');
if ( $sub_search_ids !== false ) {
if ( $sub_search_ids ) {
$where_clause .= 'AND (' . $items_table . '.ResourceId IN (' . implode(',', $sub_search_ids) . '))';
}
else {
$where_clause .= 'AND FALSE';
}
}
}
// making relevance clause
$positive_words = $search_helper->getPositiveKeywords($keywords);
$this->Application->StoreVar('highlight_keywords', serialize($positive_words));
$revelance_parts = Array();
reset($search_config);
foreach ($positive_words as $keyword_index => $positive_word) {
$positive_word = $search_helper->transformWildcards($positive_word);
$positive_words[$keyword_index] = $this->Conn->escape($positive_word);
}
foreach ($field_list as $field) {
if (!array_key_exists($field, $search_config_map)) {
$map_key = $search_config_map[$items_table . '.' . $field];
}
else {
$map_key = $search_config_map[$field];
}
$config_elem = $search_config[ $map_key ];
$weight = $config_elem['Priority'];
// search by whole words only ([[:<:]] - word boundary)
/*$revelance_parts[] = 'IF('.$field.' REGEXP "[[:<:]]('.implode(' ', $positive_words).')[[:>:]]", '.$weight.', 0)';
foreach ($positive_words as $keyword) {
$revelance_parts[] = 'IF('.$field.' REGEXP "[[:<:]]('.$keyword.')[[:>:]]", '.$weight.', 0)';
}*/
if ( count($positive_words) > 1 ) {
$condition = $field . ' LIKE "%' . implode(' ', $positive_words) . '%"';
$revelance_parts[] = 'IF(' . $condition . ', ' . $weight_sum . ', 0)';
}
// search by partial word matches too
foreach ( $positive_words as $keyword ) {
$revelance_parts[] = 'IF(' . $field . ' LIKE "%' . $keyword . '%", ' . $weight . ', 0)';
}
}
$revelance_parts = array_unique($revelance_parts);
$conf_postfix = $this->Application->getUnitOption($event->Prefix, 'SearchConfigPostfix');
$rel_keywords = $this->Application->ConfigValue('SearchRel_Keyword_'.$conf_postfix) / 100;
$rel_pop = $this->Application->ConfigValue('SearchRel_Pop_'.$conf_postfix) / 100;
$rel_rating = $this->Application->ConfigValue('SearchRel_Rating_'.$conf_postfix) / 100;
$relevance_clause = '('.implode(' + ', $revelance_parts).') / '.$weight_sum.' * '.$rel_keywords;
if ($rel_pop && $object->isField('Hits')) {
$relevance_clause .= ' + (Hits + 1) / (MAX(Hits) + 1) * '.$rel_pop;
}
if ($rel_rating && $object->isField('CachedRating')) {
$relevance_clause .= ' + (CachedRating + 1) / (MAX(CachedRating) + 1) * '.$rel_rating;
}
// building final search query
$search_table_exists = $this->Conn->Query('SHOW TABLES LIKE "'.$search_table.'"');
if (!$this->Application->GetVar('do_not_drop_search_table')) {
if ( $search_table_exists ) {
$this->Conn->Query('TRUNCATE TABLE '.$search_table);
}
$this->Application->SetVar('do_not_drop_search_table', true);
}
if ($search_table_exists) {
$select_intro = 'INSERT INTO '.$search_table.' (Relevance, ItemId, ResourceId, ItemType, EdPick) ';
}
else {
$select_intro = 'CREATE TABLE '.$search_table.' ENGINE = MEMORY AS ';
}
$edpick_clause = $this->Application->getUnitOption($event->Prefix.'.EditorsPick', 'Fields') ? $items_table.'.EditorsPick' : '0';
$sql = $select_intro.' SELECT '.$relevance_clause.' AS Relevance,
'.$items_table.'.'.$this->Application->getUnitOption($event->Prefix, 'IDField').' AS ItemId,
'.$items_table.'.ResourceId,
'.$this->Application->getUnitOption($event->Prefix, 'ItemType').' AS ItemType,
'.$edpick_clause.' AS EdPick
FROM '.$object->TableName.'
'.implode(' ', $join_clauses).'
WHERE '.$where_clause.'
GROUP BY '.$items_table.'.'.$this->Application->getUnitOption($event->Prefix, 'IDField').' ORDER BY Relevance DESC';
$this->Conn->Query($sql);
if ( !$search_table_exists ) {
$sql = 'ALTER TABLE ' . $search_table . '
ADD INDEX (ResourceId),
ADD INDEX (Relevance)';
$this->Conn->Query($sql);
$this->Application->StoreVar('search_performed', 1);
}
}
/**
* Enter description here...
*
* @param kEvent $event
*/
function OnSubSearch($event)
{
// keep search results from other items after doing a sub-search on current item type
$this->Application->SetVar('do_not_drop_search_table', true);
/** @var kSearchHelper $search_helper */
$search_helper = $this->Application->recallObject('SearchHelper');
$search_table = $search_helper->getSearchTable();
$sql = 'SHOW TABLES LIKE "' . $search_table . '"';
$ids = array();
if ( $this->Conn->Query($sql) ) {
$item_type = $this->Application->getUnitOption($event->Prefix, 'ItemType');
// 1. get ids to be used as search bounds
$sql = 'SELECT DISTINCT ResourceId
FROM ' . $search_table . '
WHERE ItemType = ' . $item_type;
$ids = $this->Conn->GetCol($sql);
// 2. delete previously found ids
$sql = 'DELETE FROM ' . $search_table . '
WHERE ItemType = ' . $item_type;
$this->Conn->Query($sql);
}
$event->setEventParam('ResultIds', $ids);
$event->CallSubEvent('OnSimpleSearch');
}
/**
* Enter description here...
*
* @param kEvent $event
* @todo Change all hardcoded Products table & In-Commerce module usage to dynamic usage from item config !!!
*/
function OnAdvancedSearch($event)
{
/** @var kHTTPQuery $query_object */
$query_object = $this->Application->recallObject('HTTPQuery');
if ( !isset($query_object->Post['andor']) ) {
// used when navigating by pages or changing sorting in search results
return;
}
$this->Application->RemoveVar('keywords');
$this->Application->RemoveVar('Search_Keywords');
$module_name = $this->Application->findModule('Var', $event->Prefix, 'Name');
$sql = 'SELECT *
FROM '.$this->Application->getUnitOption('confs', 'TableName').'
WHERE (ModuleName = '.$this->Conn->qstr($module_name).') AND (AdvancedSearch = 1)';
$search_config = $this->Conn->Query($sql);
$lang = $this->Application->GetVar('m_lang');
/** @var kDBList $object */
$object = $event->getObject();
$object->SetPage(1);
$items_table = $this->Application->getUnitOption($event->Prefix, 'TableName');
$search_keywords = $this->Application->GetVar('value'); // will not be changed
$keywords = $this->Application->GetVar('value'); // will be changed down there
$verbs = $this->Application->GetVar('verb');
$glues = $this->Application->GetVar('andor');
$and_conditions = Array();
$or_conditions = Array();
$and_having_conditions = Array();
$or_having_conditions = Array();
$join_clauses = Array();
$highlight_keywords = Array();
$relevance_parts = Array();
$alias_counter = 0;
$custom_fields = $this->Application->getUnitOption($event->Prefix, 'CustomFields');
if ($custom_fields) {
$custom_table = $this->Application->getUnitOption($event->Prefix.'-cdata', 'TableName');
$join_clauses[] = ' LEFT JOIN '.$custom_table.' custom_data ON '.$items_table.'.ResourceId = custom_data.ResourceId';
}
$search_log = '';
$weight_sum = 0;
// processing fields and preparing conditions
foreach ($search_config as $record) {
$field = $record['FieldName'];
$join_clause = '';
$condition_mode = 'WHERE';
// field processing
$local_table = TABLE_PREFIX.$record['TableName'];
$weight_sum += $record['Priority']; // counting weight sum; used when making relevance clause
// processing multilingual fields
if ( $object->GetFieldOption($field, 'formatter') == 'kMultiLanguage' ) {
$field_name = 'l'.$lang.'_'.$field;
}
else {
$field_name = $field;
}
// processing fields from other tables
$foreign_field = $record['ForeignField'];
if ( $foreign_field ) {
$exploded = explode(':', $foreign_field, 2);
if($exploded[0] == 'CALC')
{
$user_groups = $this->Application->RecallVar('UserGroups');
$field_name = str_replace('{PREFIX}', TABLE_PREFIX, $exploded[1]);
$join_clause = str_replace('{PREFIX}', TABLE_PREFIX, $record['JoinClause']);
$join_clause = str_replace('{USER_GROUPS}', $user_groups, $join_clause);
$join_clause = ' LEFT JOIN '.$join_clause;
$condition_mode = 'HAVING';
}
else {
$exploded = explode('.', $foreign_field);
$foreign_table = TABLE_PREFIX.$exploded[0];
if($record['CustomFieldId']) {
$exploded[1] = 'l'.$lang.'_'.$exploded[1];
}
$alias_counter++;
$alias = 't'.$alias_counter;
$field_name = $alias.'.'.$exploded[1];
$join_clause = str_replace('{ForeignTable}', $alias, $record['JoinClause']);
$join_clause = str_replace('{LocalTable}', $items_table, $join_clause);
if($record['CustomFieldId'])
{
$join_clause .= ' AND '.$alias.'.CustomFieldId='.$record['CustomFieldId'];
}
$join_clause = ' LEFT JOIN '.$foreign_table.' '.$alias.'
ON '.$join_clause;
}
}
else
{
// processing fields from local table
if ($record['CustomFieldId']) {
$local_table = 'custom_data';
$field_name = 'l'.$lang.'_cust_'.array_search($field_name, $custom_fields);
}
$field_name = $local_table.'.'.$field_name;
}
$condition = $this->getAdvancedSearchCondition($field_name, $record, $keywords, $verbs, $highlight_keywords);
if ($record['CustomFieldId'] && strlen($condition)) {
// search in primary value of custom field + value in current language
$field_name = $local_table.'.'.'l'.$this->Application->GetDefaultLanguageId().'_cust_'.array_search($field, $custom_fields);
$primary_condition = $this->getAdvancedSearchCondition($field_name, $record, $keywords, $verbs, $highlight_keywords);
$condition = '('.$condition.' OR '.$primary_condition.')';
}
if ($condition) {
if ($join_clause) {
$join_clauses[] = $join_clause;
}
$relevance_parts[] = 'IF('.$condition.', '.$record['Priority'].', 0)';
if ($glues[$field] == 1) { // and
if ($condition_mode == 'WHERE') {
$and_conditions[] = $condition;
}
else {
$and_having_conditions[] = $condition;
}
}
else { // or
if ($condition_mode == 'WHERE') {
$or_conditions[] = $condition;
}
else {
$or_having_conditions[] = $condition;
}
}
// create search log record
$search_log_data = Array('search_config' => $record, 'verb' => getArrayValue($verbs, $field), 'value' => ($record['FieldType'] == 'range') ? $search_keywords[$field.'_from'].'|'.$search_keywords[$field.'_to'] : $search_keywords[$field]);
$search_log[] = $this->Application->Phrase('la_Field').' "'.$this->getHuman('Field', $search_log_data).'" '.$this->getHuman('Verb', $search_log_data).' '.$this->Application->Phrase('la_Value').' '.$this->getHuman('Value', $search_log_data).' '.$this->Application->Phrase($glues[$field] == 1 ? 'lu_And' : 'lu_Or');
}
}
if ($search_log) {
$search_log = implode('
', $search_log);
$search_log = preg_replace('/(.*) '.preg_quote($this->Application->Phrase('lu_and'), '/').'|'.preg_quote($this->Application->Phrase('lu_or'), '/').'$/is', '\\1', $search_log);
$this->saveToSearchLog($search_log, 1); // advanced search
}
$this->Application->StoreVar('highlight_keywords', serialize($highlight_keywords));
// making relevance clause
if($relevance_parts)
{
$conf_postfix = $this->Application->getUnitOption($event->Prefix, 'SearchConfigPostfix');
$rel_keywords = $this->Application->ConfigValue('SearchRel_Keyword_'.$conf_postfix) / 100;
$rel_pop = $this->Application->ConfigValue('SearchRel_Pop_'.$conf_postfix) / 100;
$rel_rating = $this->Application->ConfigValue('SearchRel_Rating_'.$conf_postfix) / 100;
$relevance_clause = '('.implode(' + ', $relevance_parts).') / '.$weight_sum.' * '.$rel_keywords;
$relevance_clause .= ' + (Hits + 1) / (MAX(Hits) + 1) * '.$rel_pop;
$relevance_clause .= ' + (CachedRating + 1) / (MAX(CachedRating) + 1) * '.$rel_rating;
}
else
{
$relevance_clause = '0';
}
// building having clause
if($or_having_conditions)
{
$and_having_conditions[] = '('.implode(' OR ', $or_having_conditions).')';
}
$having_clause = implode(' AND ', $and_having_conditions);
$having_clause = $having_clause ? ' HAVING '.$having_clause : '';
// building where clause
if($or_conditions)
{
$and_conditions[] = '('.implode(' OR ', $or_conditions).')';
}
// $and_conditions[] = $items_table.'.Status = 1';
$where_clause = implode(' AND ', $and_conditions);
if(!$where_clause)
{
if($having_clause)
{
$where_clause = '1';
}
else
{
$where_clause = '0';
$this->Application->SetVar('adv_search_error', 1);
}
}
$where_clause .= ' AND '.$items_table.'.Status = 1';
/** @var kSearchHelper $search_helper */
$search_helper = $this->Application->recallObject('SearchHelper');
// Building final search query.
$search_table = $search_helper->getSearchTable();
$search_table_exists = $this->Conn->Query('SHOW TABLES LIKE "'.$search_table.'"');
if ($search_table_exists) {
$this->Conn->Query('TRUNCATE TABLE '.$search_table);
$select_intro = 'INSERT INTO '.$search_table.' (Relevance, ItemId, ResourceId, ItemType, EdPick) ';
}
else {
$select_intro = 'CREATE TABLE '.$search_table.' ENGINE = MEMORY AS ';
}
$id_field = $this->Application->getUnitOption($event->Prefix, 'IDField');
$fields = $this->Application->getUnitOption($event->Prefix, 'Fields');
$pick_field = isset($fields['EditorsPick']) ? $items_table.'.EditorsPick' : '0';
$sql = $select_intro.'SELECT '.$relevance_clause.' AS Relevance,
'.$items_table.'.'.$id_field.' AS ItemId,
'.$items_table.'.ResourceId AS ResourceId,
11 AS ItemType,
'.$pick_field.' AS EdPick
FROM '.$items_table.'
'.implode(' ', $join_clauses).'
WHERE '.$where_clause.'
GROUP BY '.$items_table.'.'.$id_field.
$having_clause;
$this->Conn->Query($sql);
if ( !$search_table_exists ) {
$sql = 'ALTER TABLE ' . $search_table . '
ADD INDEX (ResourceId),
ADD INDEX (Relevance)';
$this->Conn->Query($sql);
}
}
function getAdvancedSearchCondition($field_name, $record, $keywords, $verbs, &$highlight_keywords)
{
$field = $record['FieldName'];
$condition_patterns = Array (
'any' => '%s LIKE %s',
'contains' => '%s LIKE %s',
'notcontains' => '(NOT (%1$s LIKE %2$s) OR %1$s IS NULL)',
'is' => '%s = %s',
'isnot' => '(%1$s != %2$s OR %1$s IS NULL)'
);
$condition = '';
switch ($record['FieldType']) {
case 'select':
$keywords[$field] = $this->Application->unescapeRequestVariable($keywords[$field]);
if ($keywords[$field]) {
$condition = sprintf($condition_patterns['is'], $field_name, $this->Conn->qstr( $keywords[$field] ));
}
break;
case 'multiselect':
$keywords[$field] = $this->Application->unescapeRequestVariable($keywords[$field]);
if ($keywords[$field]) {
$condition = Array ();
$values = explode('|', substr($keywords[$field], 1, -1));
foreach ($values as $selected_value) {
$condition[] = sprintf($condition_patterns['contains'], $field_name, $this->Conn->qstr('%|'.$selected_value.'|%'));
}
$condition = '('.implode(' OR ', $condition).')';
}
break;
case 'text':
$keywords[$field] = $this->Application->unescapeRequestVariable($keywords[$field]);
if (mb_strlen($keywords[$field]) >= $this->Application->ConfigValue('Search_MinKeyword_Length')) {
$highlight_keywords[] = $keywords[$field];
if (in_array($verbs[$field], Array('any', 'contains', 'notcontains'))) {
$keywords[$field] = '%'.strtr($keywords[$field], Array('%' => '\\%', '_' => '\\_')).'%';
}
$condition = sprintf($condition_patterns[$verbs[$field]], $field_name, $this->Conn->qstr( $keywords[$field] ));
}
break;
case 'boolean':
if ($keywords[$field] != -1) {
$property_mappings = $this->Application->getUnitOption($this->Prefix, 'ItemPropertyMappings');
$items_table = $this->Application->getUnitOption($this->Prefix, 'TableName');
switch ($field) {
case 'HotItem':
$hot_limit_var = getArrayValue($property_mappings, 'HotLimit');
if ($hot_limit_var) {
$hot_limit = (int)$this->Application->getDBCache($hot_limit_var);
$condition = 'IF('.$items_table.'.HotItem = 2,
IF('.$items_table.'.Hits >= '.
$hot_limit.
', 1, 0), '.$items_table.'.HotItem) = '.$keywords[$field];
}
break;
case 'PopItem':
$votes2pop_var = getArrayValue($property_mappings, 'VotesToPop');
$rating2pop_var = getArrayValue($property_mappings, 'RatingToPop');
if ($votes2pop_var && $rating2pop_var) {
$condition = 'IF('.$items_table.'.PopItem = 2, IF('.$items_table.'.CachedVotesQty >= '.
$this->Application->ConfigValue($votes2pop_var).
' AND '.$items_table.'.CachedRating >= '.
$this->Application->ConfigValue($rating2pop_var).
', 1, 0), '.$items_table.'.PopItem) = '.$keywords[$field];
}
break;
case 'NewItem':
$new_days_var = getArrayValue($property_mappings, 'NewDays');
if ($new_days_var) {
$condition = 'IF('.$items_table.'.NewItem = 2,
IF('.$items_table.'.CreatedOn >= (UNIX_TIMESTAMP() - '.
$this->Application->ConfigValue($new_days_var).
'*3600*24), 1, 0), '.$items_table.'.NewItem) = '.$keywords[$field];
}
break;
case 'EditorsPick':
$condition = $items_table.'.EditorsPick = '.$keywords[$field];
break;
}
}
break;
case 'range':
$range_conditions = Array();
if ($keywords[$field.'_from'] && !preg_match("/[^0-9]/i", $keywords[$field.'_from'])) {
$range_conditions[] = $field_name.' >= '.$keywords[$field.'_from'];
}
if ($keywords[$field.'_to'] && !preg_match("/[^0-9]/i", $keywords[$field.'_to'])) {
$range_conditions[] = $field_name.' <= '.$keywords[$field.'_to'];
}
if ($range_conditions) {
$condition = implode(' AND ', $range_conditions);
}
break;
case 'date':
if ($keywords[$field]) {
if (in_array($keywords[$field], Array('today', 'yesterday'))) {
$current_time = getdate();
$day_begin = adodb_mktime(0, 0, 0, $current_time['mon'], $current_time['mday'], $current_time['year']);
$time_mapping = Array('today' => $day_begin, 'yesterday' => ($day_begin - 86400));
$min_time = $time_mapping[$keywords[$field]];
}
else {
$time_mapping = Array (
'last_week' => 604800, 'last_month' => 2628000, 'last_3_months' => 7884000,
'last_6_months' => 15768000, 'last_year' => 31536000,
);
$min_time = adodb_mktime() - $time_mapping[$keywords[$field]];
}
$condition = $field_name.' > '.$min_time;
}
break;
}
return $condition;
}
/**
* Returns human readable representation of searched data to be placed in search log
* @param string $type
* @param Array $search_data
* @return string
* @access protected
*/
protected function getHuman($type, $search_data)
{
// all 3 variables are retrieved from $search_data array
/** @var Array $search_config */
/** @var string $verb */
/** @var string $value */
$type = ucfirst(strtolower($type));
extract($search_data, EXTR_SKIP);
switch ($type) {
case 'Field':
return $this->Application->Phrase($search_config['DisplayName']);
break;
case 'Verb':
return $verb ? $this->Application->Phrase('lu_advsearch_'.$verb) : '';
break;
case 'Value':
switch ($search_config['FieldType']) {
case 'date':
$values = Array(0 => 'lu_comm_Any', 'today' => 'lu_comm_Today',
'yesterday' => 'lu_comm_Yesterday', 'last_week' => 'lu_comm_LastWeek',
'last_month' => 'lu_comm_LastMonth', 'last_3_months' => 'lu_comm_Last3Months',
'last_6_months' => 'lu_comm_Last6Months', 'last_year' => 'lu_comm_LastYear');
$ret = $this->Application->Phrase($values[$value]);
break;
case 'range':
$value = explode('|', $value);
return $this->Application->Phrase('lu_comm_From').' "'.$value[0].'" '.$this->Application->Phrase('lu_comm_To').' "'.$value[1].'"';
break;
case 'boolean':
$values = Array(1 => 'lu_comm_Yes', 0 => 'lu_comm_No', -1 => 'lu_comm_Both');
$ret = $this->Application->Phrase($values[$value]);
break;
default:
$ret = $value;
break;
}
return '"'.$ret.'"';
break;
}
return '';
}
/**
* Set's correct page for list based on data provided with event
*
* @param kEvent $event
* @return void
* @access protected
* @see kDBEventHandler::OnListBuild()
*/
protected function SetPagination(kEvent $event)
{
/** @var kDBList $object */
$object = $event->getObject();
// get PerPage (forced -> session -> config -> 10)
$object->SetPerPage($this->getPerPage($event));
// main lists on Front-End have special get parameter for page
$page = $object->isMainList() ? $this->Application->GetVar('page') : false;
if ( !$page ) {
// page is given in "env" variable for given prefix
$page = $this->Application->GetVar($event->getPrefixSpecial() . '_Page');
}
if ( !$page && $event->Special ) {
// when not part of env, then variables like "prefix.special_Page" are
// replaced (by PHP) with "prefix_special_Page", so check for that too
$page = $this->Application->GetVar($event->getPrefixSpecial(true) . '_Page');
}
if ( !$object->isMainList() ) {
// main lists doesn't use session for page storing
$this->Application->StoreVarDefault($event->getPrefixSpecial() . '_Page', 1, true); // true for optional
if ( !$page ) {
if ( $this->Application->RewriteURLs() ) {
// when page not found by prefix+special, then try to search it without special at all
$page = $this->Application->GetVar($event->Prefix . '_Page');
if ( !$page ) {
// page not found in request -> get from session
$page = $this->Application->RecallVar($event->Prefix . '_Page');
}
if ( $page ) {
// page found in request -> store in session
$this->Application->StoreVar($event->getPrefixSpecial() . '_Page', $page, true); //true for optional
}
}
else {
// page not found in request -> get from session
$page = $this->Application->RecallVar($event->getPrefixSpecial() . '_Page');
}
}
else {
// page found in request -> store in session
$this->Application->StoreVar($event->getPrefixSpecial() . '_Page', $page, true); //true for optional
}
if ( !$event->getEventParam('skip_counting') ) {
// when stored page is larger, then maximal list page number
// (such case is also processed in kDBList::Query method)
$pages = $object->GetTotalPages();
if ( $page > $pages ) {
$page = 1;
$this->Application->StoreVar($event->getPrefixSpecial() . '_Page', 1, true);
}
}
}
$object->SetPage($page);
}
/* === RELATED TO IMPORT/EXPORT: BEGIN === */
/**
* Shows export dialog
*
* @param kEvent $event
* @return void
* @access protected
*/
protected function OnExport(kEvent $event)
{
$selected_ids = $this->StoreSelectedIDs($event);
if ( implode(',', $selected_ids) == '' ) {
// K4 fix when no ids found bad selected ids array is formed
$selected_ids = false;
}
$selected_cats_ids = $this->Application->GetVar('export_categories');
$this->Application->StoreVar($event->Prefix . '_export_ids', $selected_ids ? implode(',', $selected_ids) : '');
$this->Application->StoreVar($event->Prefix . '_export_cats_ids', $selected_cats_ids);
/** @var kCatDBItemExportHelper $export_helper */
$export_helper = $this->Application->recallObject('CatItemExportHelper');
$redirect_params = Array (
$this->Prefix . '.export_event' => 'OnNew',
'pass' => 'all,' . $this->Prefix . '.export'
);
$event->setRedirectParams($redirect_params);
}
/**
* Performs each export step & displays progress percent
*
* @param kEvent $event
*/
function OnExportProgress($event)
{
/** @var kCatDBItemExportHelper $export_object */
$export_object = $this->Application->recallObject('CatItemExportHelper');
$action_method = 'perform'.ucfirst($event->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 ($event->Special == 'import') {
$this->Application->StoreVar('PermCache_UpdateRequired', 1);
$event->SetRedirectParam('m_cat_id', $this->Application->RecallVar('ImportCategory'));
$event->SetRedirectParam('anchor', 'tab-' . $event->Prefix);
$event->redirect = 'catalog/catalog';
}
elseif ($event->Special == 'export') {
$event->redirect = $export_object->getModuleName($event) . '/' . $event->Special . '_finish';
$event->SetRedirectParam('pass', 'all');
}
return ;
}
$export_options = $export_object->loadOptions($event);
echo $export_options['start_from'] * 100 / $export_options['total_records'];
$event->status = kEvent::erSTOP;
}
/**
* Returns specific to each item type columns only
*
* @param kEvent $event
* @return Array
* @access protected
*/
public function getCustomExportColumns(kEvent $event)
{
return Array (
'__VIRTUAL__ThumbnailImage' => 'ThumbnailImage',
'__VIRTUAL__FullImage' => 'FullImage',
'__VIRTUAL__ImageAlt' => 'ImageAlt'
);
}
/**
* Sets non standart virtual fields (e.g. to other tables)
*
* @param kEvent $event
*/
function setCustomExportColumns($event)
{
$this->restorePrimaryImage($event);
}
/**
* Create/Update primary image record in info found in imported data
*
* @param kEvent $event
* @return void
* @access protected
*/
protected function restorePrimaryImage($event)
{
/** @var kCatDBItem $object */
$object = $event->getObject();
if ( !$object->GetDBField('ThumbnailImage') && !$object->GetDBField('FullImage') ) {
return ;
}
$image_data = $object->getPrimaryImageData();
/** @var kDBItem $image */
$image = $this->Application->recallObject('img', NULL, Array ('skip_autoload' => true));
if ( $image_data ) {
$image->Load($image_data['ImageId']);
}
else {
$image->Clear();
$image->SetDBField('Name', 'main');
$image->SetDBField('DefaultImg', 1);
$image->SetDBField('ResourceId', $object->GetDBField('ResourceId'));
}
if ( $object->GetDBField('ImageAlt') ) {
$image->SetDBField('AltName', $object->GetDBField('ImageAlt'));
}
if ( $object->GetDBField('ThumbnailImage') ) {
$thumbnail_field = $this->isURL($object->GetDBField('ThumbnailImage')) ? 'ThumbUrl' : 'ThumbPath';
$image->SetDBField($thumbnail_field, $object->GetDBField('ThumbnailImage'));
$image->SetDBField('LocalThumb', $thumbnail_field == 'ThumbPath' ? 1 : 0);
}
if ( !$object->GetDBField('FullImage') ) {
$image->SetDBField('SameImages', 1);
}
else {
$image->SetDBField('SameImages', 0);
$full_field = $this->isURL($object->GetDBField('FullImage')) ? 'Url' : 'LocalPath';
$image->SetDBField($full_field, $object->GetDBField('FullImage'));
$image->SetDBField('LocalImage', $full_field == 'LocalPath' ? 1 : 0);
}
if ( $image->isLoaded() ) {
$image->Update();
}
else {
$image->Create();
}
}
/**
* Detects if image url is specified in a given path (instead of path on disk)
*
* @param string $path
* @return bool
* @access protected
*/
protected function isURL($path)
{
return preg_match('#(http|https)://(.*)#', $path);
}
/**
* Prepares item for import/export operations
*
* @param kEvent $event
* @return void
* @access protected
*/
protected function OnNew(kEvent $event)
{
parent::OnNew($event);
if ( $event->Special == 'import' || $event->Special == 'export' ) {
/** @var kCatDBItemExportHelper $export_helper */
$export_helper = $this->Application->recallObject('CatItemExportHelper');
$export_helper->setRequiredFields($event);
}
}
/**
* Process items selected in item_selector
*
* @param kEvent $event
*/
function OnProcessSelected($event)
{
$dst_field = $this->Application->RecallVar('dst_field');
$selected_ids = $this->Application->GetVar('selected_ids');
if ( $dst_field == 'ItemCategory' ) {
// Item Edit -> Categories Tab -> New Categories
/** @var kCatDBItem $object */
$object = $event->getObject();
$category_ids = explode(',', $selected_ids['c']);
foreach ($category_ids as $category_id) {
$object->assignToCategory($category_id);
}
}
if ($dst_field == 'ImportCategory') {
// Tools -> Import -> Item Import -> Select Import Category
$this->Application->StoreVar('ImportCategory', $selected_ids['c']);
$event->SetRedirectParam($event->getPrefixSpecial() . '_id', 0);
$event->SetRedirectParam($event->getPrefixSpecial() . '_event', 'OnExportBegin');
}
$event->SetRedirectParam('opener', 'u');
}
/**
* Saves Import/Export settings to session
*
* @param kEvent $event
*/
function OnSaveSettings($event)
{
$event->redirect = false;
$items_info = $this->Application->GetVar($event->getPrefixSpecial(true));
if ( $items_info ) {
list($id, $field_values) = each($items_info);
/** @var kDBItem $object */
$object = $event->getObject(Array ('skip_autoload' => true));
$object->setID($id);
$object->SetFieldsFromHash($field_values);
$event->setEventParam('form_data', $field_values);
$field_values['ImportFilename'] = $object->GetDBField('ImportFilename'); //if upload formatter has renamed the file during moving !!!
$field_values['ImportSource'] = 2;
$field_values['ImportLocalFilename'] = $object->GetDBField('ImportFilename');
$items_info[$id] = $field_values;
$this->Application->StoreVar($event->getPrefixSpecial() . '_ItemsInfo', serialize($items_info));
}
}
/**
* Saves Import/Export settings to session
*
* @param kEvent $event
*/
function OnResetSettings($event)
{
$this->Application->StoreVar('ImportCategory', $this->Application->getBaseCategory());
}
/**
* Cancels item editing
* @param kEvent $event
* @return void
* @todo Used?
*/
function OnCancelAction($event)
{
$event->redirect = $this->Application->GetVar('cancel_template');
$event->SetRedirectParam('pass', 'all,' . $event->getPrefixSpecial());
}
/* === RELATED TO IMPORT/EXPORT: END === */
/**
* Stores item's owner login into separate field together with id
*
* @param kEvent $event
* @param string $id_field
* @param string $cached_field
*/
function cacheItemOwner($event, $id_field, $cached_field)
{
/** @var kDBItem $object */
$object = $event->getObject();
$object->SetDBField($cached_field, $object->GetField($id_field));
}
/**
* Saves edited item into temp table
* If there is no id, new item is created in temp table
*
* @param kEvent $event
* @return void
* @access protected
*/
protected function OnPreSave(kEvent $event)
{
parent::OnPreSave($event);
$use_pending_editing = $this->Application->getUnitOption($event->Prefix, 'UsePendingEditing');
if ( $event->status == kEvent::erSUCCESS && $use_pending_editing ) {
// decision: clone or not clone
/** @var kCatDBItem $object */
$object = $event->getObject();
if ( $object->GetID() == 0 || $object->GetDBField('OrgId') > 0 ) {
// new items or cloned items shouldn't be cloned again
return ;
}
/** @var kPermissionsHelper $perm_helper */
$perm_helper = $this->Application->recallObject('PermissionsHelper');
$owner_field = $this->getOwnerField($event->Prefix);
if ( $perm_helper->ModifyCheckPermission($object->GetDBField($owner_field), $object->GetDBField('CategoryId'), $event->Prefix) == 2 ) {
// 1. clone original item
/** @var kTempTablesHandler $temp_handler */
$temp_handler = $this->Application->recallObject($event->getPrefixSpecial() . '_TempHandler', 'kTempTablesHandler');
$cloned_ids = $temp_handler->CloneItems($event->Prefix, $event->Special, Array ($object->GetID()), NULL, NULL, NULL, true);
$ci_table = $this->Application->GetTempName(TABLE_PREFIX . 'CategoryItems');
// 2. delete record from CategoryItems (about cloned item) that was automatically created during call of Create method of kCatDBItem
$sql = 'SELECT ResourceId
FROM ' . $object->TableName . '
WHERE ' . $object->IDField . ' = ' . $cloned_ids[0];
$clone_resource_id = $this->Conn->GetOne($sql);
$sql = 'DELETE FROM ' . $ci_table . '
WHERE ItemResourceId = ' . $clone_resource_id . ' AND PrimaryCat = 1';
$this->Conn->Query($sql);
// 3. copy main item categoryitems to cloned item
$sql = ' INSERT INTO ' . $ci_table . ' (CategoryId, ItemResourceId, PrimaryCat, ItemPrefix, Filename)
SELECT CategoryId, ' . $clone_resource_id . ' AS ItemResourceId, PrimaryCat, ItemPrefix, Filename
FROM ' . $ci_table . '
WHERE ItemResourceId = ' . $object->GetDBField('ResourceId');
$this->Conn->Query($sql);
// 4. put cloned id to OrgId field of item being cloned
$sql = 'UPDATE ' . $object->TableName . '
SET OrgId = ' . $object->GetID() . '
WHERE ' . $object->IDField . ' = ' . $cloned_ids[0];
$this->Conn->Query($sql);
// 5. substitute id of item being cloned with clone id
$this->Application->SetVar($event->getPrefixSpecial() . '_id', $cloned_ids[0]);
$selected_ids = $this->getSelectedIDs($event, true);
$selected_ids[ array_search($object->GetID(), $selected_ids) ] = $cloned_ids[0];
$this->StoreSelectedIDs($event, $selected_ids);
// 6. delete original item from temp table
$temp_handler->DeleteItems($event->Prefix, $event->Special, Array ($object->GetID()));
}
}
}
/**
* Sets item's owner field
*
* @param kEvent $event
* @return void
* @access protected
*/
protected function OnPreCreate(kEvent $event)
{
parent::OnPreCreate($event);
if ( $event->status != kEvent::erSUCCESS ) {
return ;
}
/** @var kDBItem $object */
$object = $event->getObject();
$owner_field = $this->getOwnerField($event->Prefix);
$object->SetDBField($owner_field, $this->Application->RecallVar('user_id'));
}
/**
* Occurs before original item of item in pending editing got deleted (for hooking only)
*
* @param kEvent $event
* @return void
* @access protected
*/
protected function OnBeforeDeleteOriginal(kEvent $event)
{
}
/**
* Occurs after original item of item in pending editing got deleted (for hooking only)
*
* @param kEvent $event
* @return void
* @access protected
*/
protected function OnAfterDeleteOriginal(kEvent $event)
{
}
/**
* Occurs before an item has been cloned
* Id of newly created item is passed as event' 'id' param
*
* @param kEvent $event
* @return void
* @access protected
*/
protected function OnBeforeClone(kEvent $event)
{
parent::OnBeforeClone($event);
/** @var kDBItem $object */
$object = $event->getObject();
$object->SetDBField('ResourceId', 0); // this will reset it
if ( $this->Application->GetVar('ResetCatBeforeClone') ) {
$object->SetDBField('CategoryId', NULL);
}
}
/**
* Set status for new category item based on user permission in category
*
* @param kEvent $event
* @return void
* @access protected
*/
protected function OnBeforeItemCreate(kEvent $event)
{
parent::OnBeforeItemCreate($event);
/** @var kCatDBItem $object */
$object = $event->getObject();
$owner_field = $this->getOwnerField($event->Prefix);
// Don't allow creating records on behalf of another user.
if ( !$this->Application->isAdminUser && !defined('CRON') ) {
$object->SetDBField($owner_field, $object->GetOriginalField($owner_field));
}
// Auto-assign records to currently logged-in user.
if ( !$object->GetDBField($owner_field) ) {
$object->SetDBField($owner_field, $this->Application->RecallVar('user_id'));
}
if ( !$this->Application->isAdmin ) {
$this->setItemStatusByPermission($event);
}
}
/**
* Sets category item status based on user permissions (only on Front-end)
*
* @param kEvent $event
*/
function setItemStatusByPermission($event)
{
$use_pending_editing = $this->Application->getUnitOption($event->Prefix, 'UsePendingEditing');
if (!$use_pending_editing) {
return ;
}
/** @var kCatDBItem $object */
$object = $event->getObject();
/** @var kPermissionsHelper $perm_helper */
$perm_helper = $this->Application->recallObject('PermissionsHelper');
$primary_category = $object->GetDBField('CategoryId') > 0 ? $object->GetDBField('CategoryId') : $this->Application->GetVar('m_cat_id');
$item_status = $perm_helper->AddCheckPermission($primary_category, $event->Prefix);
if ($item_status == STATUS_DISABLED) {
$event->status = kEvent::erFAIL;
}
else {
$object->SetDBField('Status', $item_status);
}
}
/**
* Creates category item & redirects to confirmation template (front-end only)
*
* @param kEvent $event
* @return void
* @access protected
*/
protected function OnCreate(kEvent $event)
{
parent::OnCreate($event);
$this->SetFrontRedirectTemplate($event, 'suggest');
}
/**
* Returns item's categories (allows to exclude primary category)
*
* @param int $resource_id
* @param bool $with_primary
* @return Array
*/
function getItemCategories($resource_id, $with_primary = false)
{
$sql = 'SELECT CategoryId
FROM '.TABLE_PREFIX.'CategoryItems
WHERE (ItemResourceId = '.$resource_id.')';
if (!$with_primary) {
$sql .= ' AND (PrimaryCat = 0)';
}
return $this->Conn->GetCol($sql);
}
/**
* Adds new and removes old additional categories from category item
*
* @param kCatDBItem $object
* @param int $mode
*/
function processAdditionalCategories(&$object, $mode)
{
if ( !$object->isVirtualField('MoreCategories') ) {
// given category item doesn't require such type of processing
return ;
}
$process_categories = $object->GetDBField('MoreCategories');
if ($process_categories === '') {
// field was not in submit & have default value (when no categories submitted, then value is null)
return ;
}
if ($mode == 'create') {
// prevents first additional category to become primary
$object->assignPrimaryCategory();
}
$process_categories = $process_categories ? explode('|', substr($process_categories, 1, -1)) : Array ();
$existing_categories = $this->getItemCategories($object->GetDBField('ResourceId'));
$add_categories = array_diff($process_categories, $existing_categories);
foreach ($add_categories as $category_id) {
$object->assignToCategory($category_id);
}
$remove_categories = array_diff($existing_categories, $process_categories);
foreach ($remove_categories as $category_id) {
$object->removeFromCategory($category_id);
}
}
/**
* Creates category item & redirects to confirmation template (front-end only)
*
* @param kEvent $event
* @return void
* @access protected
*/
protected function OnUpdate(kEvent $event)
{
$use_pending = $this->Application->getUnitOption($event->Prefix, 'UsePendingEditing');
if ($this->Application->isAdminUser || !$use_pending) {
parent::OnUpdate($event);
$this->SetFrontRedirectTemplate($event, 'modify');
return ;
}
/** @var kCatDBItem $object */
$object = $event->getObject(Array('skip_autoload' => true));
$items_info = $this->Application->GetVar($event->getPrefixSpecial(true));
if ($items_info) {
/** @var kPermissionsHelper $perm_helper */
$perm_helper = $this->Application->recallObject('PermissionsHelper');
/** @var kTempTablesHandler $temp_handler */
$temp_handler = $this->Application->recallObject($event->getPrefixSpecial().'_TempHandler', 'kTempTablesHandler');
$owner_field = $this->getOwnerField($event->Prefix);
/** @var FileHelper $file_helper */
$file_helper = $this->Application->recallObject('FileHelper');
foreach ($items_info as $id => $field_values) {
$object->Load($id);
$edit_perm = $perm_helper->ModifyCheckPermission($object->GetDBField($owner_field), $object->GetDBField('CategoryId'), $event->Prefix);
if ($use_pending && !$object->GetDBField('OrgId') && ($edit_perm == STATUS_PENDING)) {
// pending editing enabled + not pending copy -> get/create pending copy & save changes to it
$original_id = $object->GetID();
$original_resource_id = $object->GetDBField('ResourceId');
$file_helper->PreserveItemFiles($field_values);
$object->Load($original_id, 'OrgId');
if (!$object->isLoaded()) {
// 1. user has no pending copy of live item -> clone live item
$cloned_ids = $temp_handler->CloneItems($event->Prefix, $event->Special, Array($original_id), NULL, NULL, NULL, true);
$object->Load($cloned_ids[0]);
$object->SetFieldsFromHash($field_values);
$event->setEventParam('form_data', $field_values);
// 1a. delete record from CategoryItems (about cloned item) that was automatically created during call of Create method of kCatDBItem
$ci_table = $this->Application->getUnitOption('ci', 'TableName');
$sql = 'DELETE FROM '.$ci_table.'
WHERE ItemResourceId = '.$object->GetDBField('ResourceId').' AND PrimaryCat = 1';
$this->Conn->Query($sql);
// 1b. copy main item categoryitems to cloned item
$sql = 'INSERT INTO '.$ci_table.' (CategoryId, ItemResourceId, PrimaryCat, ItemPrefix, Filename)
SELECT CategoryId, '.$object->GetDBField('ResourceId').' AS ItemResourceId, PrimaryCat, ItemPrefix, Filename
FROM '.$ci_table.'
WHERE ItemResourceId = '.$original_resource_id;
$this->Conn->Query($sql);
// 1c. put cloned id to OrgId field of item being cloned
$object->SetDBField('Status', STATUS_PENDING_EDITING);
$object->SetDBField('OrgId', $original_id);
}
else {
// 2. user has pending copy of live item -> just update field values
$object->SetFieldsFromHash($field_values);
$event->setEventParam('form_data', $field_values);
}
// update id in request (used for redirect in mod-rewrite mode)
$this->Application->SetVar($event->getPrefixSpecial().'_id', $object->GetID());
}
else {
// 3. already editing pending copy -> just update field values
$object->SetFieldsFromHash($field_values);
$event->setEventParam('form_data', $field_values);
}
if ($object->Update()) {
$event->status = kEvent::erSUCCESS;
}
else {
$event->status = kEvent::erFAIL;
$event->redirect = false;
break;
}
}
}
$this->SetFrontRedirectTemplate($event, 'modify');
}
/**
* Sets next template to one required for front-end after adding/modifying item
*
* @param kEvent $event
* @param string $template_key - {suggest,modify}
*/
function SetFrontRedirectTemplate($event, $template_key)
{
if ( $this->Application->isAdmin || $event->status != kEvent::erSUCCESS ) {
return;
}
// prepare redirect template
/** @var kDBItem $object */
$object = $event->getObject();
$is_active = ($object->GetDBField('Status') == STATUS_ACTIVE);
$next_template = $is_active ? 'confirm_template' : 'pending_confirm_template';
$event->redirect = $this->Application->GetVar($template_key . '_' . $next_template);
$event->SetRedirectParam('opener', 's');
// send email events
$perm_prefix = $this->Application->getUnitOption($event->Prefix, 'PermItemPrefix');
$owner_field = $this->getOwnerField($event->Prefix);
$owner_id = $object->GetDBField($owner_field);
switch ( $event->Name ) {
case 'OnCreate':
$event_suffix = $is_active ? 'ADD' : 'ADD.PENDING';
$this->Application->emailAdmin($perm_prefix . '.' . $event_suffix); // there are no ADD.PENDING event for admin :(
$this->Application->emailUser($perm_prefix . '.' . $event_suffix, $owner_id);
break;
case 'OnUpdate':
$event_suffix = $is_active ? 'MODIFY' : 'MODIFY.PENDING';
$user_id = is_numeric($object->GetDBField('ModifiedById')) ? $object->GetDBField('ModifiedById') : $owner_id;
$this->Application->emailAdmin($perm_prefix . '.' . $event_suffix); // there are no ADD.PENDING event for admin :(
$this->Application->emailUser($perm_prefix . '.' . $event_suffix, $user_id);
break;
}
}
/**
* Apply same processing to each item being selected in grid
*
* @param kEvent $event
* @return void
* @access protected
*/
protected function iterateItems(kEvent $event)
{
if ( $event->Name != 'OnMassApprove' && $event->Name != 'OnMassDecline' ) {
parent::iterateItems($event);
}
if ( $this->Application->CheckPermission('SYSTEM_ACCESS.READONLY', 1) ) {
$event->status = kEvent::erFAIL;
return ;
}
/** @var kCatDBItem $object */
$object = $event->getObject(Array ('skip_autoload' => true));
$ids = $this->StoreSelectedIDs($event);
if ( $ids ) {
foreach ($ids as $id) {
$object->Load($id);
switch ( $event->Name ) {
case 'OnMassApprove':
$object->ApproveChanges();
break;
case 'OnMassDecline':
$object->DeclineChanges();
break;
}
}
}
$this->clearSelectedIDs($event);
}
/**
* Deletes items & preserves clean env
*
* @param kEvent $event
* @return void
* @access protected
*/
protected function OnDelete(kEvent $event)
{
parent::OnDelete($event);
if ( $event->status == kEvent::erSUCCESS && !$this->Application->isAdmin ) {
$event->SetRedirectParam('pass', 'm');
$event->SetRedirectParam('m_cat_id', 0);
}
}
/**
* Checks, that currently loaded item is allowed for viewing (non permission-based)
*
* @param kEvent $event
* @return bool
* @access protected
*/
protected function checkItemStatus(kEvent $event)
{
/** @var kDBItem $object */
$object = $event->getObject();
if ( !$object->isLoaded() ) {
if ( $event->Special != 'previous' && $event->Special != 'next' ) {
$this->_errorNotFound($event);
}
return true;
}
$status = $object->GetDBField('Status');
$user_id = $this->Application->RecallVar('user_id');
$owner_field = $this->getOwnerField($event->Prefix);
if ( ($status == STATUS_PENDING_EDITING || $status == STATUS_PENDING) && ($object->GetDBField($owner_field) == $user_id) ) {
return true;
}
return $status == STATUS_ACTIVE;
}
/**
* Set's correct sorting for list based on data provided with event
*
* @param kEvent $event
* @return void
* @access protected
* @see kDBEventHandler::OnListBuild()
*/
protected function SetSorting(kEvent $event)
{
if ( !$this->Application->isAdmin ) {
$event->setEventParam('same_special', true);
}
$types = $event->getEventParam('types');
$types = $types ? explode(',', $types) : Array ();
if ( in_array('search', $types) ) {
$event->setPseudoClass('_List');
/** @var kDBList $object */
$object = $event->getObject();
// 1. no user sorting - sort by relevance
$default_sortings = parent::_getDefaultSorting($event);
$default_sorting = key($default_sortings['Sorting']) . ',' . current($default_sortings['Sorting']);
if ( $object->isMainList() ) {
$sort_by = $this->Application->GetVar('sort_by', '');
if ( !$sort_by ) {
$this->Application->SetVar('sort_by', 'Relevance,desc|' . $default_sorting);
}
}
else {
$sorting_settings = $this->getListSetting($event, 'Sortings');
$sort_by = trim(getArrayValue($sorting_settings, 'Sort1') . ',' . getArrayValue($sorting_settings, 'Sort1_Dir'), ',');
if ( !$sort_by ) {
$event->setEventParam('sort_by', 'Relevance,desc|' . $default_sorting);
}
}
$this->_removeForcedSortings($event);
}
parent::SetSorting($event);
}
/**
* Removes forced sortings
*
* @param kEvent $event
*/
protected function _removeForcedSortings(kEvent $event)
{
/** @var Array $list_sortings */
$list_sortings = $this->Application->getUnitOption($event->Prefix, 'ListSortings', Array ());
foreach ($list_sortings as $special => $sortings) {
unset($list_sortings[$special]['ForcedSorting']);
}
$this->Application->setUnitOption($event->Prefix, 'ListSortings', $list_sortings);
}
/**
* Default sorting in search results only comes from relevance field
*
* @param kEvent $event
* @return Array
* @access protected
*/
protected function _getDefaultSorting(kEvent $event)
{
$types = $event->getEventParam('types');
$types = $types ? explode(',', $types) : Array ();
return in_array('search', $types) ? Array () : parent::_getDefaultSorting($event);
}
/**
* Returns current per-page setting for list
*
* @param kEvent $event
* @return int
* @access protected
*/
protected function getPerPage(kEvent $event)
{
if ( !$this->Application->isAdmin ) {
$event->setEventParam('same_special', true);
}
return parent::getPerPage($event);
}
/**
* Returns owner field for given prefix
*
* @param $prefix
* @return string
* @access protected
*/
protected function getOwnerField($prefix)
{
return $this->Application->getUnitOption($prefix, 'OwnerField', 'CreatedById');
}
/**
* Creates virtual image fields for item
*
* @param kEvent $event
* @return void
* @access protected
*/
protected function OnAfterConfigRead(kEvent $event)
{
parent::OnAfterConfigRead($event);
if (defined('IS_INSTALL') && IS_INSTALL) {
$this->addViewPermissionJoin($event);
return ;
}
if ( !$this->Application->isAdmin ) {
/** @var FileHelper $file_helper */
$file_helper = $this->Application->recallObject('FileHelper');
$file_helper->createItemFiles($event->Prefix, true); // create image fields
$file_helper->createItemFiles($event->Prefix, false); // create file fields
}
$this->changeSortings($event)->addViewPermissionJoin($event);
// add grids for advanced view (with primary category column)
$grids = $this->Application->getUnitOption($this->Prefix, 'Grids');
$process_grids = Array ('Default', 'Radio');
foreach ($process_grids as $process_grid) {
$grid_data = $grids[$process_grid];
$grid_data['Fields']['CachedNavbar'] = Array ('title' => 'la_col_Path', 'data_block' => 'grid_primary_category_td', 'filter_block' => 'grid_like_filter');
$grids[$process_grid . 'ShowAll'] = $grid_data;
}
$this->Application->setUnitOption($this->Prefix, 'Grids', $grids);
// add options for CategoryId field (quick way to select item's primary category)
/** @var CategoryHelper $category_helper */
$category_helper = $this->Application->recallObject('CategoryHelper');
$virtual_fields = $this->Application->getUnitOption($event->Prefix, 'VirtualFields');
$virtual_fields['CategoryId']['default'] = (int)$this->Application->GetVar('m_cat_id');
$virtual_fields['CategoryId']['options'] = $category_helper->getStructureTreeAsOptions();
$this->Application->setUnitOption($event->Prefix, 'VirtualFields', $virtual_fields);
}
/**
* Changes default sorting according to system settings.
*
* @param kEvent $event Event.
*
* @return self
* @access protected
*/
protected function changeSortings(kEvent $event)
{
$remove_sortings = Array ();
if ( !$this->Application->isAdmin ) {
// remove Pick sorting on Front-end, when not required
$config_mapping = $this->Application->getUnitOption($event->Prefix, 'ConfigMapping', Array ());
if ( !isset($config_mapping['ForceEditorPick']) || !$this->Application->ConfigValue($config_mapping['ForceEditorPick']) ) {
$remove_sortings[] = 'EditorsPick';
}
}
else {
// remove all forced sortings in Admin Console
$remove_sortings = array_merge($remove_sortings, Array ('Priority', 'EditorsPick'));
}
if ( !$remove_sortings ) {
return $this;
}
/** @var Array $list_sortings */
$list_sortings = $this->Application->getUnitOption($event->Prefix, 'ListSortings', Array ());
foreach ($list_sortings as $special => $sorting_fields) {
foreach ($remove_sortings as $sorting_field) {
unset($list_sortings[$special]['ForcedSorting'][$sorting_field]);
}
}
$this->Application->setUnitOption($event->Prefix, 'ListSortings', $list_sortings);
return $this;
}
/**
* Adds permission table table JOIN clause only, when advanced catalog view permissions enabled.
*
* @param kEvent $event Event.
*
* @return self
* @access protected
*/
protected function addViewPermissionJoin(kEvent $event)
{
if ( $this->Application->ConfigValue('CheckViewPermissionsInCatalog') ) {
$join_clause = 'LEFT JOIN ' . TABLE_PREFIX . 'CategoryPermissionsCache perm ON perm.CategoryId = ' . TABLE_PREFIX . '%3$sCategoryItems.CategoryId';
}
else {
$join_clause = '';
}
/** @var array $list_sqls */
$list_sqls = $this->Application->getUnitOption($event->Prefix, 'ListSQLs');
foreach ($list_sqls as $special => $list_sql) {
$list_sqls[$special] = str_replace('{PERM_JOIN}', $join_clause, $list_sql);
}
$this->Application->setUnitOption($event->Prefix, 'ListSQLs', $list_sqls);
return $this;
}
/**
* Returns file contents associated with item
*
* @param kEvent $event
*/
function OnDownloadFile($event)
{
/** @var kCatDBItem $object */
$object = $event->getObject();
$event->status = kEvent::erSTOP;
$field = $this->Application->GetVar('field');
if (!preg_match('/^File([\d]+)/', $field)) {
return ;
}
/** @var FileHelper $file_helper */
$file_helper = $this->Application->recallObject('FileHelper');
$filename = $object->GetField($field, 'full_path');
$file_helper->DownloadFile($filename);
}
/**
* Saves user's vote
*
* @param kEvent $event
*/
function OnMakeVote($event)
{
$event->status = kEvent::erSTOP;
if ($this->Application->GetVar('ajax') != 'yes') {
// this is supposed to call from AJAX only
return ;
}
/** @var RatingHelper $rating_helper */
$rating_helper = $this->Application->recallObject('RatingHelper');
/** @var kCatDBItem $object */
$object = $event->getObject( Array ('skip_autoload' => true) );
$object->Load( $this->Application->GetVar('id') );
echo $rating_helper->makeVote($object);
}
/**
* Marks review as useful
*
* @param kEvent $event
* @return void
* @access protected
*/
protected function OnReviewHelpful($event)
{
if ( $this->Application->GetVar('ajax') == 'yes' ) {
$event->status = kEvent::erSTOP;
}
$review_id = (int)$this->Application->GetVar('review_id');
if ( !$review_id ) {
return;
}
/** @var SpamHelper $spam_helper */
$spam_helper = $this->Application->recallObject('SpamHelper');
$spam_helper->InitHelper($review_id, 'ReviewHelpful', strtotime('+1 month') - strtotime('now'));
$field = (int)$this->Application->GetVar('helpful') ? 'HelpfulCount' : 'NotHelpfulCount';
$sql = 'SELECT ' . $field . '
FROM ' . $this->Application->getUnitOption('rev', 'TableName') . '
WHERE ' . $this->Application->getUnitOption('rev', 'IDField') . ' = ' . $review_id;
$count = $this->Conn->GetOne($sql);
if ( $spam_helper->InSpamControl() ) {
if ( $this->Application->GetVar('ajax') == 'yes' ) {
echo $count;
}
return;
}
$sql = 'UPDATE ' . $this->Application->getUnitOption('rev', 'TableName') . '
SET ' . $field . ' = ' . $field . ' + 1
WHERE ' . $this->Application->getUnitOption('rev', 'IDField') . ' = ' . $review_id;
$this->Conn->Query($sql);
if ( $this->Conn->getAffectedRows() ) {
// db was changed -> review with such ID exists
$spam_helper->AddToSpamControl();
}
if ( $this->Application->GetVar('ajax') == 'yes' ) {
echo $count + 1;
}
}
/**
* [HOOK] Allows to add cloned subitem to given prefix
*
* @param kEvent $event
* @return void
* @access protected
*/
protected function OnCloneSubItem(kEvent $event)
{
parent::OnCloneSubItem($event);
if ( $event->MasterEvent->Prefix == 'fav' ) {
$clones = $this->Application->getUnitOption($event->MasterEvent->Prefix, 'Clones');
$subitem_prefix = $event->Prefix . '-' . $event->MasterEvent->Prefix;
$clones[$subitem_prefix]['ParentTableKey'] = 'ResourceId';
$clones[$subitem_prefix]['ForeignKey'] = 'ResourceId';
$this->Application->setUnitOption($event->MasterEvent->Prefix, 'Clones', $clones);
}
}
/**
* Set's new unique resource id to user
*
* @param kEvent $event
* @return void
* @access protected
*/
protected function OnAfterItemValidate(kEvent $event)
{
/** @var kDBItem $object */
$object = $event->getObject();
$resource_id = $object->GetDBField('ResourceId');
if ( !$resource_id ) {
$object->SetDBField('ResourceId', $this->Application->NextResourceId());
}
}
}
Index: branches/5.2.x/core/install/english.lang
===================================================================
--- branches/5.2.x/core/install/english.lang (revision 16673)
+++ branches/5.2.x/core/install/english.lang (revision 16674)
@@ -1,2228 +1,2229 @@
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=
U1NMIEZ1bGwgVVJMIGZvciBBZG1pbmlzdHJhdGl2ZSBDb25zb2xlIChodHRwczovL3d3dy5kb21haW4uY29tL3BhdGgpIA==
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=
QWx3YXlzIHVzZSBJbWFnZU1hZ2ljayB0byByZXNpemUgaW1hZ2Vz
Rm9yY2UgUmVkaXJlY3QgdG8gU2VsZWN0ZWQgVVJMIEVuZGluZw==
UmVkaXJlY3QgdG8gSFRUUCB3aGVuIFNTTCBpcyBub3QgcmVxdWlyZWQ=
RnVsbCBpbWFnZSBIZWlnaHQ=
RnVsbCBpbWFnZSBXaWR0aA==
VGVtcGxhdGUgZm9yIEhhcmQgTWFpbnRlbmFuY2U=
QnlwYXNzIEhUVFAgQXV0aGVudGljYXRpb24gZnJvbSBJUHMgKHNlcGFyYXRlZCBieSBzZW1pY29sb25zKQ==
UGFzc3dvcmQgZm9yIEhUVFAgQXV0aGVudGljYXRpb24=
VXNlcm5hbWUgZm9yIEhUVFAgQXV0aGVudGljYXRpb24=
S2VlcCBTZXNzaW9uIGFsaXZlIG9uIEJyb3dzZXIgY2xvc2U=
TWFpbCBGdW5jdGlvbiBIZWFkZXIgU2VwYXJhdG9y
TWFpbGluZyBMaXN0IFF1ZXVlIFBlciBTdGVw
TWFpbGluZyBMaXN0IFNlbmQgUGVyIFN0ZXA=
TWFpbnRlbmFuY2UgTWVzc2FnZSBmb3IgQWRtaW4=
TWFpbnRlbmFuY2UgTWVzc2FnZSBmb3IgRnJvbnQgRW5k
TWF4aW11bSBudW1iZXIgb2YgaW1hZ2Vz
RGVmYXVsdCBVUkwgRW5kaW5nIGluIFNFTy1mcmllbmRseSBtb2Rl
VGVtcGxhdGUgZm9yICJJbnN1ZmZpY2llbnQgUGVybWlzc2lvbnMiIEVycm9y
R1pJUCBjb21wcmVzc2lvbiBsZXZlbCAwLTk=
UGF0aCB0byBXZWJzaXRl
UGVyZm9ybSBFeGFjdCBTZWFyY2g=
Q29tbWVudHMgcGVyIHBhZ2U=
IlJlY3ljbGUgQmluIiBTZWN0aW9uSWQ=
VXNlcm5hbWUgUmVxdWlyZWQgRHVyaW5nIFJlZ2lzdHJhdGlvbg==
UmVzdG9yZSBsYXN0IHZpc2l0ZWQgQWRtaW4gU2VjdGlvbiBhZnRlciBMb2dpbg==
UmVxdWlyZSBTU0wgZm9yIEFkbWluaXN0cmF0aXZlIENvbnNvbGU=
UmVxdWlyZSBTU0wgZm9yIGxvZ2luICYgY2hlY2tvdXQ=
RnJhbWVzIGluIGFkbWluaXN0cmF0aXZlIGNvbnNvbGUgYXJlIHJlc2l6YWJsZQ==
TWluaW1hbCBTZWFyY2ggS2V5d29yZCBMZW5ndGg=
U2Vzc2lvbiBTZWN1cml0eSBDaGVjayBiYXNlZCBvbiBCcm93c2VyIFNpZ25hdHVyZQ==
U2Vzc2lvbiBDb29raWUgRG9tYWlucyAoc2luZ2xlIGRvbWFpbiBwZXIgbGluZSk=
U2Vzc2lvbiBTZWN1cml0eSBDaGVjayBiYXNlZCBvbiBJUA==
V2Vic2l0ZSBTdWJ0aXRsZQ==
VGltZSB6b25lIG9mIHRoZSBzaXRl
VGVtcGxhdGUgZm9yIFNvZnQgTWFpbnRlbmFuY2U=
U1NMIEZ1bGwgVVJMIChodHRwczovL3d3dy5kb21haW4uY29tL3BhdGgp
VXNlIFN0aWNreSBHcmlkIFNlbGVjdGlvbg==
U2VuZCBVc2VyLWRlZmluZWQgIlN5c3RlbSBMb2ciIG1lc3NhZ2VzIHRv
S2VlcCAiU3lzdGVtIExvZyIgZm9y
VGh1bWJuYWlsIEhlaWdodA==
VGh1bWJuYWlsIFdpZHRo
VHJpbSBSZXF1aXJlZCBGaWVsZHM=
VHlwZUtpdCBJRA==
VXBkYXRlIGNvdW50ZXJzIChpbiBvdGhlciBmaWx0ZXJzKSBvbiBmaWx0ZXIgY2hhbmdl
VHJhY2sgZGF0YWJhc2UgY2hhbmdlcyB0byBjaGFuZ2UgbG9n
VXNlIENvbHVtbiBGcmVlemVy
QXV0by1kZXRlY3QgVXNlcidzIGxhbmd1YWdlIGJhc2VkIG9uIGl0J3MgQnJvd3NlciBzZXR0aW5ncw==
VXNlIERvdWJsZSBTb3J0aW5n
RW5hYmxlIEhUVFAgQXV0aGVudGljYXRpb24=
RW5hYmxlIEhUTUwgR1pJUCBjb21wcmVzc2lvbg==
VXNlIFBhZ2VIaXQgY291bnRlcg==
RWRpdGluZyBXaW5kb3cgU3R5bGU=
RW1haWwgYWN0aXZhdGlvbiBleHBpcmF0aW9uIHRpbWVvdXQgKGluIG1pbnV0ZXMp
VXNlIFNtYWxsIFNlY3Rpb24gSGVhZGVycw==
Q29tcHJlc3MgQ29tcGlsZWQgUEhQIFRlbXBsYXRlcw==
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=
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==
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
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
TW9kaWZpZWQ=
+ TW9kaWZpZWQgQnk=
TW9kdWxl
TW9kdWxl
TXVsdGlsaW5ndWFs
TmFtZQ==
TmV3
TmV4dCBSdW4gT24=
Tm90ZXM=
UmV2aWV3IFdhc24ndCBIZWxwZnVs
TnVtYmVyIE9mIENsaWNrcw==
TnVtYmVyIE9mIFZpZXdz
T2NjdXJlZCBPbg==
T3BlbiBJbiBOZXcgV2luZG93
T3B0aW9ucw==
T3B0aW9uIFRpdGxl
T3JkZXI=
T3RoZXIgUmVjaXBpZW50cw==
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=
Rm9yY2UgUmVkaXJlY3QgKHdoZW4gdXNlcidzIElQIG1hdGNoZXMp
UmVmZXJyZXIgVVJM
S2V5d29yZA==
VHlwZQ==
UmVtb3RlIFVSTA==
UmVwbGFjZSBEdXBsaWNhdGVz
UmVwbGFjZW1lbnQ=
UmVwbGFjZW1lbnQgVGFncw==
UmVwbGllZCBPbg==
UmVwbHkgQmNj
UmVwbHkgQ2M=
UmVwbHkgRnJvbSBFLW1haWw=
UmVwbHkgRnJvbSBOYW1l
UmVwbHkgTWVzc2FnZSBTaWduYXR1cmU=
UmVwbGllZA==
UmVwb3J0ZWQgQnk=
UmVwb3J0ZWQgT24=
UmVxdWlyZWQ=
UmVxdWlyZSBMb2dpbg==
UmVxdWlyZSBTU0w=
Q29tbWVudA==
UHJvbW8gUm90YXRpb24gRGVsYXkgKHNlY29uZHMp
UnVsZSBUeXBl
UnVuIFNjaGVkdWxl
UnVuIFRpbWU=
U2FtZSBBcyBUaHVtYg==
U2NoZWR1bGUgRGF0ZQ==
U2VhcmNoIFRlcm0=
U2VuZGVy
U2VuZGVyJ3MgQWRkcmVzcw==
U2VuZGVyJ3MgTmFtZQ==
U2VudCBPbg==
U2VudA==
U2VydmVy
U2Vzc2lvbiBMb2cgSUQ=
U2hvcnQgRGF0ZSBGb3JtYXQ=
U2hvcnQgSVNPIENvZGU=
U2hvcnQgVGltZSBGb3JtYXQ=
U2ltcGxlIFNlYXJjaA==
U2l0ZSBEb21haW4gTGltaXRhdGlvbg==
TmFtZQ==
U2tpcCBGaXJzdCBSb3c=
U29ydCBWYWx1ZXM=
U1NMIEZ1bGwgVVJM
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=
UGhyYXNl
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==
RXZlcnlvbmU=
RXhhY3Q=
RXhwaXJlZA==
RXh0ZXJuYWw=
RXh0ZXJuYWwgVXJs
RmFpbGVk
RmVicnVhcnk=
Rmlyc3QgTmFtZQ==
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==
U2VwdGVtYmVy
U2lsZW50
U3BhY2U=
U3RhdGU=
U3ViLW1hdGNo
U3VjY2Vzcw==
U3VuZGF5
RnJvbSBvdGhlcnM=
VG8gb3RoZXJz
U3lzdGVt
Rm9yZXZlciAobmV2ZXIgZGVsZXRlZCBhdXRvbWF0aWNhbGx5KQ==
VGFi
VGVtcGxhdGU=
MyBtb250aHM=
VGh1cnNkYXk=
VGl0bGU=
VHVlc2RheQ==
MiB3ZWVrcw==
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
T3ZlcndyaXRlIEV4aXN0aW5nIFBocmFzZXM=
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==
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=
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=
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=
U2V0IFN0aWNreQ==
U2V0dGluZ3M=
U2hvdyBNZW51
U3luY2hyb25pemUgTGFuZ3VhZ2Vz
VG9vbHM=
VXAgYSBTZWN0aW9u
VmFsaWRhdGU=
Vmlldw==
VmlldyBEZXRhaWxz
Vmlldw==
VG8gRGF0ZQ==
VHJhbnNsYXRl
VHJhbnNsYXRlZA==
VHJlZQ==
Q2hlY2tib3hlcw==
RGF0ZQ==
RGF0ZSAmIFRpbWU=
TGFiZWw=
TXVsdGlwbGUgU2VsZWN0
UGFzc3dvcmQgZmllbGQ=
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==
UGFnZSBDb250ZW50
UGFyZW50IElE
UGFyZW50IFBhdGg=
SXRlbSBJcyBQb3B1bGFy
UHJpb3JpdHk=
UXR5IFNvbGQ=
UmVzb3VyY2UgSUQ=
U3RhdHVz
SXRlbSBJcyBhIFRvcCBTZWxsZXI=
VVJM
RW5hYmxpbmcgdGhpcyBvcHRpb24gd2lsbCB1bmRvIGFueSBjaGFuZ2VzIHlvdSBoYXZlIG1hZGUgdG8gZXhpc3RpbmcgcGhyYXNlcw==
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==
TWVtYmVyc2hpcCBFeHBpcmF0aW9uIE5vdGljZSBmb3IgIjxpbnAyOnVfVXNlclRpdGxlLz4iIFNlbnQ=
VXNlciA8aW5wMjp1X1VzZXJUaXRsZS8+IG1lbWJlcnNoaXAgd2lsbCBleHBpcmUgc29vbi4=
WW91ciBNZW1iZXJzaGlwIEV4cGlyZWQ=
WW91ciBtZW1iZXJzaGlwIG9uIDxpbnAyOm1fTGluayB0ZW1wbGF0ZT0iaW5kZXgiLz4gd2Vic2l0ZSBoYXMgZXhwaXJlZC4=
VXNlcidzIE1lbWJlcnNoaXAgRXhwaXJlZCAgKCA8aW5wMjp1X1VzZXJUaXRsZS8+KQ==
VXNlcidzICg8aW5wMjp1X1VzZXJUaXRsZS8+KSBtZW1iZXJzaGlwIG9uIDxpbnAyOm1fTGluayB0ZW1wbGF0ZT0iaW5kZXgiLz4gd2Vic2l0ZSBoYXMgZXhwaXJlZC4=
TmV3IHBhc3N3b3JkIGdlbmVyYXRlZA==
RGVhciA8aW5wMjp1X0ZpZWxkIG5hbWU9IkZpcnN0TmFtZSIvPiwNCg0KQSBuZXcgcGFzc3dvcmQgaGFzIGJlZW4gZ2VuZXJhdGVkIGZvciB5b3VyIHVzZXIuDQoNCk5vdyB5b3UgY2FuIGxvZ2luIHVzaW5nIHRoZSBmb2xsb3dpbmcgY3JlZGVudGlhbHM6DQoNCjxpbnAyOm1faWYgY2hlY2s9InVfRmllbGQiIG5hbWU9IlVzZXJuYW1lIj5Vc2VybmFtZTogPGlucDI6dV9GaWVsZCBuYW1lPSJVc2VybmFtZSIvPjxpbnAyOm1fZWxzZS8+RS1tYWlsOiA8aW5wMjp1X0ZpZWxkIG5hbWU9IkVtYWlsIi8+PC9pbnAyOm1faWY+IA0KUGFzc3dvcmQ6IDxpbnAyOnVfRmllbGQgbmFtZT0iUGFzc3dvcmRfcGxhaW4iLz4g
UmVzZXQgUGFzc3dvcmQgQ29uZmlybWF0aW9u
SGVsbG8sPGJyLz48YnIvPg0KDQpJdCBzZWVtcyB0aGF0IHlvdSBoYXZlIHJlcXVlc3RlZCBhIHBhc3N3b3JkIHJlc2V0IGZvciB5b3VyIEluLXBvcnRhbCBhY2NvdW50LiBJZiB5b3Ugd291bGQgbGlrZSB0byBwcm9jZWVkIGFuZCBjaGFuZ2UgdGhlIHBhc3N3b3JkLCBwbGVhc2UgY2xpY2sgb24gdGhlIGxpbmsgYmVsb3c6PGJyLz48YnIvPg0KDQo8YSBocmVmPSI8aW5wMjp1X0NvbmZpcm1QYXNzd29yZExpbmsgbm9fYW1wPSIxIi8+Ij48aW5wMjp1X0NvbmZpcm1QYXNzd29yZExpbmsgbm9fYW1wPSIxIi8+PC9hPjxici8+PGJyLz4NCg0KWW91IHdpbGwgcmVjZWl2ZSBhIHNlY29uZCBlbWFpbCB3aXRoIHlvdXIgbmV3IHBhc3N3b3JkIHNob3J0bHkuPGJyLz48YnIvPg0KDQpJZiB5b3UgYmVsaWV2ZSB5b3UgaGF2ZSByZWNlaXZlZCB0aGlzIGVtYWlsIGluIGVycm9yLCBwbGVhc2UgaWdub3JlIHRoaXMgZW1haWwuIFlvdXIgcGFzc3dvcmQgd2lsbCBub3QgYmUgY2hhbmdlZCB1bmxlc3MgeW91IGhhdmUgY2xpY2tlZCBvbiB0aGUgYWJvdmUgbGluay4NCg==
U3Vic2NyaWJlZCB0byBhIE1haWxpbmcgTGlzdCBvbiA8aW5wMjptX0xpbmsgdGVtcGxhdGU9ImluZGV4Ii8+
WW91IGhhdmUgc3Vic2NyaWJlZCB0byBhIG1haWxpbmcgbGlzdCBvbiA8aW5wMjptX0xpbmsgdGVtcGxhdGU9ImluZGV4Ii8+IHdlYnNpdGUu
TmV3IFVzZXIgaGFzIFN1YnNjcmliZWQgdG8gYSBNYWxsaW5nIExpc3Q=
TmV3IHVzZXIgPGlucDI6dV9GaWVsZCBuYW1lPSJFbWFpbCIvPiBoYXMgc3Vic2NyaWJlZCB0byBhIG1haWxpbmcgbGlzdCBvbiA8YSBocmVmPSI8aW5wMjptX0xpbmsgdGVtcGxhdGU9ImluZGV4Ii8+Ij48aW5wMjptX0xpbmsgdGVtcGxhdGU9ImluZGV4Ii8+PC9hPiB3ZWJzaXRlLg==
Q2hlY2sgb3V0IHRoaXMgV2Vic2l0ZQ==
SGVsbG8sPC9icj48L2JyPg0KDQpUaGlzIG1lc3NhZ2UgaGFzIGJlZW4gc2VudCB0byB5b3UgZnJvbSBvbmUgb2YgeW91ciBmcmllbmRzLjwvYnI+PC9icj4NCkNoZWNrIG91dCB0aGlzIHNpdGU6IDxhIGhyZWY9IjxpbnAyOm1fTGluayB0ZW1wbGF0ZT0iaW5kZXgiLz4iPjxpbnAyOm1fTGluayB0ZW1wbGF0ZT0iaW5kZXgiLz48L2E+IQ==
V2Vic2l0ZSBTdWdnZXN0ZWQgdG8gYSBGcmllbmQ=
QSB2aXNpdG9yIHN1Z2dlc3RlZCA8YSBocmVmPSI8aW5wMjptX0xpbmsgdGVtcGxhdGU9ImluZGV4Ii8+Ij48aW5wMjptX0xpbmsgdGVtcGxhdGU9ImluZGV4Ii8+PC9hPiB3ZWJzaXRlIHRvIGEgZnJpZW5kLg==
WW91IGhhdmUgYmVlbiB1bnN1YnNjcmliZWQ=
WW91IGhhdmUgc3VjY2Vzc2Z1bGx5IHVuc3Vic2NyaWJlZCBmcm9tIHRoZSBtYWlsaW5nIGxpc3Qgb24gPGEgaHJlZj0iPGlucDI6bV9CYXNlVXJsIC8+Ij48aW5wMjptX0Jhc2VVcmwgLz48L2E+IHdlYnNpdGUu
VXNlciBVbnN1YnNyaWJlZCBmcm9tIE1haWxpbmcgTGlzdA==
QSB1c2VyICI8aW5wMjp1X0ZpZWxkIG5hbWU9IkVtYWlsIi8+IiBoYXMgdW5zdWJzY3JpYmVkIGZyb20gdGhlIG1haWxpbmcgbGlzdCBvbiA8YSBocmVmPSI8aW5wMjptX0xpbmsgdGVtcGxhdGU9ImluZGV4Ii8+Ij48aW5wMjptX0xpbmsgdGVtcGxhdGU9ImluZGV4Ii8+PC9hPi4=
VXNlciBSZWdpc3RyYXRpb24gaXMgVmFsaWRhdGVk
V2VsY29tZSB0byBJbi1wb3J0YWwhPGJyLz48YnIvPg0KDQpZb3VyIHVzZXIgcmVnaXN0cmF0aW9uIGhhcyBiZWVuIGFwcHJvdmVkLiBZb3UgY2FuIGxvZ2luIG5vdyA8YSBocmVmPSI8aW5wMjptX0xpbmsgdGVtcGxhdGU9ImluZGV4Ii8+Ij48aW5wMjptX0xpbmsgdGVtcGxhdGU9ImluZGV4Ii8+PC9hPiB1c2luZyB0aGUgZm9sbG93aW5nIGluZm9ybWF0aW9uOjxici8+PGJyLz4NCg0KPT09PT09PT09PT09PT09PT09PGJyLz4NClVzZXJuYW1lOiAiPGlucDI6dV9Vc2VyVGl0bGUvPiI8YnIvPg0KUGFzc3dvcmQ6ICI8aW5wMjp1X0ZpZWxkIG5hbWU9IlBhc3N3b3JkX3BsYWluIi8+Ijxici8+DQo9PT09PT09PT09PT09PT09PT08YnIvPjxici8+DQo=
TmV3IFVzZXIgUmVnaXN0cmF0aW9uIGlzIFZhbGlkYXRlZA==
VXNlciAiPGlucDI6dV9Vc2VyVGl0bGUvPiIgaGFzIGJlZW4gdmFsaWRhdGVkLg==