further work... nothing reaaaally good yet, but getting there.

This commit is contained in:
brent s. 2016-04-07 16:33:35 -04:00
parent 241ab1689a
commit d53e6a320a
5 changed files with 1753 additions and 7 deletions

View File

@ -19,7 +19,7 @@ $plugin['flags'] = PLUGIN_LIFECYCLE_NOTIFY;
// @include_once('zem_tpl.php');

register_callback('bts_podcast_initdb','plugin_lifecycle.bts_podcast', 'enabled');
register_callback('bts_podcast_genguid','article_saved');
register_callback('bts_podcast_gen_metainfo','article_saved');

if (0) {
?>
@ -88,15 +88,21 @@ This plugin creates a *sha256* table in your Textpattern DB. There, it stores th

# --- BEGIN PLUGIN CODE ---

// Hooks
// Hooks/callbacks
function bts_podcast_initdb () {
safe_query("CREATE TABLE IF NOT EXISTS sha256 (id int(11) NOT NULL AUTO_INCREMENT,url_title varchar(64) NOT NULL,filename varchar(64) NOT NULL,type char(3) NOT NULL,checksum char(64) NOT NULL,created datetime NOT NULL DEFAULT CURRENT_TIMESTAMP,changed timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,PRIMARY KEY (id),UNIQUE KEY `unique_index` (url_title,type)");
safe_query("CREATE TABLE IF NOT EXISTS bts_podcast (id int(11) NOT NULL AUTO_INCREMENT,url_title varchar(64) NOT NULL,filename varchar(64) NOT NULL,type char(3) NOT NULL,checksum char(64) NOT NULL,bytesize varchar(16) NOT NULL,created datetime NOT NULL DEFAULT CURRENT_TIMESTAMP,changed timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,PRIMARY KEY (id),UNIQUE KEY unique_index (url_title,type)) ENGINE=InnoDB AUTO_INCREMENT=3 DEFAULT CHARSET=utf8");
}

function bts_podcast_gen_guid () {
hash_file('sha256',file_article_upload());
function bts_podcast_gen_metainfo ($input) {
$hash = hash_file('sha256',file_article_upload());
// safe_query("INSERT INTO bts_podcast (url_title,filename,type,checksum,bytesize) VALUES ('" . $input['urltitle'] . "','" . $input['mediafile'] . "','" . $input['mediatype'] . "','" . $input['mediachksum'] . "','" . $input['mediabytes'] . "') ON DUPLICATE KEY UPDATE url_title = '" . $input['urltitle'] . "', filename = '" . $input['mediafile'] . "', type = '" . $input['mediatype'] . "', checksum = '" . $input['mediachksum'] . "', bytesize = '" . $input['mediabytes'] . "'");
}

//use pluggable_ui(event,step,default content, record set)
//event, i believe, is article_ui
//maybe use step "custom_fields" and totally replace custom fields with the file uploader?
//i should also find a way to get the "S0E0" format automatically used for the url title/permlink.

// Register the plugin...
if(class_exists('\Textpattern\Tag\Registry')) {
Txp::get('\Textpattern\Tag\Registry')
@ -142,7 +148,7 @@ function bts_podcast_guid ($atts) {
), $atts));

if (($byte == '1' && $db == '1') || ($string == '')) {
$checksum = fetch('checksum','sha256','filename',bts_podcast_filename($atts));
$checksum = fetch('checksum','bts_podcast','filename',bts_podcast_filename($atts));
} elseif ($byte == '1') {
$checksum = hash_file('sha256',$string);
} else {
@ -156,13 +162,49 @@ function bts_podcast_media_uri ($atts) {
$default_vals = array('media' => 'mp3');
$default_vals['uri'] = site_url($atts) . bts_podcast_path($atts) . bts_podcast_filename($atts);
extract(lAtts(array($default_vals), $atts));
if ( $uri == '') {
if (! isset($uri)) {
$uri = site_url($atts) . bts_podcast_path($atts) . bts_podcast_filename($atts);
}
return $uri;
}

/*
function bts_podccast_filesize($atts) {
}
function bts_podcast_medialength($atts) {
}
function bts_podcast_get_guid($atts) {
}
*/

// UNDER DEVELOPMENT: needs bts_podcast_filesize (which i need to rename to actually be bytesize)
// i also need to get media length so that can be returned in the actual feed.
/*
$metainfo_mp3 = array(
//$input['urltitle']
//$input['mediafile']
//$input['mediatype']
//$input['mediachksum']
//$input['mediabytes']
urltitle => title($atts),
mediafile => bts_podcast_filename($atts),
mediatype => 'mp3',
mediachksum => bts_podcast_guid($atts),
mediabytes => bts_podcast_filesize($atts));
$metainfo_ogg = array(
//$input['urltitle']
//$input['mediafile']
//$input['mediatype']
//$input['mediachksum']
//$input['mediabytes']
urltitle => title($atts),
mediafile => bts_podcast_filename($atts),
mediatype => 'mp3',
mediachksum => bts_podcast_guid($atts),
mediabytes => bts_podcast_filesize($atts));
bts_podcast_gen_metainfo ($metainfo_mp3);
bts_podcast_gen_metainfo ($metainfo_ogg);
*/
# --- END PLUGIN CODE ---

?>

View File

@ -0,0 +1,91 @@
--- upm_file_popper-0.2.2.orig 2016-01-01 17:13:48.000000000 +0100
+++ upm_file_popper-0.2.2.new 2016-01-01 17:13:48.000000000 +0100
@@ -1,6 +1,6 @@
-if (txpinterface == 'admin')
+if (@txpinterface == 'admin')
{
add_privs('upm_file_popper', '1,2,3,4,5');
register_callback('upm_file_popper', 'upm_file_popper');

add_privs('upm_file_popper_link', '1,2,3,4,5');
@@ -9,12 +9,25 @@
add_privs('upm_file_popper_js', '1,2,3,4,5');
register_callback('upm_file_popper_js', 'upm_file_popper_js', '', 1);

add_privs('upm_file_popper_img', '1,2,3,4,5');
register_callback('upm_file_popper_img', 'upm_file_popper_img', '', 1);
+
+ register_callback('upm_file_popper_menu', 'article_ui', 'extend_col_1');
+
}

+ /**
+ * Insert upm_file_popper link in column 1 on the write-tab
+ *
+ * @param string $event (article_ui)
+ * @param string $step (extend_col_1)
+ */
+ function upm_file_popper_menu($event, $step) {
+ return '<div id="qupm_file_popper_group"><h3 class="plain lever"><a href="#qupm_file_popper-link">'.upm_file_popper_gTxt('attach_file').'</a></h3><div id="qupm_file_popper-link" class="toggle" style="display:none"><ul class="qupm_file_popper plain-list"><li><a id="qupm_file_popper-open" class="qupm_file_popper-open" href="#" onclick="myFunction();return false;">'.upm_file_popper_gTxt('attach_file').'</a></li></ul></div><script>function myFunction() {var w=700;var h=700;var t = (screen.height) ? (screen.height - h) / 2 : 0;var l = (screen.width) ? (screen.width - w) / 2 : 0;window.open("?event=upm_file_popper&bm=1&sort=id&dir=desc", "upm_file_popper", "menubar=0,toolbar=0,resizable=1,top="+t+",left="+l+",width="+w+",height="+h+"");}</script></div>';
+ }
+
// -------------------------------------------------------------

function upm_file_popper()
{
global $step, $prefs;
@@ -88,13 +101,14 @@

<script type="text/javascript" src="index.php?event=upm_file_popper_js&#38;name=pop"></script>
css;

extract(gpsa(array('page', 'sort', 'dir', 'crit', 'search_method')));
+ if ($sort === '') $sort = get_pref('file_sort_column', 'filename');
+ if ($dir === '') $dir = get_pref('file_sort_dir', 'asc');
+ $dir = ($dir == 'desc') ? 'desc' : 'asc';

- $dir = ($dir == 'desc') ? 'desc' : 'asc';
-
switch ($sort)
{
case 'id':
$sort_sql = "id $dir, filename asc";
break;
@@ -183,11 +197,11 @@

if ($rs)
{
$sort_link = 'upm_file_popper'.a.'bm=true';

- echo startTable('list'),
+ echo startTable('','','txp-list'),
tr(
column_head('ID', 'id', $sort_link, true, $switch_dir, $crit, $search_method).
column_head('file_name', 'filename', $sort_link, true, $switch_dir, $crit, $search_method).
column_head('description', 'description', $sort_link, true, $switch_dir, $crit, $search_method).
column_head('file_category', 'category', $sort_link, true, $switch_dir, $crit, $search_method).
@@ -397,21 +411,21 @@
$('#upm_file_popper_start').val( $('body').val() );

// ------------------------------
// create and insert popup link

- var w = 575;
- var h = 375;
+ var w = 800;
+ var h = 500;

var t = (screen.height) ? (screen.height - h) / 2 : 0;
var l = (screen.width) ? (screen.width - w) / 2 : 0;

var a = $(document.createElement('a')).
text('$lang_attach_file').
attr({
target: '_blank',
- href: '?event=upm_file_popper\u0026bm=1'
+ href: '?event=upm_file_popper\u0026bm=1\u0026sort=id\u0026dir=desc'
}).
click(function () {
var upm_file_popper = window.open(this.href, 'upm_file_popper', 'top = '+t+', left = '+l+', width = '+w+', height = '+h+', toolbar = no, location = no, directories = no, status = yes, menubar = no, scrollbars = yes, copyhistory = no, resizable = yes');
upm_file_popper.focus();
return false;

636
upm_file_popper-0.2.2.old Normal file
View File

@ -0,0 +1,636 @@
if (txpinterface == 'admin')
{
add_privs('upm_file_popper', '1,2,3,4,5');
register_callback('upm_file_popper', 'upm_file_popper');

add_privs('upm_file_popper_link', '1,2,3,4,5');
register_callback('upm_file_popper_link', 'article');

add_privs('upm_file_popper_js', '1,2,3,4,5');
register_callback('upm_file_popper_js', 'upm_file_popper_js', '', 1);

add_privs('upm_file_popper_img', '1,2,3,4,5');
register_callback('upm_file_popper_img', 'upm_file_popper_img', '', 1);
}

// -------------------------------------------------------------

function upm_file_popper()
{
global $step, $prefs;

if ($step == 'upm_file_popper_change_pageby')
{
event_change_pageby('file');
$GLOBALS['prefs'] = get_prefs();
}

upm_file_popper_list();
}

// -------------------------------------------------------------

function upm_file_popper_list()
{
global $file_base_path, $prefs;

pagetop(upm_file_popper_gTxt('file_selector'));

echo <<<css
<style type="text/css">
<!--
label {
cursor: pointer;
color: #000;
}

img {
border: none;
}

ul {
margin: 0;
padding: 0;
list-style: none;
}

li {
margin: 0 0 2px 0;
padding: 0;
}

p {
margin: 5px 0;
padding: 0;
}

.right {
text-align: right;
}

.center {
margin: 0 auto;
text-align: center;
}

#no {
margin-left: 2em;
}

#return, #success, #failed {
padding: 1em;
text-align: center;
background-color: #fff;
border: 5px solid #fc3;
}
-->
</style>

<script type="text/javascript" src="index.php?event=upm_file_popper_js&#38;name=pop"></script>
css;

extract(gpsa(array('page', 'sort', 'dir', 'crit', 'search_method')));

$dir = ($dir == 'desc') ? 'desc' : 'asc';

switch ($sort)
{
case 'id':
$sort_sql = "id $dir, filename asc";
break;

case 'filename':
$sort_sql = "filename $dir";
break;

case 'description':
$sort_sql = 'description '.$dir.', filename desc';
break;

case 'category':
$sort_sql = "category $dir, filename asc";
break;

case 'downloads':
$sort_sql = "downloads $dir, filename asc";
break;

default:
$dir = 'desc';
$sort_sql = "filename $dir";
break;
}

$switch_dir = ($dir == 'desc') ? 'asc' : 'desc';

$criteria = 1;

if ($search_method and $crit)
{
$crit_escaped = doSlash($crit);

$critsql = array(
'id' => "id = '$crit_escaped'",
'filename' => "filename like '%$crit_escaped%'",
'category' => "category like '%$crit_escaped%'",
'description' => "description like '%$crit_escaped%'"
);

if (array_key_exists($search_method, $critsql))
{
$criteria = $critsql[$search_method];
$limit = 500;
}

else
{
$search_method = '';
$crit = '';
}
}

else
{
$search_method = '';
$crit = '';
}

$total = safe_count('txp_file', "$criteria");

if ($total < 1)
{
if ($criteria != 1)
{
echo n.upm_file_popper_search_form($crit, $search_method, $sort, $dir).
n.graf(gTxt('no_results_found'), ' style="text-align: center;"');
}

else
{
echo n.graf(gTxt('no_files_recorded'), ' style="text-align: center;"');
}

return;
}

$limit = max($prefs['file_list_pageby'], 15);

list($page, $offset, $numPages) = pager($total, $limit, $page);

echo upm_file_popper_search_form($crit, $search_method, $sort, $dir);

$rs = safe_rows_start('*', 'txp_file', "$criteria order by $sort_sql limit $offset, $limit");

if ($rs)
{
$sort_link = 'upm_file_popper'.a.'bm=true';

echo startTable('list'),
tr(
column_head('ID', 'id', $sort_link, true, $switch_dir, $crit, $search_method).
column_head('file_name', 'filename', $sort_link, true, $switch_dir, $crit, $search_method).
column_head('description', 'description', $sort_link, true, $switch_dir, $crit, $search_method).
column_head('file_category', 'category', $sort_link, true, $switch_dir, $crit, $search_method).
hCell().
hCell(gTxt('tags')).
hCell(gTxt('status')).
column_head('downloads', 'downloads', $sort_link, true, $switch_dir, $crit, $search_method)
);

while ($a = nextRow($rs))
{
extract($a);

// god I hate javascript in php
$insert = '<a href="#" onclick="upm_file_popper_attachFile('.chr(39).$id.chr(39).'); return false;"><img src="index.php?event=upm_file_popper_img" width="16px" height="16px" alt="'.upm_file_popper_gTxt('attach_file').'" title="'.upm_file_popper_gTxt('attach_file').'" /></a>';

$tag_url = '?event=tag'.a.'tag_name=file_download_link'.a.'id='.$id.a.'description='.urlencode($description).
a.'filename='.urlencode($filename);

$file_exists = file_exists(build_file_path($file_base_path, $filename));

$status = ($file_exists) ?
'<span class="ok">'.gTxt('file_status_ok').'</span>' :
'<span class="not-ok">'.gTxt('file_status_missing').'</span>';

if (!isset($downloads))
{
safe_alter('txp_file', "ADD downloads INT DEFAULT '0' NOT NULL");
$downloads = 0;
}

elseif (empty($downloads))
{
$downloads = '0';
}


echo n.n.tr(

n.td($id).

td('<a href="#" onclick="upm_file_popper_warnEditFile('.$id.'); return false;">'.$filename.'</a>', 125).

td($description, 150).
td($category, 90).

td($insert).

td(
n.'<ul>'.
n.t.'<li><a target="_blank" href="'.$tag_url.a.'type=textile" onclick="popWin(this.href, 400, 250); return false;">Textile</a></li>'.
n.t.'<li><a target="_blank" href="'.$tag_url.a.'type=textpattern" onclick="popWin(this.href, 400, 250); return false;">Textpattern</a></li>'.
n.t.'<li><a target="_blank" href="'.$tag_url.a.'type=xhtml" onclick="popWin(this.href, 400, 250); return false;">XHTML</a></li>'.
n.'</ul>'
, 75).

td($status, 45).

td(
($downloads == '0' ? gTxt('none') : $downloads)
, 25)
);
}

echo endTable().

nav_form('upm_file_popper', $page, $numPages, $sort, $dir, $crit, $search_method).

upm_file_popper_pageby_form().

n.tag(
n.graf(upm_file_popper_gTxt('return')).
n.graf('<a id="yes" href="#" onclick="upm_file_popper_goBack(this.href); return false;">'.gTxt('yes').'</a>.'.
' <a id="no" href="#" onclick="upm_file_popper_done(\'return\'); return false;">'.gTxt('no').'</a>.')
, 'div', ' id="return" style="display: none; width: 200px; height: 75px;"').

n.graf(upm_file_popper_gTxt('success'), ' id="success" style="display: none; width: 150px; height: 35px;"').
n.graf(upm_file_popper_gTxt('failed'), ' id="failed" style="display: none; width: 150px; height: 35px;"');
}
}

// -------------------------------------------------------------

function upm_file_popper_search_form($crit, $method, $sort, $dir)
{
$default_method = 'filename';

$method = ($method) ? $method : $default_method;

$methods = array(
'id' => gTxt('id'),
'filename' => gTxt('file_name'),
'description' => gTxt('description'),
'category' => gTxt('file_category')
);

return n.n.'<form method="get" action="index.php" style="margin: auto; text-align: center;">'.
graf(
'<label for="upm-file-popper-search">'.gTxt('search').'</label>'.sp.
selectInput('search_method', $methods, $method, '', '', 'upm-file-popper-search').sp.
fInput('text', 'crit', $crit, 'edit', '', '', '15').
eInput('upm_file_popper').
hInput('bm','true').
fInput('submit', 'search', gTxt('go'), 'smallerbox')
).

($crit ? n.graf('<a href="?event=upm_file_popper'.a.'bm=true">'.upm_file_popper_gTxt('view_all').'</a>') : '').

n.'</form>';
}

// -------------------------------------------------------------

function upm_file_popper_pageby_form()
{
global $prefs;

$vals = array(
15 => 15,
25 => 25,
50 => 50,
100 => 100
);

$select_page = selectInput('qty', $vals, $prefs['file_list_pageby'], '', 1);

// proper localisation
$page = str_replace('{page}', $select_page, gTxt('view_per_page'));

return form(
'<div style="margin: auto; text-align: center;">'.
$page.
eInput('upm_file_popper').
sInput('upm_file_popper_change_pageby').
hInput('bm', '1').
'<noscript> <input type="submit" value="'.gTxt('go').'" class="smallerbox" /></noscript>'.
'</div>'
);
}

// -------------------------------------------------------------

function upm_file_popper_link()
{
$view = gps('view');

if ($view == 'text' or empty($view))
{
echo <<<form

<form action="">
<input type="hidden" id="upm_file_popper_start" value="">
</form>

<script type="text/javascript" src="index.php?event=upm_file_popper_js&#38;name=link"></script>
form;
}
}

// -------------------------------------------------------------

function upm_file_popper_js()
{
global $prefs;

while (@ob_end_clean());

header("Content-type: text/javascript");

if (empty($prefs['upm_file_field']))
{
$lang_forgot_field = upm_file_popper_gTxt('forgot_field');

echo <<<js
/*
upm_file_popper - custom field has not been defined
*/

$(document).ready(function() {
alert('$lang_forgot_field');
});
js;
exit(0);
}

else
{
$upm_file_field = !empty($prefs['upm_file_field']) ? $prefs['upm_file_field'] : '';
$upm_file_field = str_replace('_', '-', $upm_file_field);
}

if (gps('name') == 'link')
{
$txt = gTxt('advanced_options');

$lang_attach_file = upm_file_popper_gTxt('attach_file');

echo <<<js
/*
upm_file_popper - article window
*/

$(document).ready(function() {
// ------------------------------
// setup article edit tracking

$('#upm_file_popper_start').val( $('body').val() );

// ------------------------------
// create and insert popup link

var w = 575;
var h = 375;

var t = (screen.height) ? (screen.height - h) / 2 : 0;
var l = (screen.width) ? (screen.width - w) / 2 : 0;

var a = $(document.createElement('a')).
text('$lang_attach_file').
attr({
target: '_blank',
href: '?event=upm_file_popper\u0026bm=1'
}).
click(function () {
var upm_file_popper = window.open(this.href, 'upm_file_popper', 'top = '+t+', left = '+l+', width = '+w+', height = '+h+', toolbar = no, location = no, directories = no, status = yes, menubar = no, scrollbars = yes, copyhistory = no, resizable = yes');
upm_file_popper.focus();
return false;
});

var link = $(document.createElement('h3')).
addClass('plain').
append(a);

$('h3.plain > a:contains("$txt")').
before(link);
});
js;

exit(0);
}

elseif (gps('name') == 'pop')
{
$lang_check_leave = upm_file_popper_gTxt('check_leave');

echo <<<js
/*
upm_file_popper - popup window
*/

function upm_file_popper_attachFile(id)
{
var field = $('#$upm_file_field', window.opener.document).val();

if ($('form[name="article"]', window.opener))
{
if (field == '')
{
$('#$upm_file_field', window.opener.document).val(id);
return upm_file_popper_showMsg('success');
}

else
{
$('#$upm_file_field', window.opener.document).val(field + ',' + id);
return upm_file_popper_showMsg('success');
}
}

return upm_file_popper_showMsg('failed');
}

// -------------------------------------------------------------

function upm_file_popper_warnEditFile(id)
{
if ($('#body', window.opener.document).val() != $('#upm_file_popper_start', window.opener.document).val())
{
var check = confirm('$lang_check_leave');

if (check)
{
upm_file_popper_goEditFile(id);
}
}

else
{
upm_file_popper_goEditFile(id);
}
}

// -------------------------------------------------------------

function upm_file_popper_goEditFile(id)
{
window.opener.focus();

if ($('input[name="step"]', window.opener.document).val() != 'create')
{
$('#yes').attr('href', window.opener.document.location);
upm_file_popper_showMsg('return');
}

window.opener.document.location = '?event=file\u0026step=file_edit\u0026id='+id;
}

// -------------------------------------------------------------

function upm_file_popper_goBack(url)
{
window.opener.focus();

upm_file_popper_done('return');

window.opener.document.location = url;
}

// -------------------------------------------------------------

function upm_file_popper_showMsg(id)
{
var msg = $('#'+id);

msg.css({
position: 'absolute',
top: 100 + upm_file_popper_scrollTop() + 'px',
left: ( (upm_file_popper_pageWidth() / 2) - (parseInt(msg.css('width')) / 2) ) + upm_file_popper_scrollLeft() + 'px',
display: 'block'
});

if (id != 'return')
{
setTimeout("upm_file_popper_done('"+id+"')", 1000);
}
}

// -------------------------------------------------------------

function upm_file_popper_done(id)
{
$('#'+id).css('display', 'none');
}

// -------------------------------------------------------------

function upm_file_popper_pageWidth()
{
if (self.innerWidth)
{
return self.innerWidth;
}

else if (document.documentElement && document.documentElement.clientWidth)
{
return document.documentElement.clientWidth;
}

return 0;
}

// -------------------------------------------------------------

function upm_file_popper_scrollTop()
{
if (self.pageYOffset)
{
return self.pageYOffset;
}

else if (document.documentElement && document.documentElement.scrollTop)
{
return document.documentElement.scrollTop;
}

return 0;
}

// -------------------------------------------------------------

function upm_file_popper_scrollLeft()
{
if (self.pageYOffset)
{
return self.pageXOffset;
}

else if (document.documentElement && document.documentElement.scrollTop)
{
return document.documentElement.scrollLeft;
}

return 0;
}
js;

exit(0);
}
}

// -------------------------------------------------------------

function upm_file_popper_img()
{
while (@ob_end_clean());

header("Content-type: image/gif");

echo base64_decode('iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABGdBTUEAAK/INwWK6'.
'QAAABl0RVh0U29mdHdhcmUAQWRvYmUgSW1hZ2VSZWFkeXHJZTwAAAJvSURBVDjLpZPrS5NhGIf9W7YvBYO'.
'khlkoqCklWChv2WyKik7blnNris72bi6dus0DLZ0TDxW1odtopDs4D8MDZuLU0kXq61CijSIIasOvv94VT'.
'UfLiB74fXngup7nvrnvJABJ/5PfLnTTdcwOj4RsdYmo5glBWP6iOtzwvIKSWstI0Wgx80SBblpKtE9KQs/'.
'We7EaWoT/8wbWP61gMmCH0lMDvokT4j25TiQU/ITFkek9Ow6+7WH2gwsmahCPdwyw75uw9HEO2gUZSkfyI'.
'9zBPCJOoJ2SMmg46N61YO/rNoa39Xi41oFuXysMfh36/Fp0b7bAfWAH6RGi0HglWNCbzYgJaFjRv6zGuy+'.
'b9It96N3SQvNKiV9HvSaDfFEIxXItnPs23BzJQd6DDEVM0OKsoVwBG/1VMzpXVWhbkUM2K4oJBDYuGmbKI'.
'J0qxsAbHfRLzbjcnUbFBIpx/qH3vQv9b3U03IQ/HfFkERTzfFj8w8jSpR7GBE123uFEYAzaDRIqX/2JAtJ'.
'bDat/COkd7CNBva2cMvq0MGxp0PRSCPF8BXjWG3FgNHc9XPT71Ojy3sMFdfJRCeKxEsVtKwFHwALZfCUk3'.
'tIfNR8XiJwc1LmL4dg141JPKtj3WUdNFJqLGFVPC4OkR4BxajTWsChY64wmCnMxsWPCHcutKBxMVp5mxA1'.
'S+aMComToaqTRUQknLTH62kHOVEE+VQnjahscNCy0cMBWsSI0TCQcZc5ALkEYckL5A5noWSBhfm2AecMAj'.
'bcRWV0pUTh0HE64TNf0mczcnnQyu/MilaFJCae1nw2fbz1DnVOxyGTlKeZft/Ff8x1BRssfACjTwQAAAAB'.
'JRU5ErkJggg==');

exit(0);
}

// -------------------------------------------------------------

function upm_file_popper_gTxt($var, $atts = array())
{
$lang = array(
'attach' => 'Attach',
'attach_file' => 'Attach File',
'check_leave' => 'You have made changes to the current post which you have not saved. Continue without saving?',
'description_for' => 'Description for',
'failed' => 'Insert failed.',
'file_selector' => 'File Selector',
'forgot_field' => 'You forgot to define the custom field for upm_file/upm_file_popper to use. Ensure that you have a custom field available, and that you have upm_file installed and activated, then visit Extensions > upm_file.',
'no_description' => 'No description has been defined for this file.',
'packet_custom_field' => 'Packet Custom Field',
'return' => 'Return to editing the post?',
'success' => 'Success.',
'view_all' => 'View All'
);

return strtr($lang[$var], $atts);
}

650
upm_file_popper-0.2.2.orig Normal file
View File

@ -0,0 +1,650 @@
if (@txpinterface == 'admin')
{
add_privs('upm_file_popper', '1,2,3,4,5');
register_callback('upm_file_popper', 'upm_file_popper');

add_privs('upm_file_popper_link', '1,2,3,4,5');
register_callback('upm_file_popper_link', 'article');

add_privs('upm_file_popper_js', '1,2,3,4,5');
register_callback('upm_file_popper_js', 'upm_file_popper_js', '', 1);

add_privs('upm_file_popper_img', '1,2,3,4,5');
register_callback('upm_file_popper_img', 'upm_file_popper_img', '', 1);

register_callback('upm_file_popper_menu', 'article_ui', 'extend_col_1');

}

/**
* Insert upm_file_popper link in column 1 on the write-tab
*
* @param string $event (article_ui)
* @param string $step (extend_col_1)
*/
function upm_file_popper_menu($event, $step) {
return '<div id="qupm_file_popper_group"><h3 class="plain lever"><a href="#qupm_file_popper-link">'.upm_file_popper_gTxt('attach_file').'</a></h3><div id="qupm_file_popper-link" class="toggle" style="display:none"><ul class="qupm_file_popper plain-list"><li><a id="qupm_file_popper-open" class="qupm_file_popper-open" href="#" onclick="myFunction();return false;">'.upm_file_popper_gTxt('attach_file').'</a></li></ul></div><script>function myFunction() {var w=700;var h=700;var t = (screen.height) ? (screen.height - h) / 2 : 0;var l = (screen.width) ? (screen.width - w) / 2 : 0;window.open("?event=upm_file_popper&bm=1&sort=id&dir=desc", "upm_file_popper", "menubar=0,toolbar=0,resizable=1,top="+t+",left="+l+",width="+w+",height="+h+"");}</script></div>';
}

// -------------------------------------------------------------

function upm_file_popper()
{
global $step, $prefs;

if ($step == 'upm_file_popper_change_pageby')
{
event_change_pageby('file');
$GLOBALS['prefs'] = get_prefs();
}

upm_file_popper_list();
}

// -------------------------------------------------------------

function upm_file_popper_list()
{
global $file_base_path, $prefs;

pagetop(upm_file_popper_gTxt('file_selector'));

echo <<<css
<style type="text/css">
<!--
label {
cursor: pointer;
color: #000;
}

img {
border: none;
}

ul {
margin: 0;
padding: 0;
list-style: none;
}

li {
margin: 0 0 2px 0;
padding: 0;
}

p {
margin: 5px 0;
padding: 0;
}

.right {
text-align: right;
}

.center {
margin: 0 auto;
text-align: center;
}

#no {
margin-left: 2em;
}

#return, #success, #failed {
padding: 1em;
text-align: center;
background-color: #fff;
border: 5px solid #fc3;
}
-->
</style>

<script type="text/javascript" src="index.php?event=upm_file_popper_js&#38;name=pop"></script>
css;

extract(gpsa(array('page', 'sort', 'dir', 'crit', 'search_method')));
if ($sort === '') $sort = get_pref('file_sort_column', 'filename');
if ($dir === '') $dir = get_pref('file_sort_dir', 'asc');
$dir = ($dir == 'desc') ? 'desc' : 'asc';

switch ($sort)
{
case 'id':
$sort_sql = "id $dir, filename asc";
break;

case 'filename':
$sort_sql = "filename $dir";
break;

case 'description':
$sort_sql = 'description '.$dir.', filename desc';
break;

case 'category':
$sort_sql = "category $dir, filename asc";
break;

case 'downloads':
$sort_sql = "downloads $dir, filename asc";
break;

default:
$dir = 'desc';
$sort_sql = "filename $dir";
break;
}

$switch_dir = ($dir == 'desc') ? 'asc' : 'desc';

$criteria = 1;

if ($search_method and $crit)
{
$crit_escaped = doSlash($crit);

$critsql = array(
'id' => "id = '$crit_escaped'",
'filename' => "filename like '%$crit_escaped%'",
'category' => "category like '%$crit_escaped%'",
'description' => "description like '%$crit_escaped%'"
);

if (array_key_exists($search_method, $critsql))
{
$criteria = $critsql[$search_method];
$limit = 500;
}

else
{
$search_method = '';
$crit = '';
}
}

else
{
$search_method = '';
$crit = '';
}

$total = safe_count('txp_file', "$criteria");

if ($total < 1)
{
if ($criteria != 1)
{
echo n.upm_file_popper_search_form($crit, $search_method, $sort, $dir).
n.graf(gTxt('no_results_found'), ' style="text-align: center;"');
}

else
{
echo n.graf(gTxt('no_files_recorded'), ' style="text-align: center;"');
}

return;
}

$limit = max($prefs['file_list_pageby'], 15);

list($page, $offset, $numPages) = pager($total, $limit, $page);

echo upm_file_popper_search_form($crit, $search_method, $sort, $dir);

$rs = safe_rows_start('*', 'txp_file', "$criteria order by $sort_sql limit $offset, $limit");

if ($rs)
{
$sort_link = 'upm_file_popper'.a.'bm=true';

echo startTable('','','txp-list'),
tr(
column_head('ID', 'id', $sort_link, true, $switch_dir, $crit, $search_method).
column_head('file_name', 'filename', $sort_link, true, $switch_dir, $crit, $search_method).
column_head('description', 'description', $sort_link, true, $switch_dir, $crit, $search_method).
column_head('file_category', 'category', $sort_link, true, $switch_dir, $crit, $search_method).
hCell().
hCell(gTxt('tags')).
hCell(gTxt('status')).
column_head('downloads', 'downloads', $sort_link, true, $switch_dir, $crit, $search_method)
);

while ($a = nextRow($rs))
{
extract($a);

// god I hate javascript in php
$insert = '<a href="#" onclick="upm_file_popper_attachFile('.chr(39).$id.chr(39).'); return false;"><img src="index.php?event=upm_file_popper_img" width="16px" height="16px" alt="'.upm_file_popper_gTxt('attach_file').'" title="'.upm_file_popper_gTxt('attach_file').'" /></a>';

$tag_url = '?event=tag'.a.'tag_name=file_download_link'.a.'id='.$id.a.'description='.urlencode($description).
a.'filename='.urlencode($filename);

$file_exists = file_exists(build_file_path($file_base_path, $filename));

$status = ($file_exists) ?
'<span class="ok">'.gTxt('file_status_ok').'</span>' :
'<span class="not-ok">'.gTxt('file_status_missing').'</span>';

if (!isset($downloads))
{
safe_alter('txp_file', "ADD downloads INT DEFAULT '0' NOT NULL");
$downloads = 0;
}

elseif (empty($downloads))
{
$downloads = '0';
}


echo n.n.tr(

n.td($id).

td('<a href="#" onclick="upm_file_popper_warnEditFile('.$id.'); return false;">'.$filename.'</a>', 125).

td($description, 150).
td($category, 90).

td($insert).

td(
n.'<ul>'.
n.t.'<li><a target="_blank" href="'.$tag_url.a.'type=textile" onclick="popWin(this.href, 400, 250); return false;">Textile</a></li>'.
n.t.'<li><a target="_blank" href="'.$tag_url.a.'type=textpattern" onclick="popWin(this.href, 400, 250); return false;">Textpattern</a></li>'.
n.t.'<li><a target="_blank" href="'.$tag_url.a.'type=xhtml" onclick="popWin(this.href, 400, 250); return false;">XHTML</a></li>'.
n.'</ul>'
, 75).

td($status, 45).

td(
($downloads == '0' ? gTxt('none') : $downloads)
, 25)
);
}

echo endTable().

nav_form('upm_file_popper', $page, $numPages, $sort, $dir, $crit, $search_method).

upm_file_popper_pageby_form().

n.tag(
n.graf(upm_file_popper_gTxt('return')).
n.graf('<a id="yes" href="#" onclick="upm_file_popper_goBack(this.href); return false;">'.gTxt('yes').'</a>.'.
' <a id="no" href="#" onclick="upm_file_popper_done(\'return\'); return false;">'.gTxt('no').'</a>.')
, 'div', ' id="return" style="display: none; width: 200px; height: 75px;"').

n.graf(upm_file_popper_gTxt('success'), ' id="success" style="display: none; width: 150px; height: 35px;"').
n.graf(upm_file_popper_gTxt('failed'), ' id="failed" style="display: none; width: 150px; height: 35px;"');
}
}

// -------------------------------------------------------------

function upm_file_popper_search_form($crit, $method, $sort, $dir)
{
$default_method = 'filename';

$method = ($method) ? $method : $default_method;

$methods = array(
'id' => gTxt('id'),
'filename' => gTxt('file_name'),
'description' => gTxt('description'),
'category' => gTxt('file_category')
);

return n.n.'<form method="get" action="index.php" style="margin: auto; text-align: center;">'.
graf(
'<label for="upm-file-popper-search">'.gTxt('search').'</label>'.sp.
selectInput('search_method', $methods, $method, '', '', 'upm-file-popper-search').sp.
fInput('text', 'crit', $crit, 'edit', '', '', '15').
eInput('upm_file_popper').
hInput('bm','true').
fInput('submit', 'search', gTxt('go'), 'smallerbox')
).

($crit ? n.graf('<a href="?event=upm_file_popper'.a.'bm=true">'.upm_file_popper_gTxt('view_all').'</a>') : '').

n.'</form>';
}

// -------------------------------------------------------------

function upm_file_popper_pageby_form()
{
global $prefs;

$vals = array(
15 => 15,
25 => 25,
50 => 50,
100 => 100
);

$select_page = selectInput('qty', $vals, $prefs['file_list_pageby'], '', 1);

// proper localisation
$page = str_replace('{page}', $select_page, gTxt('view_per_page'));

return form(
'<div style="margin: auto; text-align: center;">'.
$page.
eInput('upm_file_popper').
sInput('upm_file_popper_change_pageby').
hInput('bm', '1').
'<noscript> <input type="submit" value="'.gTxt('go').'" class="smallerbox" /></noscript>'.
'</div>'
);
}

// -------------------------------------------------------------

function upm_file_popper_link()
{
$view = gps('view');

if ($view == 'text' or empty($view))
{
echo <<<form

<form action="">
<input type="hidden" id="upm_file_popper_start" value="">
</form>

<script type="text/javascript" src="index.php?event=upm_file_popper_js&#38;name=link"></script>
form;
}
}

// -------------------------------------------------------------

function upm_file_popper_js()
{
global $prefs;

while (@ob_end_clean());

header("Content-type: text/javascript");

if (empty($prefs['upm_file_field']))
{
$lang_forgot_field = upm_file_popper_gTxt('forgot_field');

echo <<<js
/*
upm_file_popper - custom field has not been defined
*/

$(document).ready(function() {
alert('$lang_forgot_field');
});
js;
exit(0);
}

else
{
$upm_file_field = !empty($prefs['upm_file_field']) ? $prefs['upm_file_field'] : '';
$upm_file_field = str_replace('_', '-', $upm_file_field);
}

if (gps('name') == 'link')
{
$txt = gTxt('advanced_options');

$lang_attach_file = upm_file_popper_gTxt('attach_file');

echo <<<js
/*
upm_file_popper - article window
*/

$(document).ready(function() {
// ------------------------------
// setup article edit tracking

$('#upm_file_popper_start').val( $('body').val() );

// ------------------------------
// create and insert popup link

var w = 800;
var h = 500;

var t = (screen.height) ? (screen.height - h) / 2 : 0;
var l = (screen.width) ? (screen.width - w) / 2 : 0;

var a = $(document.createElement('a')).
text('$lang_attach_file').
attr({
target: '_blank',
href: '?event=upm_file_popper\u0026bm=1\u0026sort=id\u0026dir=desc'
}).
click(function () {
var upm_file_popper = window.open(this.href, 'upm_file_popper', 'top = '+t+', left = '+l+', width = '+w+', height = '+h+', toolbar = no, location = no, directories = no, status = yes, menubar = no, scrollbars = yes, copyhistory = no, resizable = yes');
upm_file_popper.focus();
return false;
});

var link = $(document.createElement('h3')).
addClass('plain').
append(a);

$('h3.plain > a:contains("$txt")').
before(link);
});
js;

exit(0);
}

elseif (gps('name') == 'pop')
{
$lang_check_leave = upm_file_popper_gTxt('check_leave');

echo <<<js
/*
upm_file_popper - popup window
*/

function upm_file_popper_attachFile(id)
{
var field = $('#$upm_file_field', window.opener.document).val();

if ($('form[name="article"]', window.opener))
{
if (field == '')
{
$('#$upm_file_field', window.opener.document).val(id);
return upm_file_popper_showMsg('success');
}

else
{
$('#$upm_file_field', window.opener.document).val(field + ',' + id);
return upm_file_popper_showMsg('success');
}
}

return upm_file_popper_showMsg('failed');
}

// -------------------------------------------------------------

function upm_file_popper_warnEditFile(id)
{
if ($('#body', window.opener.document).val() != $('#upm_file_popper_start', window.opener.document).val())
{
var check = confirm('$lang_check_leave');

if (check)
{
upm_file_popper_goEditFile(id);
}
}

else
{
upm_file_popper_goEditFile(id);
}
}

// -------------------------------------------------------------

function upm_file_popper_goEditFile(id)
{
window.opener.focus();

if ($('input[name="step"]', window.opener.document).val() != 'create')
{
$('#yes').attr('href', window.opener.document.location);
upm_file_popper_showMsg('return');
}

window.opener.document.location = '?event=file\u0026step=file_edit\u0026id='+id;
}

// -------------------------------------------------------------

function upm_file_popper_goBack(url)
{
window.opener.focus();

upm_file_popper_done('return');

window.opener.document.location = url;
}

// -------------------------------------------------------------

function upm_file_popper_showMsg(id)
{
var msg = $('#'+id);

msg.css({
position: 'absolute',
top: 100 + upm_file_popper_scrollTop() + 'px',
left: ( (upm_file_popper_pageWidth() / 2) - (parseInt(msg.css('width')) / 2) ) + upm_file_popper_scrollLeft() + 'px',
display: 'block'
});

if (id != 'return')
{
setTimeout("upm_file_popper_done('"+id+"')", 1000);
}
}

// -------------------------------------------------------------

function upm_file_popper_done(id)
{
$('#'+id).css('display', 'none');
}

// -------------------------------------------------------------

function upm_file_popper_pageWidth()
{
if (self.innerWidth)
{
return self.innerWidth;
}

else if (document.documentElement && document.documentElement.clientWidth)
{
return document.documentElement.clientWidth;
}

return 0;
}

// -------------------------------------------------------------

function upm_file_popper_scrollTop()
{
if (self.pageYOffset)
{
return self.pageYOffset;
}

else if (document.documentElement && document.documentElement.scrollTop)
{
return document.documentElement.scrollTop;
}

return 0;
}

// -------------------------------------------------------------

function upm_file_popper_scrollLeft()
{
if (self.pageYOffset)
{
return self.pageXOffset;
}

else if (document.documentElement && document.documentElement.scrollTop)
{
return document.documentElement.scrollLeft;
}

return 0;
}
js;

exit(0);
}
}

// -------------------------------------------------------------

function upm_file_popper_img()
{
while (@ob_end_clean());

header("Content-type: image/gif");

echo base64_decode('iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABGdBTUEAAK/INwWK6'.
'QAAABl0RVh0U29mdHdhcmUAQWRvYmUgSW1hZ2VSZWFkeXHJZTwAAAJvSURBVDjLpZPrS5NhGIf9W7YvBYO'.
'khlkoqCklWChv2WyKik7blnNris72bi6dus0DLZ0TDxW1odtopDs4D8MDZuLU0kXq61CijSIIasOvv94VT'.
'UfLiB74fXngup7nvrnvJABJ/5PfLnTTdcwOj4RsdYmo5glBWP6iOtzwvIKSWstI0Wgx80SBblpKtE9KQs/'.
'We7EaWoT/8wbWP61gMmCH0lMDvokT4j25TiQU/ITFkek9Ow6+7WH2gwsmahCPdwyw75uw9HEO2gUZSkfyI'.
'9zBPCJOoJ2SMmg46N61YO/rNoa39Xi41oFuXysMfh36/Fp0b7bAfWAH6RGi0HglWNCbzYgJaFjRv6zGuy+'.
'b9It96N3SQvNKiV9HvSaDfFEIxXItnPs23BzJQd6DDEVM0OKsoVwBG/1VMzpXVWhbkUM2K4oJBDYuGmbKI'.
'J0qxsAbHfRLzbjcnUbFBIpx/qH3vQv9b3U03IQ/HfFkERTzfFj8w8jSpR7GBE123uFEYAzaDRIqX/2JAtJ'.
'bDat/COkd7CNBva2cMvq0MGxp0PRSCPF8BXjWG3FgNHc9XPT71Ojy3sMFdfJRCeKxEsVtKwFHwALZfCUk3'.
'tIfNR8XiJwc1LmL4dg141JPKtj3WUdNFJqLGFVPC4OkR4BxajTWsChY64wmCnMxsWPCHcutKBxMVp5mxA1'.
'S+aMComToaqTRUQknLTH62kHOVEE+VQnjahscNCy0cMBWsSI0TCQcZc5ALkEYckL5A5noWSBhfm2AecMAj'.
'bcRWV0pUTh0HE64TNf0mczcnnQyu/MilaFJCae1nw2fbz1DnVOxyGTlKeZft/Ff8x1BRssfACjTwQAAAAB'.
'JRU5ErkJggg==');

exit(0);
}

// -------------------------------------------------------------

function upm_file_popper_gTxt($var, $atts = array())
{
$lang = array(
'attach' => 'Attach',
'attach_file' => 'Attach File',
'check_leave' => 'You have made changes to the current post which you have not saved. Continue without saving?',
'description_for' => 'Description for',
'failed' => 'Insert failed.',
'file_selector' => 'File Selector',
'forgot_field' => 'You forgot to define the custom field for upm_file/upm_file_popper to use. Ensure that you have a custom field available, and that you have upm_file installed and activated, then visit Extensions > upm_file.',
'no_description' => 'No description has been defined for this file.',
'packet_custom_field' => 'Packet Custom Field',
'return' => 'Return to editing the post?',
'success' => 'Success.',
'view_all' => 'View All'
);

return strtr($lang[$var], $atts);
}

327
upm_file_popper-0.2.2.txt Normal file
View File

@ -0,0 +1,327 @@
# upm_file_popper v.0.2.2
# An easy-to-use file picker, for use with upm_file.

# Mary Fredborg
# http://utterplush.com/txp-plugins/upm_file_popper

# ..........................................................................
# A plugin for Textpattern
# http://textpattern.com/
#
# Adding Plugins to Your Textpattern Installation
# http://textpattern.net/wiki/index.php?title=Intermediate_Weblog_Model#Adding_Plugins_to_Your_Textpattern_Installation
# ..........................................................................

YToxMTp7czo0OiJuYW1lIjtzOjE1OiJ1cG1fZmlsZV9wb3BwZXIiO3M6MTE6ImRlc2NyaXB0
aW9uIjtzOjUwOiJBbiBlYXN5LXRvLXVzZSBmaWxlIHBpY2tlciwgZm9yIHVzZSB3aXRoIHVw
bV9maWxlLiI7czo3OiJ2ZXJzaW9uIjtzOjU6IjAuMi4yIjtzOjQ6InR5cGUiO2k6MTtzOjY6
ImF1dGhvciI7czoxMzoiTWFyeSBGcmVkYm9yZyI7czoxMDoiYXV0aG9yX3VyaSI7czo0OToi
aHR0cDovL3V0dGVycGx1c2guY29tL3R4cC1wbHVnaW5zL3VwbV9maWxlX3BvcHBlciI7czo0
OiJjb2RlIjtzOjE1ODk2OiJpZiAodHhwaW50ZXJmYWNlID09ICdhZG1pbicpCgl7CgkJYWRk
X3ByaXZzKCd1cG1fZmlsZV9wb3BwZXInLCAnMSwyLDMsNCw1Jyk7CgkJcmVnaXN0ZXJfY2Fs
bGJhY2soJ3VwbV9maWxlX3BvcHBlcicsICd1cG1fZmlsZV9wb3BwZXInKTsKCgkJYWRkX3By
aXZzKCd1cG1fZmlsZV9wb3BwZXJfbGluaycsICcxLDIsMyw0LDUnKTsKCQlyZWdpc3Rlcl9j
YWxsYmFjaygndXBtX2ZpbGVfcG9wcGVyX2xpbmsnLCAnYXJ0aWNsZScpOwoKCQlhZGRfcHJp
dnMoJ3VwbV9maWxlX3BvcHBlcl9qcycsICcxLDIsMyw0LDUnKTsKCQlyZWdpc3Rlcl9jYWxs
YmFjaygndXBtX2ZpbGVfcG9wcGVyX2pzJywgJ3VwbV9maWxlX3BvcHBlcl9qcycsICcnLCAx
KTsKCgkJYWRkX3ByaXZzKCd1cG1fZmlsZV9wb3BwZXJfaW1nJywgJzEsMiwzLDQsNScpOwoJ
CXJlZ2lzdGVyX2NhbGxiYWNrKCd1cG1fZmlsZV9wb3BwZXJfaW1nJywgJ3VwbV9maWxlX3Bv
cHBlcl9pbWcnLCAnJywgMSk7Cgl9CgovLyAtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0t
LS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tCgoJZnVuY3Rpb24gdXBtX2ZpbGVf
cG9wcGVyKCkKCXsKCQlnbG9iYWwgJHN0ZXAsICRwcmVmczsKCgkJaWYgKCRzdGVwID09ICd1
cG1fZmlsZV9wb3BwZXJfY2hhbmdlX3BhZ2VieScpCgkJewoJCQlldmVudF9jaGFuZ2VfcGFn
ZWJ5KCdmaWxlJyk7CgkJCSRHTE9CQUxTWydwcmVmcyddID0gZ2V0X3ByZWZzKCk7CgkJfQoK
CQl1cG1fZmlsZV9wb3BwZXJfbGlzdCgpOwoJfQoKLy8gLS0tLS0tLS0tLS0tLS0tLS0tLS0t
LS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLQoKCWZ1bmN0aW9uIHVw
bV9maWxlX3BvcHBlcl9saXN0KCkKCXsKCQlnbG9iYWwgJGZpbGVfYmFzZV9wYXRoLCAkcHJl
ZnM7CgoJCXBhZ2V0b3AodXBtX2ZpbGVfcG9wcGVyX2dUeHQoJ2ZpbGVfc2VsZWN0b3InKSk7
CgoJZWNobyA8PDxjc3MKPHN0eWxlIHR5cGU9InRleHQvY3NzIj4KPCEtLQpsYWJlbCB7CmN1
cnNvcjogcG9pbnRlcjsKY29sb3I6ICMwMDA7Cn0KCmltZyB7CmJvcmRlcjogbm9uZTsKfQoK
dWwgewptYXJnaW46IDA7CnBhZGRpbmc6IDA7Cmxpc3Qtc3R5bGU6IG5vbmU7Cn0KCmxpIHsK
bWFyZ2luOiAwIDAgMnB4IDA7CnBhZGRpbmc6IDA7Cn0KCnAgewptYXJnaW46IDVweCAwOwpw
YWRkaW5nOiAwOwp9CgoucmlnaHQgewp0ZXh0LWFsaWduOiByaWdodDsKfQoKLmNlbnRlciB7
Cm1hcmdpbjogMCBhdXRvOwp0ZXh0LWFsaWduOiBjZW50ZXI7Cn0KCiNubyB7Cm1hcmdpbi1s
ZWZ0OiAyZW07Cn0KCiNyZXR1cm4sICNzdWNjZXNzLCAjZmFpbGVkIHsKcGFkZGluZzogMWVt
Owp0ZXh0LWFsaWduOiBjZW50ZXI7CmJhY2tncm91bmQtY29sb3I6ICNmZmY7CmJvcmRlcjog
NXB4IHNvbGlkICNmYzM7Cn0KLS0+Cjwvc3R5bGU+Cgo8c2NyaXB0IHR5cGU9InRleHQvamF2
YXNjcmlwdCIgc3JjPSJpbmRleC5waHA/ZXZlbnQ9dXBtX2ZpbGVfcG9wcGVyX2pzJiMzODtu
YW1lPXBvcCI+PC9zY3JpcHQ+CmNzczsKCgkJZXh0cmFjdChncHNhKGFycmF5KCdwYWdlJywg
J3NvcnQnLCAnZGlyJywgJ2NyaXQnLCAnc2VhcmNoX21ldGhvZCcpKSk7CgoJCSRkaXIgPSAo
JGRpciA9PSAnZGVzYycpID8gJ2Rlc2MnIDogJ2FzYyc7CgoJCXN3aXRjaCAoJHNvcnQpCgkJ
ewoJCQljYXNlICdpZCc6CgkJCQkkc29ydF9zcWwgPSAiaWQgJGRpciwgZmlsZW5hbWUgYXNj
IjsKCQkJYnJlYWs7CgoJCQljYXNlICdmaWxlbmFtZSc6CgkJCQkkc29ydF9zcWwgPSAiZmls
ZW5hbWUgJGRpciI7CgkJCWJyZWFrOwoKCQkJY2FzZSAnZGVzY3JpcHRpb24nOgoJCQkJJHNv
cnRfc3FsID0gJ2Rlc2NyaXB0aW9uICcuJGRpci4nLCBmaWxlbmFtZSBkZXNjJzsKCQkJYnJl
YWs7CgoJCQljYXNlICdjYXRlZ29yeSc6CgkJCQkkc29ydF9zcWwgPSAiY2F0ZWdvcnkgJGRp
ciwgZmlsZW5hbWUgYXNjIjsKCQkJYnJlYWs7CgoJCQljYXNlICdkb3dubG9hZHMnOgoJCQkJ
JHNvcnRfc3FsID0gImRvd25sb2FkcyAkZGlyLCBmaWxlbmFtZSBhc2MiOwoJCQlicmVhazsK
CgkJCWRlZmF1bHQ6CgkJCQkkZGlyID0gJ2Rlc2MnOwoJCQkJJHNvcnRfc3FsID0gImZpbGVu
YW1lICRkaXIiOwoJCQlicmVhazsKCQl9CgoJCSRzd2l0Y2hfZGlyID0gKCRkaXIgPT0gJ2Rl
c2MnKSA/ICdhc2MnIDogJ2Rlc2MnOwoKCQkkY3JpdGVyaWEgPSAxOwoKCQlpZiAoJHNlYXJj
aF9tZXRob2QgYW5kICRjcml0KQoJCXsKCQkJJGNyaXRfZXNjYXBlZCA9IGRvU2xhc2goJGNy
aXQpOwoKCQkJJGNyaXRzcWwgPSBhcnJheSgKCQkJCSdpZCcJCQkJCT0+ICJpZCA9ICckY3Jp
dF9lc2NhcGVkJyIsCgkJCQknZmlsZW5hbWUnCQk9PiAiZmlsZW5hbWUgbGlrZSAnJSRjcml0
X2VzY2FwZWQlJyIsCgkJCQknY2F0ZWdvcnknCQk9PiAiY2F0ZWdvcnkgbGlrZSAnJSRjcml0
X2VzY2FwZWQlJyIsCgkJCQknZGVzY3JpcHRpb24nID0+ICJkZXNjcmlwdGlvbiBsaWtlICcl
JGNyaXRfZXNjYXBlZCUnIgoJCQkpOwoKCQkJaWYgKGFycmF5X2tleV9leGlzdHMoJHNlYXJj
aF9tZXRob2QsICRjcml0c3FsKSkKCQkJewoJCQkJJGNyaXRlcmlhID0gJGNyaXRzcWxbJHNl
YXJjaF9tZXRob2RdOwoJCQkJJGxpbWl0ID0gNTAwOwoJCQl9CgoJCQllbHNlCgkJCXsKCQkJ
CSRzZWFyY2hfbWV0aG9kID0gJyc7CgkJCQkkY3JpdCA9ICcnOwoJCQl9CgkJfQoKCQllbHNl
CgkJewoJCQkkc2VhcmNoX21ldGhvZCA9ICcnOwoJCQkkY3JpdCA9ICcnOwoJCX0KCgkJJHRv
dGFsID0gc2FmZV9jb3VudCgndHhwX2ZpbGUnLCAiJGNyaXRlcmlhIik7CgoJCWlmICgkdG90
YWwgPCAxKQoJCXsKCQkJaWYgKCRjcml0ZXJpYSAhPSAxKQoJCQl7CgkJCQllY2hvIG4udXBt
X2ZpbGVfcG9wcGVyX3NlYXJjaF9mb3JtKCRjcml0LCAkc2VhcmNoX21ldGhvZCwgJHNvcnQs
ICRkaXIpLgoJCQkJCW4uZ3JhZihnVHh0KCdub19yZXN1bHRzX2ZvdW5kJyksICcgc3R5bGU9
InRleHQtYWxpZ246IGNlbnRlcjsiJyk7CgkJCX0KCgkJCWVsc2UKCQkJewoJCQkJZWNobyBu
LmdyYWYoZ1R4dCgnbm9fZmlsZXNfcmVjb3JkZWQnKSwgJyBzdHlsZT0idGV4dC1hbGlnbjog
Y2VudGVyOyInKTsKCQkJfQoKCQkJcmV0dXJuOwoJCX0KCgkJJGxpbWl0ID0gbWF4KCRwcmVm
c1snZmlsZV9saXN0X3BhZ2VieSddLCAxNSk7CgoJCWxpc3QoJHBhZ2UsICRvZmZzZXQsICRu
dW1QYWdlcykgPSBwYWdlcigkdG90YWwsICRsaW1pdCwgJHBhZ2UpOwoKCQllY2hvIHVwbV9m
aWxlX3BvcHBlcl9zZWFyY2hfZm9ybSgkY3JpdCwgJHNlYXJjaF9tZXRob2QsICRzb3J0LCAk
ZGlyKTsKCgkJJHJzID0gc2FmZV9yb3dzX3N0YXJ0KCcqJywgJ3R4cF9maWxlJywgIiRjcml0
ZXJpYSBvcmRlciBieSAkc29ydF9zcWwgbGltaXQgJG9mZnNldCwgJGxpbWl0Iik7CgoJCWlm
ICgkcnMpCgkJewoJCQkkc29ydF9saW5rID0gJ3VwbV9maWxlX3BvcHBlcicuYS4nYm09dHJ1
ZSc7CgoJCQllY2hvIHN0YXJ0VGFibGUoJ2xpc3QnKSwKCQkJCXRyKAoJCQkJCWNvbHVtbl9o
ZWFkKCdJRCcsICdpZCcsICRzb3J0X2xpbmssIHRydWUsICRzd2l0Y2hfZGlyLCAkY3JpdCwg
JHNlYXJjaF9tZXRob2QpLgoJCQkJCWNvbHVtbl9oZWFkKCdmaWxlX25hbWUnLCAnZmlsZW5h
bWUnLCAkc29ydF9saW5rLCB0cnVlLAkkc3dpdGNoX2RpciwgJGNyaXQsICRzZWFyY2hfbWV0
aG9kKS4KCQkJCQljb2x1bW5faGVhZCgnZGVzY3JpcHRpb24nLCAnZGVzY3JpcHRpb24nLCAk
c29ydF9saW5rLCB0cnVlLCAkc3dpdGNoX2RpciwgJGNyaXQsICRzZWFyY2hfbWV0aG9kKS4K
CQkJCQljb2x1bW5faGVhZCgnZmlsZV9jYXRlZ29yeScsICdjYXRlZ29yeScsICRzb3J0X2xp
bmssIHRydWUsICRzd2l0Y2hfZGlyLCAkY3JpdCwgJHNlYXJjaF9tZXRob2QpLgoJCQkJCWhD
ZWxsKCkuCgkJCQkJaENlbGwoZ1R4dCgndGFncycpKS4KCQkJCQloQ2VsbChnVHh0KCdzdGF0
dXMnKSkuCgkJCQkJY29sdW1uX2hlYWQoJ2Rvd25sb2FkcycsICdkb3dubG9hZHMnLCAkc29y
dF9saW5rLCB0cnVlLCAkc3dpdGNoX2RpciwgJGNyaXQsICRzZWFyY2hfbWV0aG9kKQoJCQkJ
KTsKCgkJCXdoaWxlICgkYSA9IG5leHRSb3coJHJzKSkKCQkJewoJCQkJZXh0cmFjdCgkYSk7
CgoJCQkJLy8gZ29kIEkgaGF0ZSBqYXZhc2NyaXB0IGluIHBocAoJCQkJJGluc2VydCA9ICc8
YSBocmVmPSIjIiBvbmNsaWNrPSJ1cG1fZmlsZV9wb3BwZXJfYXR0YWNoRmlsZSgnLmNocigz
OSkuJGlkLmNocigzOSkuJyk7IHJldHVybiBmYWxzZTsiPjxpbWcgc3JjPSJpbmRleC5waHA/
ZXZlbnQ9dXBtX2ZpbGVfcG9wcGVyX2ltZyIgd2lkdGg9IjE2cHgiIGhlaWdodD0iMTZweCIg
YWx0PSInLnVwbV9maWxlX3BvcHBlcl9nVHh0KCdhdHRhY2hfZmlsZScpLiciIHRpdGxlPSIn
LnVwbV9maWxlX3BvcHBlcl9nVHh0KCdhdHRhY2hfZmlsZScpLiciIC8+PC9hPic7CgoJCQkJ
JHRhZ191cmwgPSAnP2V2ZW50PXRhZycuYS4ndGFnX25hbWU9ZmlsZV9kb3dubG9hZF9saW5r
Jy5hLidpZD0nLiRpZC5hLidkZXNjcmlwdGlvbj0nLnVybGVuY29kZSgkZGVzY3JpcHRpb24p
LgoJCQkJCWEuJ2ZpbGVuYW1lPScudXJsZW5jb2RlKCRmaWxlbmFtZSk7CgoJCQkJJGZpbGVf
ZXhpc3RzID0gZmlsZV9leGlzdHMoYnVpbGRfZmlsZV9wYXRoKCRmaWxlX2Jhc2VfcGF0aCwg
JGZpbGVuYW1lKSk7CgoJCQkJJHN0YXR1cyA9ICgkZmlsZV9leGlzdHMpID8KCQkJCQknPHNw
YW4gY2xhc3M9Im9rIj4nLmdUeHQoJ2ZpbGVfc3RhdHVzX29rJykuJzwvc3Bhbj4nIDoKCQkJ
CQknPHNwYW4gY2xhc3M9Im5vdC1vayI+Jy5nVHh0KCdmaWxlX3N0YXR1c19taXNzaW5nJyku
Jzwvc3Bhbj4nOwoKCQkJCWlmICghaXNzZXQoJGRvd25sb2FkcykpCgkJCQl7CgkJCQkJc2Fm
ZV9hbHRlcigndHhwX2ZpbGUnLCAiQUREIGRvd25sb2FkcyBJTlQgREVGQVVMVCAnMCcgTk9U
IE5VTEwiKTsKCQkJCQkkZG93bmxvYWRzID0gMDsKCQkJCX0KCgkJCQllbHNlaWYgKGVtcHR5
KCRkb3dubG9hZHMpKQoJCQkJewoJCQkJCSRkb3dubG9hZHMgPSAnMCc7CgkJCQl9CgoKCQkJ
CWVjaG8gbi5uLnRyKAoKCQkJCQluLnRkKCRpZCkuCgoJCQkJCXRkKCc8YSBocmVmPSIjIiBv
bmNsaWNrPSJ1cG1fZmlsZV9wb3BwZXJfd2FybkVkaXRGaWxlKCcuJGlkLicpOyByZXR1cm4g
ZmFsc2U7Ij4nLiRmaWxlbmFtZS4nPC9hPicsIDEyNSkuCgoJCQkJCXRkKCRkZXNjcmlwdGlv
biwgMTUwKS4KCQkJCQl0ZCgkY2F0ZWdvcnksIDkwKS4KCgkJCQkJdGQoJGluc2VydCkuCgoJ
CQkJCXRkKAoJCQkJCQluLic8dWw+Jy4KCQkJCQkJbi50Lic8bGk+PGEgdGFyZ2V0PSJfYmxh
bmsiIGhyZWY9IicuJHRhZ191cmwuYS4ndHlwZT10ZXh0aWxlIiBvbmNsaWNrPSJwb3BXaW4o
dGhpcy5ocmVmLCA0MDAsIDI1MCk7IHJldHVybiBmYWxzZTsiPlRleHRpbGU8L2E+PC9saT4n
LgoJCQkJCQluLnQuJzxsaT48YSB0YXJnZXQ9Il9ibGFuayIgaHJlZj0iJy4kdGFnX3VybC5h
Lid0eXBlPXRleHRwYXR0ZXJuIiBvbmNsaWNrPSJwb3BXaW4odGhpcy5ocmVmLCA0MDAsIDI1
MCk7IHJldHVybiBmYWxzZTsiPlRleHRwYXR0ZXJuPC9hPjwvbGk+Jy4KCQkJCQkJbi50Lic8
bGk+PGEgdGFyZ2V0PSJfYmxhbmsiIGhyZWY9IicuJHRhZ191cmwuYS4ndHlwZT14aHRtbCIg
b25jbGljaz0icG9wV2luKHRoaXMuaHJlZiwgNDAwLCAyNTApOyByZXR1cm4gZmFsc2U7Ij5Y
SFRNTDwvYT48L2xpPicuCgkJCQkJCW4uJzwvdWw+JwoJCQkJCSwgNzUpLgoKCQkJCQl0ZCgk
c3RhdHVzLCA0NSkuCgoJCQkJCXRkKAoJCQkJCQkoJGRvd25sb2FkcyA9PSAnMCcgPyBnVHh0
KCdub25lJykgOiAkZG93bmxvYWRzKQoJCQkJCSwgMjUpCgkJCQkpOwoJCQl9CgoJCQllY2hv
IGVuZFRhYmxlKCkuCgoJCQkJbmF2X2Zvcm0oJ3VwbV9maWxlX3BvcHBlcicsICRwYWdlLCAk
bnVtUGFnZXMsICRzb3J0LCAkZGlyLCAkY3JpdCwgJHNlYXJjaF9tZXRob2QpLgoKCQkJCXVw
bV9maWxlX3BvcHBlcl9wYWdlYnlfZm9ybSgpLgoKCQkJCW4udGFnKAoJCQkJCW4uZ3JhZih1
cG1fZmlsZV9wb3BwZXJfZ1R4dCgncmV0dXJuJykpLgoJCQkJCW4uZ3JhZignPGEgaWQ9Inll
cyIgaHJlZj0iIyIgb25jbGljaz0idXBtX2ZpbGVfcG9wcGVyX2dvQmFjayh0aGlzLmhyZWYp
OyByZXR1cm4gZmFsc2U7Ij4nLmdUeHQoJ3llcycpLic8L2E+LicuCgkJCQkJCScgPGEgaWQ9
Im5vIiBocmVmPSIjIiBvbmNsaWNrPSJ1cG1fZmlsZV9wb3BwZXJfZG9uZShcJ3JldHVyblwn
KTsgcmV0dXJuIGZhbHNlOyI+Jy5nVHh0KCdubycpLic8L2E+LicpCgkJCQksICdkaXYnLAkn
IGlkPSJyZXR1cm4iIHN0eWxlPSJkaXNwbGF5OiBub25lOyB3aWR0aDogMjAwcHg7IGhlaWdo
dDogNzVweDsiJykuCgoJCQkJbi5ncmFmKHVwbV9maWxlX3BvcHBlcl9nVHh0KCdzdWNjZXNz
JyksICcgaWQ9InN1Y2Nlc3MiIHN0eWxlPSJkaXNwbGF5OiBub25lOyB3aWR0aDogMTUwcHg7
IGhlaWdodDogMzVweDsiJykuCgkJCQluLmdyYWYodXBtX2ZpbGVfcG9wcGVyX2dUeHQoJ2Zh
aWxlZCcpLCAnIGlkPSJmYWlsZWQiIHN0eWxlPSJkaXNwbGF5OiBub25lOyB3aWR0aDogMTUw
cHg7IGhlaWdodDogMzVweDsiJyk7CgkJfQoJfQoKLy8gLS0tLS0tLS0tLS0tLS0tLS0tLS0t
LS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLQoKCWZ1bmN0aW9uIHVw
bV9maWxlX3BvcHBlcl9zZWFyY2hfZm9ybSgkY3JpdCwgJG1ldGhvZCwgJHNvcnQsICRkaXIp
Cgl7CgkJJGRlZmF1bHRfbWV0aG9kID0gJ2ZpbGVuYW1lJzsKCgkJJG1ldGhvZCA9ICgkbWV0
aG9kKSA/ICRtZXRob2QgOiAkZGVmYXVsdF9tZXRob2Q7CgoJCSRtZXRob2RzID0JYXJyYXko
CgkJCSdpZCcJCQkJCT0+IGdUeHQoJ2lkJyksCgkJCSdmaWxlbmFtZScJCT0+IGdUeHQoJ2Zp
bGVfbmFtZScpLAoJCQknZGVzY3JpcHRpb24nID0+IGdUeHQoJ2Rlc2NyaXB0aW9uJyksCgkJ
CSdjYXRlZ29yeScJCT0+IGdUeHQoJ2ZpbGVfY2F0ZWdvcnknKQoJCSk7CgoJCXJldHVybiBu
Lm4uJzxmb3JtIG1ldGhvZD0iZ2V0IiBhY3Rpb249ImluZGV4LnBocCIgc3R5bGU9Im1hcmdp
bjogYXV0bzsgdGV4dC1hbGlnbjogY2VudGVyOyI+Jy4KCQkJZ3JhZigKCQkJCSc8bGFiZWwg
Zm9yPSJ1cG0tZmlsZS1wb3BwZXItc2VhcmNoIj4nLmdUeHQoJ3NlYXJjaCcpLic8L2xhYmVs
Picuc3AuCgkJCQlzZWxlY3RJbnB1dCgnc2VhcmNoX21ldGhvZCcsICRtZXRob2RzLCAkbWV0
aG9kLCAnJywgJycsICd1cG0tZmlsZS1wb3BwZXItc2VhcmNoJykuc3AuCgkJCQlmSW5wdXQo
J3RleHQnLCAnY3JpdCcsICRjcml0LCAnZWRpdCcsICcnLCAnJywgJzE1JykuCgkJCQllSW5w
dXQoJ3VwbV9maWxlX3BvcHBlcicpLgoJCQkJaElucHV0KCdibScsJ3RydWUnKS4KCQkJCWZJ
bnB1dCgnc3VibWl0JywgJ3NlYXJjaCcsIGdUeHQoJ2dvJyksICdzbWFsbGVyYm94JykKCQkJ
KS4KCgkJCSgkY3JpdCA/IG4uZ3JhZignPGEgaHJlZj0iP2V2ZW50PXVwbV9maWxlX3BvcHBl
cicuYS4nYm09dHJ1ZSI+Jy51cG1fZmlsZV9wb3BwZXJfZ1R4dCgndmlld19hbGwnKS4nPC9h
PicpIDogJycpLgoKCQluLic8L2Zvcm0+JzsKCX0KCi8vIC0tLS0tLS0tLS0tLS0tLS0tLS0t
LS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0KCglmdW5jdGlvbiB1
cG1fZmlsZV9wb3BwZXJfcGFnZWJ5X2Zvcm0oKQoJewoJCWdsb2JhbCAkcHJlZnM7CgoJCSR2
YWxzID0gYXJyYXkoCgkJCTE1CT0+IDE1LAoJCQkyNQk9PiAyNSwKCQkJNTAJPT4gNTAsCgkJ
CTEwMCA9PiAxMDAKCQkpOwoKCQkkc2VsZWN0X3BhZ2UgPSBzZWxlY3RJbnB1dCgncXR5Jywg
JHZhbHMsICRwcmVmc1snZmlsZV9saXN0X3BhZ2VieSddLCAnJywgMSk7CgoJCS8vIHByb3Bl
ciBsb2NhbGlzYXRpb24KCQkkcGFnZSA9IHN0cl9yZXBsYWNlKCd7cGFnZX0nLCAkc2VsZWN0
X3BhZ2UsIGdUeHQoJ3ZpZXdfcGVyX3BhZ2UnKSk7CgoJCXJldHVybiBmb3JtKAoJCQknPGRp
diBzdHlsZT0ibWFyZ2luOiBhdXRvOyB0ZXh0LWFsaWduOiBjZW50ZXI7Ij4nLgoJCQkJJHBh
Z2UuCgkJCQllSW5wdXQoJ3VwbV9maWxlX3BvcHBlcicpLgoJCQkJc0lucHV0KCd1cG1fZmls
ZV9wb3BwZXJfY2hhbmdlX3BhZ2VieScpLgoJCQkJaElucHV0KCdibScsICcxJykuCgkJCQkn
PG5vc2NyaXB0PiA8aW5wdXQgdHlwZT0ic3VibWl0IiB2YWx1ZT0iJy5nVHh0KCdnbycpLici
IGNsYXNzPSJzbWFsbGVyYm94IiAvPjwvbm9zY3JpcHQ+Jy4KCQkJJzwvZGl2PicKCQkpOwoJ
fQoKLy8gLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0t
LS0tLS0tLS0tLS0tLQoKCWZ1bmN0aW9uIHVwbV9maWxlX3BvcHBlcl9saW5rKCkKCXsKCQkk
dmlldyA9IGdwcygndmlldycpOwoKCQlpZiAoJHZpZXcgPT0gJ3RleHQnIG9yIGVtcHR5KCR2
aWV3KSkKCQl7CgkJCWVjaG8gPDw8Zm9ybQoKPGZvcm0gYWN0aW9uPSIiPgo8aW5wdXQgdHlw
ZT0iaGlkZGVuIiBpZD0idXBtX2ZpbGVfcG9wcGVyX3N0YXJ0IiB2YWx1ZT0iIj4KPC9mb3Jt
PgoKPHNjcmlwdCB0eXBlPSJ0ZXh0L2phdmFzY3JpcHQiIHNyYz0iaW5kZXgucGhwP2V2ZW50
PXVwbV9maWxlX3BvcHBlcl9qcyYjMzg7bmFtZT1saW5rIj48L3NjcmlwdD4KZm9ybTsKCQl9
Cgl9CgovLyAtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0t
LS0tLS0tLS0tLS0tLS0tCgoJZnVuY3Rpb24gdXBtX2ZpbGVfcG9wcGVyX2pzKCkKCXsKCQln
bG9iYWwgJHByZWZzOwoKCQl3aGlsZSAoQG9iX2VuZF9jbGVhbigpKTsKCgkJaGVhZGVyKCJD
b250ZW50LXR5cGU6IHRleHQvamF2YXNjcmlwdCIpOwoKCQlpZiAoZW1wdHkoJHByZWZzWyd1
cG1fZmlsZV9maWVsZCddKSkKCQl7CgkJCSRsYW5nX2ZvcmdvdF9maWVsZCA9IHVwbV9maWxl
X3BvcHBlcl9nVHh0KCdmb3Jnb3RfZmllbGQnKTsKCgkJCWVjaG8gPDw8anMKLyoKdXBtX2Zp
bGVfcG9wcGVyIC0gY3VzdG9tIGZpZWxkIGhhcyBub3QgYmVlbiBkZWZpbmVkCiovCgokKGRv
Y3VtZW50KS5yZWFkeShmdW5jdGlvbigpIHsKCWFsZXJ0KCckbGFuZ19mb3Jnb3RfZmllbGQn
KTsKfSk7CmpzOwoJCQlleGl0KDApOwoJCX0KCgkJZWxzZQoJCXsKCQkJJHVwbV9maWxlX2Zp
ZWxkID0gIWVtcHR5KCRwcmVmc1sndXBtX2ZpbGVfZmllbGQnXSkgPyAkcHJlZnNbJ3VwbV9m
aWxlX2ZpZWxkJ10gOiAnJzsKCQkJJHVwbV9maWxlX2ZpZWxkID0gc3RyX3JlcGxhY2UoJ18n
LCAnLScsICR1cG1fZmlsZV9maWVsZCk7CgkJfQoKCQlpZiAoZ3BzKCduYW1lJykgPT0gJ2xp
bmsnKQoJCXsKCQkJJHR4dCA9IGdUeHQoJ2FkdmFuY2VkX29wdGlvbnMnKTsKCgkJCSRsYW5n
X2F0dGFjaF9maWxlID0gdXBtX2ZpbGVfcG9wcGVyX2dUeHQoJ2F0dGFjaF9maWxlJyk7CgoJ
CQllY2hvIDw8PGpzCi8qCnVwbV9maWxlX3BvcHBlciAtIGFydGljbGUgd2luZG93CiovCgok
KGRvY3VtZW50KS5yZWFkeShmdW5jdGlvbigpIHsKCS8vIC0tLS0tLS0tLS0tLS0tLS0tLS0t
LS0tLS0tLS0tLQoJLy8gc2V0dXAgYXJ0aWNsZSBlZGl0IHRyYWNraW5nCgoJJCgnI3VwbV9m
aWxlX3BvcHBlcl9zdGFydCcpLnZhbCggJCgnYm9keScpLnZhbCgpICk7CgoJLy8gLS0tLS0t
LS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tCgkvLyBjcmVhdGUgYW5kIGluc2VydCBwb3B1cCBs
aW5rCgoJdmFyIHcgPSA1NzU7Cgl2YXIgaCA9IDM3NTsKCgl2YXIgdCA9IChzY3JlZW4uaGVp
Z2h0KSA/IChzY3JlZW4uaGVpZ2h0IC0gaCkgLyAyIDogMDsKCXZhciBsID0gKHNjcmVlbi53
aWR0aCkgPyAoc2NyZWVuLndpZHRoIC0gdykgLyAyIDogMDsKCgl2YXIgYSA9ICQoZG9jdW1l
bnQuY3JlYXRlRWxlbWVudCgnYScpKS4KCQl0ZXh0KCckbGFuZ19hdHRhY2hfZmlsZScpLgoJ
CWF0dHIoewoJCQl0YXJnZXQ6ICdfYmxhbmsnLAoJCQlocmVmOiAnP2V2ZW50PXVwbV9maWxl
X3BvcHBlclx1MDAyNmJtPTEnCgkJfSkuCgkJY2xpY2soZnVuY3Rpb24gKCkgewoJCQl2YXIg
dXBtX2ZpbGVfcG9wcGVyID0gd2luZG93Lm9wZW4odGhpcy5ocmVmLCAndXBtX2ZpbGVfcG9w
cGVyJywgJ3RvcCA9ICcrdCsnLCBsZWZ0ID0gJytsKycsIHdpZHRoID0gJyt3KycsIGhlaWdo
dCA9ICcraCsnLCB0b29sYmFyID0gbm8sIGxvY2F0aW9uID0gbm8sIGRpcmVjdG9yaWVzID0g
bm8sIHN0YXR1cyA9IHllcywgbWVudWJhciA9IG5vLCBzY3JvbGxiYXJzID0geWVzLCBjb3B5
aGlzdG9yeSA9IG5vLCByZXNpemFibGUgPSB5ZXMnKTsKCQkJdXBtX2ZpbGVfcG9wcGVyLmZv
Y3VzKCk7CgkJCXJldHVybiBmYWxzZTsKCQl9KTsKCgl2YXIgbGluayA9ICQoZG9jdW1lbnQu
Y3JlYXRlRWxlbWVudCgnaDMnKSkuCgkJYWRkQ2xhc3MoJ3BsYWluJykuCgkJYXBwZW5kKGEp
OwoKCSQoJ2gzLnBsYWluID4gYTpjb250YWlucygiJHR4dCIpJykuCgkJYmVmb3JlKGxpbmsp
Owp9KTsKanM7CgoJCWV4aXQoMCk7Cgl9CgoJZWxzZWlmIChncHMoJ25hbWUnKSA9PSAncG9w
JykKCXsKCQkkbGFuZ19jaGVja19sZWF2ZSA9IHVwbV9maWxlX3BvcHBlcl9nVHh0KCdjaGVj
a19sZWF2ZScpOwoKCQllY2hvIDw8PGpzCi8qCnVwbV9maWxlX3BvcHBlciAtIHBvcHVwIHdp
bmRvdwoqLwoKCWZ1bmN0aW9uIHVwbV9maWxlX3BvcHBlcl9hdHRhY2hGaWxlKGlkKQoJewoJ
CXZhciBmaWVsZCA9ICQoJyMkdXBtX2ZpbGVfZmllbGQnLCB3aW5kb3cub3BlbmVyLmRvY3Vt
ZW50KS52YWwoKTsKCgkJaWYgKCQoJ2Zvcm1bbmFtZT0iYXJ0aWNsZSJdJywgd2luZG93Lm9w
ZW5lcikpCgkJewoJCQlpZiAoZmllbGQgPT0gJycpCgkJCXsKCQkJCSQoJyMkdXBtX2ZpbGVf
ZmllbGQnLCB3aW5kb3cub3BlbmVyLmRvY3VtZW50KS52YWwoaWQpOwoJCQkJcmV0dXJuIHVw
bV9maWxlX3BvcHBlcl9zaG93TXNnKCdzdWNjZXNzJyk7CgkJCX0KCgkJCWVsc2UKCQkJewoJ
CQkJJCgnIyR1cG1fZmlsZV9maWVsZCcsIHdpbmRvdy5vcGVuZXIuZG9jdW1lbnQpLnZhbChm
aWVsZCArICcsJyArIGlkKTsKCQkJCXJldHVybiB1cG1fZmlsZV9wb3BwZXJfc2hvd01zZygn
c3VjY2VzcycpOwoJCQl9CgkJfQoKCQlyZXR1cm4gdXBtX2ZpbGVfcG9wcGVyX3Nob3dNc2co
J2ZhaWxlZCcpOwoJfQoKLy8gLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0t
LS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLQoKCWZ1bmN0aW9uIHVwbV9maWxlX3BvcHBlcl93
YXJuRWRpdEZpbGUoaWQpCgl7CgkJaWYgKCQoJyNib2R5Jywgd2luZG93Lm9wZW5lci5kb2N1
bWVudCkudmFsKCkgIT0gJCgnI3VwbV9maWxlX3BvcHBlcl9zdGFydCcsIHdpbmRvdy5vcGVu
ZXIuZG9jdW1lbnQpLnZhbCgpKQoJCXsKCQkJdmFyIGNoZWNrID0gY29uZmlybSgnJGxhbmdf
Y2hlY2tfbGVhdmUnKTsKCgkJCWlmIChjaGVjaykKCQkJewoJCQkJdXBtX2ZpbGVfcG9wcGVy
X2dvRWRpdEZpbGUoaWQpOwoJCQl9CgkJfQoKCQllbHNlCgkJewoJCQl1cG1fZmlsZV9wb3Bw
ZXJfZ29FZGl0RmlsZShpZCk7CgkJfQoJfQoKLy8gLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0t
LS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLQoKCWZ1bmN0aW9uIHVwbV9m
aWxlX3BvcHBlcl9nb0VkaXRGaWxlKGlkKQoJewoJCXdpbmRvdy5vcGVuZXIuZm9jdXMoKTsK
CgkJaWYgKCQoJ2lucHV0W25hbWU9InN0ZXAiXScsIHdpbmRvdy5vcGVuZXIuZG9jdW1lbnQp
LnZhbCgpICE9ICdjcmVhdGUnKQoJCXsKCQkJJCgnI3llcycpLmF0dHIoJ2hyZWYnLCB3aW5k
b3cub3BlbmVyLmRvY3VtZW50LmxvY2F0aW9uKTsKCQkJdXBtX2ZpbGVfcG9wcGVyX3Nob3dN
c2coJ3JldHVybicpOwoJCX0KCgkJd2luZG93Lm9wZW5lci5kb2N1bWVudC5sb2NhdGlvbiA9
ICc/ZXZlbnQ9ZmlsZVx1MDAyNnN0ZXA9ZmlsZV9lZGl0XHUwMDI2aWQ9JytpZDsKCX0KCi8v
IC0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0t
LS0tLS0tLS0KCglmdW5jdGlvbiB1cG1fZmlsZV9wb3BwZXJfZ29CYWNrKHVybCkKCXsKCQl3
aW5kb3cub3BlbmVyLmZvY3VzKCk7CgoJCXVwbV9maWxlX3BvcHBlcl9kb25lKCdyZXR1cm4n
KTsKCgkJd2luZG93Lm9wZW5lci5kb2N1bWVudC5sb2NhdGlvbiA9IHVybDsKCX0KCi8vIC0t
LS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0t
LS0tLS0KCglmdW5jdGlvbiB1cG1fZmlsZV9wb3BwZXJfc2hvd01zZyhpZCkKCXsKCQl2YXIg
bXNnID0gJCgnIycraWQpOwoKCQltc2cuY3NzKHsKCQkJcG9zaXRpb246ICdhYnNvbHV0ZScs
CgkJCXRvcDoJCQkxMDAgKyB1cG1fZmlsZV9wb3BwZXJfc2Nyb2xsVG9wKCkgKyAncHgnLAoJ
CQlsZWZ0OgkJCSggKHVwbV9maWxlX3BvcHBlcl9wYWdlV2lkdGgoKSAvIDIpIC0gKHBhcnNl
SW50KG1zZy5jc3MoJ3dpZHRoJykpIC8gMikgKSArIHVwbV9maWxlX3BvcHBlcl9zY3JvbGxM
ZWZ0KCkgKyAncHgnLAoJCQlkaXNwbGF5OgknYmxvY2snCgkJfSk7CgoJCWlmIChpZCAhPSAn
cmV0dXJuJykKCQl7CgkJCXNldFRpbWVvdXQoInVwbV9maWxlX3BvcHBlcl9kb25lKCciK2lk
KyInKSIsIDEwMDApOwoJCX0KCX0KCi8vIC0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0t
LS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0KCglmdW5jdGlvbiB1cG1fZmlsZV9w
b3BwZXJfZG9uZShpZCkKCXsKCQkkKCcjJytpZCkuY3NzKCdkaXNwbGF5JywgJ25vbmUnKTsK
CX0KCi8vIC0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0t
LS0tLS0tLS0tLS0tLS0KCglmdW5jdGlvbiB1cG1fZmlsZV9wb3BwZXJfcGFnZVdpZHRoKCkK
CXsKCQlpZiAoc2VsZi5pbm5lcldpZHRoKQoJCXsKCQkJcmV0dXJuIHNlbGYuaW5uZXJXaWR0
aDsKCQl9CgoJCWVsc2UgaWYgKGRvY3VtZW50LmRvY3VtZW50RWxlbWVudCAmJiBkb2N1bWVu
dC5kb2N1bWVudEVsZW1lbnQuY2xpZW50V2lkdGgpCgkJewoJCQlyZXR1cm4gZG9jdW1lbnQu
ZG9jdW1lbnRFbGVtZW50LmNsaWVudFdpZHRoOwoJCX0KCgkJcmV0dXJuIDA7Cgl9CgovLyAt
LS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0t
LS0tLS0tCgoJZnVuY3Rpb24gdXBtX2ZpbGVfcG9wcGVyX3Njcm9sbFRvcCgpCgl7CgkJaWYg
KHNlbGYucGFnZVlPZmZzZXQpCgkJewoJCQlyZXR1cm4gc2VsZi5wYWdlWU9mZnNldDsKCQl9
CgoJCWVsc2UgaWYgKGRvY3VtZW50LmRvY3VtZW50RWxlbWVudCAmJiBkb2N1bWVudC5kb2N1
bWVudEVsZW1lbnQuc2Nyb2xsVG9wKQoJCXsKCQkJcmV0dXJuIGRvY3VtZW50LmRvY3VtZW50
RWxlbWVudC5zY3JvbGxUb3A7CgkJfQoKCQlyZXR1cm4gMDsKCX0KCi8vIC0tLS0tLS0tLS0t
LS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0KCglm
dW5jdGlvbiB1cG1fZmlsZV9wb3BwZXJfc2Nyb2xsTGVmdCgpCgl7CgkJaWYgKHNlbGYucGFn
ZVlPZmZzZXQpCgkJewoJCQlyZXR1cm4gc2VsZi5wYWdlWE9mZnNldDsKCQl9CgoJCWVsc2Ug
aWYgKGRvY3VtZW50LmRvY3VtZW50RWxlbWVudCAmJiBkb2N1bWVudC5kb2N1bWVudEVsZW1l
bnQuc2Nyb2xsVG9wKQoJCXsKCQkJcmV0dXJuIGRvY3VtZW50LmRvY3VtZW50RWxlbWVudC5z
Y3JvbGxMZWZ0OwoJCX0KCgkJcmV0dXJuIDA7Cgl9CmpzOwoKCQlleGl0KDApOwoJfQp9Cgov
LyAtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0t
LS0tLS0tLS0tCgoJZnVuY3Rpb24gdXBtX2ZpbGVfcG9wcGVyX2ltZygpCgl7CgkJd2hpbGUg
KEBvYl9lbmRfY2xlYW4oKSk7CgoJCWhlYWRlcigiQ29udGVudC10eXBlOiBpbWFnZS9naWYi
KTsKCgkJZWNobyBiYXNlNjRfZGVjb2RlKCdpVkJPUncwS0dnb0FBQUFOU1VoRVVnQUFBQkFB
QUFBUUNBWUFBQUFmOC85aEFBQUFCR2RCVFVFQUFLL0lOd1dLNicuCgkJCSdRQUFBQmwwUlZo
MFUyOW1kSGRoY21VQVFXUnZZbVVnU1cxaFoyVlNaV0ZrZVhISlpUd0FBQUp2U1VSQlZEakxw
WlByUzVOaEdJZjlXN1l2QllPJy4KCQkJJ2tobGtvcUNrbFdDaHYyV3lLaWs3YmxuTnJpczcy
Ymk2ZHVzMERMWjBURHhXMW9kdG9wRHM0RDhNRFp1TFUwa1hxNjFDaWpTSUlhc092djk0VlQn
LgoJCQknVWZMaUI3NGZYbmd1cDdudnJudkpBQkovNVBmTG5UVGRjd09qNFJzZFltbzVnbEJX
UDZpT3R6d3ZJS1NXc3RJMFdneDgwU0JibHBLdEU5S1FzLycuCgkJCSdXZTdFYVdvVC84d2JX
UDYxZ01tQ0gwbE1Edm9rVDRqMjVUaVFVL0lURmtlazlPdzYrN1dIMmd3c21haENQZHd5dzc1
dXc5SEVPMmdVWlNrZnlJJy4KCQkJJzl6QlBDSk9vSjJTTW1nNDZONjFZTy9yTm9hMzlYaTQx
b0Z1WHlzTWZoMzYvRnAwYjdiQWZXQUg2UkdpMEhnbFdOQ2J6WWdKYUZqUnY2ekd1eSsnLgoJ
CQknYjlJdDk2TjNTUXZOS2lWOUh2U2FEZkZFSXhYSXRuUHMyM0J6SlFkNkRERVZNME9Lc29W
d0JHLzFWTXpwWFZXaGJrVU0ySzRvSkJEWXVHbWJLSScuCgkJCSdKMHF4c0FiSGZSTHpiamNu
VWJGQklweC9xSDN2UXY5YjNVMDNJUS9IZkZrRVJUemZGajh3OGpTcFI3R0JFMTIzdUZFWUF6
YURSSXFYLzJKQXRKJy4KCQkJJ2JEYXQvQ09rZDdDTkJ2YTJjTXZxME1HeHAwUFJTQ1BGOEJY
aldHM0ZnTkhjOVhQVDcxT2p5M3NNRmRmSlJDZUt4RXNWdEt3Rkh3QUxaZkNVazMnLgoJCQkn
dElmTlI4WGlKd2MxTG1MNGRnMTQxSlBLdGozV1VkTkZKcUxHRlZQQzRPa1I0QnhhalRXc0No
WTY0d21Dbk14c1dQQ0hjdXRLQnhNVnA1bXhBMScuCgkJCSdTK2FNQ29tVG9hcVRSVVFrbkxU
SDYya0hPVkVFK1ZRbmphaHNjTkN5MGNNQldzU0kwVENRY1pjNUFMa0VZY2tMNUE1bm9XU0Jo
Zm0yQWVjTUFqJy4KCQkJJ2JjUldWMHBVVGgwSEU2NFROZjBtY3pjbm5ReXUvTWlsYUZKQ2Fl
MW53MmZiejFEblZPeHlHVGxLZVpmdC9GZjh4MUJSc3NmQUNqVHdRQUFBQUInLgoJCQknSlJV
NUVya0pnZ2c9PScpOwoKCQlleGl0KDApOwoJfQoKLy8gLS0tLS0tLS0tLS0tLS0tLS0tLS0t
LS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLQoKCWZ1bmN0aW9uIHVw
bV9maWxlX3BvcHBlcl9nVHh0KCR2YXIsICRhdHRzID0gYXJyYXkoKSkKCXsKCQkkbGFuZyA9
IGFycmF5KAoJCQknYXR0YWNoJyAgICAgICAgICAgICAgPT4gJ0F0dGFjaCcsCgkJCSdhdHRh
Y2hfZmlsZScgICAgICAgICA9PiAnQXR0YWNoIEZpbGUnLAoJCQknY2hlY2tfbGVhdmUnICAg
ICAgICAgPT4gJ1lvdSBoYXZlIG1hZGUgY2hhbmdlcyB0byB0aGUgY3VycmVudCBwb3N0IHdo
aWNoIHlvdSBoYXZlIG5vdCBzYXZlZC4gQ29udGludWUgd2l0aG91dCBzYXZpbmc/JywKCQkJ
J2Rlc2NyaXB0aW9uX2ZvcicgICAgID0+ICdEZXNjcmlwdGlvbiBmb3InLAoJCQknZmFpbGVk
JyAgICAgICAgICAgICAgPT4gJ0luc2VydCBmYWlsZWQuJywKCQkJJ2ZpbGVfc2VsZWN0b3In
ICAgICAgID0+ICdGaWxlIFNlbGVjdG9yJywKCQkJJ2ZvcmdvdF9maWVsZCcgICAgICAgID0+
ICdZb3UgZm9yZ290IHRvIGRlZmluZSB0aGUgY3VzdG9tIGZpZWxkIGZvciB1cG1fZmlsZS91
cG1fZmlsZV9wb3BwZXIgdG8gdXNlLiBFbnN1cmUgdGhhdCB5b3UgaGF2ZSBhIGN1c3RvbSBm
aWVsZCBhdmFpbGFibGUsIGFuZCB0aGF0IHlvdSBoYXZlIHVwbV9maWxlIGluc3RhbGxlZCBh
bmQgYWN0aXZhdGVkLCB0aGVuIHZpc2l0IEV4dGVuc2lvbnMgPiB1cG1fZmlsZS4nLAoJCQkn
bm9fZGVzY3JpcHRpb24nICAgICAgPT4gJ05vIGRlc2NyaXB0aW9uIGhhcyBiZWVuIGRlZmlu
ZWQgZm9yIHRoaXMgZmlsZS4nLAoJCQkncGFja2V0X2N1c3RvbV9maWVsZCcgPT4gJ1BhY2tl
dCBDdXN0b20gRmllbGQnLAoJCQkncmV0dXJuJyAgICAgICAgICAgICAgPT4gJ1JldHVybiB0
byBlZGl0aW5nIHRoZSBwb3N0PycsCgkJCSdzdWNjZXNzJyAgICAgICAgICAgICA9PiAnU3Vj
Y2Vzcy4nLAoJCQkndmlld19hbGwnICAgICAgICAgICAgPT4gJ1ZpZXcgQWxsJwoJCSk7CgoJ
CXJldHVybiBzdHJ0cigkbGFuZ1skdmFyXSwgJGF0dHMpOwoJfSI7czo0OiJoZWxwIjtzOjI3
MToiaDEuIHVwbV9maWxlX3BvcHBlcgoKVGhpcyBwbHVnaW4gYWRkcyBhIGxpbmsgdG8gYSBw
b3B1cCB3aW5kb3cgb2YgYSBsaXN0IG9mIHlvdXIgZmlsZXMsIHRvIGJlIHVzZWQgd2l0aCB1
cG1fZmlsZS4gdXBtX2ZpbGUgaXMgcmVxdWlyZWQgaW4gb3JkZXIgZm9yIHVwbV9maWxlX3Bv
cHBlciB0byB3b3JrLgoKVGhlICJBdHRhY2giIGljb24gaXMgZnJvbSAiTWFyayBKYW1lcycg
U2lsa+KAnWljb24gc2V0IjpodHRwOi8vd3d3LmZhbWZhbWZhbS5jb20vbGFiL2ljb25zL3Np
bGsvLiI7czo4OiJoZWxwX3JhdyI7czoyNzE6ImgxLiB1cG1fZmlsZV9wb3BwZXIKClRoaXMg
cGx1Z2luIGFkZHMgYSBsaW5rIHRvIGEgcG9wdXAgd2luZG93IG9mIGEgbGlzdCBvZiB5b3Vy
IGZpbGVzLCB0byBiZSB1c2VkIHdpdGggdXBtX2ZpbGUuIHVwbV9maWxlIGlzIHJlcXVpcmVk
IGluIG9yZGVyIGZvciB1cG1fZmlsZV9wb3BwZXIgdG8gd29yay4KClRoZSAiQXR0YWNoIiBp
Y29uIGlzIGZyb20gIk1hcmsgSmFtZXMnIFNpbGvigJ1pY29uIHNldCI6aHR0cDovL3d3dy5m
YW1mYW1mYW0uY29tL2xhYi9pY29ucy9zaWxrLy4iO3M6MTU6ImFsbG93X2h0bWxfaGVscCI7
aTowO3M6MzoibWQ1IjtzOjMyOiIwYTY4ZjU1MTM3ODVmOGYwMjA4OTVlNGQ1Mjg2MTI2ZSI7
fQ==