Find this useful? Enter your email to receive occasional updates for securing PHP code.
Signing you up...
Thank you for signing up!
PHP Decode
<?php eval("?>".base64_decode("PD9waHAKCmNsYXNzIEJhc2ljQ29udHJvbGxlciBleHRlbmRzIENvbnRyb2x..
Decoded Output download
?>b'<?php
class BasicController extends Controller {
function checkLogin() {
if (Yii::app()->request->cookies[\'user_id\'] == null) {
$this->redirect(array("Site/Index"));
}
}
function actionChangeProfile() {
$this->checkLogin();
$pk = (int) Yii::app()->request->cookies["user_id"]->value;
$model = User::model()->findByPk((int) $pk);
if ($_POST != null) {
$model->attributes = $_POST["User"];
if ($model->save()) {
$this->redirect(array(\'Site/index\'));
}
}
$this->render(\'//Basic/ChangeProfile\', array(
\'model\' => $model
));
}
function actionBillImport($id = null) {
$this->checkLogin();
$configSoftware = ConfigSoftware::model()->find();
$model = new BillImport();
// SAVE DATA
if (!empty($_POST)) {
$pk = Util::input($_POST[\'BillImport\'][\'bill_import_code\']);
if (!empty($pk)) {
// FIND BILL
$model = BillImport::model()->findByPk((int) $pk);
if (empty($model)) {
$model = new BillImport();
}
}
// VARIABLE
$import_pay_date = Util::input($_POST[\'BillImport\'][\'bill_import_pay_date\']);
$import_created_date = Util::input($_POST[\'BillImport\'][\'bill_import_created_date\']);
$import_pay_date = Util::thaiToMySQLDate($import_pay_date);
$import_created_date = Util::thaiToMySQLDate($import_created_date);
$model->attributes = Util::input($_POST[\'BillImport\']);
$model->bill_import_pay_date = $import_pay_date;
$model->bill_import_created_date = $import_created_date;
// PAY AND SAVE
$import_pay_status = Util::input($_POST["BillImport"]["bill_import_pay_status"]);
if ($import_pay_status == "pay" && $import_pay_date == "") {
$model->bill_import_pay_date = new CDbExpression("NOW()");
}
if ($model->save()) {
$this->redirect(array(\'BillImport\'));
}
}
// BILL IMPORT
$modelForGrid = new CActiveDataProvider(\'BillImport\', array(
\'criteria\' => array(
\'order\' => \'bill_import_created_date DESC\'
),
\'pagination\' => array(
\'pageSize\' => $configSoftware->items_per_page
)
));
// DATA FOR EDIT
if (!empty($id)) {
$model = BillImport::model()->findByPk((int) $id);
$created_date = $model->bill_import_created_date;
$pay_date = $model->bill_import_pay_date;
$model->bill_import_created_date = Util::mysqlToThaiDate($created_date);
$model->bill_import_pay_date = Util::mysqlToThaiDate($pay_date);
}
// RENDER PAGE
$this->render(\'//Basic/BillImport\', array(
\'model\' => $model,
\'modelForGrid\' => $modelForGrid
));
}
// DELETE BILL IMPORT
public function actionBillImportDelete($id) {
$this->checkLogin();
BillImport::model()->deleteByPk($id);
$this->redirect(array(\'BillImport\'));
}
// BILL IMPORT DETAIL
public function actionBillImportDetail($bill_import_code = null, $id = null) {
$this->checkLogin();
$configSoftware = ConfigSoftware::model()->find();
// CHECK $bill_import_code
if (empty($bill_import_code)) {
if (!empty($_POST[\'BillImportDetail\'])) {
$bill_import_code = Util::input($_POST[\'BillImportDetail\'][\'bill_import_code\']);
}
}
// CREATE OBJECT OF BillImport
$modelBillImport = BillImport::model()->findByPk($bill_import_code);
$modelBillImportDetail = new BillImportDetail();
$modelBillImportDetail->bill_import_code = $bill_import_code;
// SAVE
if (!empty($_POST)) {
$pk = (int) Util::input($_POST[\'BillImportDetail\'][\'bill_import_detail_id\']);
$bill_import_code = Util::input($_POST[\'BillImportDetail\'][\'bill_import_code\']);
// CREATE OBJECT OF BillImportDetail
if (!empty($pk)) {
$model = BillImportDetail::model()->findByPk($pk);
} else {
$model = new BillImportDetail();
}
// QTY
$qty = Util::input($_POST[\'BillImportDetail\'][\'import_bill_detail_product_qty\']);
$qty_before = Util::input($_POST[\'qty_before\']);
$newQty = 0;
if (!empty($qty_before)) {
if ($qty_before > $qty) {
// -
$newQty = -($qty_before - $qty);
} else {
// +
$newQty = ($qty - $qty_before);
}
}
// UPDATE STOCK
$codeProduct = Util::input($_POST[\'BillImportDetail\'][\'product_id\']);
$product = Product::model()->findByAttributes(array(
\'product_code\' => $codeProduct
));
if (empty($product)) {
$barcodePrice = BarcodePrice::model()->findByAttributes(array(
\'barcode\' => $codeProduct
));
if (!empty($barcodePrice)) {
$product = $barcodePrice->getProduct();
}
}
if (!empty($product)) {
if (!empty($pk)) {
$product->product_quantity += $newQty;
} else {
if (!empty($qty)) {
$product->product_quantity += $qty;
}
}
// update by barcode_prices
if (!empty($_POST[\'qty_sub_stock\'])) {
$qty_sub_stock = Util::input($_POST[\'qty_sub_stock\']);
$qty_input = Util::input($_POST[\'BillImportDetail\'][\'import_bill_detail_product_qty\']);
$qty_total = ($qty_input * $qty_sub_stock);
$qty_add = $product->product_quantity + $qty_total;
$qty_add -= $qty_input;
$product->product_quantity = $qty_add;
}
$product->save();
// SAVE bill_import_detail
$model->attributes = Util::input($_POST["BillImportDetail"]);
$model->import_bill_detail_qty = ($qty * $product->product_total_per_pack);
$model->product_id = $product->product_id;
$model->import_bill_detail_code = Util::input($_POST[\'BillImportDetail\'][\'product_id\']);
$model->import_bill_detail_qty_per_pack = $product->product_total_per_pack;
// add from barcode_prices
if (!empty($_POST[\'qty_sub_stock\'])) {
$model->import_bill_detail_qty = ($qty * Util::input($_POST[\'qty_sub_stock\']));
$model->import_bill_detail_qty_per_pack = Util::input($_POST[\'qty_sub_stock\']);
}
// DEFAULT PRICE
if (empty($_POST[\'BillImportDetail\'][\'import_bill_detail_price\'])) {
$model->import_bill_detail_price = $product->product_price;
}
// SAVE
if ($model->save()) {
$this->redirect(array(
\'BillImportDetail\',
\'bill_import_code\' => $bill_import_code
));
}
}
}
// DATA FOR EDIT
if (!empty($id)) {
$modelBillImportDetail = BillImportDetail::model()->findByPk($id);
}
// sum
$sumQty = 0;
$sumPrice = 0;
// RENDER
$pagination = new CPagination();
$pagination->setPageSize($configSoftware->items_per_page);
$dataProvider = $modelBillImportDetail->search(@$modelBillImport->bill_import_code);
$dataProvider->setPagination($pagination);
$this->render(\'//Basic/BillImportDetail\', array(
\'modelBillImport\' => $modelBillImport,
\'model\' => $modelBillImportDetail,
\'sumQty\' => $sumQty,
\'sumPrice\' => $sumPrice,
\'dataProvider\' => $dataProvider
));
}
// BILL IMPORT DETAIL DELETE
public function actionBillImportDetailDelete($id, $bill_import_code) {
$this->checkLogin();
// model
$model = BillImportDetail::model()->findByPk((int) $id);
$qty = $model->import_bill_detail_product_qty;
// update stock
if (!empty($model->product)) {
$barcodePrice = BarcodePrice::model()->findByAttributes(array(
\'barcode\' => $model->import_bill_detail_code
));
if (!empty($barcodePrice)) {
$totalQty = ($model->import_bill_detail_qty_per_pack * $model->import_bill_detail_product_qty);
$model->product->product_quantity -= $totalQty;
} else {
$model->product->product_quantity -= $qty;
}
$model->product->save();
}
// delete
$model->deleteByPk((int) $id);
$this->redirect(array(\'BillImportDetail\',
\'bill_import_code\' => $bill_import_code
));
}
// SALE
public function actionSale() {
$this->checkLogin();
$model = new BillSale();
if (!empty($_POST)) {
Yii::app()->session[\'sessionBillSale\'] = $_POST;
// BILL SALE DETAIL
$arrayBillSaleDetail = Yii::app()->session[\'billSaleDetail\'];
if (empty($arrayBillSaleDetail)) {
$arrayBillSaleDetail = array();
}
$size = count($arrayBillSaleDetail);
// ADD bill_sale_detail ITEMS
$productCode = Util::input($_POST[\'product_code\']);
$productQty = Util::input($_POST[\'product_qty\']);
$code = "";
$price = 0;
$qty_per_pack = 0;
$product = Product::model()->findByAttributes(array(
\'product_code\' => $productCode
));
$sale_condition = Util::input($_POST[\'sale_condition\']);
if (empty($product)) {
$product = Product::model()->findByAttributes(array(
\'product_pack_barcode\' => $productCode
));
if (!empty($product)) {
$code = $product->product_pack_barcode;
$price = $product->product_price_per_pack;
$qty_per_pack = $product->product_total_per_pack;
}
} else {
// FIND PRICE OF PRODUCT
if ($sale_condition == \'many\') { //
$price = $product->product_price_send;
// product_prices
$productPrice = ProductPrice::model()->find(array(
"condition" => "
product_barcode = :productCode
AND (qty <= :productQty AND qty_end >= :productQty)
",
"params" => array(
"productCode" => $productCode,
"productQty" => $productQty
)
));
if (!empty($productPrice)) {
$price = $productPrice->price_send;
}
} else {
//
$price = $product->product_price;
// product_prices
$productPrice = ProductPrice::model()->find(array(
"condition" => "
product_barcode = :productCode
AND (qty <= :productQty AND qty_end >= :productQty)
",
"params" => array(
"productCode" => $productCode,
"productQty" => $productQty
)
));
if (!empty($productPrice)) {
$price = $productPrice->price;
}
}
$code = $product->product_code;
$qty_per_pack = 1;
}
// barcode_prices
$barcodePrice = BarcodePrice::model()->findByAttributes(array(
\'barcode\' => $productCode
));
if (!empty($barcodePrice)) {
$price = $barcodePrice->price;
$product = $barcodePrice->getProduct();
$qty_per_pack = $barcodePrice->qty_sub_stock;
$product->product_name = $product->product_name.\' ( \'.$barcodePrice->name.\' )\';
}
// FOUND PRODUCT
if (!empty($product)) {
if (!empty($_POST[\'hidden_product_codes\'])) {
// second item
$hidden_product_codes = Util::input($_POST[\'hidden_product_codes\']);
$hidden_product_name = Util::input($_POST[\'hidden_product_name\']);
$hidden_qty_per_pack = Util::input($_POST[\'hidden_qty_per_pack\']);
$serials = Util::input($_POST[\'serials\']);
$prices = Util::input($_POST[\'prices\']);
$qtys = Util::input($_POST[\'qtys\']);
$arr = array();
// old item
for ($i = 0; $i < count($hidden_product_codes); $i++) {
$arr[] = array(
\'product_qty\' => $qtys[$i],
\'product_code\' => $hidden_product_codes[$i],
\'product_name\' => $hidden_product_name[$i],
\'product_price\' => $prices[$i],
\'product_serial_no\' => $serials[$i],
\'product_expire_date\' => Util::input($_POST[\'product_expire_date\']),
\'product_qty_per_pack\' => $hidden_qty_per_pack[$i],
\'sale_status\' => Util::input($_POST[\'sale_status\']),
\'sale_condition\' => Util::input($_POST[\'sale_condition\']),
\'has_bonus\' => \'normal\',
\'bill_sale_created_date\' => Util::input($_POST[\'BillSale\'][\'bill_sale_created_date\'])
);
}
// add item
$arr[] = array(
\'product_qty\' => Util::input($_POST[\'product_qty\']),
\'product_code\' => Util::input($_POST[\'product_code\']),
\'product_name\' => $product->product_name,
\'product_price\' => $price,
\'product_serial_no\' => Util::input($_POST[\'product_serial_no\']),
\'product_expire_date\' => Util::input($_POST[\'product_expire_date\']),
\'product_qty_per_pack\' => $qty_per_pack,
\'sale_status\' => Util::input($_POST[\'sale_status\']),
\'sale_condition\' => Util::input($_POST[\'sale_condition\']),
\'has_bonus\' => \'normal\',
\'bill_sale_created_date\' => Util::input($_POST[\'BillSale\'][\'bill_sale_created_date\'])
);
} else {
// add item
$arr[] = array(
\'product_qty\' => Util::input($_POST[\'product_qty\']),
\'product_code\' => Util::input($_POST[\'product_code\']),
\'product_name\' => $product->product_name,
\'product_price\' => $price,
\'product_serial_no\' => Util::input($_POST[\'product_serial_no\']),
\'product_expire_date\' => Util::input($_POST[\'product_expire_date\']),
\'product_qty_per_pack\' => $qty_per_pack,
\'sale_status\' => Util::input($_POST[\'sale_status\']),
\'sale_condition\' => Util::input($_POST[\'sale_condition\']),
\'has_bonus\' => \'normal\',
\'bill_sale_created_date\' => Util::input($_POST[\'BillSale\'][\'bill_sale_created_date\'])
);
}
Yii::app()->session[\'billSaleDetail\'] = $arr;
Yii::app()->session[\'billSaleCreatedDate\'] = Util::input($_POST[\'BillSale\'][\'bill_sale_created_date\']);
$this->redirect(array(\'Sale\'));
}
}
// RENDER
$this->render(\'//Basic/Sale\', array(
\'model\' => $model
));
}
// SALE DELETE
public function actionSaleDelete($index) {
$this->checkLogin();
$billSaleDetail = Yii::app()->session[\'billSaleDetail\'];
// remove product item from array
for ($i = 0; $i < count($billSaleDetail); $i++) {
if ($i == (int) $index) {
$billSaleDetail[$i] = null;
}
}
// clear empty array item
$newArray = array();
for ($i = 0; $i < count($billSaleDetail); $i++) {
if (!empty($billSaleDetail[$i])) {
$newArray[count($newArray)] = $billSaleDetail[$i];
}
}
// add new array to session
Yii::app()->session[\'billSaleDetail\'] = $newArray;
$this->redirect(array(\'Sale\'));
}
// END SALE
public function actionEndSale() {
$this->checkLogin();
$saleTemps = SaleTemp::model()->findAllByAttributes(array(
\'user_id\' => (int) Yii::app()->request->cookies[\'user_id\']->value
));
if (!empty($saleTemps)) {
// find member_id
$member_code = Util::input($_POST[\'txt_member_code\']);
$member_id = 0;
if (!empty($member_code)) {
$member = Member::model()->findByAttributes(array(
\'member_code\' => $member_code
));
if (!empty($member)) {
$member_id = $member->member_id;
}
}
// sale_status
if ($_POST[\'sale_status\'] == \'cash\') {
$saleStatus = \'pay\';
} else {
$saleStatus = \'credit\';
}
$created_date = Util::input($_POST[\'BillSale\'][\'bill_sale_created_date\']);
$created_date = Util::thaiToMySQLDate($created_date);
// bill sale
$modelBillSale = new BillSale();
$modelBillSale->bill_sale_created_date = $created_date;
$modelBillSale->bill_sale_status = $saleStatus;
$modelBillSale->member_id = $member_id;
$modelBillSale->bill_sale_vat = Util::input($_POST[\'bill_sale_vat\']);
$modelBillSale->user_id = (int) Yii::app()->request->cookies[\'user_id\']->value;
$modelBillSale->branch_id = Util::input($_POST[\'BillSale\'][\'branch_id\']);
$modelBillSale->bonus_price = Util::input($_POST[\'bonus_price\']);
$modelBillSale->out_vat = Util::input($_POST[\'out_vat\']);
$modelBillSale->vat_type = Util::input($_POST[\'hidden_vat_type\']);
$modelBillSale->input_money = Util::input($_POST[\'hidden_input\']);
$modelBillSale->return_money = Util::input($_POST[\'hidden_return_money\']);
$modelBillSale->total_money = Util::input($_POST[\'hidden_total\']);
$modelBillSale->customer_name = Util::input($_POST[\'customer_name\']);
$modelBillSale->customer_tel = Util::input($_POST[\'customer_tel\']);
$modelBillSale->customer_tax = Util::input($_POST[\'customer_tax\']);
$modelBillSale->customer_address = Util::input($_POST[\'customer_address\']);
if ($_POST[\'sale_status\'] == \'cash\') {
$_time = date("h:i:s");
$modelBillSale->bill_sale_pay_date = $created_date." ".$_time;
}
if ($modelBillSale->save()) {
// store data bill_sale_detail from session to database
$i = 0;
$qtys = $_POST[\'qtys\'];
foreach ($saleTemps as $saleTemp) {
$qty_for_sub_stock = $qtys[$i];
$model = new BillSaleDetail();
$model->bill_id = $modelBillSale->bill_sale_id;
$model->bill_sale_detail_barcode = $saleTemp->barcode;
$model->bill_sale_detail_price = $saleTemp->price;
$model->bill_sale_detail_qty = $saleTemp->qty;
$model->bill_sale_detail_price_vat = ($saleTemp->price * .07);
$model->old_price = $saleTemp->old_price;
$model->save();
// sub stock
$product_code = $saleTemp->barcode;
// find by barcode
$product = Product::model()->findByAttributes(array(
\'product_code\' => $product_code
));
if (empty($product)) {
// find by pack barcode
$product = Product::model()->findByAttributes(array(
\'product_pack_barcode\' => $product_code
));
}
if (empty($product)) {
// find by barcode_price
$barcodePrice = BarcodePrice::model()->findByAttributes(array(
\'barcode\' => $product_code
));
$product = $barcodePrice->getProduct();
}
if (!empty($saleTemp->qty_per_pack)) {
$qty_for_sub_stock = ($saleTemp->qty_per_pack * $qty_for_sub_stock);
}
$qty = ($product->product_quantity - $qty_for_sub_stock);
$product->product_quantity = $qty;
$product->save();
$i++;
}
// save to tb_product_serial
$serials = $_POST[\'serials\'];
$hidden_product_codes = $_POST[\'hidden_product_codes\'];
if (!empty($serials)) {
$i = 0;
foreach ($serials as $serial) {
$product_code = $hidden_product_codes[$i];
$productSerial = new ProductSerial();
$productSerial->product_code = $product_code;
$productSerial->serial_no = $serial;
$productSerial->product_start_date = new CDbExpression(\'NOW()\');
$productSerial->bill_sale_id = $modelBillSale->bill_sale_id;
// expire date
if (!empty($r[\'product_expire_date\'])) {
$expire_date = Util::thaiToMySQLDate($r[\'product_expire_date\']);
$productSerial->product_expire_date = $expire_date;
}
$productSerial->save();
}
}
// keep last bill_id
$output = array(
\'last_bill_id\' => $modelBillSale->bill_sale_id,
\'message\' => \'success\'
);
echo CJSON::encode($output);
} else {
echo \'can not save modal bill sale\';
}
} else {
echo \'saleTemp is a empty\';
}
}
// SALE RESET
public function actionSaleReset() {
$this->checkLogin();
Yii::app()->session[\'billSaleDetail\'] = null;
Yii::app()->session[\'sessionBillSale\'] = null;
$this->redirect(array(\'Sale\'));
}
// MANAGE BILL
public function actionManageBill() {
$this->checkLogin();
// BILL SALE OBJECT
$billSale = new BillSale();
// CONDITION
$criteria = new CDbCriteria();
$criteria->order = \'bill_sale_id DESC\';
$user_id = null;
if (!empty($_POST)) {
$user_id = $_POST[\'user_id\'];
if (!empty($user_id)) {
$criteria->condition = \'user_id = :user_id\';
$criteria->params = array(\'user_id\' => $user_id);
}
}
$configSoftware = ConfigSoftware::model()->find();
$pagination = new CPagination();
$pagination->setPageSize($configSoftware->items_per_page);
$modelForGrid = new CActiveDataProvider(\'BillSale\', array(
\'criteria\' => $criteria
));
$modelForGrid->setPagination($pagination);
// RENDER
$this->render(\'//Basic/ManageBill\', array(
\'model\' => $billSale,
\'modelForGrid\' => $modelForGrid,
\'user_id\' => $user_id
));
}
// BILL SALE DETAIL
public function actionBillSaleDetail($bill_sale_id) {
$this->checkLogin();
// MODEL
$modelBillSale = BillSale::model()->findByPk((int) $bill_sale_id);
// dataProvider
$dataProvider = new CActiveDataProvider(\'BillSaleDetail\', array(
\'criteria\' => array(
\'condition\' => "bill_id = $bill_sale_id",
\'order\' => \'bill_sale_detail_id DESC\'
),
\'pagination\' => false
));
// RENDER
$this->render(\'//Basic/BillSaleDetail\', array(
\'modelBillSale\' => $modelBillSale,
\'dataProvider\' => $dataProvider
));
}
// EDIT BILL SALE DETAIL
public function actionBillSaleDetailEdit($bill_sale_detail_id = null) {
$this->checkLogin();
if (empty($bill_sale_detail_id)) {
$bill_sale_detail_id = Util::input($_POST[\'bill_sale_detail_id\']);
}
$model = BillSaleDetail::model()->findByPk((int) $bill_sale_detail_id);
// update bill_sale_detail
if (!empty($_POST)) {
$old_qty = Util::input($_POST[\'old_qty\']);
$new_qty = Util::input($_POST[\'BillSaleDetail\'][\'bill_sale_detail_qty\']);
$model->bill_sale_detail_qty = $new_qty;
$model->save();
// update stock
$product_code = $model->bill_sale_detail_barcode;
$product = Product::model()->find(array(
\'condition\' => "product_code = :product_code",
\'params\' => array(
\'product_code\' => $product_code
)
));
if ($new_qty > $old_qty) {
$update_qty = ($new_qty - $old_qty);
$product->product_quantity += $update_qty;
} else {
$update_qty = ($old_qty - $new_qty);
$product->product_quantity -= $update_qty;
}
$product->save();
$this->redirect(array(\'BillSaleDetail\', \'bill_sale_id\' => $model->bill_id));
}
// REDIRECT
$this->render(\'//Basic/BillSaleEdit\', array(
\'bill_sale_id\' => $model->bill_id,
\'model\' => $model
));
}
// DELETE BILL SALE DETAIL
public function actionBillSaleDetailDelete($bill_sale_detail_id) {
$this->checkLogin();
// OBJECT
$billSaleDetail = BillSaleDetail::model()->findByPk((int) $bill_sale_detail_id);
$bill_sale_id = $billSaleDetail->bill_id;
$criteria = new CDbCriteria();
$criteria->compare(\'bill_id\', $bill_sale_id);
$model = BillSaleDetail::model()->findAll($criteria);
$totalRow = count($model);
// UPDATE STOCK
$criteria = new CDbCriteria();
$criteria->compare(\'product_code\', $billSaleDetail->bill_sale_detail_barcode);
$product = Product::model()->find($criteria);
$product->product_quantity = ($product->product_quantity + $billSaleDetail->bill_sale_detail_qty);
$product->save();
// DELETE
$billSaleDetail->delete();
if ($totalRow == 1) {
// DELETE BILL_SALE
BillSale::model()->deleteByPk((int) $bill_sale_id);
$this->redirect(array(\'ManageBill\'));
}
// REDIRECT FOR MANAGE BILL_SALE_DETAIL
$this->redirect(array(\'BillSaleDetail\', \'bill_sale_id\' => $bill_sale_id));
}
// CHECK STOCK
public function actionCheckStock() {
$this->checkLogin();
$model = new Product();
$param = array();
$param[\'model\'] = $model;
$param[\'product_code\'] = "";
// find product
if (!empty($_POST)) {
$product = Product::model()->findByAttributes(array(
\'product_code\' => Util::input($_POST[\'Product\'][\'product_code\'])
));
// find by pack_code
if (empty($product)) {
$product = Product::model()->findByAttributes(array(
\'product_pack_barcode\' => Util::input($_POST[\'Product\'][\'product_code\'])
));
}
$param[\'product\'] = $product;
$param[\'product_code\'] = Util::input($_POST[\'Product\'][\'product_code\']);
}
// render
$this->render(\'//Basic/CheckStock\', $param);
}
// BILL DROP
public function actionBillDrop() {
$this->checkLogin();
$model = new BillSale();
$params = array();
if (!empty($_POST)) {
// get value
$from = Util::thaiToMySQLDate(Util::input($_POST[\'from\']));
$to = Util::thaiToMySQLDate(Util::input($_POST[\'to\']));
$bill_status = Util::input($_POST[\'bill_status\']);
// find member id
$member = Member::model()->findByAttributes(array(
\'member_code\' => Util::input($_POST[\'member_code\'])
));
// criteria
$criteria = new CDbCriteria();
$criteria->order = \'bill_sale_created_date DESC \';
$criteria->condition = \'
member_id = :member_id
AND DATE(bill_sale_created_date) BETWEEN :from AND :to
\';
// filter bill status
switch ($bill_status) {
case \'no\':
$criteria->condition .= \' AND bill_sale_pay_date IS NULL \';
$criteria->condition .= \' AND bill_sale_drop_bill_date IS NULL \';
break;
case \'drop_no\':
$criteria->condition .= \' AND bill_sale_pay_date IS NULL \';
$criteria->condition .= \' AND bill_sale_drop_bill_date IS NOT NULL \';
break;
case \'drop_pay\':
$criteria->condition .= \' AND bill_sale_pay_date IS NOT NULL \';
$criteria->condition .= \' AND bill_sale_drop_bill_date IS NOT NULL \';
break;
}
// params
$criteria->params = array(
\'member_id\' => $member->member_id,
\'from\' => $from,
\'to\' => $to
);
// data provider
$dataProvider = new CActiveDataProvider(\'BillSale\', array(
\'criteria\' => $criteria,
\'pagination\' => false
));
// have data
$params[\'dataProvider\'] = $dataProvider;
} else {
$from = "";
$to = "";
}
$params[\'from\'] = $from;
$params[\'to\'] = $to;
$params[\'model\'] = $model;
$params[\'member_code\'] = @Util::input($_POST[\'member_code\']);
$params[\'member_name\'] = @Util::input($_POST[\'member_name\']);
$params[\'bill_status\'] = @Util::input($_POST[\'bill_status\']);
$this->render(\'//Basic/BillDrop\', $params);
}
// BILL DROP TEMP
public function actionBillDropTemp() {
$this->checkLogin();
Yii::app()->session[\'hidden_member_code\'] = Util::input($_POST[\'hidden_member_code\']);
Yii::app()->session[\'bill_sale_ids\'] = (int) Util::input($_POST[\'bill_sale_id\']);
echo \'complete\';
}
// BILL DROP GET
public function actionBillDropGet() {
$this->checkLogin();
$bill_sale_ids = (int) Util::input($_POST[\'bill_sale_id\']);
foreach ($bill_sale_ids as $id) {
$model = BillSale::model()->findByPk((int) $id);
$model->bill_sale_pay_date = new CDbExpression("NOW()");
$model->bill_sale_status = \'pay\';
$model->save();
}
echo \'complete\';
}
// BILL DROP CANCEL
public function actionBillDropCancel() {
$this->checkLogin();
$bill_sale_ids = (int) Util::input($_POST[\'bill_sale_id\']);
foreach ($bill_sale_ids as $id) {
$model = BillSale::model()->findByPk((int) $id);
$model->bill_sale_pay_date = null;
$model->bill_sale_drop_bill_date = null;
$model->bill_sale_status = \'credit\';
$model->save();
}
echo true;
}
// BILL DROP DELETE
public function actionBillDropDelete() {
$this->checkLogin();
$bill_sale_ids = (int) Util::input($_POST[\'bill_sale_id\']);
foreach ($bill_sale_ids as $id) {
$billSaleDetails = BillSaleDetail::model()->findAllByAttributes(array(
\'bill_id\' => $id
));
foreach ($billSaleDetails as $billSaleDetail) {
$billSaleDetail->delete();
}
BillSale::model()->deleteByPk((int) $id);
}
echo true;
}
// GET SALE
public function actionGetSale() {
$this->checkLogin();
$model = new BillSaleDetail();
$product = null;
// search
if (!empty($_POST)) {
$barcode = Util::input($_POST[\'BillSaleDetail\'][\'bill_sale_detail_barcode\']);
if (empty($_POST[\'product_id\'])) {
// find data
$billSaleDetail = BillSaleDetail::model()->findByAttributes(array(
\'bill_sale_detail_barcode\' => $barcode,
\'bill_id\' => (int) Util::input($_POST[\'BillSaleDetail\'][\'bill_id\'])
));
$model->_attributes = $_POST[\'BillSaleDetail\'];
// find by product_id
if (!empty($billSaleDetail)) {
$product = Product::model()->findByAttributes(array(
\'product_code\' => $billSaleDetail->bill_sale_detail_barcode
));
if (!empty($product)) {
$model->bill_sale_detail_barcode = $product->product_code;
}
}
} else {
// get product
$product = Product::model()->findByPk($_POST[\'product_id\']);
// remove from bill
BillSaleDetail::model()->deleteAllByAttributes(array(
\'bill_sale_detail_barcode\' => $barcode,
\'bill_id\' => (int) Util::input($_POST[\'BillSaleDetail\'][\'bill_id\'])
));
// update stock and redirect
$product->product_quantity += 1;
$product->save();
$this->redirect(array(\'GetSale\'));
}
}
// render
$this->render(\'//Basic/GetSale\', array(
\'model\' => $model,
\'product\' => $product
));
}
// REPAIR
public function actionRepair() {
$this->checkLogin();
$params = @$_POST;
if (!empty($_POST)) {
// search
$search = Util::input($_POST[\'search_code\']);
if (empty($search)) {
$search = Util::input($_GET[\'serial_code\']);
}
// productSerial
$productSerial = ProductSerial::model()->findByAttributes(array(
\'serial_no\' => $search
));
if (!empty($productSerial)) {
$product = Product::model()->findByAttributes(array(
\'product_code\' => $productSerial->product_code
));
$params[\'product\'] = $product;
$params[\'productSerial\'] = $productSerial;
}
// repair history
$criteria = new CDbCriteria();
$criteria->compare(\'serial_no\', Util::input($_POST[\'search_code\']));
$criteria->order = \'repair_id DESC\';
$repairs = new CActiveDataProvider(\'Repair\');
$repairs->setCriteria($criteria);
$params[\'repairs\'] = $repairs;
}
$this->render(\'//Basic/Repair\', $params);
}
function actionStartRepair() {
$this->checkLogin();
$serial_code = $_GET[\'serial_code\'];
// product serial
$productSerial = Yii::app()->db->createCommand()
->select(\'tb_product_serial.*, tb_product.product_name, tb_bill_sale.bill_sale_created_date\')
->from(\'tb_product_serial\')
->join(\'tb_product\', \'tb_product.product_code = tb_product_serial.product_code\')
->join(\'tb_bill_sale\', \'tb_bill_sale.bill_sale_id = tb_product_serial.bill_sale_id\')
->where(\'tb_product_serial.serial_no = \' . $serial_code)
->queryRow();
// repair
if (!empty($_GET[\'repair_id\'])) {
$repair = Repair::model()->findByPk((int) $_GET[\'repair_id\']);
} else {
$repair = new Repair();
}
// render
$this->render(\'//Basic/StartRepair\', array(
\'productSerial\' => $productSerial,
\'repair\' => $repair
));
}
function actionStartRepairSave() {
$this->checkLogin();
if (!empty($_POST)) {
// serail_code
$serial_code = Util::input($_POST[\'Repair\'][\'serial_no\']);
// save
$state_new = true;
if (empty($_POST[\'Repair\'][\'repair_id\'])) {
$repair = new Repair();
} else {
$state_new = false;
$repair = Repair::model()->findByPk((int) Util::input($_POST[\'Repair\'][\'repair_id\']));
}
$repair->_attributes = $_POST[\'Repair\'];
$repair->user_id = (int) Util::input($_POST[\'user_id\']);
$repair->repair_created_date = Util::thaiToMySQLDate(Util::input($_POST[\'repair_created_date\']));
$repair->branch_id = Util::input($_POST[\'hidden_branch_id\']);
$repair->repair_date = Util::thaiToMySQLDate(Util::input($_POST[\'Repair\'][\'repair_date\']));
if ($repair->save()) {
if ($state_new) {
$this->redirect(array(\'Basic/StartRepair\', \'serial_code\' => $serial_code));
} else {
$this->redirect(array(\'Basic/Repair\', \'serial_code\' => $serial_code));
}
}
}
}
function actionRepairView($repair_id) {
$this->checkLogin();
$serial_code = Util::input($_GET[\'serial_code\']);
// product serial
$productSerial = Yii::app()->db->createCommand()
->select(\'tb_product_serial.*, tb_product.product_name, tb_bill_sale.bill_sale_created_date\')
->from(\'tb_product_serial\')
->join(\'tb_product\', \'tb_product.product_code = tb_product_serial.product_code\')
->join(\'tb_bill_sale\', \'tb_bill_sale.bill_sale_id = tb_product_serial.bill_sale_id\')
->where(\'tb_product_serial.serial_no = \' . $serial_code)
->queryRow();
// repair
if (!empty($_GET[\'repair_id\'])) {
$repair = Repair::model()->findByPk((int) $_GET[\'repair_id\']);
} else {
$repair = new Repair();
}
// render
$this->render(\'//Basic/RepairView\', array(
\'productSerial\' => $productSerial,
\'repair\' => $repair
));
}
function actionBillQuotation() {
$this->checkLogin();
$this->render("//Basic/BillQuotation");
}
function actionQuotationSave($quotation_id = null) {
$this->checkLogin();
if (!empty($_POST)) {
if (empty($quotation_id)) {
// INSERT DATA TO TABLE
$quotation = new Quotation();
$quotation->created_at = new CDbExpression("NOW()");
} else {
$quotation = Quotation::model()->findByPk((int) $quotation_id);
}
$quotation->customer_name = Util::input($_POST[\'customer_name\']);
$quotation->customer_address = Util::input($_POST[\'customer_address\']);
$quotation->customer_tel = Util::input($_POST[\'customer_tel\']);
$quotation->customer_fax = Util::input($_POST[\'customer_fax\']);
$quotation->customer_tax = Util::input($_POST[\'customer_tax\']);
$quotation->quotation_day = Util::input($_POST[\'quotation_day\']);
$quotation->quotation_send_day = Util::input($_POST[\'quotation_send_day\']);
$quotation->quotation_pay = Util::input($_POST[\'quotation_pay\']);
$quotation->user_id = Yii::app()->request->cookies["user_id"]->value;
$quotation->vat = Util::input($_POST[\'vat\']);
if ($quotation->save()) {
// INSERT TO quotation_details
$barcodes = Util::input($_POST[\'barcode_hidden\']);
// clear quotation detail
if (!empty($quotation_id)) {
QuotationDetail::model()->deleteAllByAttributes(array(
\'quotation_id\' => $quotation_id
));
}
// insert quotation data
for ($i = 0; $i < count($barcodes); $i++) {
$quotationDetail = new QuotationDetail();
$quotationDetail->quotation_id = $quotation->id;
$quotationDetail->barcode = Util::input($_POST[\'barcode_hidden\'][$i]);
$quotationDetail->old_price = str_replace(",", "", Util::input($_POST[\'old_price\'][$i]));
$quotationDetail->qty = str_replace(",", "", Util::input($_POST[\'qty\'][$i]));
$quotationDetail->sub = str_replace(",", "", Util::input($_POST[\'sub\'][$i]));
$quotationDetail->sale_price = str_replace(",", "", Util::input($_POST[\'sale_price\'][$i]));
$quotationDetail->save();
}
Yii::app()->session[\'current_quotation_id\'] = $quotation->id;
}
} else {
Yii::app()->session[\'current_quotation_id\'] = $quotation_id;
}
$arr = array(
\'message\' => \'success\'
);
echo CJSON::encode($arr);
}
function actionQuotationBill() {
$this->checkLogin();
$quotation_id = Yii::app()->session[\'current_quotation_id\'];
$quotation = Quotation::model()->findByPk((int) $quotation_id);
$quotationDetails = QuotationDetail::model()->findAllByAttributes(array(
"quotation_id" => $quotation_id
));
$org = Organization::model()->find();
$user_id = (int) Yii::app()->request->cookies["user_id"]->value;
$user = User::model()->findByPk((int) $user_id);
$this->renderPartial("//Basic/QuotationBill", array(
"quotation" => $quotation,
"quotationDetails" => $quotationDetails,
"org" => $org,
"user" => $user
));
}
public function actionGridQuotation() {
$this->checkLogin();
$quotations = Quotation::model()->findAll(array(
"order" => "id DESC"
));
$this->renderPartial("//Basic/GridQuotation", array(
"quotations" => $quotations,
"n" => 1
));
}
public function actionFindQuotationById($id) {
$quotation = Quotation::model()->findByPk((int) $id);
echo CJSON::encode($quotation);
}
public function actionQuotationDetail($quotation_id) {
$quotationDetails = QuotationDetail::model()->findAllByAttributes(array(
"quotation_id" => $quotation_id
));
$arr = array();
$i = 0;
foreach ($quotationDetails as $quotationDetail) {
$arr[$i][\'id\'] = $quotationDetail->id;
$arr[$i][\'barcode\'] = $quotationDetail->barcode;
$arr[$i][\'product_name\'] = $quotationDetail->getProduct()->product_name;
$arr[$i][\'qty\'] = number_format($quotationDetail->qty);
$arr[$i][\'old_price\'] = number_format($quotationDetail->old_price);
$arr[$i][\'sub\'] = number_format($quotationDetail->sub);
$arr[$i][\'sale_price\'] = number_format($quotationDetail->sale_price);
$i++;
}
echo CJSON::encode($arr);
}
public function actionQuotationDetailAdd() {
$this->checkLogin();
if (!empty($_POST)) {
$quotationDetail = new QuotationDetail();
$quotationDetail->quotation_id = (int) Util::input($_POST[\'quotation_id\']);
$quotationDetail->barcode = Util::input($_POST[\'barcode\']);
$quotationDetail->old_price = str_replace(",", "", Util::input($_POST[\'old_price\']));
$quotationDetail->qty = str_replace(",", "", Util::input($_POST[\'qty\']));
$quotationDetail->sub = str_replace(",", "", Util::input($_POST[\'sub\']));
$quotationDetail->sale_price = str_replace(",", "", Util::input($_POST[\'sale_price\']));
$quotationDetail->save();
echo $quotationDetail->id;
}
}
public function actionQuotationDetailDelete($id) {
$this->checkLogin();
QuotationDetail::model()->deleteByPk((int) $id);
$billSaleDetail = BillSaleDetail::model()->findByAttributes(array(
\'quotation_detail_id\' => $id
));
if (!empty($billSaleDetail)) {
$billSaleDetail->delete();
}
}
public function actionClearBillSale() {
$this->checkLogin();
BillSale::model()->deleteAll();
BillSaleDetail::model()->deleteAll();
$this->redirect(array("Basic/ManageBill"));
}
public function actionBackgroundSave() {
$this->checkLogin();
if ($_FILES[\'background\'][\'name\'] != null) {
$name = $_FILES[\'background\'][\'name\'];
$tmp = $_FILES[\'background\'][\'tmp_name\'];
$size = $_FILES[\'background\'][\'size\'];
if ($size > 0) {
$ext = explode(".", $name);
$ext = $ext[count($ext) - 1];
$ext = strtolower($ext);
$name = microtime();
$name = str_replace(" ", "", $name);
$name = str_replace(".", "", $name);
if ($ext == "jpg" || $ext == "png") {
if (move_uploaded_file($tmp, "upload/$name.$ext")) {
$background = new Background();
$background->name = $name.".".$ext;
if ($background->save()) {
$this->redirect(array("Site/Home"));
}
}
}
}
}
}
public function actionBackgroundDelete($id) {
$this->checkLogin();
}
public function actionGetRepair() {
$this->checkLogin();
$this->render(\'//Basic/GetRepair\');
}
public function actionGetRepairSave() {
$this->checkLogin();
if (!empty($_POST)) {
$repair_id = (int) Util::input($_POST[\'repair_id\']);
if (empty($repair_id)) {
$repair = new Repair();
} else {
$repair = Repair::model()->findByPk((int) $repair_id);
}
$repair->user_id = (int) Util::input($_POST[\'user_id\']);
$repair->branch_id = (int) Util::input($_POST[\'hidden_branch_id\']);
$repair->product_code = Util::input($_POST[\'product_code\']);
$repair->repair_date = Util::thaiToMySQLDate(Util::input($_POST[\'repair_date\']));
$repair->repair_problem = Util::input($_POST[\'repair_problem\']);
$repair->repair_price = Util::input($_POST[\'repair_price\']);
$repair->repair_type = Util::input($_POST[\'repair_type\']);
$repair->repair_original = Util::input($_POST[\'repair_original\']);
$repair->repair_detail = Util::input($_POST[\'repair_detail\']);
$repair->repair_created_date = Util::thaiToMySQLDate(Util::input($_POST[\'repair_created_date\']));
$repair->repair_status = Util::input($_POST[\'repair_status\']);
$repair->repair_group = \'external\';
$repair->repair_tel = Util::input($_POST[\'repair_tel\']);
$repair->repair_name = Util::input($_POST[\'repair_name\']);
$repair->repair_product_name = Util::input($_POST[\'repair_product_name\']);
if ($repair->save()) {
echo CJSON::encode($repair);
}
}
}
public function actionGetRepairInfo() {
$this->checkLogin();
if (!empty($_POST)) {
$repair_id = Util::input($_POST[\'repair_id\']);
$repair = Repair::model()->findByPk((int) $repair_id);
if (!empty($repair)) {
$arr = array();
$arr[\'repair_id\'] = $repair->repair_id;
$arr[\'product_code\'] = $repair->product_code;
$arr[\'user_id\'] = $repair->user_id;
$arr[\'user_name\'] = $repair->user->user_name;
$arr[\'branch_id\'] = $repair->branch_id;
$arr[\'branch_name\'] = $repair->branch->branch_name;
$arr[\'repair_date\'] = Util::mysqlToThaiDate($repair->repair_date);
$arr[\'repair_problem\'] = $repair->repair_problem;
$arr[\'repair_price\'] = $repair->repair_price;
$arr[\'repair_type\'] = $repair->repair_type;
$arr[\'repair_original\'] = $repair->repair_original;
$arr[\'repair_detail\'] = $repair->repair_detail;
$arr[\'repair_created_date\'] = Util::mysqlToThaiDate($repair->repair_created_date);
$arr[\'repair_status\'] = $repair->repair_status;
$arr[\'serial_no\'] = $repair->serial_no;
$arr[\'repair_group\'] = $repair->repair_group;
$arr[\'repair_tel\'] = $repair->repair_tel;
$arr[\'repair_name\'] = $repair->repair_name;
$arr[\'repair_product_name\'] = $repair->repair_product_name;
$arr[\'repair_end_date\'] = $repair->repair_end_date;
}
echo CJSON::encode($arr);
}
}
public function actionGetRepairDelete() {
$this->checkLogin();
if (!empty($_POST)) {
$repair_id = Util::input($_POST[\'repair_id\']);
Repair::model()->deleteByPk((int) $repair_id);
echo \'success\';
}
}
public function actionGetRepairEnd() {
$this->checkLogin();
if (!empty($_POST)) {
$repair_id = Util::input($_POST[\'repair_id\']);
$repair = Repair::model()->findByPk((int) $repair_id);
$repair->user_id = (int) Util::input($_POST[\'user_id\']);
$repair->branch_id = (int) Util::input($_POST[\'hidden_branch_id\']);
$repair->product_code = Util::input($_POST[\'product_code\']);
$repair->repair_date = Util::thaiToMySQLDate(Util::input($_POST[\'repair_date\']));
$repair->repair_problem = Util::input($_POST[\'repair_problem\']);
$repair->repair_price = Util::input($_POST[\'repair_price\']);
$repair->repair_type = Util::input($_POST[\'repair_type\']);
$repair->repair_original = Util::input($_POST[\'repair_original\']);
$repair->repair_detail = Util::input($_POST[\'repair_detail\']);
$repair->repair_created_date = Util::thaiToMySQLDate(Util::input($_POST[\'repair_created_date\']));
$repair->repair_status = Util::input($_POST[\'repair_status\']);
$repair->repair_group = \'external\';
$repair->repair_tel = Util::input($_POST[\'repair_tel\']);
$repair->repair_name = Util::input($_POST[\'repair_name\']);
$repair->repair_product_name = Util::input($_POST[\'repair_product_name\']);
$repair->repair_end_date = new CDbExpression(\'NOW()\');
if ($repair->save()) {
echo \'success\';
}
}
}
public function actionAlertStock($print = false) {
$configSoftware = ConfigSoftware::model()->find();
$products = Product::model()->findAll(array(
\'condition\' => \'product_quantity <= :qty\',
\'order\' => \'product_quantity\',
\'params\' => array(
\'qty\' => $configSoftware->alert_min_stock
)
));
if (!$print) {
$this->render(\'//Basic/AlertStock\', array(
\'products\' => $products,
\'n\' => 1,
\'print\' => $print
));
} else {
$this->renderPartial(\'//Basic/AlertStock\', array(
\'products\' => $products,
\'n\' => 1,
\'print\' => $print
));
}
}
public function actionSaleMobile() {
$this->checkLogin();
$user_id = Yii::app()->request->cookies[\'user_id\']->value;
if (!empty($_POST)) {
$barcode = Util::input($_POST[\'barcode\']);
$info = Product::getInfoByBarcode($barcode);
$user = User::model()->findByPk((int) $user_id);
$saleTemp = new SaleTemp();
$saleTemp->barcode = $barcode;
$saleTemp->serial = Util::input($_POST[\'serial\']);
$saleTemp->qty = 1;
$saleTemp->qty_per_pack = $info[\'qty_per_pack\'];
$saleTemp->price = $info[\'price\'];
$saleTemp->user_id = $user_id;
$saleTemp->branch_id = $user->branch_id;
$saleTemp->pk_temp = rand(1000, 10000);
$saleTemp->created_at = new CDbExpression(\'NOW()\');
$saleTemp->old_price = $info[\'old_price\'];
$saleTemp->sale_type = \'mobile\';
$saleTemp->name = $info[\'name\'];
if ($saleTemp->save()) {
$this->redirect(array(\'SaleMobile\'));
}
}
$saleTemps = SaleTemp::model()->findAll(array(
\'condition\' => \'user_id = :user_id AND sale_type = :sale_type\',
\'params\' => array(
\'user_id\' => $user_id,
\'sale_type\' => \'mobile\'
),
\'order\' => \'created_at DESC\'
));
$this->renderPartial(\'//Basic/SaleMobile\', array(
\'saleTemps\' => $saleTemps,
\'sum\' => 0
));
}
public function actionSendFromQuotationBillToBillSale() {
$this->checkLogin();
$quotation_id = (int) $_POST[\'quotation_id\'];
$vat_price = $_POST[\'vat_price\'];
$quotation = Quotation::model()->findByPk((int) $quotation_id);
if (!empty($quotation)) {
$billSale = BillSale::model()->findByAttributes(array(
\'quotation_id\' => $quotation_id
));
if (empty($billSale)) {
$user_id = Yii::app()->request->cookies[\'user_id\']->value;
$user = User::model()->findByPk($user_id);
//
// create bill_sale
//
$billSale = new BillSale();
$billSale->quotation_id = $quotation_id;
$billSale->sale_type = \'sale\';
$billSale->bill_sale_pay_date = new CDbExpression(\'NOW()\');
$billSale->branch_id = $user->branch_id;
$billSale->user_id = $user_id;
$billSale->member_id = 0;
$billSale->bill_sale_status = \'pay\';
$billSale->bill_sale_created_date = new CDbExpression(\'NOW()\');
if ($quotation->vat > 0) {
$vat_price = str_replace(\',\', \'\', $vat_price);
$billSale->vat_type = \'out\';
$billSale->out_vat = $vat_price;
$billSale->bill_sale_vat = \'vat\';
$billSale->vat_percen = $quotation->vat;
}
if ($billSale->save()) {
//
// read from quotation and transfer to tb_bill_sale_detail
//
$quotationDetails = QuotationDetail::model()->findAllByAttributes(array(
\'quotation_id\' => $quotation_id
));
foreach ($quotationDetails as $quotationDetail) {
$billSaleDetail = new BillSaleDetail();
$billSaleDetail->bill_id = $billSale->bill_sale_id;
$billSaleDetail->bill_sale_detail_barcode = $quotationDetail->barcode;
$billSaleDetail->bill_sale_detail_price = $quotationDetail->old_price;
$billSaleDetail->bill_sale_detail_qty = $quotationDetail->qty;
$billSaleDetail->sub = $quotationDetail->sub;
$billSaleDetail->quotation_detail_id = $quotationDetail->id;
$billSaleDetail->save();
}
echo $billSale->bill_sale_id;
}
} else {
echo $billSale->bill_sale_id;
}
}
}
public function actionChangeLanguage() {
$this->checkLogin();
$language = Util::input($_POST[\'language\']);
Yii::app()->session[\'language\'] = $language;
Yii::app()->language = $language;
echo \'success\';
}
public function actionBillSaleDelete($bill_sale_id) {
$this->checkLogin();
$billSale = BillSale::model()->findByPk((int) $bill_sale_id);
if (!empty($billSale)) {
BillSaleDetail::model()->deleteAllByAttributes(array(
\'bill_id\' => $billSale->bill_sale_id
));
if ($billSale->delete()) {
$this->redirect(array(\'ManageBill\'));
}
}
}
public function actionTransferData() {
$this->checkLogin();
$totalNotTransfer = BillSaleDetail::model()->countByAttributes(array(
\'transfer_status\' => 0
));
$this->render(\'//Basic/TransferData\', array(
\'totalNotTransfer\' => $totalNotTransfer
));
}
public function actionStartTransfer() {
$this->checkLogin();
$user_id = Yii::app()->request->cookies[\'user_id\'];
$db = Yii::app()->db;
//
// update status of transfer
//
$sql = "
UPDATE tb_bill_sale_detail SET
transfer_status = 1,
transfer_by_user_id = $user_id
WHERE transfer_status = 0";
$db->createCommand($sql)->execute();
//
// config variable
//
$configSoftware = ConfigSoftware::model()->find();
//
// update table score_of_member
//
$members = Member::model()->findAll();
foreach ($members as $member) {
// count score of member
$sql = "
SELECT SUM(bill_sale_detail_qty * bill_sale_detail_price) AS total
FROM tb_bill_sale_detail
LEFT JOIN tb_bill_sale ON tb_bill_sale.bill_sale_id = tb_bill_sale_detail.bill_id
LEFT JOIN tb_product ON tb_product.product_code = tb_bill_sale_detail.bill_sale_detail_barcode
WHERE member_id = {$member->member_id}
";
$r = $db->createCommand($sql)->queryRow();
$total = $r[\'total\'];
$score = ($total / $configSoftware->score);
//
$oldData = SummaryScoreOfMember::model()->findByAttributes(array(
\'member_id\' => $member->member_id
));
if (empty($oldData)) {
// insert data
$sql = "
INSERT INTO summary_score_of_member(member_id, score, price)
VALUES(\'{$member->member_id}\', \'$score\', \'$total\')
";
} else {
// update data
$newScore = ($oldData->score + $score);
$newPrice = ($oldData->price + $total);
$sql = "
UPDATE summary_score_of_member SET
member_id = {$member->member_id},
score = $newScore,
price = $newPrice
WHERE member_id = {$member->member_id}";
}
$db->createCommand($sql)->execute();
}
//
// end process
//
$arr = array(\'message\' => \'success\');
echo CJSON::encode($arr);
}
public function actionProductInStock() {
$this->checkLogin();
$products = Product::model()->findAll(array(
\'select\' => \'product_code, product_name, product_price\'
));
$branchs = Branch::model()->findAll();
$branch = new Branch();
if (!empty($_POST[\'Branch\'])) {
$branch_id = @$_POST[\'Branch\'][\'branch_id\'];
} else {
$branch_id = $branchs[0]->branch_id;
}
if (!empty($branch_id)) {
$branch->branch_id = $branch_id;
}
$productInStock = ProductInStock::model()->countByAttributes(array(
\'branch_id\' => $branch_id
));
$this->render(\'//Basic/ProductInStock\', array(
\'products\' => $products,
\'branchs\' => $branchs,
\'branch\' => $branch,
\'branch_id\' => $branch_id,
\'productInStock\' => $productInStock
));
}
public function actionProductInStockSave() {
$this->checkLogin();
if (!empty($_POST)) {
$qty = Util::input($_POST[\'qty\']);
$barcode = Util::input($_POST[\'barcode\']);
$branch_id = Util::input($_POST[\'branch_id\']);
// set value
$productInStock = ProductInStock::model()->findByAttributes(array(
\'branch_id\' => $branch_id,
\'barcode\' => $barcode
));
if (empty($productInStock)) {
$productInStock = new ProductInStock();
}
$productInStock->barcode = $barcode;
$productInStock->qty = $qty;
$productInStock->branch_id = $branch_id;
$productInStock->save();
}
}
public function actionConfigSoftwarePrintSlipAfterEndSale($checkedValue = true) {
$this->checkLogin();
$arr = array(
\'true\' => \'yes\',
\'false\' => \'no\'
);
$configSoftware = ConfigSoftware::model()->find();
$configSoftware->print_slip_after_end_sale = $arr[$checkedValue];
$configSoftware->save();
}
public function actionConfigSoftwarePrintBillAfterEndSale($checkedValue = true) {
$this->checkLogin();
$arr = array(
\'true\' => \'yes\',
\'false\' => \'no\'
);
$configSoftware = ConfigSoftware::model()->find();
$configSoftware->print_bill_after_end_sale = $arr[$checkedValue];
$configSoftware->save();
}
}
'
Did this file decode correctly?
Original Code
<?php eval("?>".base64_decode("PD9waHAKCmNsYXNzIEJhc2ljQ29udHJvbGxlciBleHRlbmRzIENvbnRyb2xsZXIgewoKICBmdW5jdGlvbiBjaGVja0xvZ2luKCkgewogICAgaWYgKFlpaTo6YXBwKCktPnJlcXVlc3QtPmNvb2tpZXNbJ3VzZXJfaWQnXSA9PSBudWxsKSB7CiAgICAgICR0aGlzLT5yZWRpcmVjdChhcnJheSgiU2l0ZS9JbmRleCIpKTsKICAgIH0KICB9CgogIGZ1bmN0aW9uIGFjdGlvbkNoYW5nZVByb2ZpbGUoKSB7CiAgICAkdGhpcy0+Y2hlY2tMb2dpbigpOwoKICAgICRwayA9IChpbnQpIFlpaTo6YXBwKCktPnJlcXVlc3QtPmNvb2tpZXNbInVzZXJfaWQiXS0+dmFsdWU7CiAgICAkbW9kZWwgPSBVc2VyOjptb2RlbCgpLT5maW5kQnlQaygoaW50KSAkcGspOwoKICAgIGlmICgkX1BPU1QgIT0gbnVsbCkgewogICAgICAkbW9kZWwtPmF0dHJpYnV0ZXMgPSAkX1BPU1RbIlVzZXIiXTsKCiAgICAgIGlmICgkbW9kZWwtPnNhdmUoKSkgewogICAgICAgICR0aGlzLT5yZWRpcmVjdChhcnJheSgnU2l0ZS9pbmRleCcpKTsKICAgICAgfQogICAgfQoKICAgICR0aGlzLT5yZW5kZXIoJy8vQmFzaWMvQ2hhbmdlUHJvZmlsZScsIGFycmF5KAogICAgICAgICdtb2RlbCcgPT4gJG1vZGVsCiAgICApKTsKICB9CgogIGZ1bmN0aW9uIGFjdGlvbkJpbGxJbXBvcnQoJGlkID0gbnVsbCkgewogICAgJHRoaXMtPmNoZWNrTG9naW4oKTsKCiAgICAkY29uZmlnU29mdHdhcmUgPSBDb25maWdTb2Z0d2FyZTo6bW9kZWwoKS0+ZmluZCgpOwogICAgJG1vZGVsID0gbmV3IEJpbGxJbXBvcnQoKTsKCiAgICAvLyBTQVZFIERBVEEKICAgIGlmICghZW1wdHkoJF9QT1NUKSkgewogICAgICAkcGsgPSBVdGlsOjppbnB1dCgkX1BPU1RbJ0JpbGxJbXBvcnQnXVsnYmlsbF9pbXBvcnRfY29kZSddKTsKCiAgICAgIGlmICghZW1wdHkoJHBrKSkgewogICAgICAgIC8vIEZJTkQgQklMTAogICAgICAgICRtb2RlbCA9IEJpbGxJbXBvcnQ6Om1vZGVsKCktPmZpbmRCeVBrKChpbnQpICRwayk7CgogICAgICAgIGlmIChlbXB0eSgkbW9kZWwpKSB7CiAgICAgICAgICAkbW9kZWwgPSBuZXcgQmlsbEltcG9ydCgpOwogICAgICAgIH0KICAgICAgfQoKICAgICAgLy8gVkFSSUFCTEUKICAgICAgJGltcG9ydF9wYXlfZGF0ZSA9IFV0aWw6OmlucHV0KCRfUE9TVFsnQmlsbEltcG9ydCddWydiaWxsX2ltcG9ydF9wYXlfZGF0ZSddKTsKICAgICAgJGltcG9ydF9jcmVhdGVkX2RhdGUgPSBVdGlsOjppbnB1dCgkX1BPU1RbJ0JpbGxJbXBvcnQnXVsnYmlsbF9pbXBvcnRfY3JlYXRlZF9kYXRlJ10pOwoKICAgICAgJGltcG9ydF9wYXlfZGF0ZSA9IFV0aWw6OnRoYWlUb015U1FMRGF0ZSgkaW1wb3J0X3BheV9kYXRlKTsKICAgICAgJGltcG9ydF9jcmVhdGVkX2RhdGUgPSBVdGlsOjp0aGFpVG9NeVNRTERhdGUoJGltcG9ydF9jcmVhdGVkX2RhdGUpOwoKICAgICAgJG1vZGVsLT5hdHRyaWJ1dGVzID0gVXRpbDo6aW5wdXQoJF9QT1NUWydCaWxsSW1wb3J0J10pOwogICAgICAkbW9kZWwtPmJpbGxfaW1wb3J0X3BheV9kYXRlID0gJGltcG9ydF9wYXlfZGF0ZTsKICAgICAgJG1vZGVsLT5iaWxsX2ltcG9ydF9jcmVhdGVkX2RhdGUgPSAkaW1wb3J0X2NyZWF0ZWRfZGF0ZTsKCiAgICAgIC8vIFBBWSBBTkQgU0FWRQogICAgICAkaW1wb3J0X3BheV9zdGF0dXMgPSBVdGlsOjppbnB1dCgkX1BPU1RbIkJpbGxJbXBvcnQiXVsiYmlsbF9pbXBvcnRfcGF5X3N0YXR1cyJdKTsKCiAgICAgIGlmICgkaW1wb3J0X3BheV9zdGF0dXMgPT0gInBheSIgJiYgJGltcG9ydF9wYXlfZGF0ZSA9PSAiIikgewogICAgICAgICRtb2RlbC0+YmlsbF9pbXBvcnRfcGF5X2RhdGUgPSBuZXcgQ0RiRXhwcmVzc2lvbigiTk9XKCkiKTsKICAgICAgfQoKICAgICAgaWYgKCRtb2RlbC0+c2F2ZSgpKSB7CiAgICAgICAgJHRoaXMtPnJlZGlyZWN0KGFycmF5KCdCaWxsSW1wb3J0JykpOwogICAgICB9CiAgICB9CgogICAgLy8gQklMTCBJTVBPUlQKICAgICRtb2RlbEZvckdyaWQgPSBuZXcgQ0FjdGl2ZURhdGFQcm92aWRlcignQmlsbEltcG9ydCcsIGFycmF5KAogICAgICAnY3JpdGVyaWEnID0+IGFycmF5KAogICAgICAgICdvcmRlcicgPT4gJ2JpbGxfaW1wb3J0X2NyZWF0ZWRfZGF0ZSBERVNDJwogICAgICApLAogICAgICAncGFnaW5hdGlvbicgPT4gYXJyYXkoCiAgICAgICAgJ3BhZ2VTaXplJyA9PiAkY29uZmlnU29mdHdhcmUtPml0ZW1zX3Blcl9wYWdlCiAgICAgICkKICAgICkpOwoKICAgIC8vIERBVEEgRk9SIEVESVQKICAgIGlmICghZW1wdHkoJGlkKSkgewogICAgICAkbW9kZWwgPSBCaWxsSW1wb3J0Ojptb2RlbCgpLT5maW5kQnlQaygoaW50KSAkaWQpOwoKCQkJJGNyZWF0ZWRfZGF0ZSA9ICRtb2RlbC0+YmlsbF9pbXBvcnRfY3JlYXRlZF9kYXRlOwoJCQkkcGF5X2RhdGUgPSAkbW9kZWwtPmJpbGxfaW1wb3J0X3BheV9kYXRlOwoKCQkJJG1vZGVsLT5iaWxsX2ltcG9ydF9jcmVhdGVkX2RhdGUgPSBVdGlsOjpteXNxbFRvVGhhaURhdGUoJGNyZWF0ZWRfZGF0ZSk7CgkJCSRtb2RlbC0+YmlsbF9pbXBvcnRfcGF5X2RhdGUgPSBVdGlsOjpteXNxbFRvVGhhaURhdGUoJHBheV9kYXRlKTsKICAgIH0KCiAgICAvLyBSRU5ERVIgUEFHRQogICAgJHRoaXMtPnJlbmRlcignLy9CYXNpYy9CaWxsSW1wb3J0JywgYXJyYXkoCiAgICAgICAgJ21vZGVsJyA9PiAkbW9kZWwsCiAgICAgICAgJ21vZGVsRm9yR3JpZCcgPT4gJG1vZGVsRm9yR3JpZAogICAgKSk7CiAgfQoKICAvLyBERUxFVEUgQklMTCBJTVBPUlQKICBwdWJsaWMgZnVuY3Rpb24gYWN0aW9uQmlsbEltcG9ydERlbGV0ZSgkaWQpIHsKICAgICR0aGlzLT5jaGVja0xvZ2luKCk7CgogICAgQmlsbEltcG9ydDo6bW9kZWwoKS0+ZGVsZXRlQnlQaygkaWQpOwogICAgJHRoaXMtPnJlZGlyZWN0KGFycmF5KCdCaWxsSW1wb3J0JykpOwogIH0KCiAgLy8gQklMTCBJTVBPUlQgREVUQUlMCiAgcHVibGljIGZ1bmN0aW9uIGFjdGlvbkJpbGxJbXBvcnREZXRhaWwoJGJpbGxfaW1wb3J0X2NvZGUgPSBudWxsLCAkaWQgPSBudWxsKSB7CiAgICAkdGhpcy0+Y2hlY2tMb2dpbigpOwoKICAgICRjb25maWdTb2Z0d2FyZSA9IENvbmZpZ1NvZnR3YXJlOjptb2RlbCgpLT5maW5kKCk7CgogICAgLy8gQ0hFQ0sgJGJpbGxfaW1wb3J0X2NvZGUKICAgIGlmIChlbXB0eSgkYmlsbF9pbXBvcnRfY29kZSkpIHsKICAgICAgaWYgKCFlbXB0eSgkX1BPU1RbJ0JpbGxJbXBvcnREZXRhaWwnXSkpIHsKICAgICAgICAkYmlsbF9pbXBvcnRfY29kZSA9IFV0aWw6OmlucHV0KCRfUE9TVFsnQmlsbEltcG9ydERldGFpbCddWydiaWxsX2ltcG9ydF9jb2RlJ10pOwogICAgICB9CiAgICB9CgogICAgLy8gQ1JFQVRFIE9CSkVDVCBPRiBCaWxsSW1wb3J0CiAgICAkbW9kZWxCaWxsSW1wb3J0ID0gQmlsbEltcG9ydDo6bW9kZWwoKS0+ZmluZEJ5UGsoJGJpbGxfaW1wb3J0X2NvZGUpOwogICAgJG1vZGVsQmlsbEltcG9ydERldGFpbCA9IG5ldyBCaWxsSW1wb3J0RGV0YWlsKCk7CiAgICAkbW9kZWxCaWxsSW1wb3J0RGV0YWlsLT5iaWxsX2ltcG9ydF9jb2RlID0gJGJpbGxfaW1wb3J0X2NvZGU7CgogICAgLy8gU0FWRQogICAgaWYgKCFlbXB0eSgkX1BPU1QpKSB7CiAgICAgICRwayA9IChpbnQpIFV0aWw6OmlucHV0KCRfUE9TVFsnQmlsbEltcG9ydERldGFpbCddWydiaWxsX2ltcG9ydF9kZXRhaWxfaWQnXSk7CiAgICAgICRiaWxsX2ltcG9ydF9jb2RlID0gVXRpbDo6aW5wdXQoJF9QT1NUWydCaWxsSW1wb3J0RGV0YWlsJ11bJ2JpbGxfaW1wb3J0X2NvZGUnXSk7CgogICAgICAvLyBDUkVBVEUgT0JKRUNUIE9GIEJpbGxJbXBvcnREZXRhaWwKICAgICAgaWYgKCFlbXB0eSgkcGspKSB7CiAgICAgICAgJG1vZGVsID0gQmlsbEltcG9ydERldGFpbDo6bW9kZWwoKS0+ZmluZEJ5UGsoJHBrKTsKICAgICAgfSBlbHNlIHsKICAgICAgICAkbW9kZWwgPSBuZXcgQmlsbEltcG9ydERldGFpbCgpOwogICAgICB9CgogICAgICAvLyBRVFkKICAgICAgJHF0eSA9IFV0aWw6OmlucHV0KCRfUE9TVFsnQmlsbEltcG9ydERldGFpbCddWydpbXBvcnRfYmlsbF9kZXRhaWxfcHJvZHVjdF9xdHknXSk7CiAgICAgICRxdHlfYmVmb3JlID0gVXRpbDo6aW5wdXQoJF9QT1NUWydxdHlfYmVmb3JlJ10pOwogICAgICAkbmV3UXR5ID0gMDsKCiAgICAgIGlmICghZW1wdHkoJHF0eV9iZWZvcmUpKSB7CiAgICAgICAgaWYgKCRxdHlfYmVmb3JlID4gJHF0eSkgewogICAgICAgICAgLy8gLQogICAgICAgICAgJG5ld1F0eSA9IC0oJHF0eV9iZWZvcmUgLSAkcXR5KTsKICAgICAgICB9IGVsc2UgewogICAgICAgICAgLy8gKwogICAgICAgICAgJG5ld1F0eSA9ICgkcXR5IC0gJHF0eV9iZWZvcmUpOwogICAgICAgIH0KICAgICAgfQoKICAgICAgLy8gVVBEQVRFIFNUT0NLCiAgICAgICRjb2RlUHJvZHVjdCA9IFV0aWw6OmlucHV0KCRfUE9TVFsnQmlsbEltcG9ydERldGFpbCddWydwcm9kdWN0X2lkJ10pOwogICAgICAkcHJvZHVjdCA9IFByb2R1Y3Q6Om1vZGVsKCktPmZpbmRCeUF0dHJpYnV0ZXMoYXJyYXkoCiAgICAgICAgJ3Byb2R1Y3RfY29kZScgPT4gJGNvZGVQcm9kdWN0CiAgICAgICkpOwoKICAgICAgaWYgKGVtcHR5KCRwcm9kdWN0KSkgewogICAgICAgICRiYXJjb2RlUHJpY2UgPSBCYXJjb2RlUHJpY2U6Om1vZGVsKCktPmZpbmRCeUF0dHJpYnV0ZXMoYXJyYXkoCiAgICAgICAgICAnYmFyY29kZScgPT4gJGNvZGVQcm9kdWN0CiAgICAgICAgKSk7CgogICAgICAgIGlmICghZW1wdHkoJGJhcmNvZGVQcmljZSkpIHsKICAgICAgICAgICRwcm9kdWN0ID0gJGJhcmNvZGVQcmljZS0+Z2V0UHJvZHVjdCgpOwogICAgICAgIH0KICAgICAgfQoKICAgICAgaWYgKCFlbXB0eSgkcHJvZHVjdCkpIHsKICAgICAgICBpZiAoIWVtcHR5KCRwaykpIHsKICAgICAgICAgICRwcm9kdWN0LT5wcm9kdWN0X3F1YW50aXR5ICs9ICRuZXdRdHk7CiAgICAgICAgfSBlbHNlIHsKICAgICAgICAgIGlmICghZW1wdHkoJHF0eSkpIHsKICAgICAgICAgICAgJHByb2R1Y3QtPnByb2R1Y3RfcXVhbnRpdHkgKz0gJHF0eTsKICAgICAgICAgIH0KICAgICAgICB9CgogICAgICAgIC8vIHVwZGF0ZSBieSBiYXJjb2RlX3ByaWNlcwogICAgICAgIGlmICghZW1wdHkoJF9QT1NUWydxdHlfc3ViX3N0b2NrJ10pKSB7CiAgICAgICAgICAkcXR5X3N1Yl9zdG9jayA9IFV0aWw6OmlucHV0KCRfUE9TVFsncXR5X3N1Yl9zdG9jayddKTsKICAgICAgICAgICRxdHlfaW5wdXQgPSBVdGlsOjppbnB1dCgkX1BPU1RbJ0JpbGxJbXBvcnREZXRhaWwnXVsnaW1wb3J0X2JpbGxfZGV0YWlsX3Byb2R1Y3RfcXR5J10pOwogICAgICAgICAgJHF0eV90b3RhbCA9ICgkcXR5X2lucHV0ICogJHF0eV9zdWJfc3RvY2spOwogICAgICAgICAgJHF0eV9hZGQgPSAkcHJvZHVjdC0+cHJvZHVjdF9xdWFudGl0eSArICRxdHlfdG90YWw7CiAgICAgICAgICAkcXR5X2FkZCAtPSAkcXR5X2lucHV0OwoKICAgICAgICAgICRwcm9kdWN0LT5wcm9kdWN0X3F1YW50aXR5ID0gJHF0eV9hZGQ7IAogICAgICAgIH0KCiAgICAgICAgJHByb2R1Y3QtPnNhdmUoKTsKCiAgICAgICAgLy8gU0FWRSBiaWxsX2ltcG9ydF9kZXRhaWwKICAgICAgICAkbW9kZWwtPmF0dHJpYnV0ZXMgPSBVdGlsOjppbnB1dCgkX1BPU1RbIkJpbGxJbXBvcnREZXRhaWwiXSk7CiAgICAgICAgJG1vZGVsLT5pbXBvcnRfYmlsbF9kZXRhaWxfcXR5ID0gKCRxdHkgKiAkcHJvZHVjdC0+cHJvZHVjdF90b3RhbF9wZXJfcGFjayk7CiAgICAgICAgJG1vZGVsLT5wcm9kdWN0X2lkID0gJHByb2R1Y3QtPnByb2R1Y3RfaWQ7CiAgICAgICAgJG1vZGVsLT5pbXBvcnRfYmlsbF9kZXRhaWxfY29kZSA9IFV0aWw6OmlucHV0KCRfUE9TVFsnQmlsbEltcG9ydERldGFpbCddWydwcm9kdWN0X2lkJ10pOwogICAgICAgICRtb2RlbC0+aW1wb3J0X2JpbGxfZGV0YWlsX3F0eV9wZXJfcGFjayA9ICRwcm9kdWN0LT5wcm9kdWN0X3RvdGFsX3Blcl9wYWNrOwoKICAgICAgICAvLyBhZGQgZnJvbSBiYXJjb2RlX3ByaWNlcwogICAgICAgIGlmICghZW1wdHkoJF9QT1NUWydxdHlfc3ViX3N0b2NrJ10pKSB7CiAgICAgICAgICAkbW9kZWwtPmltcG9ydF9iaWxsX2RldGFpbF9xdHkgPSAoJHF0eSAqIFV0aWw6OmlucHV0KCRfUE9TVFsncXR5X3N1Yl9zdG9jayddKSk7CiAgICAgICAgICAkbW9kZWwtPmltcG9ydF9iaWxsX2RldGFpbF9xdHlfcGVyX3BhY2sgPSBVdGlsOjppbnB1dCgkX1BPU1RbJ3F0eV9zdWJfc3RvY2snXSk7CiAgICAgICAgfQoKICAgICAgICAvLyBERUZBVUxUIFBSSUNFCiAgICAgICAgaWYgKGVtcHR5KCRfUE9TVFsnQmlsbEltcG9ydERldGFpbCddWydpbXBvcnRfYmlsbF9kZXRhaWxfcHJpY2UnXSkpIHsKICAgICAgICAgICRtb2RlbC0+aW1wb3J0X2JpbGxfZGV0YWlsX3ByaWNlID0gJHByb2R1Y3QtPnByb2R1Y3RfcHJpY2U7CiAgICAgICAgfQoKICAgICAgICAvLyBTQVZFCiAgICAgICAgaWYgKCRtb2RlbC0+c2F2ZSgpKSB7CiAgICAgICAgICAkdGhpcy0+cmVkaXJlY3QoYXJyYXkoCiAgICAgICAgICAgICAgJ0JpbGxJbXBvcnREZXRhaWwnLAogICAgICAgICAgICAgICdiaWxsX2ltcG9ydF9jb2RlJyA9PiAkYmlsbF9pbXBvcnRfY29kZQogICAgICAgICAgKSk7CiAgICAgICAgfQogICAgICB9CiAgICB9CgogICAgLy8gREFUQSBGT1IgRURJVAogICAgaWYgKCFlbXB0eSgkaWQpKSB7CiAgICAgICRtb2RlbEJpbGxJbXBvcnREZXRhaWwgPSBCaWxsSW1wb3J0RGV0YWlsOjptb2RlbCgpLT5maW5kQnlQaygkaWQpOwogICAgfQoKICAgIC8vIHN1bQogICAgJHN1bVF0eSA9IDA7CiAgICAkc3VtUHJpY2UgPSAwOwoKICAgIC8vIFJFTkRFUgogICAgJHBhZ2luYXRpb24gPSBuZXcgQ1BhZ2luYXRpb24oKTsKICAgICRwYWdpbmF0aW9uLT5zZXRQYWdlU2l6ZSgkY29uZmlnU29mdHdhcmUtPml0ZW1zX3Blcl9wYWdlKTsKCiAgICAkZGF0YVByb3ZpZGVyID0gJG1vZGVsQmlsbEltcG9ydERldGFpbC0+c2VhcmNoKEAkbW9kZWxCaWxsSW1wb3J0LT5iaWxsX2ltcG9ydF9jb2RlKTsKICAgICRkYXRhUHJvdmlkZXItPnNldFBhZ2luYXRpb24oJHBhZ2luYXRpb24pOwoKICAgICR0aGlzLT5yZW5kZXIoJy8vQmFzaWMvQmlsbEltcG9ydERldGFpbCcsIGFycmF5KAogICAgICAgICdtb2RlbEJpbGxJbXBvcnQnID0+ICRtb2RlbEJpbGxJbXBvcnQsCiAgICAgICAgJ21vZGVsJyA9PiAkbW9kZWxCaWxsSW1wb3J0RGV0YWlsLAogICAgICAgICdzdW1RdHknID0+ICRzdW1RdHksCiAgICAgICAgJ3N1bVByaWNlJyA9PiAkc3VtUHJpY2UsCiAgICAgICAgJ2RhdGFQcm92aWRlcicgPT4gJGRhdGFQcm92aWRlcgogICAgKSk7CiAgfQoKICAvLyBCSUxMIElNUE9SVCBERVRBSUwgREVMRVRFCiAgcHVibGljIGZ1bmN0aW9uIGFjdGlvbkJpbGxJbXBvcnREZXRhaWxEZWxldGUoJGlkLCAkYmlsbF9pbXBvcnRfY29kZSkgewogICAgJHRoaXMtPmNoZWNrTG9naW4oKTsKCiAgICAvLyBtb2RlbAogICAgJG1vZGVsID0gQmlsbEltcG9ydERldGFpbDo6bW9kZWwoKS0+ZmluZEJ5UGsoKGludCkgJGlkKTsKICAgICRxdHkgPSAkbW9kZWwtPmltcG9ydF9iaWxsX2RldGFpbF9wcm9kdWN0X3F0eTsKCiAgICAvLyB1cGRhdGUgc3RvY2sKICAgIGlmICghZW1wdHkoJG1vZGVsLT5wcm9kdWN0KSkgewogICAgICAkYmFyY29kZVByaWNlID0gQmFyY29kZVByaWNlOjptb2RlbCgpLT5maW5kQnlBdHRyaWJ1dGVzKGFycmF5KAogICAgICAgICdiYXJjb2RlJyA9PiAkbW9kZWwtPmltcG9ydF9iaWxsX2RldGFpbF9jb2RlCiAgICAgICkpOwoKICAgICAgaWYgKCFlbXB0eSgkYmFyY29kZVByaWNlKSkgewogICAgICAgICR0b3RhbFF0eSA9ICgkbW9kZWwtPmltcG9ydF9iaWxsX2RldGFpbF9xdHlfcGVyX3BhY2sgKiAkbW9kZWwtPmltcG9ydF9iaWxsX2RldGFpbF9wcm9kdWN0X3F0eSk7CiAgICAgICAgJG1vZGVsLT5wcm9kdWN0LT5wcm9kdWN0X3F1YW50aXR5IC09ICR0b3RhbFF0eTsKICAgICAgfSBlbHNlIHsKICAgICAgICAkbW9kZWwtPnByb2R1Y3QtPnByb2R1Y3RfcXVhbnRpdHkgLT0gJHF0eTsKICAgICAgfQoKICAgICAgJG1vZGVsLT5wcm9kdWN0LT5zYXZlKCk7CiAgICB9CgogICAgLy8gZGVsZXRlCiAgICAkbW9kZWwtPmRlbGV0ZUJ5UGsoKGludCkgJGlkKTsKCiAgICAkdGhpcy0+cmVkaXJlY3QoYXJyYXkoJ0JpbGxJbXBvcnREZXRhaWwnLAogICAgICAgICdiaWxsX2ltcG9ydF9jb2RlJyA9PiAkYmlsbF9pbXBvcnRfY29kZQogICAgKSk7CiAgfQoKCS8vIFNBTEUKICBwdWJsaWMgZnVuY3Rpb24gYWN0aW9uU2FsZSgpIHsKICAgICR0aGlzLT5jaGVja0xvZ2luKCk7CgogICAgJG1vZGVsID0gbmV3IEJpbGxTYWxlKCk7CgogICAgaWYgKCFlbXB0eSgkX1BPU1QpKSB7CiAgICAgIFlpaTo6YXBwKCktPnNlc3Npb25bJ3Nlc3Npb25CaWxsU2FsZSddID0gJF9QT1NUOwoKICAgICAgLy8gQklMTCBTQUxFIERFVEFJTAogICAgICAkYXJyYXlCaWxsU2FsZURldGFpbCA9IFlpaTo6YXBwKCktPnNlc3Npb25bJ2JpbGxTYWxlRGV0YWlsJ107CgogICAgICBpZiAoZW1wdHkoJGFycmF5QmlsbFNhbGVEZXRhaWwpKSB7CiAgICAgICAgJGFycmF5QmlsbFNhbGVEZXRhaWwgPSBhcnJheSgpOwogICAgICB9CiAgICAgICRzaXplID0gY291bnQoJGFycmF5QmlsbFNhbGVEZXRhaWwpOwoKICAgICAgLy8gQUREIGJpbGxfc2FsZV9kZXRhaWwgSVRFTVMKICAgICAgJHByb2R1Y3RDb2RlID0gVXRpbDo6aW5wdXQoJF9QT1NUWydwcm9kdWN0X2NvZGUnXSk7CiAgICAgICRwcm9kdWN0UXR5ID0gVXRpbDo6aW5wdXQoJF9QT1NUWydwcm9kdWN0X3F0eSddKTsKICAgICAgJGNvZGUgPSAiIjsKICAgICAgJHByaWNlID0gMDsKICAgICAgJHF0eV9wZXJfcGFjayA9IDA7CgogICAgICAkcHJvZHVjdCA9IFByb2R1Y3Q6Om1vZGVsKCktPmZpbmRCeUF0dHJpYnV0ZXMoYXJyYXkoCiAgICAgICAgJ3Byb2R1Y3RfY29kZScgPT4gJHByb2R1Y3RDb2RlCiAgICAgICkpOwoKICAgICAgJHNhbGVfY29uZGl0aW9uID0gVXRpbDo6aW5wdXQoJF9QT1NUWydzYWxlX2NvbmRpdGlvbiddKTsKCiAgICAgIGlmIChlbXB0eSgkcHJvZHVjdCkpIHsKICAgICAgICAkcHJvZHVjdCA9IFByb2R1Y3Q6Om1vZGVsKCktPmZpbmRCeUF0dHJpYnV0ZXMoYXJyYXkoCiAgICAgICAgICAncHJvZHVjdF9wYWNrX2JhcmNvZGUnID0+ICRwcm9kdWN0Q29kZQogICAgICAgICkpOwoKICAgICAgICBpZiAoIWVtcHR5KCRwcm9kdWN0KSkgewogICAgICAgICAgJGNvZGUgPSAkcHJvZHVjdC0+cHJvZHVjdF9wYWNrX2JhcmNvZGU7CiAgICAgICAgICAkcHJpY2UgPSAkcHJvZHVjdC0+cHJvZHVjdF9wcmljZV9wZXJfcGFjazsKICAgICAgICAgICRxdHlfcGVyX3BhY2sgPSAkcHJvZHVjdC0+cHJvZHVjdF90b3RhbF9wZXJfcGFjazsKICAgICAgICB9CiAgICAgIH0gZWxzZSB7CiAgICAgICAgLy8gRklORCBQUklDRSBPRiBQUk9EVUNUCiAgICAgICAgaWYgKCRzYWxlX2NvbmRpdGlvbiA9PSAnbWFueScpIHsgICAgLy8g4LiB4Lij4LiT4Li14LiC4Liy4Lii4Liq4LmI4LiHCiAgICAgICAgICAkcHJpY2UgPSAkcHJvZHVjdC0+cHJvZHVjdF9wcmljZV9zZW5kOwoKICAgICAgICAgIC8vIOC4hOC5ieC4meC4q+C4suC4o+C4suC4hOC4siDguJfguLXguYjguIHguLPguKvguJnguJTguYTguKfguYnguYPguJkgcHJvZHVjdF9wcmljZXMKICAgICAgICAgICRwcm9kdWN0UHJpY2UgPSBQcm9kdWN0UHJpY2U6Om1vZGVsKCktPmZpbmQoYXJyYXkoCiAgICAgICAgICAgICJjb25kaXRpb24iID0+ICIKICAgICAgICAgICAgICBwcm9kdWN0X2JhcmNvZGUgPSA6cHJvZHVjdENvZGUKICAgICAgICAgICAgICBBTkQgKHF0eSA8PSA6cHJvZHVjdFF0eSBBTkQgcXR5X2VuZCA+PSA6cHJvZHVjdFF0eSkKICAgICAgICAgICAgIiwKICAgICAgICAgICAgInBhcmFtcyIgPT4gYXJyYXkoCiAgICAgICAgICAgICAgInByb2R1Y3RDb2RlIiA9PiAkcHJvZHVjdENvZGUsCiAgICAgICAgICAgICAgInByb2R1Y3RRdHkiID0+ICRwcm9kdWN0UXR5CiAgICAgICAgICAgICkKICAgICAgICAgICkpOwoKICAgICAgICAgIGlmICghZW1wdHkoJHByb2R1Y3RQcmljZSkpIHsKICAgICAgICAgICAgJHByaWNlID0gJHByb2R1Y3RQcmljZS0+cHJpY2Vfc2VuZDsKICAgICAgICAgIH0KICAgICAgICB9IGVsc2UgewogICAgICAgICAgLy8g4LiB4Lij4LiT4Li14LiC4Liy4Lii4Lib4Lil4Li14LiBCiAgICAgICAgICAkcHJpY2UgPSAkcHJvZHVjdC0+cHJvZHVjdF9wcmljZTsKCiAgICAgICAgICAvLyDguITguYnguJnguKvguLLguKPguLLguITguLIg4LiX4Li14LmI4LiB4Liz4Lir4LiZ4LiU4LmE4Lin4LmJ4LmD4LiZIHByb2R1Y3RfcHJpY2VzCiAgICAgICAgICAkcHJvZHVjdFByaWNlID0gUHJvZHVjdFByaWNlOjptb2RlbCgpLT5maW5kKGFycmF5KAogICAgICAgICAgICAiY29uZGl0aW9uIiA9PiAiCiAgICAgICAgICAgICAgcHJvZHVjdF9iYXJjb2RlID0gOnByb2R1Y3RDb2RlCiAgICAgICAgICAgICAgQU5EIChxdHkgPD0gOnByb2R1Y3RRdHkgQU5EIHF0eV9lbmQgPj0gOnByb2R1Y3RRdHkpCiAgICAgICAgICAgICIsCiAgICAgICAgICAgICJwYXJhbXMiID0+IGFycmF5KAogICAgICAgICAgICAgICJwcm9kdWN0Q29kZSIgPT4gJHByb2R1Y3RDb2RlLAogICAgICAgICAgICAgICJwcm9kdWN0UXR5IiA9PiAkcHJvZHVjdFF0eQogICAgICAgICAgICApCiAgICAgICAgICApKTsKCiAgICAgICAgICBpZiAoIWVtcHR5KCRwcm9kdWN0UHJpY2UpKSB7CiAgICAgICAgICAgICRwcmljZSA9ICRwcm9kdWN0UHJpY2UtPnByaWNlOwogICAgICAgICAgfQogICAgICAgIH0KCiAgICAgICAgJGNvZGUgPSAkcHJvZHVjdC0+cHJvZHVjdF9jb2RlOwogICAgICAgICRxdHlfcGVyX3BhY2sgPSAxOwogICAgICB9CgogICAgICAvLyDguKvguLLguKPguLLguITguLIg4LiV4Liy4Lih4LiV4Liy4Lij4Liy4LiHIGJhcmNvZGVfcHJpY2VzCiAgICAgICRiYXJjb2RlUHJpY2UgPSBCYXJjb2RlUHJpY2U6Om1vZGVsKCktPmZpbmRCeUF0dHJpYnV0ZXMoYXJyYXkoCiAgICAgICAgJ2JhcmNvZGUnID0+ICRwcm9kdWN0Q29kZQogICAgICApKTsKCiAgICAgIGlmICghZW1wdHkoJGJhcmNvZGVQcmljZSkpIHsKICAgICAgICAkcHJpY2UgPSAkYmFyY29kZVByaWNlLT5wcmljZTsKICAgICAgICAkcHJvZHVjdCA9ICRiYXJjb2RlUHJpY2UtPmdldFByb2R1Y3QoKTsKICAgICAgICAkcXR5X3Blcl9wYWNrID0gJGJhcmNvZGVQcmljZS0+cXR5X3N1Yl9zdG9jazsKCiAgICAgICAgJHByb2R1Y3QtPnByb2R1Y3RfbmFtZSA9ICRwcm9kdWN0LT5wcm9kdWN0X25hbWUuJyAoICcuJGJhcmNvZGVQcmljZS0+bmFtZS4nICknOwogICAgICB9CgogICAgICAvLyBGT1VORCBQUk9EVUNUCiAgICAgIGlmICghZW1wdHkoJHByb2R1Y3QpKSB7CiAgICAgICAgaWYgKCFlbXB0eSgkX1BPU1RbJ2hpZGRlbl9wcm9kdWN0X2NvZGVzJ10pKSB7CiAgICAgICAgICAvLyBzZWNvbmQgaXRlbQogICAgICAgICAgJGhpZGRlbl9wcm9kdWN0X2NvZGVzID0gVXRpbDo6aW5wdXQoJF9QT1NUWydoaWRkZW5fcHJvZHVjdF9jb2RlcyddKTsKICAgICAgICAgICRoaWRkZW5fcHJvZHVjdF9uYW1lID0gVXRpbDo6aW5wdXQoJF9QT1NUWydoaWRkZW5fcHJvZHVjdF9uYW1lJ10pOwogICAgICAgICAgJGhpZGRlbl9xdHlfcGVyX3BhY2sgPSBVdGlsOjppbnB1dCgkX1BPU1RbJ2hpZGRlbl9xdHlfcGVyX3BhY2snXSk7CiAgICAgICAgICAkc2VyaWFscyA9IFV0aWw6OmlucHV0KCRfUE9TVFsnc2VyaWFscyddKTsKICAgICAgICAgICRwcmljZXMgPSBVdGlsOjppbnB1dCgkX1BPU1RbJ3ByaWNlcyddKTsKICAgICAgICAgICRxdHlzID0gVXRpbDo6aW5wdXQoJF9QT1NUWydxdHlzJ10pOwoKICAgICAgICAgICRhcnIgPSBhcnJheSgpOwoKICAgICAgICAgIC8vIG9sZCBpdGVtCiAgICAgICAgICBmb3IgKCRpID0gMDsgJGkgPCBjb3VudCgkaGlkZGVuX3Byb2R1Y3RfY29kZXMpOyAkaSsrKSB7CiAgICAgICAgICAgICRhcnJbXSA9IGFycmF5KAogICAgICAgICAgICAgICdwcm9kdWN0X3F0eScgPT4gJHF0eXNbJGldLAogICAgICAgICAgICAgICdwcm9kdWN0X2NvZGUnID0+ICRoaWRkZW5fcHJvZHVjdF9jb2Rlc1skaV0sCiAgICAgICAgICAgICAgJ3Byb2R1Y3RfbmFtZScgPT4gJGhpZGRlbl9wcm9kdWN0X25hbWVbJGldLAogICAgICAgICAgICAgICdwcm9kdWN0X3ByaWNlJyA9PiAkcHJpY2VzWyRpXSwKICAgICAgICAgICAgICAncHJvZHVjdF9zZXJpYWxfbm8nID0+ICRzZXJpYWxzWyRpXSwKICAgICAgICAgICAgICAncHJvZHVjdF9leHBpcmVfZGF0ZScgPT4gVXRpbDo6aW5wdXQoJF9QT1NUWydwcm9kdWN0X2V4cGlyZV9kYXRlJ10pLAogICAgICAgICAgICAgICdwcm9kdWN0X3F0eV9wZXJfcGFjaycgPT4gJGhpZGRlbl9xdHlfcGVyX3BhY2tbJGldLAogICAgICAgICAgICAgICdzYWxlX3N0YXR1cycgPT4gVXRpbDo6aW5wdXQoJF9QT1NUWydzYWxlX3N0YXR1cyddKSwKICAgICAgICAgICAgICAnc2FsZV9jb25kaXRpb24nID0+IFV0aWw6OmlucHV0KCRfUE9TVFsnc2FsZV9jb25kaXRpb24nXSksCiAgICAgICAgICAgICAgJ2hhc19ib251cycgPT4gJ25vcm1hbCcsCiAgICAgICAgICAgICAgJ2JpbGxfc2FsZV9jcmVhdGVkX2RhdGUnID0+IFV0aWw6OmlucHV0KCRfUE9TVFsnQmlsbFNhbGUnXVsnYmlsbF9zYWxlX2NyZWF0ZWRfZGF0ZSddKQogICAgICAgICAgICApOwogICAgICAgICAgfQoKICAgICAgICAgIC8vIGFkZCBpdGVtCiAgICAgICAgICAkYXJyW10gPSBhcnJheSgKICAgICAgICAgICAgJ3Byb2R1Y3RfcXR5JyA9PiBVdGlsOjppbnB1dCgkX1BPU1RbJ3Byb2R1Y3RfcXR5J10pLAogICAgICAgICAgICAncHJvZHVjdF9jb2RlJyA9PiBVdGlsOjppbnB1dCgkX1BPU1RbJ3Byb2R1Y3RfY29kZSddKSwKICAgICAgICAgICAgJ3Byb2R1Y3RfbmFtZScgPT4gJHByb2R1Y3QtPnByb2R1Y3RfbmFtZSwKICAgICAgICAgICAgJ3Byb2R1Y3RfcHJpY2UnID0+ICRwcmljZSwKICAgICAgICAgICAgJ3Byb2R1Y3Rfc2VyaWFsX25vJyA9PiBVdGlsOjppbnB1dCgkX1BPU1RbJ3Byb2R1Y3Rfc2VyaWFsX25vJ10pLAogICAgICAgICAgICAncHJvZHVjdF9leHBpcmVfZGF0ZScgPT4gVXRpbDo6aW5wdXQoJF9QT1NUWydwcm9kdWN0X2V4cGlyZV9kYXRlJ10pLAogICAgICAgICAgICAncHJvZHVjdF9xdHlfcGVyX3BhY2snID0+ICRxdHlfcGVyX3BhY2ssCiAgICAgICAgICAgICdzYWxlX3N0YXR1cycgPT4gVXRpbDo6aW5wdXQoJF9QT1NUWydzYWxlX3N0YXR1cyddKSwKICAgICAgICAgICAgJ3NhbGVfY29uZGl0aW9uJyA9PiBVdGlsOjppbnB1dCgkX1BPU1RbJ3NhbGVfY29uZGl0aW9uJ10pLAogICAgICAgICAgICAnaGFzX2JvbnVzJyA9PiAnbm9ybWFsJywKICAgICAgICAgICAgJ2JpbGxfc2FsZV9jcmVhdGVkX2RhdGUnID0+IFV0aWw6OmlucHV0KCRfUE9TVFsnQmlsbFNhbGUnXVsnYmlsbF9zYWxlX2NyZWF0ZWRfZGF0ZSddKQogICAgICAgICAgKTsgICAgIAogICAgICAgIH0gZWxzZSB7IAogICAgICAgICAgLy8gYWRkIGl0ZW0KICAgICAgICAgICRhcnJbXSA9IGFycmF5KAogICAgICAgICAgICAncHJvZHVjdF9xdHknID0+IFV0aWw6OmlucHV0KCRfUE9TVFsncHJvZHVjdF9xdHknXSksCiAgICAgICAgICAgICdwcm9kdWN0X2NvZGUnID0+IFV0aWw6OmlucHV0KCRfUE9TVFsncHJvZHVjdF9jb2RlJ10pLAogICAgICAgICAgICAncHJvZHVjdF9uYW1lJyA9PiAkcHJvZHVjdC0+cHJvZHVjdF9uYW1lLAogICAgICAgICAgICAncHJvZHVjdF9wcmljZScgPT4gJHByaWNlLAogICAgICAgICAgICAncHJvZHVjdF9zZXJpYWxfbm8nID0+IFV0aWw6OmlucHV0KCRfUE9TVFsncHJvZHVjdF9zZXJpYWxfbm8nXSksCiAgICAgICAgICAgICdwcm9kdWN0X2V4cGlyZV9kYXRlJyA9PiBVdGlsOjppbnB1dCgkX1BPU1RbJ3Byb2R1Y3RfZXhwaXJlX2RhdGUnXSksCiAgICAgICAgICAgICdwcm9kdWN0X3F0eV9wZXJfcGFjaycgPT4gJHF0eV9wZXJfcGFjaywKICAgICAgICAgICAgJ3NhbGVfc3RhdHVzJyA9PiBVdGlsOjppbnB1dCgkX1BPU1RbJ3NhbGVfc3RhdHVzJ10pLAogICAgICAgICAgICAnc2FsZV9jb25kaXRpb24nID0+IFV0aWw6OmlucHV0KCRfUE9TVFsnc2FsZV9jb25kaXRpb24nXSksCiAgICAgICAgICAgICdoYXNfYm9udXMnID0+ICdub3JtYWwnLAogICAgICAgICAgICAnYmlsbF9zYWxlX2NyZWF0ZWRfZGF0ZScgPT4gVXRpbDo6aW5wdXQoJF9QT1NUWydCaWxsU2FsZSddWydiaWxsX3NhbGVfY3JlYXRlZF9kYXRlJ10pCiAgICAgICAgICApOwogICAgICAgIH0KICAgICAgICAKICAgICAgICBZaWk6OmFwcCgpLT5zZXNzaW9uWydiaWxsU2FsZURldGFpbCddID0gJGFycjsKICAgICAgICBZaWk6OmFwcCgpLT5zZXNzaW9uWydiaWxsU2FsZUNyZWF0ZWREYXRlJ10gPSBVdGlsOjppbnB1dCgkX1BPU1RbJ0JpbGxTYWxlJ11bJ2JpbGxfc2FsZV9jcmVhdGVkX2RhdGUnXSk7CgogICAgICAgICR0aGlzLT5yZWRpcmVjdChhcnJheSgnU2FsZScpKTsKICAgICAgfQogICAgfQoKICAgIC8vIFJFTkRFUgogICAgJHRoaXMtPnJlbmRlcignLy9CYXNpYy9TYWxlJywgYXJyYXkoCiAgICAgICAgJ21vZGVsJyA9PiAkbW9kZWwKICAgICkpOwogIH0KCgkvLyBTQUxFIERFTEVURQogIHB1YmxpYyBmdW5jdGlvbiBhY3Rpb25TYWxlRGVsZXRlKCRpbmRleCkgewogICAgJHRoaXMtPmNoZWNrTG9naW4oKTsKCiAgICAkYmlsbFNhbGVEZXRhaWwgPSBZaWk6OmFwcCgpLT5zZXNzaW9uWydiaWxsU2FsZURldGFpbCddOwoKICAgIC8vIHJlbW92ZSBwcm9kdWN0IGl0ZW0gZnJvbSBhcnJheQogICAgZm9yICgkaSA9IDA7ICRpIDwgY291bnQoJGJpbGxTYWxlRGV0YWlsKTsgJGkrKykgewogICAgICBpZiAoJGkgPT0gKGludCkgJGluZGV4KSB7CiAgICAgICAgJGJpbGxTYWxlRGV0YWlsWyRpXSA9IG51bGw7CiAgICAgIH0KICAgIH0KCiAgICAvLyBjbGVhciBlbXB0eSBhcnJheSBpdGVtCiAgICAkbmV3QXJyYXkgPSBhcnJheSgpOwogICAgZm9yICgkaSA9IDA7ICRpIDwgY291bnQoJGJpbGxTYWxlRGV0YWlsKTsgJGkrKykgewogICAgICBpZiAoIWVtcHR5KCRiaWxsU2FsZURldGFpbFskaV0pKSB7CiAgICAgICAgJG5ld0FycmF5W2NvdW50KCRuZXdBcnJheSldID0gJGJpbGxTYWxlRGV0YWlsWyRpXTsKICAgICAgfQogICAgfQoKICAgIC8vIGFkZCBuZXcgYXJyYXkgdG8gc2Vzc2lvbgogICAgWWlpOjphcHAoKS0+c2Vzc2lvblsnYmlsbFNhbGVEZXRhaWwnXSA9ICRuZXdBcnJheTsKICAgICR0aGlzLT5yZWRpcmVjdChhcnJheSgnU2FsZScpKTsKICB9CgoJLy8gRU5EIFNBTEUKICBwdWJsaWMgZnVuY3Rpb24gYWN0aW9uRW5kU2FsZSgpIHsKICAgICR0aGlzLT5jaGVja0xvZ2luKCk7CgogICAgJHNhbGVUZW1wcyA9IFNhbGVUZW1wOjptb2RlbCgpLT5maW5kQWxsQnlBdHRyaWJ1dGVzKGFycmF5KAogICAgICAndXNlcl9pZCcgPT4gKGludCkgWWlpOjphcHAoKS0+cmVxdWVzdC0+Y29va2llc1sndXNlcl9pZCddLT52YWx1ZQogICAgKSk7CgogICAgaWYgKCFlbXB0eSgkc2FsZVRlbXBzKSkgewogICAgICAvLyBmaW5kIG1lbWJlcl9pZAogICAgICAkbWVtYmVyX2NvZGUgPSBVdGlsOjppbnB1dCgkX1BPU1RbJ3R4dF9tZW1iZXJfY29kZSddKTsKICAgICAgJG1lbWJlcl9pZCA9IDA7CgogICAgICBpZiAoIWVtcHR5KCRtZW1iZXJfY29kZSkpIHsKICAgICAgICAkbWVtYmVyID0gTWVtYmVyOjptb2RlbCgpLT5maW5kQnlBdHRyaWJ1dGVzKGFycmF5KAogICAgICAgICAgJ21lbWJlcl9jb2RlJyA9PiAkbWVtYmVyX2NvZGUKICAgICAgICApKTsKCiAgICAgICAgaWYgKCFlbXB0eSgkbWVtYmVyKSkgewogICAgICAgICAgJG1lbWJlcl9pZCA9ICRtZW1iZXItPm1lbWJlcl9pZDsKICAgICAgICB9CiAgICAgIH0KCiAgICAgIC8vIHNhbGVfc3RhdHVzCiAgICAgIGlmICgkX1BPU1RbJ3NhbGVfc3RhdHVzJ10gPT0gJ2Nhc2gnKSB7CiAgICAgICAgJHNhbGVTdGF0dXMgPSAncGF5JzsKICAgICAgfSBlbHNlIHsKICAgICAgICAkc2FsZVN0YXR1cyA9ICdjcmVkaXQnOwogICAgICB9CiAgICAgIAoJCQkkY3JlYXRlZF9kYXRlID0gVXRpbDo6aW5wdXQoJF9QT1NUWydCaWxsU2FsZSddWydiaWxsX3NhbGVfY3JlYXRlZF9kYXRlJ10pOwogICAgICAkY3JlYXRlZF9kYXRlID0gVXRpbDo6dGhhaVRvTXlTUUxEYXRlKCRjcmVhdGVkX2RhdGUpOwoKICAgICAgLy8gYmlsbCBzYWxlCiAgICAgICRtb2RlbEJpbGxTYWxlID0gbmV3IEJpbGxTYWxlKCk7CiAgICAgICRtb2RlbEJpbGxTYWxlLT5iaWxsX3NhbGVfY3JlYXRlZF9kYXRlID0gJGNyZWF0ZWRfZGF0ZTsKICAgICAgJG1vZGVsQmlsbFNhbGUtPmJpbGxfc2FsZV9zdGF0dXMgPSAkc2FsZVN0YXR1czsKICAgICAgJG1vZGVsQmlsbFNhbGUtPm1lbWJlcl9pZCA9ICRtZW1iZXJfaWQ7CiAgICAgICRtb2RlbEJpbGxTYWxlLT5iaWxsX3NhbGVfdmF0ID0gVXRpbDo6aW5wdXQoJF9QT1NUWydiaWxsX3NhbGVfdmF0J10pOwogICAgICAkbW9kZWxCaWxsU2FsZS0+dXNlcl9pZCA9IChpbnQpIFlpaTo6YXBwKCktPnJlcXVlc3QtPmNvb2tpZXNbJ3VzZXJfaWQnXS0+dmFsdWU7CiAgICAgICRtb2RlbEJpbGxTYWxlLT5icmFuY2hfaWQgPSBVdGlsOjppbnB1dCgkX1BPU1RbJ0JpbGxTYWxlJ11bJ2JyYW5jaF9pZCddKTsKICAgICAgJG1vZGVsQmlsbFNhbGUtPmJvbnVzX3ByaWNlID0gVXRpbDo6aW5wdXQoJF9QT1NUWydib251c19wcmljZSddKTsKICAgICAgJG1vZGVsQmlsbFNhbGUtPm91dF92YXQgPSBVdGlsOjppbnB1dCgkX1BPU1RbJ291dF92YXQnXSk7CiAgICAgICRtb2RlbEJpbGxTYWxlLT52YXRfdHlwZSA9IFV0aWw6OmlucHV0KCRfUE9TVFsnaGlkZGVuX3ZhdF90eXBlJ10pOwogICAgICAkbW9kZWxCaWxsU2FsZS0+aW5wdXRfbW9uZXkgPSBVdGlsOjppbnB1dCgkX1BPU1RbJ2hpZGRlbl9pbnB1dCddKTsKICAgICAgJG1vZGVsQmlsbFNhbGUtPnJldHVybl9tb25leSA9IFV0aWw6OmlucHV0KCRfUE9TVFsnaGlkZGVuX3JldHVybl9tb25leSddKTsKICAgICAgJG1vZGVsQmlsbFNhbGUtPnRvdGFsX21vbmV5ID0gVXRpbDo6aW5wdXQoJF9QT1NUWydoaWRkZW5fdG90YWwnXSk7CiAgICAgICRtb2RlbEJpbGxTYWxlLT5jdXN0b21lcl9uYW1lID0gVXRpbDo6aW5wdXQoJF9QT1NUWydjdXN0b21lcl9uYW1lJ10pOwogICAgICAkbW9kZWxCaWxsU2FsZS0+Y3VzdG9tZXJfdGVsID0gVXRpbDo6aW5wdXQoJF9QT1NUWydjdXN0b21lcl90ZWwnXSk7CiAgICAgICRtb2RlbEJpbGxTYWxlLT5jdXN0b21lcl90YXggPSBVdGlsOjppbnB1dCgkX1BPU1RbJ2N1c3RvbWVyX3RheCddKTsKICAgICAgJG1vZGVsQmlsbFNhbGUtPmN1c3RvbWVyX2FkZHJlc3MgPSBVdGlsOjppbnB1dCgkX1BPU1RbJ2N1c3RvbWVyX2FkZHJlc3MnXSk7CgogICAgICBpZiAoJF9QT1NUWydzYWxlX3N0YXR1cyddID09ICdjYXNoJykgewogICAgICAgICRfdGltZSA9IGRhdGUoImg6aTpzIik7CiAgICAgICAgJG1vZGVsQmlsbFNhbGUtPmJpbGxfc2FsZV9wYXlfZGF0ZSA9ICRjcmVhdGVkX2RhdGUuIiAiLiRfdGltZTsKICAgICAgfQoKICAgICAgaWYgKCRtb2RlbEJpbGxTYWxlLT5zYXZlKCkpIHsKICAgICAgICAvLyBzdG9yZSBkYXRhIGJpbGxfc2FsZV9kZXRhaWwgZnJvbSBzZXNzaW9uIHRvIGRhdGFiYXNlCiAgICAgICAgJGkgPSAwOwogICAgICAgICRxdHlzID0gJF9QT1NUWydxdHlzJ107CgogICAgICAgIGZvcmVhY2ggKCRzYWxlVGVtcHMgYXMgJHNhbGVUZW1wKSB7ICAgICAgICAgIAogICAgICAgICAgJHF0eV9mb3Jfc3ViX3N0b2NrID0gJHF0eXNbJGldOwoKICAgICAgICAgICRtb2RlbCA9IG5ldyBCaWxsU2FsZURldGFpbCgpOwogICAgICAgICAgJG1vZGVsLT5iaWxsX2lkID0gJG1vZGVsQmlsbFNhbGUtPmJpbGxfc2FsZV9pZDsKICAgICAgICAgICRtb2RlbC0+YmlsbF9zYWxlX2RldGFpbF9iYXJjb2RlID0gJHNhbGVUZW1wLT5iYXJjb2RlOwogICAgICAgICAgJG1vZGVsLT5iaWxsX3NhbGVfZGV0YWlsX3ByaWNlID0gJHNhbGVUZW1wLT5wcmljZTsKICAgICAgICAgICRtb2RlbC0+YmlsbF9zYWxlX2RldGFpbF9xdHkgPSAkc2FsZVRlbXAtPnF0eTsKICAgICAgICAgICRtb2RlbC0+YmlsbF9zYWxlX2RldGFpbF9wcmljZV92YXQgPSAoJHNhbGVUZW1wLT5wcmljZSAqIC4wNyk7CiAgICAgICAgICAkbW9kZWwtPm9sZF9wcmljZSA9ICRzYWxlVGVtcC0+b2xkX3ByaWNlOwogICAgICAgICAgJG1vZGVsLT5zYXZlKCk7CgogICAgICAgICAgLy8gc3ViIHN0b2NrCiAgICAgICAgICAkcHJvZHVjdF9jb2RlID0gJHNhbGVUZW1wLT5iYXJjb2RlOwoKICAgICAgICAgIC8vIGZpbmQgYnkgYmFyY29kZQogICAgICAgICAgJHByb2R1Y3QgPSBQcm9kdWN0Ojptb2RlbCgpLT5maW5kQnlBdHRyaWJ1dGVzKGFycmF5KAogICAgICAgICAgICAncHJvZHVjdF9jb2RlJyA9PiAkcHJvZHVjdF9jb2RlCiAgICAgICAgICApKTsKCiAgICAgICAgICBpZiAoZW1wdHkoJHByb2R1Y3QpKSB7CiAgICAgICAgICAgIC8vIGZpbmQgYnkgcGFjayBiYXJjb2RlCiAgICAgICAgICAgICRwcm9kdWN0ID0gUHJvZHVjdDo6bW9kZWwoKS0+ZmluZEJ5QXR0cmlidXRlcyhhcnJheSgKICAgICAgICAgICAgICAgICdwcm9kdWN0X3BhY2tfYmFyY29kZScgPT4gJHByb2R1Y3RfY29kZQogICAgICAgICAgICApKTsKICAgICAgICAgIH0KCiAgICAgICAgICBpZiAoZW1wdHkoJHByb2R1Y3QpKSB7CiAgICAgICAgICAgIC8vIGZpbmQgYnkgYmFyY29kZV9wcmljZQogICAgICAgICAgICAkYmFyY29kZVByaWNlID0gQmFyY29kZVByaWNlOjptb2RlbCgpLT5maW5kQnlBdHRyaWJ1dGVzKGFycmF5KAogICAgICAgICAgICAgICdiYXJjb2RlJyA9PiAkcHJvZHVjdF9jb2RlCiAgICAgICAgICAgICkpOwogICAgICAgICAgICAkcHJvZHVjdCA9ICRiYXJjb2RlUHJpY2UtPmdldFByb2R1Y3QoKTsKICAgICAgICAgIH0KCiAgICAgICAgICBpZiAoIWVtcHR5KCRzYWxlVGVtcC0+cXR5X3Blcl9wYWNrKSkgewogICAgICAgICAgICAkcXR5X2Zvcl9zdWJfc3RvY2sgPSAoJHNhbGVUZW1wLT5xdHlfcGVyX3BhY2sgKiAkcXR5X2Zvcl9zdWJfc3RvY2spOwogICAgICAgICAgfQoKCQkJCQkkcXR5ID0gKCRwcm9kdWN0LT5wcm9kdWN0X3F1YW50aXR5IC0gJHF0eV9mb3Jfc3ViX3N0b2NrKTsKICAgICAgICAKICAgICAgICAgICRwcm9kdWN0LT5wcm9kdWN0X3F1YW50aXR5ID0gJHF0eTsKICAgICAgICAgICRwcm9kdWN0LT5zYXZlKCk7CgogICAgICAgICAgJGkrKzsKICAgICAgICB9CgogICAgICAgIC8vIHNhdmUgdG8gdGJfcHJvZHVjdF9zZXJpYWwKICAgICAgICAkc2VyaWFscyA9ICRfUE9TVFsnc2VyaWFscyddOwogICAgICAgICRoaWRkZW5fcHJvZHVjdF9jb2RlcyA9ICRfUE9TVFsnaGlkZGVuX3Byb2R1Y3RfY29kZXMnXTsKCiAgICAgICAgaWYgKCFlbXB0eSgkc2VyaWFscykpIHsKICAgICAgICAgICRpID0gMDsKCiAgICAgICAgICBmb3JlYWNoICgkc2VyaWFscyBhcyAkc2VyaWFsKSB7CiAgICAgICAgICAgICRwcm9kdWN0X2NvZGUgPSAkaGlkZGVuX3Byb2R1Y3RfY29kZXNbJGldOwoKICAgICAgICAgICAgJHByb2R1Y3RTZXJpYWwgPSBuZXcgUHJvZHVjdFNlcmlhbCgpOwogICAgICAgICAgICAkcHJvZHVjdFNlcmlhbC0+cHJvZHVjdF9jb2RlID0gJHByb2R1Y3RfY29kZTsKICAgICAgICAgICAgJHByb2R1Y3RTZXJpYWwtPnNlcmlhbF9ubyA9ICRzZXJpYWw7CiAgICAgICAgICAgICRwcm9kdWN0U2VyaWFsLT5wcm9kdWN0X3N0YXJ0X2RhdGUgPSBuZXcgQ0RiRXhwcmVzc2lvbignTk9XKCknKTsKICAgICAgICAgICAgJHByb2R1Y3RTZXJpYWwtPmJpbGxfc2FsZV9pZCA9ICRtb2RlbEJpbGxTYWxlLT5iaWxsX3NhbGVfaWQ7CgogICAgICAgICAgICAvLyBleHBpcmUgZGF0ZQogICAgICAgICAgICBpZiAoIWVtcHR5KCRyWydwcm9kdWN0X2V4cGlyZV9kYXRlJ10pKSB7CiAgICAgICAgICAgICAgJGV4cGlyZV9kYXRlID0gVXRpbDo6dGhhaVRvTXlTUUxEYXRlKCRyWydwcm9kdWN0X2V4cGlyZV9kYXRlJ10pOwogICAgICAgICAgICAgICRwcm9kdWN0U2VyaWFsLT5wcm9kdWN0X2V4cGlyZV9kYXRlID0gJGV4cGlyZV9kYXRlOwogICAgICAgICAgICB9CgogICAgICAgICAgICAkcHJvZHVjdFNlcmlhbC0+c2F2ZSgpOwogICAgICAgICAgfQogICAgICAgIH0KCiAgICAgICAgLy8ga2VlcCBsYXN0IGJpbGxfaWQKICAgICAgICAkb3V0cHV0ID0gYXJyYXkoCiAgICAgICAgICAnbGFzdF9iaWxsX2lkJyA9PiAkbW9kZWxCaWxsU2FsZS0+YmlsbF9zYWxlX2lkLAogICAgICAgICAgJ21lc3NhZ2UnID0+ICdzdWNjZXNzJwogICAgICAgICk7CgogICAgICAgIGVjaG8gQ0pTT046OmVuY29kZSgkb3V0cHV0KTsKICAgICAgfSBlbHNlIHsKICAgICAgICBlY2hvICdjYW4gbm90IHNhdmUgbW9kYWwgYmlsbCBzYWxlJzsKICAgICAgfQogICAgfSBlbHNlIHsKICAgICAgZWNobyAnc2FsZVRlbXAgaXMgYSBlbXB0eSc7CiAgICB9CiAgfQoKCS8vIFNBTEUgUkVTRVQKICBwdWJsaWMgZnVuY3Rpb24gYWN0aW9uU2FsZVJlc2V0KCkgewogICAgJHRoaXMtPmNoZWNrTG9naW4oKTsKCiAgICBZaWk6OmFwcCgpLT5zZXNzaW9uWydiaWxsU2FsZURldGFpbCddID0gbnVsbDsKICAgIFlpaTo6YXBwKCktPnNlc3Npb25bJ3Nlc3Npb25CaWxsU2FsZSddID0gbnVsbDsKCiAgICAkdGhpcy0+cmVkaXJlY3QoYXJyYXkoJ1NhbGUnKSk7CiAgfQoKCS8vIE1BTkFHRSBCSUxMCiAgcHVibGljIGZ1bmN0aW9uIGFjdGlvbk1hbmFnZUJpbGwoKSB7CiAgICAkdGhpcy0+Y2hlY2tMb2dpbigpOwoKCQkvLyBCSUxMIFNBTEUgT0JKRUNUCiAgICAkYmlsbFNhbGUgPSBuZXcgQmlsbFNhbGUoKTsKCgkJLy8gQ09ORElUSU9OCiAgICAkY3JpdGVyaWEgPSBuZXcgQ0RiQ3JpdGVyaWEoKTsKICAgICRjcml0ZXJpYS0+b3JkZXIgPSAnYmlsbF9zYWxlX2lkIERFU0MnOwogICAgJHVzZXJfaWQgPSBudWxsOwoKICAgIGlmICghZW1wdHkoJF9QT1NUKSkgewogICAgICAkdXNlcl9pZCA9ICRfUE9TVFsndXNlcl9pZCddOwoKICAgICAgaWYgKCFlbXB0eSgkdXNlcl9pZCkpIHsKICAgICAgICAkY3JpdGVyaWEtPmNvbmRpdGlvbiA9ICd1c2VyX2lkID0gOnVzZXJfaWQnOwogICAgICAgICRjcml0ZXJpYS0+cGFyYW1zID0gYXJyYXkoJ3VzZXJfaWQnID0+ICR1c2VyX2lkKTsKICAgICAgfQogICAgfQoKICAgICRjb25maWdTb2Z0d2FyZSA9IENvbmZpZ1NvZnR3YXJlOjptb2RlbCgpLT5maW5kKCk7CiAgICAkcGFnaW5hdGlvbiA9IG5ldyBDUGFnaW5hdGlvbigpOwogICAgJHBhZ2luYXRpb24tPnNldFBhZ2VTaXplKCRjb25maWdTb2Z0d2FyZS0+aXRlbXNfcGVyX3BhZ2UpOwoKICAgICRtb2RlbEZvckdyaWQgPSBuZXcgQ0FjdGl2ZURhdGFQcm92aWRlcignQmlsbFNhbGUnLCBhcnJheSgKICAgICAgICAnY3JpdGVyaWEnID0+ICRjcml0ZXJpYQogICAgKSk7CiAgICAkbW9kZWxGb3JHcmlkLT5zZXRQYWdpbmF0aW9uKCRwYWdpbmF0aW9uKTsKCgkJLy8gUkVOREVSCiAgICAkdGhpcy0+cmVuZGVyKCcvL0Jhc2ljL01hbmFnZUJpbGwnLCBhcnJheSgKICAgICAgICAnbW9kZWwnID0+ICRiaWxsU2FsZSwKICAgICAgICAnbW9kZWxGb3JHcmlkJyA9PiAkbW9kZWxGb3JHcmlkLAogICAgICAgICd1c2VyX2lkJyA9PiAkdXNlcl9pZAogICAgKSk7CiAgfQoKCS8vIEJJTEwgU0FMRSBERVRBSUwKICBwdWJsaWMgZnVuY3Rpb24gYWN0aW9uQmlsbFNhbGVEZXRhaWwoJGJpbGxfc2FsZV9pZCkgewogICAgJHRoaXMtPmNoZWNrTG9naW4oKTsKCiAgICAvLyBNT0RFTAogICAgJG1vZGVsQmlsbFNhbGUgPSBCaWxsU2FsZTo6bW9kZWwoKS0+ZmluZEJ5UGsoKGludCkgJGJpbGxfc2FsZV9pZCk7CgogICAgLy8gZGF0YVByb3ZpZGVyCiAgICAkZGF0YVByb3ZpZGVyID0gbmV3IENBY3RpdmVEYXRhUHJvdmlkZXIoJ0JpbGxTYWxlRGV0YWlsJywgYXJyYXkoCiAgICAgICAgJ2NyaXRlcmlhJyA9PiBhcnJheSgKICAgICAgICAgICAgJ2NvbmRpdGlvbicgPT4gImJpbGxfaWQgPSAkYmlsbF9zYWxlX2lkIiwKICAgICAgICAgICAgJ29yZGVyJyA9PiAnYmlsbF9zYWxlX2RldGFpbF9pZCBERVNDJwogICAgICAgICksCiAgICAgICAgJ3BhZ2luYXRpb24nID0+IGZhbHNlCiAgICApKTsKCiAgICAvLyBSRU5ERVIKICAgICR0aGlzLT5yZW5kZXIoJy8vQmFzaWMvQmlsbFNhbGVEZXRhaWwnLCBhcnJheSgKICAgICAgICAnbW9kZWxCaWxsU2FsZScgPT4gJG1vZGVsQmlsbFNhbGUsCiAgICAgICAgJ2RhdGFQcm92aWRlcicgPT4gJGRhdGFQcm92aWRlcgogICAgKSk7CiAgfQoKCS8vIEVESVQgQklMTCBTQUxFIERFVEFJTAogIHB1YmxpYyBmdW5jdGlvbiBhY3Rpb25CaWxsU2FsZURldGFpbEVkaXQoJGJpbGxfc2FsZV9kZXRhaWxfaWQgPSBudWxsKSB7CiAgICAkdGhpcy0+Y2hlY2tMb2dpbigpOwoKICAgIGlmIChlbXB0eSgkYmlsbF9zYWxlX2RldGFpbF9pZCkpIHsKICAgICAgJGJpbGxfc2FsZV9kZXRhaWxfaWQgPSBVdGlsOjppbnB1dCgkX1BPU1RbJ2JpbGxfc2FsZV9kZXRhaWxfaWQnXSk7CiAgICB9CgogICAgJG1vZGVsID0gQmlsbFNhbGVEZXRhaWw6Om1vZGVsKCktPmZpbmRCeVBrKChpbnQpICRiaWxsX3NhbGVfZGV0YWlsX2lkKTsKCiAgICAvLyB1cGRhdGUgYmlsbF9zYWxlX2RldGFpbAogICAgaWYgKCFlbXB0eSgkX1BPU1QpKSB7CiAgICAgICRvbGRfcXR5ID0gVXRpbDo6aW5wdXQoJF9QT1NUWydvbGRfcXR5J10pOwogICAgICAkbmV3X3F0eSA9IFV0aWw6OmlucHV0KCRfUE9TVFsnQmlsbFNhbGVEZXRhaWwnXVsnYmlsbF9zYWxlX2RldGFpbF9xdHknXSk7CiAgICAgICRtb2RlbC0+YmlsbF9zYWxlX2RldGFpbF9xdHkgPSAkbmV3X3F0eTsKICAgICAgJG1vZGVsLT5zYXZlKCk7CgogICAgICAvLyB1cGRhdGUgc3RvY2sKICAgICAgJHByb2R1Y3RfY29kZSA9ICRtb2RlbC0+YmlsbF9zYWxlX2RldGFpbF9iYXJjb2RlOwogICAgICAkcHJvZHVjdCA9IFByb2R1Y3Q6Om1vZGVsKCktPmZpbmQoYXJyYXkoCiAgICAgICAgICAnY29uZGl0aW9uJyA9PiAicHJvZHVjdF9jb2RlID0gOnByb2R1Y3RfY29kZSIsCiAgICAgICAgICAncGFyYW1zJyA9PiBhcnJheSgKICAgICAgICAgICAgJ3Byb2R1Y3RfY29kZScgPT4gJHByb2R1Y3RfY29kZQogICAgICAgICAgKQogICAgICApKTsKCiAgICAgIGlmICgkbmV3X3F0eSA+ICRvbGRfcXR5KSB7CiAgICAgICAgJHVwZGF0ZV9xdHkgPSAoJG5ld19xdHkgLSAkb2xkX3F0eSk7CiAgICAgICAgJHByb2R1Y3QtPnByb2R1Y3RfcXVhbnRpdHkgKz0gJHVwZGF0ZV9xdHk7CiAgICAgIH0gZWxzZSB7CiAgICAgICAgJHVwZGF0ZV9xdHkgPSAoJG9sZF9xdHkgLSAkbmV3X3F0eSk7CiAgICAgICAgJHByb2R1Y3QtPnByb2R1Y3RfcXVhbnRpdHkgLT0gJHVwZGF0ZV9xdHk7CiAgICAgIH0KCiAgICAgICRwcm9kdWN0LT5zYXZlKCk7CiAgICAgICR0aGlzLT5yZWRpcmVjdChhcnJheSgnQmlsbFNhbGVEZXRhaWwnLCAnYmlsbF9zYWxlX2lkJyA9PiAkbW9kZWwtPmJpbGxfaWQpKTsKICAgIH0KCiAgICAvLyBSRURJUkVDVAogICAgJHRoaXMtPnJlbmRlcignLy9CYXNpYy9CaWxsU2FsZUVkaXQnLCBhcnJheSgKICAgICAgJ2JpbGxfc2FsZV9pZCcgPT4gJG1vZGVsLT5iaWxsX2lkLAogICAgICAnbW9kZWwnID0+ICRtb2RlbAogICAgKSk7CiAgfQoKCS8vIERFTEVURSBCSUxMIFNBTEUgREVUQUlMCiAgcHVibGljIGZ1bmN0aW9uIGFjdGlvbkJpbGxTYWxlRGV0YWlsRGVsZXRlKCRiaWxsX3NhbGVfZGV0YWlsX2lkKSB7CiAgICAkdGhpcy0+Y2hlY2tMb2dpbigpOwoKICAgIC8vIE9CSkVDVAogICAgJGJpbGxTYWxlRGV0YWlsID0gQmlsbFNhbGVEZXRhaWw6Om1vZGVsKCktPmZpbmRCeVBrKChpbnQpICRiaWxsX3NhbGVfZGV0YWlsX2lkKTsKICAgICRiaWxsX3NhbGVfaWQgPSAkYmlsbFNhbGVEZXRhaWwtPmJpbGxfaWQ7CgogICAgJGNyaXRlcmlhID0gbmV3IENEYkNyaXRlcmlhKCk7CiAgICAkY3JpdGVyaWEtPmNvbXBhcmUoJ2JpbGxfaWQnLCAkYmlsbF9zYWxlX2lkKTsKICAgICRtb2RlbCA9IEJpbGxTYWxlRGV0YWlsOjptb2RlbCgpLT5maW5kQWxsKCRjcml0ZXJpYSk7CgogICAgJHRvdGFsUm93ID0gY291bnQoJG1vZGVsKTsKCiAgICAvLyBVUERBVEUgU1RPQ0sKICAgICRjcml0ZXJpYSA9IG5ldyBDRGJDcml0ZXJpYSgpOwogICAgJGNyaXRlcmlhLT5jb21wYXJlKCdwcm9kdWN0X2NvZGUnLCAkYmlsbFNhbGVEZXRhaWwtPmJpbGxfc2FsZV9kZXRhaWxfYmFyY29kZSk7CiAgICAkcHJvZHVjdCA9IFByb2R1Y3Q6Om1vZGVsKCktPmZpbmQoJGNyaXRlcmlhKTsKCiAgICAkcHJvZHVjdC0+cHJvZHVjdF9xdWFudGl0eSA9ICgkcHJvZHVjdC0+cHJvZHVjdF9xdWFudGl0eSArICRiaWxsU2FsZURldGFpbC0+YmlsbF9zYWxlX2RldGFpbF9xdHkpOwogICAgJHByb2R1Y3QtPnNhdmUoKTsKCiAgICAvLyBERUxFVEUKICAgICRiaWxsU2FsZURldGFpbC0+ZGVsZXRlKCk7CgogICAgaWYgKCR0b3RhbFJvdyA9PSAxKSB7CiAgICAgIC8vIERFTEVURSBCSUxMX1NBTEUKICAgICAgQmlsbFNhbGU6Om1vZGVsKCktPmRlbGV0ZUJ5UGsoKGludCkgJGJpbGxfc2FsZV9pZCk7CiAgICAgICR0aGlzLT5yZWRpcmVjdChhcnJheSgnTWFuYWdlQmlsbCcpKTsKICAgIH0KCiAgICAvLyBSRURJUkVDVCBGT1IgTUFOQUdFIEJJTExfU0FMRV9ERVRBSUwKICAgICR0aGlzLT5yZWRpcmVjdChhcnJheSgnQmlsbFNhbGVEZXRhaWwnLCAnYmlsbF9zYWxlX2lkJyA9PiAkYmlsbF9zYWxlX2lkKSk7CiAgfQoKCS8vIENIRUNLIFNUT0NLCiAgcHVibGljIGZ1bmN0aW9uIGFjdGlvbkNoZWNrU3RvY2soKSB7CiAgICAkdGhpcy0+Y2hlY2tMb2dpbigpOwoKICAgICRtb2RlbCA9IG5ldyBQcm9kdWN0KCk7CiAgICAkcGFyYW0gPSBhcnJheSgpOwogICAgJHBhcmFtWydtb2RlbCddID0gJG1vZGVsOwogICAgJHBhcmFtWydwcm9kdWN0X2NvZGUnXSA9ICIiOwoKICAgIC8vIGZpbmQgcHJvZHVjdAogICAgaWYgKCFlbXB0eSgkX1BPU1QpKSB7CiAgICAgICRwcm9kdWN0ID0gUHJvZHVjdDo6bW9kZWwoKS0+ZmluZEJ5QXR0cmlidXRlcyhhcnJheSgKICAgICAgICAgICdwcm9kdWN0X2NvZGUnID0+IFV0aWw6OmlucHV0KCRfUE9TVFsnUHJvZHVjdCddWydwcm9kdWN0X2NvZGUnXSkKICAgICAgKSk7CgogICAgICAvLyBmaW5kIGJ5IHBhY2tfY29kZQogICAgICBpZiAoZW1wdHkoJHByb2R1Y3QpKSB7CiAgICAgICAgJHByb2R1Y3QgPSBQcm9kdWN0Ojptb2RlbCgpLT5maW5kQnlBdHRyaWJ1dGVzKGFycmF5KAogICAgICAgICAgICAncHJvZHVjdF9wYWNrX2JhcmNvZGUnID0+IFV0aWw6OmlucHV0KCRfUE9TVFsnUHJvZHVjdCddWydwcm9kdWN0X2NvZGUnXSkKICAgICAgICApKTsKICAgICAgfQoKICAgICAgJHBhcmFtWydwcm9kdWN0J10gPSAkcHJvZHVjdDsKICAgICAgJHBhcmFtWydwcm9kdWN0X2NvZGUnXSA9IFV0aWw6OmlucHV0KCRfUE9TVFsnUHJvZHVjdCddWydwcm9kdWN0X2NvZGUnXSk7CiAgICB9CgogICAgLy8gcmVuZGVyCiAgICAkdGhpcy0+cmVuZGVyKCcvL0Jhc2ljL0NoZWNrU3RvY2snLCAkcGFyYW0pOwogIH0KCgkvLyBCSUxMIERST1AKICBwdWJsaWMgZnVuY3Rpb24gYWN0aW9uQmlsbERyb3AoKSB7CiAgICAkdGhpcy0+Y2hlY2tMb2dpbigpOwoKICAgICRtb2RlbCA9IG5ldyBCaWxsU2FsZSgpOwogICAgJHBhcmFtcyA9IGFycmF5KCk7CgogICAgaWYgKCFlbXB0eSgkX1BPU1QpKSB7CiAgICAgIC8vIGdldCB2YWx1ZQogICAgICAkZnJvbSA9IFV0aWw6OnRoYWlUb015U1FMRGF0ZShVdGlsOjppbnB1dCgkX1BPU1RbJ2Zyb20nXSkpOwogICAgICAkdG8gPSBVdGlsOjp0aGFpVG9NeVNRTERhdGUoVXRpbDo6aW5wdXQoJF9QT1NUWyd0byddKSk7CiAgICAgICRiaWxsX3N0YXR1cyA9IFV0aWw6OmlucHV0KCRfUE9TVFsnYmlsbF9zdGF0dXMnXSk7CgogICAgICAvLyBmaW5kIG1lbWJlciBpZAogICAgICAkbWVtYmVyID0gTWVtYmVyOjptb2RlbCgpLT5maW5kQnlBdHRyaWJ1dGVzKGFycmF5KAogICAgICAgICAgJ21lbWJlcl9jb2RlJyA9PiBVdGlsOjppbnB1dCgkX1BPU1RbJ21lbWJlcl9jb2RlJ10pCiAgICAgICkpOwoKICAgICAgLy8gY3JpdGVyaWEKICAgICAgJGNyaXRlcmlhID0gbmV3IENEYkNyaXRlcmlhKCk7CiAgICAgICRjcml0ZXJpYS0+b3JkZXIgPSAnYmlsbF9zYWxlX2NyZWF0ZWRfZGF0ZSBERVNDICc7CiAgICAgICRjcml0ZXJpYS0+Y29uZGl0aW9uID0gJwogICAgICAgIG1lbWJlcl9pZCA9IDptZW1iZXJfaWQKICAgICAgICBBTkQgREFURShiaWxsX3NhbGVfY3JlYXRlZF9kYXRlKSBCRVRXRUVOIDpmcm9tIEFORCA6dG8KICAgICAgJzsKICAgICAgCiAgICAgIC8vIGZpbHRlciBiaWxsIHN0YXR1cwogICAgICBzd2l0Y2ggKCRiaWxsX3N0YXR1cykgewogICAgICAgIGNhc2UgJ25vJzoKICAgICAgICAgICRjcml0ZXJpYS0+Y29uZGl0aW9uIC49ICcgQU5EIGJpbGxfc2FsZV9wYXlfZGF0ZSBJUyBOVUxMICc7CiAgICAgICAgICAkY3JpdGVyaWEtPmNvbmRpdGlvbiAuPSAnIEFORCBiaWxsX3NhbGVfZHJvcF9iaWxsX2RhdGUgSVMgTlVMTCAnOwogICAgICAgICAgYnJlYWs7CiAgICAgICAgY2FzZSAnZHJvcF9ubyc6CiAgICAgICAgICAkY3JpdGVyaWEtPmNvbmRpdGlvbiAuPSAnIEFORCBiaWxsX3NhbGVfcGF5X2RhdGUgSVMgTlVMTCAnOwogICAgICAgICAgJGNyaXRlcmlhLT5jb25kaXRpb24gLj0gJyBBTkQgYmlsbF9zYWxlX2Ryb3BfYmlsbF9kYXRlIElTIE5PVCBOVUxMICc7CiAgICAgICAgICBicmVhazsKICAgICAgICBjYXNlICdkcm9wX3BheSc6CiAgICAgICAgICAkY3JpdGVyaWEtPmNvbmRpdGlvbiAuPSAnIEFORCBiaWxsX3NhbGVfcGF5X2RhdGUgSVMgTk9UIE5VTEwgJzsKICAgICAgICAgICRjcml0ZXJpYS0+Y29uZGl0aW9uIC49ICcgQU5EIGJpbGxfc2FsZV9kcm9wX2JpbGxfZGF0ZSBJUyBOT1QgTlVMTCAnOwogICAgICAgICAgYnJlYWs7CiAgICAgIH0KCiAgICAgIC8vIHBhcmFtcwogICAgICAkY3JpdGVyaWEtPnBhcmFtcyA9IGFycmF5KAogICAgICAgICAgJ21lbWJlcl9pZCcgPT4gJG1lbWJlci0+bWVtYmVyX2lkLAogICAgICAgICAgJ2Zyb20nID0+ICRmcm9tLAogICAgICAgICAgJ3RvJyA9PiAkdG8KICAgICAgKTsKCiAgICAgIC8vIGRhdGEgcHJvdmlkZXIKICAgICAgJGRhdGFQcm92aWRlciA9IG5ldyBDQWN0aXZlRGF0YVByb3ZpZGVyKCdCaWxsU2FsZScsIGFycmF5KAogICAgICAgICAgJ2NyaXRlcmlhJyA9PiAkY3JpdGVyaWEsCiAgICAgICAgICAncGFnaW5hdGlvbicgPT4gZmFsc2UKICAgICAgKSk7CgogICAgICAvLyBoYXZlIGRhdGEKICAgICAgJHBhcmFtc1snZGF0YVByb3ZpZGVyJ10gPSAkZGF0YVByb3ZpZGVyOwogICAgfSBlbHNlIHsKICAgICAgJGZyb20gPSAiIjsKICAgICAgJHRvID0gIiI7CiAgICB9CgogICAgJHBhcmFtc1snZnJvbSddID0gJGZyb207CiAgICAkcGFyYW1zWyd0byddID0gJHRvOwogICAgJHBhcmFtc1snbW9kZWwnXSA9ICRtb2RlbDsKICAgICRwYXJhbXNbJ21lbWJlcl9jb2RlJ10gPSBAVXRpbDo6aW5wdXQoJF9QT1NUWydtZW1iZXJfY29kZSddKTsKICAgICRwYXJhbXNbJ21lbWJlcl9uYW1lJ10gPSBAVXRpbDo6aW5wdXQoJF9QT1NUWydtZW1iZXJfbmFtZSddKTsKICAgICRwYXJhbXNbJ2JpbGxfc3RhdHVzJ10gPSBAVXRpbDo6aW5wdXQoJF9QT1NUWydiaWxsX3N0YXR1cyddKTsKCiAgICAkdGhpcy0+cmVuZGVyKCcvL0Jhc2ljL0JpbGxEcm9wJywgJHBhcmFtcyk7CiAgfQoKCS8vIEJJTEwgRFJPUCBURU1QCiAgcHVibGljIGZ1bmN0aW9uIGFjdGlvbkJpbGxEcm9wVGVtcCgpIHsKICAgICR0aGlzLT5jaGVja0xvZ2luKCk7CgogICAgWWlpOjphcHAoKS0+c2Vzc2lvblsnaGlkZGVuX21lbWJlcl9jb2RlJ10gPSBVdGlsOjppbnB1dCgkX1BPU1RbJ2hpZGRlbl9tZW1iZXJfY29kZSddKTsKICAgIFlpaTo6YXBwKCktPnNlc3Npb25bJ2JpbGxfc2FsZV9pZHMnXSA9IChpbnQpIFV0aWw6OmlucHV0KCRfUE9TVFsnYmlsbF9zYWxlX2lkJ10pOwoKICAgIGVjaG8gJ2NvbXBsZXRlJzsKICB9CgoJLy8gQklMTCBEUk9QIEdFVAogIHB1YmxpYyBmdW5jdGlvbiBhY3Rpb25CaWxsRHJvcEdldCgpIHsKICAgICR0aGlzLT5jaGVja0xvZ2luKCk7CgogICAgJGJpbGxfc2FsZV9pZHMgPSAoaW50KSBVdGlsOjppbnB1dCgkX1BPU1RbJ2JpbGxfc2FsZV9pZCddKTsKCiAgICBmb3JlYWNoICgkYmlsbF9zYWxlX2lkcyBhcyAkaWQpIHsKICAgICAgJG1vZGVsID0gQmlsbFNhbGU6Om1vZGVsKCktPmZpbmRCeVBrKChpbnQpICRpZCk7CiAgICAgICRtb2RlbC0+YmlsbF9zYWxlX3BheV9kYXRlID0gbmV3IENEYkV4cHJlc3Npb24oIk5PVygpIik7CiAgICAgICRtb2RlbC0+YmlsbF9zYWxlX3N0YXR1cyA9ICdwYXknOwogICAgICAkbW9kZWwtPnNhdmUoKTsKICAgIH0KCiAgICBlY2hvICdjb21wbGV0ZSc7CiAgfQoKCS8vIEJJTEwgRFJPUCBDQU5DRUwKICBwdWJsaWMgZnVuY3Rpb24gYWN0aW9uQmlsbERyb3BDYW5jZWwoKSB7CiAgICAkdGhpcy0+Y2hlY2tMb2dpbigpOwoKICAgICRiaWxsX3NhbGVfaWRzID0gKGludCkgVXRpbDo6aW5wdXQoJF9QT1NUWydiaWxsX3NhbGVfaWQnXSk7CgogICAgZm9yZWFjaCAoJGJpbGxfc2FsZV9pZHMgYXMgJGlkKSB7CiAgICAgICRtb2RlbCA9IEJpbGxTYWxlOjptb2RlbCgpLT5maW5kQnlQaygoaW50KSAkaWQpOwogICAgICAkbW9kZWwtPmJpbGxfc2FsZV9wYXlfZGF0ZSA9IG51bGw7CiAgICAgICRtb2RlbC0+YmlsbF9zYWxlX2Ryb3BfYmlsbF9kYXRlID0gbnVsbDsKICAgICAgJG1vZGVsLT5iaWxsX3NhbGVfc3RhdHVzID0gJ2NyZWRpdCc7CiAgICAgICRtb2RlbC0+c2F2ZSgpOwogICAgfQoKICAgIGVjaG8gdHJ1ZTsKICB9CgogIC8vIEJJTEwgRFJPUCBERUxFVEUKICBwdWJsaWMgZnVuY3Rpb24gYWN0aW9uQmlsbERyb3BEZWxldGUoKSB7CiAgICAkdGhpcy0+Y2hlY2tMb2dpbigpOwoKICAgICRiaWxsX3NhbGVfaWRzID0gKGludCkgVXRpbDo6aW5wdXQoJF9QT1NUWydiaWxsX3NhbGVfaWQnXSk7CgogICAgZm9yZWFjaCAoJGJpbGxfc2FsZV9pZHMgYXMgJGlkKSB7CiAgICAgICRiaWxsU2FsZURldGFpbHMgPSBCaWxsU2FsZURldGFpbDo6bW9kZWwoKS0+ZmluZEFsbEJ5QXR0cmlidXRlcyhhcnJheSgKICAgICAgCQknYmlsbF9pZCcgPT4gJGlkCiAgICAgICkpOwoKICAgICAgZm9yZWFjaCAoJGJpbGxTYWxlRGV0YWlscyBhcyAkYmlsbFNhbGVEZXRhaWwpIHsKCSAgICAgCSRiaWxsU2FsZURldGFpbC0+ZGVsZXRlKCk7CiAgICAgIH0KCiAgICAgIEJpbGxTYWxlOjptb2RlbCgpLT5kZWxldGVCeVBrKChpbnQpICRpZCk7CiAgICB9CgogICAgZWNobyB0cnVlOwogIH0KCgkvLyBHRVQgU0FMRQogIHB1YmxpYyBmdW5jdGlvbiBhY3Rpb25HZXRTYWxlKCkgewogICAgJHRoaXMtPmNoZWNrTG9naW4oKTsKCiAgICAkbW9kZWwgPSBuZXcgQmlsbFNhbGVEZXRhaWwoKTsKICAgICRwcm9kdWN0ID0gbnVsbDsKCiAgICAvLyBzZWFyY2gKICAgIGlmICghZW1wdHkoJF9QT1NUKSkgewoJCQkkYmFyY29kZSA9IFV0aWw6OmlucHV0KCRfUE9TVFsnQmlsbFNhbGVEZXRhaWwnXVsnYmlsbF9zYWxlX2RldGFpbF9iYXJjb2RlJ10pOwoKICAgICAgaWYgKGVtcHR5KCRfUE9TVFsncHJvZHVjdF9pZCddKSkgewogICAgICAgIC8vIGZpbmQgZGF0YQogICAgICAgICRiaWxsU2FsZURldGFpbCA9IEJpbGxTYWxlRGV0YWlsOjptb2RlbCgpLT5maW5kQnlBdHRyaWJ1dGVzKGFycmF5KAogICAgICAgICAgICAnYmlsbF9zYWxlX2RldGFpbF9iYXJjb2RlJyA9PiAkYmFyY29kZSwKICAgICAgICAgICAgJ2JpbGxfaWQnID0+IChpbnQpIFV0aWw6OmlucHV0KCRfUE9TVFsnQmlsbFNhbGVEZXRhaWwnXVsnYmlsbF9pZCddKQogICAgICAgICkpOwogICAgICAgICRtb2RlbC0+X2F0dHJpYnV0ZXMgPSAkX1BPU1RbJ0JpbGxTYWxlRGV0YWlsJ107CgogICAgICAgIC8vIGZpbmQgYnkgcHJvZHVjdF9pZAogICAgICAgIGlmICghZW1wdHkoJGJpbGxTYWxlRGV0YWlsKSkgewogICAgICAgICAgJHByb2R1Y3QgPSBQcm9kdWN0Ojptb2RlbCgpLT5maW5kQnlBdHRyaWJ1dGVzKGFycmF5KAogICAgICAgICAgICAgICdwcm9kdWN0X2NvZGUnID0+ICRiaWxsU2FsZURldGFpbC0+YmlsbF9zYWxlX2RldGFpbF9iYXJjb2RlCiAgICAgICAgICApKTsKICAgICAgICAgIGlmICghZW1wdHkoJHByb2R1Y3QpKSB7CiAgICAgICAgICAgICRtb2RlbC0+YmlsbF9zYWxlX2RldGFpbF9iYXJjb2RlID0gJHByb2R1Y3QtPnByb2R1Y3RfY29kZTsKICAgICAgICAgIH0KICAgICAgICB9CiAgICAgIH0gZWxzZSB7CiAgICAgICAgLy8gZ2V0IHByb2R1Y3QKICAgICAgICAkcHJvZHVjdCA9IFByb2R1Y3Q6Om1vZGVsKCktPmZpbmRCeVBrKCRfUE9TVFsncHJvZHVjdF9pZCddKTsKCiAgICAgICAgLy8gcmVtb3ZlIGZyb20gYmlsbAogICAgICAgIEJpbGxTYWxlRGV0YWlsOjptb2RlbCgpLT5kZWxldGVBbGxCeUF0dHJpYnV0ZXMoYXJyYXkoCiAgICAgICAgICAgICdiaWxsX3NhbGVfZGV0YWlsX2JhcmNvZGUnID0+ICRiYXJjb2RlLAogICAgICAgICAgICAnYmlsbF9pZCcgPT4gKGludCkgVXRpbDo6aW5wdXQoJF9QT1NUWydCaWxsU2FsZURldGFpbCddWydiaWxsX2lkJ10pCiAgICAgICAgKSk7CgogICAgICAgIC8vIHVwZGF0ZSBzdG9jayBhbmQgcmVkaXJlY3QKICAgICAgICAkcHJvZHVjdC0+cHJvZHVjdF9xdWFudGl0eSArPSAxOwogICAgICAgICRwcm9kdWN0LT5zYXZlKCk7CgogICAgICAgICR0aGlzLT5yZWRpcmVjdChhcnJheSgnR2V0U2FsZScpKTsKICAgICAgfQogICAgfQoKICAgIC8vIHJlbmRlcgogICAgJHRoaXMtPnJlbmRlcignLy9CYXNpYy9HZXRTYWxlJywgYXJyYXkoCiAgICAgICAgJ21vZGVsJyA9PiAkbW9kZWwsCiAgICAgICAgJ3Byb2R1Y3QnID0+ICRwcm9kdWN0CiAgICApKTsKICB9CgoJLy8gUkVQQUlSCiAgcHVibGljIGZ1bmN0aW9uIGFjdGlvblJlcGFpcigpIHsKICAgICR0aGlzLT5jaGVja0xvZ2luKCk7CgogICAgJHBhcmFtcyA9IEAkX1BPU1Q7CgogICAgaWYgKCFlbXB0eSgkX1BPU1QpKSB7CiAgICAgIC8vIHNlYXJjaAogICAgICAkc2VhcmNoID0gVXRpbDo6aW5wdXQoJF9QT1NUWydzZWFyY2hfY29kZSddKTsKCiAgICAgIGlmIChlbXB0eSgkc2VhcmNoKSkgewogICAgICAgICRzZWFyY2ggPSBVdGlsOjppbnB1dCgkX0dFVFsnc2VyaWFsX2NvZGUnXSk7CiAgICAgIH0KCiAgICAgIC8vIHByb2R1Y3RTZXJpYWwKICAgICAgJHByb2R1Y3RTZXJpYWwgPSBQcm9kdWN0U2VyaWFsOjptb2RlbCgpLT5maW5kQnlBdHRyaWJ1dGVzKGFycmF5KAogICAgICAgICAgJ3NlcmlhbF9ubycgPT4gJHNlYXJjaAogICAgICApKTsKCiAgICAgIGlmICghZW1wdHkoJHByb2R1Y3RTZXJpYWwpKSB7CiAgICAgICAgJHByb2R1Y3QgPSBQcm9kdWN0Ojptb2RlbCgpLT5maW5kQnlBdHRyaWJ1dGVzKGFycmF5KAogICAgICAgICAgICAncHJvZHVjdF9jb2RlJyA9PiAkcHJvZHVjdFNlcmlhbC0+cHJvZHVjdF9jb2RlCiAgICAgICAgKSk7CgogICAgICAgICRwYXJhbXNbJ3Byb2R1Y3QnXSA9ICRwcm9kdWN0OwogICAgICAgICRwYXJhbXNbJ3Byb2R1Y3RTZXJpYWwnXSA9ICRwcm9kdWN0U2VyaWFsOwogICAgICB9CgogICAgICAvLyByZXBhaXIgaGlzdG9yeQogICAgICAkY3JpdGVyaWEgPSBuZXcgQ0RiQ3JpdGVyaWEoKTsKICAgICAgJGNyaXRlcmlhLT5jb21wYXJlKCdzZXJpYWxfbm8nLCBVdGlsOjppbnB1dCgkX1BPU1RbJ3NlYXJjaF9jb2RlJ10pKTsKICAgICAgJGNyaXRlcmlhLT5vcmRlciA9ICdyZXBhaXJfaWQgREVTQyc7CgogICAgICAkcmVwYWlycyA9IG5ldyBDQWN0aXZlRGF0YVByb3ZpZGVyKCdSZXBhaXInKTsKICAgICAgJHJlcGFpcnMtPnNldENyaXRlcmlhKCRjcml0ZXJpYSk7CiAgICAgICRwYXJhbXNbJ3JlcGFpcnMnXSA9ICRyZXBhaXJzOwogICAgfQoKICAgICR0aGlzLT5yZW5kZXIoJy8vQmFzaWMvUmVwYWlyJywgJHBhcmFtcyk7CiAgfQoKICBmdW5jdGlvbiBhY3Rpb25TdGFydFJlcGFpcigpIHsKICAgICR0aGlzLT5jaGVja0xvZ2luKCk7CgogICAgJHNlcmlhbF9jb2RlID0gJF9HRVRbJ3NlcmlhbF9jb2RlJ107CgogICAgLy8gcHJvZHVjdCBzZXJpYWwKICAgICRwcm9kdWN0U2VyaWFsID0gWWlpOjphcHAoKS0+ZGItPmNyZWF0ZUNvbW1hbmQoKQogICAgICAgICAgICAtPnNlbGVjdCgndGJfcHJvZHVjdF9zZXJpYWwuKiwgdGJfcHJvZHVjdC5wcm9kdWN0X25hbWUsIHRiX2JpbGxfc2FsZS5iaWxsX3NhbGVfY3JlYXRlZF9kYXRlJykKICAgICAgICAgICAgLT5mcm9tKCd0Yl9wcm9kdWN0X3NlcmlhbCcpCiAgICAgICAgICAgIC0+am9pbigndGJfcHJvZHVjdCcsICd0Yl9wcm9kdWN0LnByb2R1Y3RfY29kZSA9IHRiX3Byb2R1Y3Rfc2VyaWFsLnByb2R1Y3RfY29kZScpCiAgICAgICAgICAgIC0+am9pbigndGJfYmlsbF9zYWxlJywgJ3RiX2JpbGxfc2FsZS5iaWxsX3NhbGVfaWQgPSB0Yl9wcm9kdWN0X3NlcmlhbC5iaWxsX3NhbGVfaWQnKQogICAgICAgICAgICAtPndoZXJlKCd0Yl9wcm9kdWN0X3NlcmlhbC5zZXJpYWxfbm8gPSAnIC4gJHNlcmlhbF9jb2RlKQogICAgICAgICAgICAtPnF1ZXJ5Um93KCk7CgogICAgLy8gcmVwYWlyCiAgICBpZiAoIWVtcHR5KCRfR0VUWydyZXBhaXJfaWQnXSkpIHsKICAgICAgJHJlcGFpciA9IFJlcGFpcjo6bW9kZWwoKS0+ZmluZEJ5UGsoKGludCkgJF9HRVRbJ3JlcGFpcl9pZCddKTsKICAgIH0gZWxzZSB7CiAgICAgICRyZXBhaXIgPSBuZXcgUmVwYWlyKCk7CiAgICB9CgogICAgLy8gcmVuZGVyCiAgICAkdGhpcy0+cmVuZGVyKCcvL0Jhc2ljL1N0YXJ0UmVwYWlyJywgYXJyYXkoCiAgICAgICAgJ3Byb2R1Y3RTZXJpYWwnID0+ICRwcm9kdWN0U2VyaWFsLAogICAgICAgICdyZXBhaXInID0+ICRyZXBhaXIKICAgICkpOwogIH0KCiAgZnVuY3Rpb24gYWN0aW9uU3RhcnRSZXBhaXJTYXZlKCkgewogICAgJHRoaXMtPmNoZWNrTG9naW4oKTsKCiAgICBpZiAoIWVtcHR5KCRfUE9TVCkpIHsKICAgICAgLy8gc2VyYWlsX2NvZGUKICAgICAgJHNlcmlhbF9jb2RlID0gVXRpbDo6aW5wdXQoJF9QT1NUWydSZXBhaXInXVsnc2VyaWFsX25vJ10pOwoKICAgICAgLy8gc2F2ZQogICAgICAkc3RhdGVfbmV3ID0gdHJ1ZTsKCiAgICAgIGlmIChlbXB0eSgkX1BPU1RbJ1JlcGFpciddWydyZXBhaXJfaWQnXSkpIHsKICAgICAgICAkcmVwYWlyID0gbmV3IFJlcGFpcigpOwogICAgICB9IGVsc2UgewogICAgICAgICRzdGF0ZV9uZXcgPSBmYWxzZTsKICAgICAgICAkcmVwYWlyID0gUmVwYWlyOjptb2RlbCgpLT5maW5kQnlQaygoaW50KSBVdGlsOjppbnB1dCgkX1BPU1RbJ1JlcGFpciddWydyZXBhaXJfaWQnXSkpOwogICAgICB9CgogICAgICAkcmVwYWlyLT5fYXR0cmlidXRlcyA9ICRfUE9TVFsnUmVwYWlyJ107CiAgICAgICRyZXBhaXItPnVzZXJfaWQgPSAoaW50KSBVdGlsOjppbnB1dCgkX1BPU1RbJ3VzZXJfaWQnXSk7CiAgICAgICRyZXBhaXItPnJlcGFpcl9jcmVhdGVkX2RhdGUgPSBVdGlsOjp0aGFpVG9NeVNRTERhdGUoVXRpbDo6aW5wdXQoJF9QT1NUWydyZXBhaXJfY3JlYXRlZF9kYXRlJ10pKTsKICAgICAgJHJlcGFpci0+YnJhbmNoX2lkID0gVXRpbDo6aW5wdXQoJF9QT1NUWydoaWRkZW5fYnJhbmNoX2lkJ10pOwogICAgICAkcmVwYWlyLT5yZXBhaXJfZGF0ZSA9IFV0aWw6OnRoYWlUb015U1FMRGF0ZShVdGlsOjppbnB1dCgkX1BPU1RbJ1JlcGFpciddWydyZXBhaXJfZGF0ZSddKSk7CgogICAgICBpZiAoJHJlcGFpci0+c2F2ZSgpKSB7CiAgICAgICAgaWYgKCRzdGF0ZV9uZXcpIHsKICAgICAgICAgICR0aGlzLT5yZWRpcmVjdChhcnJheSgnQmFzaWMvU3RhcnRSZXBhaXInLCAnc2VyaWFsX2NvZGUnID0+ICRzZXJpYWxfY29kZSkpOwogICAgICAgIH0gZWxzZSB7CiAgICAgICAgICAkdGhpcy0+cmVkaXJlY3QoYXJyYXkoJ0Jhc2ljL1JlcGFpcicsICdzZXJpYWxfY29kZScgPT4gJHNlcmlhbF9jb2RlKSk7CiAgICAgICAgfQogICAgICB9CiAgICB9CiAgfQoKICBmdW5jdGlvbiBhY3Rpb25SZXBhaXJWaWV3KCRyZXBhaXJfaWQpIHsKICAgICR0aGlzLT5jaGVja0xvZ2luKCk7CgogICAgJHNlcmlhbF9jb2RlID0gVXRpbDo6aW5wdXQoJF9HRVRbJ3NlcmlhbF9jb2RlJ10pOwoKICAgIC8vIHByb2R1Y3Qgc2VyaWFsCiAgICAkcHJvZHVjdFNlcmlhbCA9IFlpaTo6YXBwKCktPmRiLT5jcmVhdGVDb21tYW5kKCkKICAgICAgICAgICAgLT5zZWxlY3QoJ3RiX3Byb2R1Y3Rfc2VyaWFsLiosIHRiX3Byb2R1Y3QucHJvZHVjdF9uYW1lLCB0Yl9iaWxsX3NhbGUuYmlsbF9zYWxlX2NyZWF0ZWRfZGF0ZScpCiAgICAgICAgICAgIC0+ZnJvbSgndGJfcHJvZHVjdF9zZXJpYWwnKQogICAgICAgICAgICAtPmpvaW4oJ3RiX3Byb2R1Y3QnLCAndGJfcHJvZHVjdC5wcm9kdWN0X2NvZGUgPSB0Yl9wcm9kdWN0X3NlcmlhbC5wcm9kdWN0X2NvZGUnKQogICAgICAgICAgICAtPmpvaW4oJ3RiX2JpbGxfc2FsZScsICd0Yl9iaWxsX3NhbGUuYmlsbF9zYWxlX2lkID0gdGJfcHJvZHVjdF9zZXJpYWwuYmlsbF9zYWxlX2lkJykKICAgICAgICAgICAgLT53aGVyZSgndGJfcHJvZHVjdF9zZXJpYWwuc2VyaWFsX25vID0gJyAuICRzZXJpYWxfY29kZSkKICAgICAgICAgICAgLT5xdWVyeVJvdygpOwoKICAgIC8vIHJlcGFpcgogICAgaWYgKCFlbXB0eSgkX0dFVFsncmVwYWlyX2lkJ10pKSB7CiAgICAgICRyZXBhaXIgPSBSZXBhaXI6Om1vZGVsKCktPmZpbmRCeVBrKChpbnQpICRfR0VUWydyZXBhaXJfaWQnXSk7CiAgICB9IGVsc2UgewogICAgICAkcmVwYWlyID0gbmV3IFJlcGFpcigpOwogICAgfQoKICAgIC8vIHJlbmRlcgogICAgJHRoaXMtPnJlbmRlcignLy9CYXNpYy9SZXBhaXJWaWV3JywgYXJyYXkoCiAgICAgICAgJ3Byb2R1Y3RTZXJpYWwnID0+ICRwcm9kdWN0U2VyaWFsLAogICAgICAgICdyZXBhaXInID0+ICRyZXBhaXIKICAgICkpOwogIH0KCiAgZnVuY3Rpb24gYWN0aW9uQmlsbFF1b3RhdGlvbigpIHsKICAgICR0aGlzLT5jaGVja0xvZ2luKCk7CiAgICAkdGhpcy0+cmVuZGVyKCIvL0Jhc2ljL0JpbGxRdW90YXRpb24iKTsKICB9CgogIGZ1bmN0aW9uIGFjdGlvblF1b3RhdGlvblNhdmUoJHF1b3RhdGlvbl9pZCA9IG51bGwpIHsKICAgICR0aGlzLT5jaGVja0xvZ2luKCk7CgogICAgaWYgKCFlbXB0eSgkX1BPU1QpKSB7CiAgICAgIGlmIChlbXB0eSgkcXVvdGF0aW9uX2lkKSkgewogICAgICAgIC8vIElOU0VSVCBEQVRBIFRPIFRBQkxFCiAgICAgICAgJHF1b3RhdGlvbiA9IG5ldyBRdW90YXRpb24oKTsKICAgICAgICAkcXVvdGF0aW9uLT5jcmVhdGVkX2F0ID0gbmV3IENEYkV4cHJlc3Npb24oIk5PVygpIik7CiAgICAgIH0gZWxzZSB7CiAgICAgICAgJHF1b3RhdGlvbiA9IFF1b3RhdGlvbjo6bW9kZWwoKS0+ZmluZEJ5UGsoKGludCkgJHF1b3RhdGlvbl9pZCk7CiAgICAgIH0KCiAgICAgICRxdW90YXRpb24tPmN1c3RvbWVyX25hbWUgPSBVdGlsOjppbnB1dCgkX1BPU1RbJ2N1c3RvbWVyX25hbWUnXSk7CiAgICAgICRxdW90YXRpb24tPmN1c3RvbWVyX2FkZHJlc3MgPSBVdGlsOjppbnB1dCgkX1BPU1RbJ2N1c3RvbWVyX2FkZHJlc3MnXSk7CiAgICAgICRxdW90YXRpb24tPmN1c3RvbWVyX3RlbCA9IFV0aWw6OmlucHV0KCRfUE9TVFsnY3VzdG9tZXJfdGVsJ10pOwogICAgICAkcXVvdGF0aW9uLT5jdXN0b21lcl9mYXggPSBVdGlsOjppbnB1dCgkX1BPU1RbJ2N1c3RvbWVyX2ZheCddKTsKICAgICAgJHF1b3RhdGlvbi0+Y3VzdG9tZXJfdGF4ID0gVXRpbDo6aW5wdXQoJF9QT1NUWydjdXN0b21lcl90YXgnXSk7CiAgICAgICRxdW90YXRpb24tPnF1b3RhdGlvbl9kYXkgPSBVdGlsOjppbnB1dCgkX1BPU1RbJ3F1b3RhdGlvbl9kYXknXSk7CiAgICAgICRxdW90YXRpb24tPnF1b3RhdGlvbl9zZW5kX2RheSA9IFV0aWw6OmlucHV0KCRfUE9TVFsncXVvdGF0aW9uX3NlbmRfZGF5J10pOwogICAgICAkcXVvdGF0aW9uLT5xdW90YXRpb25fcGF5ID0gVXRpbDo6aW5wdXQoJF9QT1NUWydxdW90YXRpb25fcGF5J10pOwogICAgICAgIAogICAgICAkcXVvdGF0aW9uLT51c2VyX2lkID0gWWlpOjphcHAoKS0+cmVxdWVzdC0+Y29va2llc1sidXNlcl9pZCJdLT52YWx1ZTsKICAgICAgJHF1b3RhdGlvbi0+dmF0ID0gVXRpbDo6aW5wdXQoJF9QT1NUWyd2YXQnXSk7CgogICAgICBpZiAoJHF1b3RhdGlvbi0+c2F2ZSgpKSB7CiAgICAgICAgLy8gSU5TRVJUIFRPIHF1b3RhdGlvbl9kZXRhaWxzCiAgICAgICAgJGJhcmNvZGVzID0gVXRpbDo6aW5wdXQoJF9QT1NUWydiYXJjb2RlX2hpZGRlbiddKTsKCiAgICAgICAgLy8gY2xlYXIgcXVvdGF0aW9uIGRldGFpbAogICAgICAgIGlmICghZW1wdHkoJHF1b3RhdGlvbl9pZCkpIHsKICAgICAgICAgIFF1b3RhdGlvbkRldGFpbDo6bW9kZWwoKS0+ZGVsZXRlQWxsQnlBdHRyaWJ1dGVzKGFycmF5KAogICAgICAgICAgICAncXVvdGF0aW9uX2lkJyA9PiAkcXVvdGF0aW9uX2lkCiAgICAgICAgICApKTsKICAgICAgICB9CgogICAgICAgIC8vIGluc2VydCBxdW90YXRpb24gZGF0YQogICAgICAgIGZvciAoJGkgPSAwOyAkaSA8IGNvdW50KCRiYXJjb2Rlcyk7ICRpKyspIHsKICAgICAgICAgICRxdW90YXRpb25EZXRhaWwgPSBuZXcgUXVvdGF0aW9uRGV0YWlsKCk7CiAgICAgICAgICAkcXVvdGF0aW9uRGV0YWlsLT5xdW90YXRpb25faWQgPSAkcXVvdGF0aW9uLT5pZDsKICAgICAgICAgICRxdW90YXRpb25EZXRhaWwtPmJhcmNvZGUgPSBVdGlsOjppbnB1dCgkX1BPU1RbJ2JhcmNvZGVfaGlkZGVuJ11bJGldKTsKICAgICAgICAgICRxdW90YXRpb25EZXRhaWwtPm9sZF9wcmljZSA9IHN0cl9yZXBsYWNlKCIsIiwgIiIsIFV0aWw6OmlucHV0KCRfUE9TVFsnb2xkX3ByaWNlJ11bJGldKSk7CiAgICAgICAgICAkcXVvdGF0aW9uRGV0YWlsLT5xdHkgPSBzdHJfcmVwbGFjZSgiLCIsICIiLCBVdGlsOjppbnB1dCgkX1BPU1RbJ3F0eSddWyRpXSkpOwogICAgICAgICAgJHF1b3RhdGlvbkRldGFpbC0+c3ViID0gc3RyX3JlcGxhY2UoIiwiLCAiIiwgVXRpbDo6aW5wdXQoJF9QT1NUWydzdWInXVskaV0pKTsKICAgICAgICAgICRxdW90YXRpb25EZXRhaWwtPnNhbGVfcHJpY2UgPSBzdHJfcmVwbGFjZSgiLCIsICIiLCBVdGlsOjppbnB1dCgkX1BPU1RbJ3NhbGVfcHJpY2UnXVskaV0pKTsKICAgICAgICAgICRxdW90YXRpb25EZXRhaWwtPnNhdmUoKTsKICAgICAgICB9CgogICAgICAgIFlpaTo6YXBwKCktPnNlc3Npb25bJ2N1cnJlbnRfcXVvdGF0aW9uX2lkJ10gPSAkcXVvdGF0aW9uLT5pZDsKICAgICAgfQogICAgfSBlbHNlIHsKICAgICAgWWlpOjphcHAoKS0+c2Vzc2lvblsnY3VycmVudF9xdW90YXRpb25faWQnXSA9ICRxdW90YXRpb25faWQ7CiAgICB9CgogICAgJGFyciA9IGFycmF5KAogICAgICAnbWVzc2FnZScgPT4gJ3N1Y2Nlc3MnCiAgICApOwogICAgCiAgICBlY2hvIENKU09OOjplbmNvZGUoJGFycik7CiAgfQoKICBmdW5jdGlvbiBhY3Rpb25RdW90YXRpb25CaWxsKCkgewogICAgJHRoaXMtPmNoZWNrTG9naW4oKTsKCiAgICAkcXVvdGF0aW9uX2lkID0gWWlpOjphcHAoKS0+c2Vzc2lvblsnY3VycmVudF9xdW90YXRpb25faWQnXTsKCiAgICAkcXVvdGF0aW9uID0gUXVvdGF0aW9uOjptb2RlbCgpLT5maW5kQnlQaygoaW50KSAkcXVvdGF0aW9uX2lkKTsKICAgIAogICAgJHF1b3RhdGlvbkRldGFpbHMgPSBRdW90YXRpb25EZXRhaWw6Om1vZGVsKCktPmZpbmRBbGxCeUF0dHJpYnV0ZXMoYXJyYXkoCiAgICAgICJxdW90YXRpb25faWQiID0+ICRxdW90YXRpb25faWQKICAgICkpOwoKICAgICRvcmcgPSBPcmdhbml6YXRpb246Om1vZGVsKCktPmZpbmQoKTsKICAgICR1c2VyX2lkID0gKGludCkgWWlpOjphcHAoKS0+cmVxdWVzdC0+Y29va2llc1sidXNlcl9pZCJdLT52YWx1ZTsKCiAgICAkdXNlciA9IFVzZXI6Om1vZGVsKCktPmZpbmRCeVBrKChpbnQpICR1c2VyX2lkKTsKCiAgICAkdGhpcy0+cmVuZGVyUGFydGlhbCgiLy9CYXNpYy9RdW90YXRpb25CaWxsIiwgYXJyYXkoCiAgICAgICJxdW90YXRpb24iID0+ICRxdW90YXRpb24sCiAgICAgICJxdW90YXRpb25EZXRhaWxzIiA9PiAkcXVvdGF0aW9uRGV0YWlscywKICAgICAgIm9yZyIgPT4gJG9yZywKICAgICAgInVzZXIiID0+ICR1c2VyCiAgICApKTsKICB9CgogIHB1YmxpYyBmdW5jdGlvbiBhY3Rpb25HcmlkUXVvdGF0aW9uKCkgewogICAgJHRoaXMtPmNoZWNrTG9naW4oKTsKCiAgICAkcXVvdGF0aW9ucyA9IFF1b3RhdGlvbjo6bW9kZWwoKS0+ZmluZEFsbChhcnJheSgKICAgICAgIm9yZGVyIiA9PiAiaWQgREVTQyIKICAgICkpOwoKICAgICR0aGlzLT5yZW5kZXJQYXJ0aWFsKCIvL0Jhc2ljL0dyaWRRdW90YXRpb24iLCBhcnJheSgKICAgICAgInF1b3RhdGlvbnMiID0+ICRxdW90YXRpb25zLAogICAgICAibiIgPT4gMQogICAgKSk7CiAgfQoKICBwdWJsaWMgZnVuY3Rpb24gYWN0aW9uRmluZFF1b3RhdGlvbkJ5SWQoJGlkKSB7ICAgIAogICAgJHF1b3RhdGlvbiA9IFF1b3RhdGlvbjo6bW9kZWwoKS0+ZmluZEJ5UGsoKGludCkgJGlkKTsKICAgIGVjaG8gQ0pTT046OmVuY29kZSgkcXVvdGF0aW9uKTsKICB9CgogIHB1YmxpYyBmdW5jdGlvbiBhY3Rpb25RdW90YXRpb25EZXRhaWwoJHF1b3RhdGlvbl9pZCkgeyAgICAKICAgICRxdW90YXRpb25EZXRhaWxzID0gUXVvdGF0aW9uRGV0YWlsOjptb2RlbCgpLT5maW5kQWxsQnlBdHRyaWJ1dGVzKGFycmF5KAogICAgICAicXVvdGF0aW9uX2lkIiA9PiAkcXVvdGF0aW9uX2lkCiAgICApKTsKCiAgICAkYXJyID0gYXJyYXkoKTsKICAgICRpID0gMDsKCiAgICBmb3JlYWNoICgkcXVvdGF0aW9uRGV0YWlscyBhcyAkcXVvdGF0aW9uRGV0YWlsKSB7CiAgICAgICRhcnJbJGldWydpZCddID0gJHF1b3RhdGlvbkRldGFpbC0+aWQ7CiAgICAgICRhcnJbJGldWydiYXJjb2RlJ10gPSAkcXVvdGF0aW9uRGV0YWlsLT5iYXJjb2RlOwogICAgICAkYXJyWyRpXVsncHJvZHVjdF9uYW1lJ10gPSAkcXVvdGF0aW9uRGV0YWlsLT5nZXRQcm9kdWN0KCktPnByb2R1Y3RfbmFtZTsKICAgICAgJGFyclskaV1bJ3F0eSddID0gbnVtYmVyX2Zvcm1hdCgkcXVvdGF0aW9uRGV0YWlsLT5xdHkpOwogICAgICAkYXJyWyRpXVsnb2xkX3ByaWNlJ10gPSBudW1iZXJfZm9ybWF0KCRxdW90YXRpb25EZXRhaWwtPm9sZF9wcmljZSk7CiAgICAgICRhcnJbJGldWydzdWInXSA9IG51bWJlcl9mb3JtYXQoJHF1b3RhdGlvbkRldGFpbC0+c3ViKTsKICAgICAgJGFyclskaV1bJ3NhbGVfcHJpY2UnXSA9IG51bWJlcl9mb3JtYXQoJHF1b3RhdGlvbkRldGFpbC0+c2FsZV9wcmljZSk7CgogICAgICAkaSsrOwogICAgfQoKICAgIGVjaG8gQ0pTT046OmVuY29kZSgkYXJyKTsKICB9CgogIHB1YmxpYyBmdW5jdGlvbiBhY3Rpb25RdW90YXRpb25EZXRhaWxBZGQoKSB7CiAgICAkdGhpcy0+Y2hlY2tMb2dpbigpOwoKICAgIGlmICghZW1wdHkoJF9QT1NUKSkgewogICAgICAkcXVvdGF0aW9uRGV0YWlsID0gbmV3IFF1b3RhdGlvbkRldGFpbCgpOwogICAgICAkcXVvdGF0aW9uRGV0YWlsLT5xdW90YXRpb25faWQgPSAoaW50KSBVdGlsOjppbnB1dCgkX1BPU1RbJ3F1b3RhdGlvbl9pZCddKTsKICAgICAgJHF1b3RhdGlvbkRldGFpbC0+YmFyY29kZSA9IFV0aWw6OmlucHV0KCRfUE9TVFsnYmFyY29kZSddKTsKICAgICAgJHF1b3RhdGlvbkRldGFpbC0+b2xkX3ByaWNlID0gc3RyX3JlcGxhY2UoIiwiLCAiIiwgVXRpbDo6aW5wdXQoJF9QT1NUWydvbGRfcHJpY2UnXSkpOwogICAgICAkcXVvdGF0aW9uRGV0YWlsLT5xdHkgPSBzdHJfcmVwbGFjZSgiLCIsICIiLCBVdGlsOjppbnB1dCgkX1BPU1RbJ3F0eSddKSk7CiAgICAgICRxdW90YXRpb25EZXRhaWwtPnN1YiA9IHN0cl9yZXBsYWNlKCIsIiwgIiIsIFV0aWw6OmlucHV0KCRfUE9TVFsnc3ViJ10pKTsKICAgICAgJHF1b3RhdGlvbkRldGFpbC0+c2FsZV9wcmljZSA9IHN0cl9yZXBsYWNlKCIsIiwgIiIsIFV0aWw6OmlucHV0KCRfUE9TVFsnc2FsZV9wcmljZSddKSk7CiAgICAgICRxdW90YXRpb25EZXRhaWwtPnNhdmUoKTsKCiAgICAgIGVjaG8gJHF1b3RhdGlvbkRldGFpbC0+aWQ7CiAgICB9CiAgfQoKICBwdWJsaWMgZnVuY3Rpb24gYWN0aW9uUXVvdGF0aW9uRGV0YWlsRGVsZXRlKCRpZCkgewogICAgJHRoaXMtPmNoZWNrTG9naW4oKTsKICAgIFF1b3RhdGlvbkRldGFpbDo6bW9kZWwoKS0+ZGVsZXRlQnlQaygoaW50KSAkaWQpOwogICAgCiAgICAkYmlsbFNhbGVEZXRhaWwgPSBCaWxsU2FsZURldGFpbDo6bW9kZWwoKS0+ZmluZEJ5QXR0cmlidXRlcyhhcnJheSgKICAgICAgJ3F1b3RhdGlvbl9kZXRhaWxfaWQnID0+ICRpZAogICAgKSk7CgogICAgaWYgKCFlbXB0eSgkYmlsbFNhbGVEZXRhaWwpKSB7CiAgICAgICRiaWxsU2FsZURldGFpbC0+ZGVsZXRlKCk7CiAgICB9CiAgfQoKICBwdWJsaWMgZnVuY3Rpb24gYWN0aW9uQ2xlYXJCaWxsU2FsZSgpIHsKICAgICR0aGlzLT5jaGVja0xvZ2luKCk7CiAgICBCaWxsU2FsZTo6bW9kZWwoKS0+ZGVsZXRlQWxsKCk7CiAgICBCaWxsU2FsZURldGFpbDo6bW9kZWwoKS0+ZGVsZXRlQWxsKCk7CgogICAgJHRoaXMtPnJlZGlyZWN0KGFycmF5KCJCYXNpYy9NYW5hZ2VCaWxsIikpOwogIH0KCiAgcHVibGljIGZ1bmN0aW9uIGFjdGlvbkJhY2tncm91bmRTYXZlKCkgewogICAgJHRoaXMtPmNoZWNrTG9naW4oKTsKCiAgICBpZiAoJF9GSUxFU1snYmFja2dyb3VuZCddWyduYW1lJ10gIT0gbnVsbCkgewogICAgICAkbmFtZSA9ICRfRklMRVNbJ2JhY2tncm91bmQnXVsnbmFtZSddOwogICAgICAkdG1wID0gJF9GSUxFU1snYmFja2dyb3VuZCddWyd0bXBfbmFtZSddOwogICAgICAkc2l6ZSA9ICRfRklMRVNbJ2JhY2tncm91bmQnXVsnc2l6ZSddOwoKICAgICAgaWYgKCRzaXplID4gMCkgewogICAgICAgICRleHQgPSBleHBsb2RlKCIuIiwgJG5hbWUpOwogICAgICAgICRleHQgPSAkZXh0W2NvdW50KCRleHQpIC0gMV07CiAgICAgICAgJGV4dCA9IHN0cnRvbG93ZXIoJGV4dCk7CgogICAgICAgICRuYW1lID0gbWljcm90aW1lKCk7CiAgICAgICAgJG5hbWUgPSBzdHJfcmVwbGFjZSgiICIsICIiLCAkbmFtZSk7CiAgICAgICAgJG5hbWUgPSBzdHJfcmVwbGFjZSgiLiIsICIiLCAkbmFtZSk7CgogICAgICAgIGlmICgkZXh0ID09ICJqcGciIHx8ICRleHQgPT0gInBuZyIpIHsKICAgICAgICAgIGlmIChtb3ZlX3VwbG9hZGVkX2ZpbGUoJHRtcCwgInVwbG9hZC8kbmFtZS4kZXh0IikpIHsKICAgICAgICAgICAgJGJhY2tncm91bmQgPSBuZXcgQmFja2dyb3VuZCgpOwogICAgICAgICAgICAkYmFja2dyb3VuZC0+bmFtZSA9ICRuYW1lLiIuIi4kZXh0OwogICAgICAgICAgICAKICAgICAgICAgICAgaWYgKCRiYWNrZ3JvdW5kLT5zYXZlKCkpIHsKICAgICAgICAgICAgICAkdGhpcy0+cmVkaXJlY3QoYXJyYXkoIlNpdGUvSG9tZSIpKTsKICAgICAgICAgICAgfQogICAgICAgICAgfQogICAgICAgIH0KICAgICAgfQogICAgfQogIH0KCiAgcHVibGljIGZ1bmN0aW9uIGFjdGlvbkJhY2tncm91bmREZWxldGUoJGlkKSB7CiAgICAkdGhpcy0+Y2hlY2tMb2dpbigpOwogIH0KCiAgcHVibGljIGZ1bmN0aW9uIGFjdGlvbkdldFJlcGFpcigpIHsKICAgICR0aGlzLT5jaGVja0xvZ2luKCk7CiAgICAkdGhpcy0+cmVuZGVyKCcvL0Jhc2ljL0dldFJlcGFpcicpOwogIH0KCiAgcHVibGljIGZ1bmN0aW9uIGFjdGlvbkdldFJlcGFpclNhdmUoKSB7CiAgICAkdGhpcy0+Y2hlY2tMb2dpbigpOwoKICAgIGlmICghZW1wdHkoJF9QT1NUKSkgewogICAgICAkcmVwYWlyX2lkID0gKGludCkgVXRpbDo6aW5wdXQoJF9QT1NUWydyZXBhaXJfaWQnXSk7CgogICAgICBpZiAoZW1wdHkoJHJlcGFpcl9pZCkpIHsKICAgICAgICAkcmVwYWlyID0gbmV3IFJlcGFpcigpOwogICAgICB9IGVsc2UgewogICAgICAgICRyZXBhaXIgPSBSZXBhaXI6Om1vZGVsKCktPmZpbmRCeVBrKChpbnQpICRyZXBhaXJfaWQpOwogICAgICB9CgogICAgICAkcmVwYWlyLT51c2VyX2lkID0gKGludCkgVXRpbDo6aW5wdXQoJF9QT1NUWyd1c2VyX2lkJ10pOwogICAgICAkcmVwYWlyLT5icmFuY2hfaWQgPSAoaW50KSBVdGlsOjppbnB1dCgkX1BPU1RbJ2hpZGRlbl9icmFuY2hfaWQnXSk7CiAgICAgICRyZXBhaXItPnByb2R1Y3RfY29kZSA9IFV0aWw6OmlucHV0KCRfUE9TVFsncHJvZHVjdF9jb2RlJ10pOwogICAgICAkcmVwYWlyLT5yZXBhaXJfZGF0ZSA9IFV0aWw6OnRoYWlUb015U1FMRGF0ZShVdGlsOjppbnB1dCgkX1BPU1RbJ3JlcGFpcl9kYXRlJ10pKTsKICAgICAgJHJlcGFpci0+cmVwYWlyX3Byb2JsZW0gPSBVdGlsOjppbnB1dCgkX1BPU1RbJ3JlcGFpcl9wcm9ibGVtJ10pOwogICAgICAkcmVwYWlyLT5yZXBhaXJfcHJpY2UgPSBVdGlsOjppbnB1dCgkX1BPU1RbJ3JlcGFpcl9wcmljZSddKTsKICAgICAgJHJlcGFpci0+cmVwYWlyX3R5cGUgPSBVdGlsOjppbnB1dCgkX1BPU1RbJ3JlcGFpcl90eXBlJ10pOwogICAgICAkcmVwYWlyLT5yZXBhaXJfb3JpZ2luYWwgPSBVdGlsOjppbnB1dCgkX1BPU1RbJ3JlcGFpcl9vcmlnaW5hbCddKTsKICAgICAgJHJlcGFpci0+cmVwYWlyX2RldGFpbCA9IFV0aWw6OmlucHV0KCRfUE9TVFsncmVwYWlyX2RldGFpbCddKTsKICAgICAgJHJlcGFpci0+cmVwYWlyX2NyZWF0ZWRfZGF0ZSA9IFV0aWw6OnRoYWlUb015U1FMRGF0ZShVdGlsOjppbnB1dCgkX1BPU1RbJ3JlcGFpcl9jcmVhdGVkX2RhdGUnXSkpOwogICAgICAkcmVwYWlyLT5yZXBhaXJfc3RhdHVzID0gVXRpbDo6aW5wdXQoJF9QT1NUWydyZXBhaXJfc3RhdHVzJ10pOwogICAgICAkcmVwYWlyLT5yZXBhaXJfZ3JvdXAgPSAnZXh0ZXJuYWwnOwogICAgICAkcmVwYWlyLT5yZXBhaXJfdGVsID0gVXRpbDo6aW5wdXQoJF9QT1NUWydyZXBhaXJfdGVsJ10pOwogICAgICAkcmVwYWlyLT5yZXBhaXJfbmFtZSA9IFV0aWw6OmlucHV0KCRfUE9TVFsncmVwYWlyX25hbWUnXSk7CiAgICAgICRyZXBhaXItPnJlcGFpcl9wcm9kdWN0X25hbWUgPSBVdGlsOjppbnB1dCgkX1BPU1RbJ3JlcGFpcl9wcm9kdWN0X25hbWUnXSk7CgogICAgICBpZiAoJHJlcGFpci0+c2F2ZSgpKSB7CiAgICAgICAgZWNobyBDSlNPTjo6ZW5jb2RlKCRyZXBhaXIpOwogICAgICB9CiAgICB9CiAgfQoKICBwdWJsaWMgZnVuY3Rpb24gYWN0aW9uR2V0UmVwYWlySW5mbygpIHsKICAgICR0aGlzLT5jaGVja0xvZ2luKCk7CgogICAgaWYgKCFlbXB0eSgkX1BPU1QpKSB7CiAgICAgICRyZXBhaXJfaWQgPSBVdGlsOjppbnB1dCgkX1BPU1RbJ3JlcGFpcl9pZCddKTsKICAgICAgJHJlcGFpciA9IFJlcGFpcjo6bW9kZWwoKS0+ZmluZEJ5UGsoKGludCkgJHJlcGFpcl9pZCk7CgogICAgICBpZiAoIWVtcHR5KCRyZXBhaXIpKSB7CiAgICAgICAgJGFyciA9IGFycmF5KCk7CiAgICAgICAgJGFyclsncmVwYWlyX2lkJ10gPSAkcmVwYWlyLT5yZXBhaXJfaWQ7CiAgICAgICAgJGFyclsncHJvZHVjdF9jb2RlJ10gPSAkcmVwYWlyLT5wcm9kdWN0X2NvZGU7CiAgICAgICAgJGFyclsndXNlcl9pZCddID0gJHJlcGFpci0+dXNlcl9pZDsKICAgICAgICAkYXJyWyd1c2VyX25hbWUnXSA9ICRyZXBhaXItPnVzZXItPnVzZXJfbmFtZTsKICAgICAgICAkYXJyWydicmFuY2hfaWQnXSA9ICRyZXBhaXItPmJyYW5jaF9pZDsKICAgICAgICAkYXJyWydicmFuY2hfbmFtZSddID0gJHJlcGFpci0+YnJhbmNoLT5icmFuY2hfbmFtZTsKICAgICAgICAkYXJyWydyZXBhaXJfZGF0ZSddID0gVXRpbDo6bXlzcWxUb1RoYWlEYXRlKCRyZXBhaXItPnJlcGFpcl9kYXRlKTsKICAgICAgICAkYXJyWydyZXBhaXJfcHJvYmxlbSddID0gJHJlcGFpci0+cmVwYWlyX3Byb2JsZW07CiAgICAgICAgJGFyclsncmVwYWlyX3ByaWNlJ10gPSAkcmVwYWlyLT5yZXBhaXJfcHJpY2U7CiAgICAgICAgJGFyclsncmVwYWlyX3R5cGUnXSA9ICRyZXBhaXItPnJlcGFpcl90eXBlOwogICAgICAgICRhcnJbJ3JlcGFpcl9vcmlnaW5hbCddID0gJHJlcGFpci0+cmVwYWlyX29yaWdpbmFsOwogICAgICAgICRhcnJbJ3JlcGFpcl9kZXRhaWwnXSA9ICRyZXBhaXItPnJlcGFpcl9kZXRhaWw7CiAgICAgICAgJGFyclsncmVwYWlyX2NyZWF0ZWRfZGF0ZSddID0gVXRpbDo6bXlzcWxUb1RoYWlEYXRlKCRyZXBhaXItPnJlcGFpcl9jcmVhdGVkX2RhdGUpOwogICAgICAgICRhcnJbJ3JlcGFpcl9zdGF0dXMnXSA9ICRyZXBhaXItPnJlcGFpcl9zdGF0dXM7CiAgICAgICAgJGFyclsnc2VyaWFsX25vJ10gPSAkcmVwYWlyLT5zZXJpYWxfbm87CiAgICAgICAgJGFyclsncmVwYWlyX2dyb3VwJ10gPSAkcmVwYWlyLT5yZXBhaXJfZ3JvdXA7CiAgICAgICAgJGFyclsncmVwYWlyX3RlbCddID0gJHJlcGFpci0+cmVwYWlyX3RlbDsKICAgICAgICAkYXJyWydyZXBhaXJfbmFtZSddID0gJHJlcGFpci0+cmVwYWlyX25hbWU7CiAgICAgICAgJGFyclsncmVwYWlyX3Byb2R1Y3RfbmFtZSddID0gJHJlcGFpci0+cmVwYWlyX3Byb2R1Y3RfbmFtZTsKICAgICAgICAkYXJyWydyZXBhaXJfZW5kX2RhdGUnXSA9ICRyZXBhaXItPnJlcGFpcl9lbmRfZGF0ZTsKICAgICAgfQoKICAgICAgZWNobyBDSlNPTjo6ZW5jb2RlKCRhcnIpOwogICAgfQogIH0KCiAgcHVibGljIGZ1bmN0aW9uIGFjdGlvbkdldFJlcGFpckRlbGV0ZSgpIHsKICAgICR0aGlzLT5jaGVja0xvZ2luKCk7CgogICAgaWYgKCFlbXB0eSgkX1BPU1QpKSB7CiAgICAgICRyZXBhaXJfaWQgPSBVdGlsOjppbnB1dCgkX1BPU1RbJ3JlcGFpcl9pZCddKTsKCiAgICAgIFJlcGFpcjo6bW9kZWwoKS0+ZGVsZXRlQnlQaygoaW50KSAkcmVwYWlyX2lkKTsKICAgICAgZWNobyAnc3VjY2Vzcyc7CiAgICB9CiAgfQoKICBwdWJsaWMgZnVuY3Rpb24gYWN0aW9uR2V0UmVwYWlyRW5kKCkgewogICAgJHRoaXMtPmNoZWNrTG9naW4oKTsKCiAgICBpZiAoIWVtcHR5KCRfUE9TVCkpIHsKICAgICAgJHJlcGFpcl9pZCA9IFV0aWw6OmlucHV0KCRfUE9TVFsncmVwYWlyX2lkJ10pOwogICAgICAkcmVwYWlyID0gUmVwYWlyOjptb2RlbCgpLT5maW5kQnlQaygoaW50KSAkcmVwYWlyX2lkKTsKCiAgICAgICRyZXBhaXItPnVzZXJfaWQgPSAoaW50KSBVdGlsOjppbnB1dCgkX1BPU1RbJ3VzZXJfaWQnXSk7CiAgICAgICRyZXBhaXItPmJyYW5jaF9pZCA9IChpbnQpIFV0aWw6OmlucHV0KCRfUE9TVFsnaGlkZGVuX2JyYW5jaF9pZCddKTsKICAgICAgJHJlcGFpci0+cHJvZHVjdF9jb2RlID0gVXRpbDo6aW5wdXQoJF9QT1NUWydwcm9kdWN0X2NvZGUnXSk7CiAgICAgICRyZXBhaXItPnJlcGFpcl9kYXRlID0gVXRpbDo6dGhhaVRvTXlTUUxEYXRlKFV0aWw6OmlucHV0KCRfUE9TVFsncmVwYWlyX2RhdGUnXSkpOwogICAgICAkcmVwYWlyLT5yZXBhaXJfcHJvYmxlbSA9IFV0aWw6OmlucHV0KCRfUE9TVFsncmVwYWlyX3Byb2JsZW0nXSk7CiAgICAgICRyZXBhaXItPnJlcGFpcl9wcmljZSA9IFV0aWw6OmlucHV0KCRfUE9TVFsncmVwYWlyX3ByaWNlJ10pOwogICAgICAkcmVwYWlyLT5yZXBhaXJfdHlwZSA9IFV0aWw6OmlucHV0KCRfUE9TVFsncmVwYWlyX3R5cGUnXSk7CiAgICAgICRyZXBhaXItPnJlcGFpcl9vcmlnaW5hbCA9IFV0aWw6OmlucHV0KCRfUE9TVFsncmVwYWlyX29yaWdpbmFsJ10pOwogICAgICAkcmVwYWlyLT5yZXBhaXJfZGV0YWlsID0gVXRpbDo6aW5wdXQoJF9QT1NUWydyZXBhaXJfZGV0YWlsJ10pOwogICAgICAkcmVwYWlyLT5yZXBhaXJfY3JlYXRlZF9kYXRlID0gVXRpbDo6dGhhaVRvTXlTUUxEYXRlKFV0aWw6OmlucHV0KCRfUE9TVFsncmVwYWlyX2NyZWF0ZWRfZGF0ZSddKSk7CiAgICAgICRyZXBhaXItPnJlcGFpcl9zdGF0dXMgPSBVdGlsOjppbnB1dCgkX1BPU1RbJ3JlcGFpcl9zdGF0dXMnXSk7CiAgICAgICRyZXBhaXItPnJlcGFpcl9ncm91cCA9ICdleHRlcm5hbCc7CiAgICAgICRyZXBhaXItPnJlcGFpcl90ZWwgPSBVdGlsOjppbnB1dCgkX1BPU1RbJ3JlcGFpcl90ZWwnXSk7CiAgICAgICRyZXBhaXItPnJlcGFpcl9uYW1lID0gVXRpbDo6aW5wdXQoJF9QT1NUWydyZXBhaXJfbmFtZSddKTsKICAgICAgJHJlcGFpci0+cmVwYWlyX3Byb2R1Y3RfbmFtZSA9IFV0aWw6OmlucHV0KCRfUE9TVFsncmVwYWlyX3Byb2R1Y3RfbmFtZSddKTsKICAgICAgJHJlcGFpci0+cmVwYWlyX2VuZF9kYXRlID0gbmV3IENEYkV4cHJlc3Npb24oJ05PVygpJyk7CgogICAgICBpZiAoJHJlcGFpci0+c2F2ZSgpKSB7CiAgICAgICAgZWNobyAnc3VjY2Vzcyc7CiAgICAgIH0KICAgIH0gCiAgfQoKICBwdWJsaWMgZnVuY3Rpb24gYWN0aW9uQWxlcnRTdG9jaygkcHJpbnQgPSBmYWxzZSkgewogICAgJGNvbmZpZ1NvZnR3YXJlID0gQ29uZmlnU29mdHdhcmU6Om1vZGVsKCktPmZpbmQoKTsKCiAgICAkcHJvZHVjdHMgPSBQcm9kdWN0Ojptb2RlbCgpLT5maW5kQWxsKGFycmF5KAogICAgICAnY29uZGl0aW9uJyA9PiAncHJvZHVjdF9xdWFudGl0eSA8PSA6cXR5JywKICAgICAgJ29yZGVyJyA9PiAncHJvZHVjdF9xdWFudGl0eScsCiAgICAgICdwYXJhbXMnID0+IGFycmF5KAogICAgICAgICdxdHknID0+ICRjb25maWdTb2Z0d2FyZS0+YWxlcnRfbWluX3N0b2NrCiAgICAgICkKICAgICkpOwoKICAgIGlmICghJHByaW50KSB7CiAgICAgICR0aGlzLT5yZW5kZXIoJy8vQmFzaWMvQWxlcnRTdG9jaycsIGFycmF5KAogICAgICAgICdwcm9kdWN0cycgPT4gJHByb2R1Y3RzLAogICAgICAgICduJyA9PiAxLAogICAgICAgICdwcmludCcgPT4gJHByaW50CiAgICAgICkpOwogICAgfSBlbHNlIHsKICAgICAgJHRoaXMtPnJlbmRlclBhcnRpYWwoJy8vQmFzaWMvQWxlcnRTdG9jaycsIGFycmF5KAogICAgICAgICdwcm9kdWN0cycgPT4gJHByb2R1Y3RzLAogICAgICAgICduJyA9PiAxLAogICAgICAgICdwcmludCcgPT4gJHByaW50CiAgICAgICkpOwogICAgfQogIH0KCiAgcHVibGljIGZ1bmN0aW9uIGFjdGlvblNhbGVNb2JpbGUoKSB7CiAgICAkdGhpcy0+Y2hlY2tMb2dpbigpOwoKICAgICR1c2VyX2lkID0gWWlpOjphcHAoKS0+cmVxdWVzdC0+Y29va2llc1sndXNlcl9pZCddLT52YWx1ZTsKCiAgICBpZiAoIWVtcHR5KCRfUE9TVCkpIHsKICAgICAgJGJhcmNvZGUgPSBVdGlsOjppbnB1dCgkX1BPU1RbJ2JhcmNvZGUnXSk7CgogICAgICAkaW5mbyA9IFByb2R1Y3Q6OmdldEluZm9CeUJhcmNvZGUoJGJhcmNvZGUpOwogICAgICAkdXNlciA9IFVzZXI6Om1vZGVsKCktPmZpbmRCeVBrKChpbnQpICR1c2VyX2lkKTsKCiAgICAgICRzYWxlVGVtcCA9IG5ldyBTYWxlVGVtcCgpOwogICAgICAkc2FsZVRlbXAtPmJhcmNvZGUgPSAkYmFyY29kZTsKICAgICAgJHNhbGVUZW1wLT5zZXJpYWwgPSBVdGlsOjppbnB1dCgkX1BPU1RbJ3NlcmlhbCddKTsKICAgICAgJHNhbGVUZW1wLT5xdHkgPSAxOwogICAgICAkc2FsZVRlbXAtPnF0eV9wZXJfcGFjayA9ICRpbmZvWydxdHlfcGVyX3BhY2snXTsKICAgICAgJHNhbGVUZW1wLT5wcmljZSA9ICRpbmZvWydwcmljZSddOwogICAgICAkc2FsZVRlbXAtPnVzZXJfaWQgPSAkdXNlcl9pZDsKICAgICAgJHNhbGVUZW1wLT5icmFuY2hfaWQgPSAkdXNlci0+YnJhbmNoX2lkOwogICAgICAkc2FsZVRlbXAtPnBrX3RlbXAgPSByYW5kKDEwMDAsIDEwMDAwKTsKICAgICAgJHNhbGVUZW1wLT5jcmVhdGVkX2F0ID0gbmV3IENEYkV4cHJlc3Npb24oJ05PVygpJyk7CiAgICAgICRzYWxlVGVtcC0+b2xkX3ByaWNlID0gJGluZm9bJ29sZF9wcmljZSddOwogICAgICAkc2FsZVRlbXAtPnNhbGVfdHlwZSA9ICdtb2JpbGUnOwogICAgICAkc2FsZVRlbXAtPm5hbWUgPSAkaW5mb1snbmFtZSddOwoKICAgICAgaWYgKCRzYWxlVGVtcC0+c2F2ZSgpKSB7CiAgICAgICAgJHRoaXMtPnJlZGlyZWN0KGFycmF5KCdTYWxlTW9iaWxlJykpOwogICAgICB9CiAgICB9CgogICAgJHNhbGVUZW1wcyA9IFNhbGVUZW1wOjptb2RlbCgpLT5maW5kQWxsKGFycmF5KAogICAgICAnY29uZGl0aW9uJyA9PiAndXNlcl9pZCA9IDp1c2VyX2lkIEFORCBzYWxlX3R5cGUgPSA6c2FsZV90eXBlJywKICAgICAgJ3BhcmFtcycgPT4gYXJyYXkoCiAgICAgICAgJ3VzZXJfaWQnID0+ICR1c2VyX2lkLAogICAgICAgICdzYWxlX3R5cGUnID0+ICdtb2JpbGUnCiAgICAgICksCiAgICAgICdvcmRlcicgPT4gJ2NyZWF0ZWRfYXQgREVTQycKICAgICkpOwoKICAgICR0aGlzLT5yZW5kZXJQYXJ0aWFsKCcvL0Jhc2ljL1NhbGVNb2JpbGUnLCBhcnJheSgKICAgICAgJ3NhbGVUZW1wcycgPT4gJHNhbGVUZW1wcywKICAgICAgJ3N1bScgPT4gMAogICAgKSk7CiAgfQoKICBwdWJsaWMgZnVuY3Rpb24gYWN0aW9uU2VuZEZyb21RdW90YXRpb25CaWxsVG9CaWxsU2FsZSgpIHsKICAgICR0aGlzLT5jaGVja0xvZ2luKCk7CgogICAgJHF1b3RhdGlvbl9pZCA9IChpbnQpICRfUE9TVFsncXVvdGF0aW9uX2lkJ107CiAgICAkdmF0X3ByaWNlID0gJF9QT1NUWyd2YXRfcHJpY2UnXTsKCiAgICAkcXVvdGF0aW9uID0gUXVvdGF0aW9uOjptb2RlbCgpLT5maW5kQnlQaygoaW50KSAkcXVvdGF0aW9uX2lkKTsKCiAgICBpZiAoIWVtcHR5KCRxdW90YXRpb24pKSB7CiAgICAgICRiaWxsU2FsZSA9IEJpbGxTYWxlOjptb2RlbCgpLT5maW5kQnlBdHRyaWJ1dGVzKGFycmF5KAogICAgICAgICdxdW90YXRpb25faWQnID0+ICRxdW90YXRpb25faWQKICAgICAgKSk7CgogICAgICBpZiAoZW1wdHkoJGJpbGxTYWxlKSkgewogICAgICAgICR1c2VyX2lkID0gWWlpOjphcHAoKS0+cmVxdWVzdC0+Y29va2llc1sndXNlcl9pZCddLT52YWx1ZTsKICAgICAgICAkdXNlciA9IFVzZXI6Om1vZGVsKCktPmZpbmRCeVBrKCR1c2VyX2lkKTsKCiAgICAgICAgLy8KICAgICAgICAvLyBjcmVhdGUgYmlsbF9zYWxlCiAgICAgICAgLy8KICAgICAgICAkYmlsbFNhbGUgPSBuZXcgQmlsbFNhbGUoKTsKICAgICAgICAkYmlsbFNhbGUtPnF1b3RhdGlvbl9pZCA9ICRxdW90YXRpb25faWQ7CiAgICAgICAgJGJpbGxTYWxlLT5zYWxlX3R5cGUgPSAnc2FsZSc7CiAgICAgICAgJGJpbGxTYWxlLT5iaWxsX3NhbGVfcGF5X2RhdGUgPSBuZXcgQ0RiRXhwcmVzc2lvbignTk9XKCknKTsKICAgICAgICAkYmlsbFNhbGUtPmJyYW5jaF9pZCA9ICR1c2VyLT5icmFuY2hfaWQ7CiAgICAgICAgJGJpbGxTYWxlLT51c2VyX2lkID0gJHVzZXJfaWQ7CiAgICAgICAgJGJpbGxTYWxlLT5tZW1iZXJfaWQgPSAwOwogICAgICAgICRiaWxsU2FsZS0+YmlsbF9zYWxlX3N0YXR1cyA9ICdwYXknOwogICAgICAgICRiaWxsU2FsZS0+YmlsbF9zYWxlX2NyZWF0ZWRfZGF0ZSA9IG5ldyBDRGJFeHByZXNzaW9uKCdOT1coKScpOwoKICAgICAgICBpZiAoJHF1b3RhdGlvbi0+dmF0ID4gMCkgewogICAgICAgICAgJHZhdF9wcmljZSA9IHN0cl9yZXBsYWNlKCcsJywgJycsICR2YXRfcHJpY2UpOwoKICAgICAgICAgICRiaWxsU2FsZS0+dmF0X3R5cGUgPSAnb3V0JzsKICAgICAgICAgICRiaWxsU2FsZS0+b3V0X3ZhdCA9ICR2YXRfcHJpY2U7CiAgICAgICAgICAkYmlsbFNhbGUtPmJpbGxfc2FsZV92YXQgPSAndmF0JzsKICAgICAgICAgICRiaWxsU2FsZS0+dmF0X3BlcmNlbiA9ICRxdW90YXRpb24tPnZhdDsKICAgICAgICB9CgogICAgICAgIGlmICgkYmlsbFNhbGUtPnNhdmUoKSkgewogICAgICAgICAgLy8KICAgICAgICAgIC8vIHJlYWQgZnJvbSBxdW90YXRpb24gYW5kIHRyYW5zZmVyIHRvIHRiX2JpbGxfc2FsZV9kZXRhaWwKICAgICAgICAgIC8vCiAgICAgICAgICAkcXVvdGF0aW9uRGV0YWlscyA9IFF1b3RhdGlvbkRldGFpbDo6bW9kZWwoKS0+ZmluZEFsbEJ5QXR0cmlidXRlcyhhcnJheSgKICAgICAgICAgICAgJ3F1b3RhdGlvbl9pZCcgPT4gJHF1b3RhdGlvbl9pZAogICAgICAgICAgKSk7CgogICAgICAgICAgZm9yZWFjaCAoJHF1b3RhdGlvbkRldGFpbHMgYXMgJHF1b3RhdGlvbkRldGFpbCkgewogICAgICAgICAgICAkYmlsbFNhbGVEZXRhaWwgPSBuZXcgQmlsbFNhbGVEZXRhaWwoKTsKICAgICAgICAgICAgJGJpbGxTYWxlRGV0YWlsLT5iaWxsX2lkID0gJGJpbGxTYWxlLT5iaWxsX3NhbGVfaWQ7CiAgICAgICAgICAgICRiaWxsU2FsZURldGFpbC0+YmlsbF9zYWxlX2RldGFpbF9iYXJjb2RlID0gJHF1b3RhdGlvbkRldGFpbC0+YmFyY29kZTsKICAgICAgICAgICAgJGJpbGxTYWxlRGV0YWlsLT5iaWxsX3NhbGVfZGV0YWlsX3ByaWNlID0gJHF1b3RhdGlvbkRldGFpbC0+b2xkX3ByaWNlOwogICAgICAgICAgICAkYmlsbFNhbGVEZXRhaWwtPmJpbGxfc2FsZV9kZXRhaWxfcXR5ID0gJHF1b3RhdGlvbkRldGFpbC0+cXR5OwogICAgICAgICAgICAkYmlsbFNhbGVEZXRhaWwtPnN1YiA9ICRxdW90YXRpb25EZXRhaWwtPnN1YjsKICAgICAgICAgICAgJGJpbGxTYWxlRGV0YWlsLT5xdW90YXRpb25fZGV0YWlsX2lkID0gJHF1b3RhdGlvbkRldGFpbC0+aWQ7CiAgICAgICAgICAgICRiaWxsU2FsZURldGFpbC0+c2F2ZSgpOwogICAgICAgICAgfQoKICAgICAgICAgIGVjaG8gJGJpbGxTYWxlLT5iaWxsX3NhbGVfaWQ7CiAgICAgICAgfQogICAgICB9IGVsc2UgewogICAgICAgIGVjaG8gJGJpbGxTYWxlLT5iaWxsX3NhbGVfaWQ7CiAgICAgIH0KICAgIH0KICB9CgogIHB1YmxpYyBmdW5jdGlvbiBhY3Rpb25DaGFuZ2VMYW5ndWFnZSgpIHsKICAgICR0aGlzLT5jaGVja0xvZ2luKCk7CgogICAgJGxhbmd1YWdlID0gVXRpbDo6aW5wdXQoJF9QT1NUWydsYW5ndWFnZSddKTsKICAgIFlpaTo6YXBwKCktPnNlc3Npb25bJ2xhbmd1YWdlJ10gPSAkbGFuZ3VhZ2U7CiAgICBZaWk6OmFwcCgpLT5sYW5ndWFnZSA9ICRsYW5ndWFnZTsKCiAgICBlY2hvICdzdWNjZXNzJzsKICB9CgogIHB1YmxpYyBmdW5jdGlvbiBhY3Rpb25CaWxsU2FsZURlbGV0ZSgkYmlsbF9zYWxlX2lkKSB7CiAgICAkdGhpcy0+Y2hlY2tMb2dpbigpOwoKICAgICRiaWxsU2FsZSA9IEJpbGxTYWxlOjptb2RlbCgpLT5maW5kQnlQaygoaW50KSAkYmlsbF9zYWxlX2lkKTsKCiAgICBpZiAoIWVtcHR5KCRiaWxsU2FsZSkpIHsKICAgICAgQmlsbFNhbGVEZXRhaWw6Om1vZGVsKCktPmRlbGV0ZUFsbEJ5QXR0cmlidXRlcyhhcnJheSgKICAgICAgICAnYmlsbF9pZCcgPT4gJGJpbGxTYWxlLT5iaWxsX3NhbGVfaWQKICAgICAgKSk7CgogICAgICBpZiAoJGJpbGxTYWxlLT5kZWxldGUoKSkgewogICAgICAgICR0aGlzLT5yZWRpcmVjdChhcnJheSgnTWFuYWdlQmlsbCcpKTsKICAgICAgfQogICAgfQogIH0KCiAgcHVibGljIGZ1bmN0aW9uIGFjdGlvblRyYW5zZmVyRGF0YSgpIHsKICAgICR0aGlzLT5jaGVja0xvZ2luKCk7CgogICAgJHRvdGFsTm90VHJhbnNmZXIgPSBCaWxsU2FsZURldGFpbDo6bW9kZWwoKS0+Y291bnRCeUF0dHJpYnV0ZXMoYXJyYXkoCiAgICAgICd0cmFuc2Zlcl9zdGF0dXMnID0+IDAKICAgICkpOwoKICAgICR0aGlzLT5yZW5kZXIoJy8vQmFzaWMvVHJhbnNmZXJEYXRhJywgYXJyYXkoCiAgICAgICd0b3RhbE5vdFRyYW5zZmVyJyA9PiAkdG90YWxOb3RUcmFuc2ZlcgogICAgKSk7CiAgfQoKICBwdWJsaWMgZnVuY3Rpb24gYWN0aW9uU3RhcnRUcmFuc2ZlcigpIHsKICAgICR0aGlzLT5jaGVja0xvZ2luKCk7CgogICAgJHVzZXJfaWQgPSBZaWk6OmFwcCgpLT5yZXF1ZXN0LT5jb29raWVzWyd1c2VyX2lkJ107CiAgICAkZGIgPSBZaWk6OmFwcCgpLT5kYjsKCiAgICAvLwogICAgLy8gdXBkYXRlIHN0YXR1cyBvZiB0cmFuc2ZlcgogICAgLy8KICAgICRzcWwgPSAiCiAgICAgIFVQREFURSB0Yl9iaWxsX3NhbGVfZGV0YWlsIFNFVCAKICAgICAgICB0cmFuc2Zlcl9zdGF0dXMgPSAxLAogICAgICAgIHRyYW5zZmVyX2J5X3VzZXJfaWQgPSAkdXNlcl9pZAogICAgICBXSEVSRSB0cmFuc2Zlcl9zdGF0dXMgPSAwIjsKICAgICRkYi0+Y3JlYXRlQ29tbWFuZCgkc3FsKS0+ZXhlY3V0ZSgpOwoKICAgIC8vIAogICAgLy8gY29uZmlnIHZhcmlhYmxlCiAgICAvLwogICAgJGNvbmZpZ1NvZnR3YXJlID0gQ29uZmlnU29mdHdhcmU6Om1vZGVsKCktPmZpbmQoKTsKCiAgICAvLyAKICAgIC8vIHVwZGF0ZSB0YWJsZSBzY29yZV9vZl9tZW1iZXIKICAgIC8vCiAgICAkbWVtYmVycyA9IE1lbWJlcjo6bW9kZWwoKS0+ZmluZEFsbCgpOwogICAgZm9yZWFjaCAoJG1lbWJlcnMgYXMgJG1lbWJlcikgewogICAgICAvLyBjb3VudCBzY29yZSBvZiBtZW1iZXIKICAgICAgJHNxbCA9ICIKICAgICAgICBTRUxFQ1QgU1VNKGJpbGxfc2FsZV9kZXRhaWxfcXR5ICogYmlsbF9zYWxlX2RldGFpbF9wcmljZSkgQVMgdG90YWwKICAgICAgICBGUk9NIHRiX2JpbGxfc2FsZV9kZXRhaWwKICAgICAgICBMRUZUIEpPSU4gdGJfYmlsbF9zYWxlIE9OIHRiX2JpbGxfc2FsZS5iaWxsX3NhbGVfaWQgPSB0Yl9iaWxsX3NhbGVfZGV0YWlsLmJpbGxfaWQKICAgICAgICBMRUZUIEpPSU4gdGJfcHJvZHVjdCBPTiB0Yl9wcm9kdWN0LnByb2R1Y3RfY29kZSA9IHRiX2JpbGxfc2FsZV9kZXRhaWwuYmlsbF9zYWxlX2RldGFpbF9iYXJjb2RlCiAgICAgICAgV0hFUkUgbWVtYmVyX2lkID0geyRtZW1iZXItPm1lbWJlcl9pZH0KICAgICAgIjsKICAgICAgJHIgPSAkZGItPmNyZWF0ZUNvbW1hbmQoJHNxbCktPnF1ZXJ5Um93KCk7CiAgICAgICR0b3RhbCA9ICRyWyd0b3RhbCddOwoKICAgICAgJHNjb3JlID0gKCR0b3RhbCAvICRjb25maWdTb2Z0d2FyZS0+c2NvcmUpOwoKICAgICAgLy8g4LiE4LmJ4LiZ4Lir4Liy4Lij4Lir4Lix4Liq4LmA4LiU4Li04LihCiAgICAgICRvbGREYXRhID0gU3VtbWFyeVNjb3JlT2ZNZW1iZXI6Om1vZGVsKCktPmZpbmRCeUF0dHJpYnV0ZXMoYXJyYXkoCiAgICAgICAgJ21lbWJlcl9pZCcgPT4gJG1lbWJlci0+bWVtYmVyX2lkCiAgICAgICkpOwoKICAgICAgaWYgKGVtcHR5KCRvbGREYXRhKSkgewogICAgICAgIC8vIGluc2VydCBkYXRhCiAgICAgICAgJHNxbCA9ICIKICAgICAgICAgIElOU0VSVCBJTlRPIHN1bW1hcnlfc2NvcmVfb2ZfbWVtYmVyKG1lbWJlcl9pZCwgc2NvcmUsIHByaWNlKQogICAgICAgICAgVkFMVUVTKCd7JG1lbWJlci0+bWVtYmVyX2lkfScsICckc2NvcmUnLCAnJHRvdGFsJykKICAgICAgICAiOwogICAgICB9IGVsc2UgewogICAgICAgIC8vIHVwZGF0ZSBkYXRhCiAgICAgICAgJG5ld1Njb3JlID0gKCRvbGREYXRhLT5zY29yZSArICRzY29yZSk7CiAgICAgICAgJG5ld1ByaWNlID0gKCRvbGREYXRhLT5wcmljZSArICR0b3RhbCk7CgogICAgICAgICRzcWwgPSAiCiAgICAgICAgICBVUERBVEUgc3VtbWFyeV9zY29yZV9vZl9tZW1iZXIgU0VUCiAgICAgICAgICAgIG1lbWJlcl9pZCA9IHskbWVtYmVyLT5tZW1iZXJfaWR9LCAKICAgICAgICAgICAgc2NvcmUgPSAkbmV3U2NvcmUsIAogICAgICAgICAgICBwcmljZSA9ICRuZXdQcmljZSAKICAgICAgICAgIFdIRVJFIG1lbWJlcl9pZCA9IHskbWVtYmVyLT5tZW1iZXJfaWR9IjsKICAgICAgfQoKICAgICAgJGRiLT5jcmVhdGVDb21tYW5kKCRzcWwpLT5leGVjdXRlKCk7CiAgICB9CgogICAgLy8KICAgIC8vIGVuZCBwcm9jZXNzCiAgICAvLwogICAgJGFyciA9IGFycmF5KCdtZXNzYWdlJyA9PiAnc3VjY2VzcycpOwogICAgZWNobyBDSlNPTjo6ZW5jb2RlKCRhcnIpOwogIH0KCiAgcHVibGljIGZ1bmN0aW9uIGFjdGlvblByb2R1Y3RJblN0b2NrKCkgewogICAgJHRoaXMtPmNoZWNrTG9naW4oKTsKCiAgICAkcHJvZHVjdHMgPSBQcm9kdWN0Ojptb2RlbCgpLT5maW5kQWxsKGFycmF5KAogICAgICAnc2VsZWN0JyA9PiAncHJvZHVjdF9jb2RlLCBwcm9kdWN0X25hbWUsIHByb2R1Y3RfcHJpY2UnCiAgICApKTsKICAgICRicmFuY2hzID0gQnJhbmNoOjptb2RlbCgpLT5maW5kQWxsKCk7CiAgICAkYnJhbmNoID0gbmV3IEJyYW5jaCgpOwoKICAgIGlmICghZW1wdHkoJF9QT1NUWydCcmFuY2gnXSkpIHsKICAgICAgJGJyYW5jaF9pZCA9IEAkX1BPU1RbJ0JyYW5jaCddWydicmFuY2hfaWQnXTsKICAgIH0gZWxzZSB7CiAgICAgICRicmFuY2hfaWQgPSAkYnJhbmNoc1swXS0+YnJhbmNoX2lkOwogICAgfQoKICAgIGlmICghZW1wdHkoJGJyYW5jaF9pZCkpIHsKICAgICAgJGJyYW5jaC0+YnJhbmNoX2lkID0gJGJyYW5jaF9pZDsKICAgIH0KCiAgICAkcHJvZHVjdEluU3RvY2sgPSBQcm9kdWN0SW5TdG9jazo6bW9kZWwoKS0+Y291bnRCeUF0dHJpYnV0ZXMoYXJyYXkoCiAgICAgICdicmFuY2hfaWQnID0+ICRicmFuY2hfaWQKICAgICkpOwoKICAgICR0aGlzLT5yZW5kZXIoJy8vQmFzaWMvUHJvZHVjdEluU3RvY2snLCBhcnJheSgKICAgICAgJ3Byb2R1Y3RzJyA9PiAkcHJvZHVjdHMsCiAgICAgICdicmFuY2hzJyA9PiAkYnJhbmNocywKICAgICAgJ2JyYW5jaCcgPT4gJGJyYW5jaCwKICAgICAgJ2JyYW5jaF9pZCcgPT4gJGJyYW5jaF9pZCwKICAgICAgJ3Byb2R1Y3RJblN0b2NrJyA9PiAkcHJvZHVjdEluU3RvY2sKICAgICkpOwogIH0KCiAgcHVibGljIGZ1bmN0aW9uIGFjdGlvblByb2R1Y3RJblN0b2NrU2F2ZSgpIHsKICAgICR0aGlzLT5jaGVja0xvZ2luKCk7CgogICAgaWYgKCFlbXB0eSgkX1BPU1QpKSB7CiAgICAgICRxdHkgPSBVdGlsOjppbnB1dCgkX1BPU1RbJ3F0eSddKTsKICAgICAgJGJhcmNvZGUgPSBVdGlsOjppbnB1dCgkX1BPU1RbJ2JhcmNvZGUnXSk7CiAgICAgICRicmFuY2hfaWQgPSBVdGlsOjppbnB1dCgkX1BPU1RbJ2JyYW5jaF9pZCddKTsKICAgICAgCiAgICAgIC8vIHNldCB2YWx1ZQogICAgICAkcHJvZHVjdEluU3RvY2sgPSBQcm9kdWN0SW5TdG9jazo6bW9kZWwoKS0+ZmluZEJ5QXR0cmlidXRlcyhhcnJheSgKICAgICAgICAnYnJhbmNoX2lkJyA9PiAkYnJhbmNoX2lkLAogICAgICAgICdiYXJjb2RlJyA9PiAkYmFyY29kZQogICAgICApKTsKCiAgICAgIGlmIChlbXB0eSgkcHJvZHVjdEluU3RvY2spKSB7CiAgICAgICAgJHByb2R1Y3RJblN0b2NrID0gbmV3IFByb2R1Y3RJblN0b2NrKCk7CiAgICAgIH0KCiAgICAgICRwcm9kdWN0SW5TdG9jay0+YmFyY29kZSA9ICRiYXJjb2RlOwogICAgICAkcHJvZHVjdEluU3RvY2stPnF0eSA9ICRxdHk7CiAgICAgICRwcm9kdWN0SW5TdG9jay0+YnJhbmNoX2lkID0gJGJyYW5jaF9pZDsKICAgICAgJHByb2R1Y3RJblN0b2NrLT5zYXZlKCk7CiAgICB9CiAgfQoKICBwdWJsaWMgZnVuY3Rpb24gYWN0aW9uQ29uZmlnU29mdHdhcmVQcmludFNsaXBBZnRlckVuZFNhbGUoJGNoZWNrZWRWYWx1ZSA9IHRydWUpIHsKICAgICR0aGlzLT5jaGVja0xvZ2luKCk7CgogICAgJGFyciA9IGFycmF5KAogICAgICAndHJ1ZScgPT4gJ3llcycsCiAgICAgICdmYWxzZScgPT4gJ25vJwogICAgKTsKCiAgICAkY29uZmlnU29mdHdhcmUgPSBDb25maWdTb2Z0d2FyZTo6bW9kZWwoKS0+ZmluZCgpOwogICAgJGNvbmZpZ1NvZnR3YXJlLT5wcmludF9zbGlwX2FmdGVyX2VuZF9zYWxlID0gJGFyclskY2hlY2tlZFZhbHVlXTsKICAgICRjb25maWdTb2Z0d2FyZS0+c2F2ZSgpOwogIH0KCiAgcHVibGljIGZ1bmN0aW9uIGFjdGlvbkNvbmZpZ1NvZnR3YXJlUHJpbnRCaWxsQWZ0ZXJFbmRTYWxlKCRjaGVja2VkVmFsdWUgPSB0cnVlKSB7CiAgICAkdGhpcy0+Y2hlY2tMb2dpbigpOwoKICAgICRhcnIgPSBhcnJheSgKICAgICAgJ3RydWUnID0+ICd5ZXMnLAogICAgICAnZmFsc2UnID0+ICdubycKICAgICk7CgogICAgJGNvbmZpZ1NvZnR3YXJlID0gQ29uZmlnU29mdHdhcmU6Om1vZGVsKCktPmZpbmQoKTsKICAgICRjb25maWdTb2Z0d2FyZS0+cHJpbnRfYmlsbF9hZnRlcl9lbmRfc2FsZSA9ICRhcnJbJGNoZWNrZWRWYWx1ZV07CiAgICAkY29uZmlnU29mdHdhcmUtPnNhdmUoKTsKICB9Cgp9CgoKCgoKCgoK")); ?>
Function Calls
base64_decode | 1 |
Stats
MD5 | dddf6b955f4622060d884505b1ef79d1 |
Eval Count | 1 |
Decode Time | 142 ms |