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

Variables

None

Stats

MD5 dddf6b955f4622060d884505b1ef79d1
Eval Count 1
Decode Time 142 ms