Find this useful? Enter your email to receive occasional updates for securing PHP code.
Signing you up...
Thank you for signing up!
PHP Decode
eval(base64_decode('IA0KZGVmaW5lZCgnQkFTRVBBVEgnKSBPUiBleGl0KCdObyBkaXJlY3Qgc2NyaXB0IGFjY2..
Decoded Output download
defined('BASEPATH') OR exit('No direct script access allowed');
class Auth extends CI_Controller
{
public $data = [];
public function __construct()
{
parent::__construct();
$this->load->database();
$this->load->library('form_validation');
$this->load->helper(['url', 'language']);
$this->form_validation->set_error_delimiters($this->config->item('error_start_delimiter', 'ion_auth'), $this->config->item('error_end_delimiter', 'ion_auth'));
$this->lang->load('auth');
$this->load->model('Settings_model', 'settings');
$this->load->model('Log_model', 'logging');
}
public function output_json($data)
{
$this->output->set_content_type('application/json')->set_output(json_encode($data));
}
public function index() {
if (count($this->db->list_tables()) == 0) {
redirect('install');
}
$setting = $this->settings->getSetting();
if ($setting==null){
redirect('install');
}
if ($this->ion_auth->logged_in()){
$user_id = $this->ion_auth->user()->row()->id; // Get User ID
$group = $this->ion_auth->get_users_groups($user_id)->row()->name; // Get user group
redirect('dashboard');
}
$this->data['setting'] = $setting;
$this->data['identity'] = [
'name' => 'identity',
'id' => 'identity',
'type' => 'text',
'placeholder' => 'Username',
'autofocus' => 'autofocus',
'class' => 'form-control',
'autocomplete'=>'off'
];
$this->data['password'] = [
'name' => 'password',
'id' => 'password',
'type' => 'password',
'placeholder' => 'Password',
'class' => 'form-control',
];
$this->data['message'] = (validation_errors()) ? validation_errors() : $this->session->flashdata('message');
$this->load->view('_templates/auth/_header', $this->data);
$this->load->view('auth/login');
$this->load->view('_templates/auth/_footer');
}
public function cek_login()
{
$this->form_validation->set_rules('identity', str_replace(':', '', $this->lang->line('login_identity_label')), 'required|trim');
$this->form_validation->set_rules('password', str_replace(':', '', $this->lang->line('login_password_label')), 'required|trim');
if ($this->form_validation->run() === TRUE) {
$remember = (bool)$this->input->post('remember');
if ($this->ion_auth->login($this->input->post('identity'), $this->input->post('password'), $remember)){
$this->cek_akses();
}else {
$data = [
'status' => false,
'failed' => 'Incorrect Login',
];
$this->output_json($data);
}
}else{
$invalid = [
'identity' => form_error('identity'),
'password' => form_error('password')
];
$data = [
'status' => false,
'invalid' => $invalid
];
$this->output_json($data);
}
}
public function cek_akses() {
if (!$this->ion_auth->logged_in()){
$status = false; // jika false, berarti login gagal
$url = 'auth'; // url untuk redirect
} else {
$status = true; // jika true maka login berhasil
$this->logging->saveLog(1, 'Login');
$url = 'dashboard';
}
$data = [
'status' => $status,
'url' => $url
];
$this->output_json($data);
}
public function logout()
{
$this->ion_auth->logout();
redirect('login','refresh');
}
/**
* Change password
*/
public function change_password()
{
$this->form_validation->set_rules('old', $this->lang->line('change_password_validation_old_password_label'), 'required');
$this->form_validation->set_rules('new', $this->lang->line('change_password_validation_new_password_label'), 'required|min_length[' . $this->config->item('min_password_length', 'ion_auth') . ']|matches[new_confirm]');
$this->form_validation->set_rules('new_confirm', $this->lang->line('change_password_validation_new_password_confirm_label'), 'required');
if (!$this->ion_auth->logged_in())
{
redirect('auth/login', 'refresh');
}
$user = $this->ion_auth->user()->row();
if ($this->form_validation->run() === FALSE)
{
// display the form
// set the flash data error message if there is one
$this->data['message'] = (validation_errors()) ? validation_errors() : $this->session->flashdata('message');
$this->data['min_password_length'] = $this->config->item('min_password_length', 'ion_auth');
$this->data['old_password'] = [
'name' => 'old',
'id' => 'old',
'type' => 'password',
];
$this->data['new_password'] = [
'name' => 'new',
'id' => 'new',
'type' => 'password',
'pattern' => '^.{' . $this->data['min_password_length'] . '}.*$',
];
$this->data['new_password_confirm'] = [
'name' => 'new_confirm',
'id' => 'new_confirm',
'type' => 'password',
'pattern' => '^.{' . $this->data['min_password_length'] . '}.*$',
];
$this->data['user_id'] = [
'name' => 'user_id',
'id' => 'user_id',
'type' => 'hidden',
'value' => $user->id,
];
// render
$this->_render_page('auth' . DIRECTORY_SEPARATOR . 'change_password', $this->data);
}
else
{
$identity = $this->session->userdata('identity');
$change = $this->ion_auth->change_password($identity, $this->input->post('old'), $this->input->post('new'));
if ($change)
{
//if the password was successfully changed
$this->session->set_flashdata('message', $this->ion_auth->messages());
$this->logout();
}
else
{
$this->session->set_flashdata('message', $this->ion_auth->errors());
redirect('auth/change_password', 'refresh');
}
}
}
/**
* Forgot password
*/
public function forgot_password()
{
$this->data['title'] = $this->lang->line('forgot_password_heading');
// setting validation rules by checking whether identity is username or email
if ($this->config->item('identity', 'ion_auth') != 'email')
{
$this->form_validation->set_rules('identity', $this->lang->line('forgot_password_identity_label'), 'required');
}
else
{
$this->form_validation->set_rules('identity', $this->lang->line('forgot_password_validation_email_label'), 'required|valid_email');
}
if ($this->form_validation->run() === FALSE)
{
$this->data['type'] = $this->config->item('identity', 'ion_auth');
// setup the input
$this->data['identity'] = [
'name' => 'identity',
'id' => 'identity',
'class' => 'form-control',
'autocomplete' => 'off',
'autofocus' => 'autofocus'
];
if ($this->config->item('identity', 'ion_auth') != 'email')
{
$this->data['identity_label'] = $this->lang->line('forgot_password_identity_label');
}
else
{
$this->data['identity_label'] = $this->lang->line('forgot_password_email_identity_label');
}
// set any errors and display the form
$this->data['message'] = (validation_errors()) ? validation_errors() : $this->session->flashdata('message');
$this->load->view('_templates/auth/_header', $this->data);
$this->load->view('auth/forgot_password');
$this->load->view('_templates/auth/_footer');
}
else
{
$identity_column = $this->config->item('identity', 'ion_auth');
$identity = $this->ion_auth->where($identity_column, $this->input->post('identity'))->users()->row();
if (empty($identity))
{
if ($this->config->item('identity', 'ion_auth') != 'email')
{
$this->ion_auth->set_error('forgot_password_identity_not_found');
}
else
{
$this->ion_auth->set_error('forgot_password_email_not_found');
}
$this->session->set_flashdata('message', $this->ion_auth->errors());
redirect("auth/forgot_password", 'refresh');
}
// run the forgotten password method to email an activation code to the user
$forgotten = $this->ion_auth->forgotten_password($identity->{$this->config->item('identity', 'ion_auth')});
if ($forgotten)
{
// if there were no errors
$this->session->set_flashdata('success', $this->ion_auth->messages());
redirect("auth/forgot_password", 'refresh'); //we should display a confirmation page here instead of the login page
}
else
{
$this->session->set_flashdata('message', $this->ion_auth->errors());
redirect("auth/forgot_password", 'refresh');
}
}
}
/**
* Reset password - final step for forgotten password
*
* @param string|null $code The reset code
*/
public function reset_password($code = NULL)
{
if (!$code)
{
show_404();
}
$this->data['title'] = $this->lang->line('reset_password_heading');
$user = $this->ion_auth->forgotten_password_check($code);
if ($user)
{
// if the code is valid then display the password reset form
$this->form_validation->set_rules('new', $this->lang->line('reset_password_validation_new_password_label'), 'required|min_length[' . $this->config->item('min_password_length', 'ion_auth') . ']|matches[new_confirm]');
$this->form_validation->set_rules('new_confirm', $this->lang->line('reset_password_validation_new_password_confirm_label'), 'required');
if ($this->form_validation->run() === FALSE)
{
// display the form
// set the flash data error message if there is one
$this->data['message'] = (validation_errors()) ? validation_errors() : $this->session->flashdata('message');
$this->data['min_password_length'] = $this->config->item('min_password_length', 'ion_auth');
$this->data['new_password'] = [
'name' => 'new',
'id' => 'new',
'type' => 'password',
'pattern' => '^.{' . $this->data['min_password_length'] . '}.*$',
];
$this->data['new_password_confirm'] = [
'name' => 'new_confirm',
'id' => 'new_confirm',
'type' => 'password',
'pattern' => '^.{' . $this->data['min_password_length'] . '}.*$',
];
$this->data['user_id'] = [
'name' => 'user_id',
'id' => 'user_id',
'type' => 'hidden',
'value' => $user->id,
];
$this->data['csrf'] = $this->_get_csrf_nonce();
$this->data['code'] = $code;
// render
$this->load->view('_templates/auth/_header');
$this->load->view('auth/reset_password', $this->data);
$this->load->view('_templates/auth/_footer');
}
else
{
$identity = $user->{$this->config->item('identity', 'ion_auth')};
// do we have a valid request?
if ($this->_valid_csrf_nonce() === FALSE || $user->id != $this->input->post('user_id'))
{
// something fishy might be up
$this->ion_auth->clear_forgotten_password_code($identity);
show_error($this->lang->line('error_csrf'));
}
else
{
// finally change the password
$change = $this->ion_auth->reset_password($identity, $this->input->post('new'));
if ($change)
{
// if the password was successfully changed
$this->session->set_flashdata('message', $this->ion_auth->messages());
redirect("auth/login", 'refresh');
}
else
{
$this->session->set_flashdata('message', $this->ion_auth->errors());
redirect('auth/reset_password/' . $code, 'refresh');
}
}
}
}
else
{
// if the code is invalid then send them back to the forgot password page
$this->session->set_flashdata('message', $this->ion_auth->errors());
redirect("auth/forgot_password", 'refresh');
}
}
/**
* Activate the user
*
* @param int $id The user ID
* @param string|bool $code The activation code
*/
public function activate($id, $code = FALSE)
{
$activation = FALSE;
if ($code !== FALSE)
{
$activation = $this->ion_auth->activate($id, $code);
}
else if ($this->ion_auth->is_admin())
{
$activation = $this->ion_auth->activate($id);
}
if ($activation)
{
// redirect them to the auth page
$this->session->set_flashdata('message', $this->ion_auth->messages());
redirect("auth", 'refresh');
}
else
{
// redirect them to the forgot password page
$this->session->set_flashdata('message', $this->ion_auth->errors());
redirect("auth/forgot_password", 'refresh');
}
}
/**
* Deactivate the user
*
* @param int|string|null $id The user ID
*/
public function deactivate($id = NULL)
{
if (!$this->ion_auth->logged_in() || !$this->ion_auth->is_admin())
{
// redirect them to the home page because they must be an administrator to view this
show_error('You must be an administrator to view this page.');
}
$id = (int)$id;
$this->load->library('form_validation');
$this->form_validation->set_rules('confirm', $this->lang->line('deactivate_validation_confirm_label'), 'required');
$this->form_validation->set_rules('id', $this->lang->line('deactivate_validation_user_id_label'), 'required|alpha_numeric');
if ($this->form_validation->run() === FALSE)
{
// insert csrf check
$this->data['csrf'] = $this->_get_csrf_nonce();
$this->data['user'] = $this->ion_auth->user($id)->row();
$this->_render_page('auth' . DIRECTORY_SEPARATOR . 'deactivate_user', $this->data);
}
else
{
// do we really want to deactivate?
if ($this->input->post('confirm') == 'yes')
{
// do we have a valid request?
if ($this->_valid_csrf_nonce() === FALSE || $id != $this->input->post('id'))
{
show_error($this->lang->line('error_csrf'));
}
// do we have the right userlevel?
if ($this->ion_auth->logged_in() && $this->ion_auth->is_admin())
{
$this->ion_auth->deactivate($id);
}
}
// redirect them back to the auth page
redirect('auth', 'refresh');
}
}
/**
* Create a new user
*/
public function create_user()
{
$this->data['title'] = $this->lang->line('create_user_heading');
if (!$this->ion_auth->logged_in() || !$this->ion_auth->is_admin())
{
redirect('auth', 'refresh');
}
$tables = $this->config->item('tables', 'ion_auth');
$identity_column = $this->config->item('identity', 'ion_auth');
$this->data['identity_column'] = $identity_column;
// validate form input
$this->form_validation->set_rules('first_name', $this->lang->line('create_user_validation_fname_label'), 'trim|required');
$this->form_validation->set_rules('last_name', $this->lang->line('create_user_validation_lname_label'), 'trim|required');
if ($identity_column !== 'email')
{
$this->form_validation->set_rules('identity', $this->lang->line('create_user_validation_identity_label'), 'trim|required|is_unique[' . $tables['users'] . '.' . $identity_column . ']');
$this->form_validation->set_rules('email', $this->lang->line('create_user_validation_email_label'), 'trim|required|valid_email');
}
else
{
$this->form_validation->set_rules('email', $this->lang->line('create_user_validation_email_label'), 'trim|required|valid_email|is_unique[' . $tables['users'] . '.email]');
}
$this->form_validation->set_rules('phone', $this->lang->line('create_user_validation_phone_label'), 'trim');
$this->form_validation->set_rules('company', $this->lang->line('create_user_validation_company_label'), 'trim');
$this->form_validation->set_rules('password', $this->lang->line('create_user_validation_password_label'), 'required|min_length[' . $this->config->item('min_password_length', 'ion_auth') . ']|matches[password_confirm]');
$this->form_validation->set_rules('password_confirm', $this->lang->line('create_user_validation_password_confirm_label'), 'required');
if ($this->form_validation->run() === TRUE)
{
$email = strtolower($this->input->post('email'));
$identity = ($identity_column === 'email') ? $email : $this->input->post('identity');
$password = $this->input->post('password');
$additional_data = [
'first_name' => $this->input->post('first_name'),
'last_name' => $this->input->post('last_name'),
'company' => $this->input->post('company'),
'phone' => $this->input->post('phone'),
];
}
if ($this->form_validation->run() === TRUE && $this->ion_auth->register($identity, $password, $email, $additional_data))
{
// check to see if we are creating the user
// redirect them back to the admin page
$this->session->set_flashdata('message', $this->ion_auth->messages());
redirect("auth", 'refresh');
}
else
{
// display the create user form
// set the flash data error message if there is one
$this->data['message'] = (validation_errors() ? validation_errors() : ($this->ion_auth->errors() ? $this->ion_auth->errors() : $this->session->flashdata('message')));
$this->data['first_name'] = [
'name' => 'first_name',
'id' => 'first_name',
'type' => 'text',
'value' => $this->form_validation->set_value('first_name'),
];
$this->data['last_name'] = [
'name' => 'last_name',
'id' => 'last_name',
'type' => 'text',
'value' => $this->form_validation->set_value('last_name'),
];
$this->data['identity'] = [
'name' => 'identity',
'id' => 'identity',
'type' => 'text',
'value' => $this->form_validation->set_value('identity'),
];
$this->data['email'] = [
'name' => 'email',
'id' => 'email',
'type' => 'text',
'value' => $this->form_validation->set_value('email'),
];
$this->data['company'] = [
'name' => 'company',
'id' => 'company',
'type' => 'text',
'value' => $this->form_validation->set_value('company'),
];
$this->data['phone'] = [
'name' => 'phone',
'id' => 'phone',
'type' => 'text',
'value' => $this->form_validation->set_value('phone'),
];
$this->data['password'] = [
'name' => 'password',
'id' => 'password',
'type' => 'password',
'value' => $this->form_validation->set_value('password'),
];
$this->data['password_confirm'] = [
'name' => 'password_confirm',
'id' => 'password_confirm',
'type' => 'password',
'value' => $this->form_validation->set_value('password_confirm'),
];
$this->_render_page('auth' . DIRECTORY_SEPARATOR . 'create_user', $this->data);
}
}
/**
* Redirect a user checking if is admin
*/
public function redirectUser(){
if ($this->ion_auth->is_admin()){
redirect('auth', 'refresh');
}
redirect('/', 'refresh');
}
/**
* Edit a user
*
* @param int|string $id
*/
public function edit_user($id)
{
$this->data['title'] = $this->lang->line('edit_user_heading');
if (!$this->ion_auth->logged_in() || (!$this->ion_auth->is_admin() && !($this->ion_auth->user()->row()->id == $id)))
{
redirect('auth', 'refresh');
}
$user = $this->ion_auth->user($id)->row();
$groups = $this->ion_auth->groups()->result_array();
$currentGroups = $this->ion_auth->get_users_groups($id)->result();
//USAGE NOTE - you can do more complicated queries like this
//$groups = $this->ion_auth->where(['field' => 'value'])->groups()->result_array();
// validate form input
$this->form_validation->set_rules('first_name', $this->lang->line('edit_user_validation_fname_label'), 'trim|required');
$this->form_validation->set_rules('last_name', $this->lang->line('edit_user_validation_lname_label'), 'trim|required');
$this->form_validation->set_rules('phone', $this->lang->line('edit_user_validation_phone_label'), 'trim');
$this->form_validation->set_rules('company', $this->lang->line('edit_user_validation_company_label'), 'trim');
if (isset($_POST) && !empty($_POST))
{
// do we have a valid request?
if ($this->_valid_csrf_nonce() === FALSE || $id != $this->input->post('id'))
{
show_error($this->lang->line('error_csrf'));
}
// update the password if it was posted
if ($this->input->post('password'))
{
$this->form_validation->set_rules('password', $this->lang->line('edit_user_validation_password_label'), 'required|min_length[' . $this->config->item('min_password_length', 'ion_auth') . ']|matches[password_confirm]');
$this->form_validation->set_rules('password_confirm', $this->lang->line('edit_user_validation_password_confirm_label'), 'required');
}
if ($this->form_validation->run() === TRUE)
{
$data = [
'first_name' => $this->input->post('first_name'),
'last_name' => $this->input->post('last_name'),
'company' => $this->input->post('company'),
'phone' => $this->input->post('phone'),
];
// update the password if it was posted
if ($this->input->post('password'))
{
$data['password'] = $this->input->post('password');
}
// Only allow updating groups if user is admin
if ($this->ion_auth->is_admin())
{
// Update the groups user belongs to
$this->ion_auth->remove_from_group('', $id);
$groupData = $this->input->post('groups');
if (isset($groupData) && !empty($groupData))
{
foreach ($groupData as $grp)
{
$this->ion_auth->add_to_group($grp, $id);
}
}
}
// check to see if we are updating the user
if ($this->ion_auth->update($user->id, $data))
{
// redirect them back to the admin page if admin, or to the base url if non admin
$this->session->set_flashdata('message', $this->ion_auth->messages());
$this->redirectUser();
}
else
{
// redirect them back to the admin page if admin, or to the base url if non admin
$this->session->set_flashdata('message', $this->ion_auth->errors());
$this->redirectUser();
}
}
}
// display the edit user form
$this->data['csrf'] = $this->_get_csrf_nonce();
// set the flash data error message if there is one
$this->data['message'] = (validation_errors() ? validation_errors() : ($this->ion_auth->errors() ? $this->ion_auth->errors() : $this->session->flashdata('message')));
// pass the user to the view
$this->data['user'] = $user;
$this->data['groups'] = $groups;
$this->data['currentGroups'] = $currentGroups;
$this->data['first_name'] = [
'name' => 'first_name',
'id' => 'first_name',
'type' => 'text',
'value' => $this->form_validation->set_value('first_name', $user->first_name),
];
$this->data['last_name'] = [
'name' => 'last_name',
'id' => 'last_name',
'type' => 'text',
'value' => $this->form_validation->set_value('last_name', $user->last_name),
];
$this->data['company'] = [
'name' => 'company',
'id' => 'company',
'type' => 'text',
'value' => $this->form_validation->set_value('company', $user->company),
];
$this->data['phone'] = [
'name' => 'phone',
'id' => 'phone',
'type' => 'text',
'value' => $this->form_validation->set_value('phone', $user->phone),
];
$this->data['password'] = [
'name' => 'password',
'id' => 'password',
'type' => 'password'
];
$this->data['password_confirm'] = [
'name' => 'password_confirm',
'id' => 'password_confirm',
'type' => 'password'
];
$this->_render_page('auth/edit_user', $this->data);
}
/**
* Create a new group
*/
public function create_group()
{
$this->data['title'] = $this->lang->line('create_group_title');
if (!$this->ion_auth->logged_in() || !$this->ion_auth->is_admin())
{
redirect('auth', 'refresh');
}
// validate form input
$this->form_validation->set_rules('group_name', $this->lang->line('create_group_validation_name_label'), 'trim|required|alpha_dash');
if ($this->form_validation->run() === TRUE)
{
$new_group_id = $this->ion_auth->create_group($this->input->post('group_name'), $this->input->post('description'));
if ($new_group_id)
{
// check to see if we are creating the group
// redirect them back to the admin page
$this->session->set_flashdata('message', $this->ion_auth->messages());
redirect("auth", 'refresh');
}
else
{
$this->session->set_flashdata('message', $this->ion_auth->errors());
}
}
// display the create group form
// set the flash data error message if there is one
$this->data['message'] = (validation_errors() ? validation_errors() : ($this->ion_auth->errors() ? $this->ion_auth->errors() : $this->session->flashdata('message')));
$this->data['group_name'] = [
'name' => 'group_name',
'id' => 'group_name',
'type' => 'text',
'value' => $this->form_validation->set_value('group_name'),
];
$this->data['description'] = [
'name' => 'description',
'id' => 'description',
'type' => 'text',
'value' => $this->form_validation->set_value('description'),
];
$this->_render_page('auth/create_group', $this->data);
}
/**
* Edit a group
*
* @param int|string $id
*/
public function edit_group($id)
{
// bail if no group id given
if (!$id || empty($id))
{
redirect('auth', 'refresh');
}
$this->data['title'] = $this->lang->line('edit_group_title');
if (!$this->ion_auth->logged_in() || !$this->ion_auth->is_admin())
{
redirect('auth', 'refresh');
}
$group = $this->ion_auth->group($id)->row();
// validate form input
$this->form_validation->set_rules('group_name', $this->lang->line('edit_group_validation_name_label'), 'trim|required|alpha_dash');
if (isset($_POST) && !empty($_POST))
{
if ($this->form_validation->run() === TRUE)
{
$group_update = $this->ion_auth->update_group($id, $_POST['group_name'], array(
'description' => $_POST['group_description']
));
if ($group_update)
{
$this->session->set_flashdata('message', $this->lang->line('edit_group_saved'));
redirect("auth", 'refresh');
}
else
{
$this->session->set_flashdata('message', $this->ion_auth->errors());
}
}
}
// set the flash data error message if there is one
$this->data['message'] = (validation_errors() ? validation_errors() : ($this->ion_auth->errors() ? $this->ion_auth->errors() : $this->session->flashdata('message')));
// pass the user to the view
$this->data['group'] = $group;
$this->data['group_name'] = [
'name' => 'group_name',
'id' => 'group_name',
'type' => 'text',
'value' => $this->form_validation->set_value('group_name', $group->name),
];
if ($this->config->item('admin_group', 'ion_auth') === $group->name) {
$this->data['group_name']['readonly'] = 'readonly';
}
$this->data['group_description'] = [
'name' => 'group_description',
'id' => 'group_description',
'type' => 'text',
'value' => $this->form_validation->set_value('group_description', $group->description),
];
$this->_render_page('auth' . DIRECTORY_SEPARATOR . 'edit_group', $this->data);
}
/**
* @return array A CSRF key-value pair
*/
public function _get_csrf_nonce()
{
$this->load->helper('string');
$key = random_string('alnum', 8);
$value = random_string('alnum', 20);
$this->session->set_flashdata('csrfkey', $key);
$this->session->set_flashdata('csrfvalue', $value);
return [$key => $value];
}
/**
* @return bool Whether the posted CSRF token matches
*/
public function _valid_csrf_nonce(){
$csrfkey = $this->input->post($this->session->flashdata('csrfkey'));
if ($csrfkey && $csrfkey === $this->session->flashdata('csrfvalue'))
{
return TRUE;
}
return FALSE;
}
public function _render_page($view, $data = NULL, $returnhtml = FALSE)//I think this makes more sense
{
$viewdata = (empty($data)) ? $this->data : $data;
$view_html = $this->load->view($view, $viewdata, $returnhtml);
// This will return html on 3rd argument being true
if ($returnhtml)
{
return $view_html;
}
}
}
Did this file decode correctly?
Original Code
eval(base64_decode('IA0KZGVmaW5lZCgnQkFTRVBBVEgnKSBPUiBleGl0KCdObyBkaXJlY3Qgc2NyaXB0IGFjY2VzcyBhbGxvd2VkJyk7DQoNCmNsYXNzIEF1dGggZXh0ZW5kcyBDSV9Db250cm9sbGVyDQp7DQoJcHVibGljICRkYXRhID0gW107DQoNCglwdWJsaWMgZnVuY3Rpb24gX19jb25zdHJ1Y3QoKQ0KCXsNCgkJcGFyZW50OjpfX2NvbnN0cnVjdCgpOw0KICAgICAgICAkdGhpcy0+bG9hZC0+ZGF0YWJhc2UoKTsNCgkJJHRoaXMtPmxvYWQtPmxpYnJhcnkoJ2Zvcm1fdmFsaWRhdGlvbicpOw0KCQkkdGhpcy0+bG9hZC0+aGVscGVyKFsndXJsJywgJ2xhbmd1YWdlJ10pOw0KCQkkdGhpcy0+Zm9ybV92YWxpZGF0aW9uLT5zZXRfZXJyb3JfZGVsaW1pdGVycygkdGhpcy0+Y29uZmlnLT5pdGVtKCdlcnJvcl9zdGFydF9kZWxpbWl0ZXInLCAnaW9uX2F1dGgnKSwgJHRoaXMtPmNvbmZpZy0+aXRlbSgnZXJyb3JfZW5kX2RlbGltaXRlcicsICdpb25fYXV0aCcpKTsNCgkJJHRoaXMtPmxhbmctPmxvYWQoJ2F1dGgnKTsNCg0KCQkkdGhpcy0+bG9hZC0+bW9kZWwoJ1NldHRpbmdzX21vZGVsJywgJ3NldHRpbmdzJyk7DQoJCSR0aGlzLT5sb2FkLT5tb2RlbCgnTG9nX21vZGVsJywgJ2xvZ2dpbmcnKTsNCgl9DQoNCglwdWJsaWMgZnVuY3Rpb24gb3V0cHV0X2pzb24oJGRhdGEpDQoJew0KCQkkdGhpcy0+b3V0cHV0LT5zZXRfY29udGVudF90eXBlKCdhcHBsaWNhdGlvbi9qc29uJyktPnNldF9vdXRwdXQoanNvbl9lbmNvZGUoJGRhdGEpKTsNCgl9DQoNCglwdWJsaWMgZnVuY3Rpb24gaW5kZXgoKSB7DQogICAgICAgIGlmIChjb3VudCgkdGhpcy0+ZGItPmxpc3RfdGFibGVzKCkpID09IDApIHsNCiAgICAgICAgICAgIHJlZGlyZWN0KCdpbnN0YWxsJyk7DQogICAgICAgIH0NCiAgICAgICAgJHNldHRpbmcgPSAkdGhpcy0+c2V0dGluZ3MtPmdldFNldHRpbmcoKTsNCgkgICAgaWYgKCRzZXR0aW5nPT1udWxsKXsNCgkgICAgICAgIHJlZGlyZWN0KCdpbnN0YWxsJyk7DQogICAgICAgIH0NCgkJaWYgKCR0aGlzLT5pb25fYXV0aC0+bG9nZ2VkX2luKCkpew0KCQkJJHVzZXJfaWQgPSAkdGhpcy0+aW9uX2F1dGgtPnVzZXIoKS0+cm93KCktPmlkOyAvLyBHZXQgVXNlciBJRA0KCQkJJGdyb3VwID0gJHRoaXMtPmlvbl9hdXRoLT5nZXRfdXNlcnNfZ3JvdXBzKCR1c2VyX2lkKS0+cm93KCktPm5hbWU7IC8vIEdldCB1c2VyIGdyb3VwDQoNCgkJCXJlZGlyZWN0KCdkYXNoYm9hcmQnKTsNCgkJfQ0KDQoJCSR0aGlzLT5kYXRhWydzZXR0aW5nJ10gPSAkc2V0dGluZzsNCgkJJHRoaXMtPmRhdGFbJ2lkZW50aXR5J10gPSBbDQoJCQknbmFtZScgPT4gJ2lkZW50aXR5JywNCgkJCSdpZCcgPT4gJ2lkZW50aXR5JywNCgkJCSd0eXBlJyA9PiAndGV4dCcsDQoJCQkncGxhY2Vob2xkZXInID0+ICdVc2VybmFtZScsDQoJCQknYXV0b2ZvY3VzJwk9PiAnYXV0b2ZvY3VzJywNCgkJCSdjbGFzcycgPT4gJ2Zvcm0tY29udHJvbCcsDQoJCQknYXV0b2NvbXBsZXRlJz0+J29mZicNCgkJXTsNCgkJJHRoaXMtPmRhdGFbJ3Bhc3N3b3JkJ10gPSBbDQoJCQknbmFtZScgPT4gJ3Bhc3N3b3JkJywNCgkJCSdpZCcgPT4gJ3Bhc3N3b3JkJywNCgkJCSd0eXBlJyA9PiAncGFzc3dvcmQnLA0KCQkJJ3BsYWNlaG9sZGVyJyA9PiAnUGFzc3dvcmQnLA0KCQkJJ2NsYXNzJyA9PiAnZm9ybS1jb250cm9sJywNCgkJXTsNCgkJJHRoaXMtPmRhdGFbJ21lc3NhZ2UnXSA9ICh2YWxpZGF0aW9uX2Vycm9ycygpKSA/IHZhbGlkYXRpb25fZXJyb3JzKCkgOiAkdGhpcy0+c2Vzc2lvbi0+Zmxhc2hkYXRhKCdtZXNzYWdlJyk7DQoNCgkJJHRoaXMtPmxvYWQtPnZpZXcoJ190ZW1wbGF0ZXMvYXV0aC9faGVhZGVyJywgJHRoaXMtPmRhdGEpOw0KCQkkdGhpcy0+bG9hZC0+dmlldygnYXV0aC9sb2dpbicpOw0KCQkkdGhpcy0+bG9hZC0+dmlldygnX3RlbXBsYXRlcy9hdXRoL19mb290ZXInKTsNCgl9DQoNCglwdWJsaWMgZnVuY3Rpb24gY2VrX2xvZ2luKCkNCgl7DQoJCSR0aGlzLT5mb3JtX3ZhbGlkYXRpb24tPnNldF9ydWxlcygnaWRlbnRpdHknLCBzdHJfcmVwbGFjZSgnOicsICcnLCAkdGhpcy0+bGFuZy0+bGluZSgnbG9naW5faWRlbnRpdHlfbGFiZWwnKSksICdyZXF1aXJlZHx0cmltJyk7DQoJCSR0aGlzLT5mb3JtX3ZhbGlkYXRpb24tPnNldF9ydWxlcygncGFzc3dvcmQnLCBzdHJfcmVwbGFjZSgnOicsICcnLCAkdGhpcy0+bGFuZy0+bGluZSgnbG9naW5fcGFzc3dvcmRfbGFiZWwnKSksICdyZXF1aXJlZHx0cmltJyk7DQoNCgkJaWYgKCR0aGlzLT5mb3JtX3ZhbGlkYXRpb24tPnJ1bigpID09PSBUUlVFKQl7DQoJCQkkcmVtZW1iZXIgPSAoYm9vbCkkdGhpcy0+aW5wdXQtPnBvc3QoJ3JlbWVtYmVyJyk7DQoJCQlpZiAoJHRoaXMtPmlvbl9hdXRoLT5sb2dpbigkdGhpcy0+aW5wdXQtPnBvc3QoJ2lkZW50aXR5JyksICR0aGlzLT5pbnB1dC0+cG9zdCgncGFzc3dvcmQnKSwgJHJlbWVtYmVyKSl7DQoJCQkJJHRoaXMtPmNla19ha3NlcygpOw0KCQkJfWVsc2Ugew0KCQkJCSRkYXRhID0gWw0KCQkJCQknc3RhdHVzJyA9PiBmYWxzZSwNCgkJCQkJJ2ZhaWxlZCcgPT4gJ0luY29ycmVjdCBMb2dpbicsDQoJCQkJXTsNCgkJCQkkdGhpcy0+b3V0cHV0X2pzb24oJGRhdGEpOw0KCQkJfQ0KCQl9ZWxzZXsNCgkJCSRpbnZhbGlkID0gWw0KCQkJCSdpZGVudGl0eScgPT4gZm9ybV9lcnJvcignaWRlbnRpdHknKSwNCgkJCQkncGFzc3dvcmQnID0+IGZvcm1fZXJyb3IoJ3Bhc3N3b3JkJykNCgkJCV07DQoJCQkkZGF0YSA9IFsNCgkJCQknc3RhdHVzJyAJPT4gZmFsc2UsDQoJCQkJJ2ludmFsaWQnIAk9PiAkaW52YWxpZA0KCQkJXTsNCgkJCSR0aGlzLT5vdXRwdXRfanNvbigkZGF0YSk7DQoJCX0NCgl9DQoNCglwdWJsaWMgZnVuY3Rpb24gY2VrX2Frc2VzKCkgew0KCQlpZiAoISR0aGlzLT5pb25fYXV0aC0+bG9nZ2VkX2luKCkpew0KCQkJJHN0YXR1cyA9IGZhbHNlOyAvLyBqaWthIGZhbHNlLCBiZXJhcnRpIGxvZ2luIGdhZ2FsDQoJCQkkdXJsID0gJ2F1dGgnOyAvLyB1cmwgdW50dWsgcmVkaXJlY3QNCgkJfSBlbHNlIHsNCgkJCSRzdGF0dXMgPSB0cnVlOyAvLyBqaWthIHRydWUgbWFrYSBsb2dpbiBiZXJoYXNpbA0KCQkJJHRoaXMtPmxvZ2dpbmctPnNhdmVMb2coMSwgJ0xvZ2luJyk7DQoNCgkJCSR1cmwgPSAnZGFzaGJvYXJkJzsNCgkJfQ0KDQoJCSRkYXRhID0gWw0KCQkJJ3N0YXR1cycgPT4gJHN0YXR1cywNCgkJCSd1cmwnCSA9PiAkdXJsDQoJCV07DQoJCSR0aGlzLT5vdXRwdXRfanNvbigkZGF0YSk7DQoJfQ0KDQoJcHVibGljIGZ1bmN0aW9uIGxvZ291dCgpDQoJew0KCQkkdGhpcy0+aW9uX2F1dGgtPmxvZ291dCgpOw0KCQlyZWRpcmVjdCgnbG9naW4nLCdyZWZyZXNoJyk7DQoJfQ0KDQogICAgLyoqDQogICAgICogQ2hhbmdlIHBhc3N3b3JkDQogICAgICovDQogICAgcHVibGljIGZ1bmN0aW9uIGNoYW5nZV9wYXNzd29yZCgpDQogICAgew0KICAgICAgICAkdGhpcy0+Zm9ybV92YWxpZGF0aW9uLT5zZXRfcnVsZXMoJ29sZCcsICR0aGlzLT5sYW5nLT5saW5lKCdjaGFuZ2VfcGFzc3dvcmRfdmFsaWRhdGlvbl9vbGRfcGFzc3dvcmRfbGFiZWwnKSwgJ3JlcXVpcmVkJyk7DQogICAgICAgICR0aGlzLT5mb3JtX3ZhbGlkYXRpb24tPnNldF9ydWxlcygnbmV3JywgJHRoaXMtPmxhbmctPmxpbmUoJ2NoYW5nZV9wYXNzd29yZF92YWxpZGF0aW9uX25ld19wYXNzd29yZF9sYWJlbCcpLCAncmVxdWlyZWR8bWluX2xlbmd0aFsnIC4gJHRoaXMtPmNvbmZpZy0+aXRlbSgnbWluX3Bhc3N3b3JkX2xlbmd0aCcsICdpb25fYXV0aCcpIC4gJ118bWF0Y2hlc1tuZXdfY29uZmlybV0nKTsNCiAgICAgICAgJHRoaXMtPmZvcm1fdmFsaWRhdGlvbi0+c2V0X3J1bGVzKCduZXdfY29uZmlybScsICR0aGlzLT5sYW5nLT5saW5lKCdjaGFuZ2VfcGFzc3dvcmRfdmFsaWRhdGlvbl9uZXdfcGFzc3dvcmRfY29uZmlybV9sYWJlbCcpLCAncmVxdWlyZWQnKTsNCg0KICAgICAgICBpZiAoISR0aGlzLT5pb25fYXV0aC0+bG9nZ2VkX2luKCkpDQogICAgICAgIHsNCiAgICAgICAgICAgIHJlZGlyZWN0KCdhdXRoL2xvZ2luJywgJ3JlZnJlc2gnKTsNCiAgICAgICAgfQ0KDQogICAgICAgICR1c2VyID0gJHRoaXMtPmlvbl9hdXRoLT51c2VyKCktPnJvdygpOw0KDQogICAgICAgIGlmICgkdGhpcy0+Zm9ybV92YWxpZGF0aW9uLT5ydW4oKSA9PT0gRkFMU0UpDQogICAgICAgIHsNCiAgICAgICAgICAgIC8vIGRpc3BsYXkgdGhlIGZvcm0NCiAgICAgICAgICAgIC8vIHNldCB0aGUgZmxhc2ggZGF0YSBlcnJvciBtZXNzYWdlIGlmIHRoZXJlIGlzIG9uZQ0KICAgICAgICAgICAgJHRoaXMtPmRhdGFbJ21lc3NhZ2UnXSA9ICh2YWxpZGF0aW9uX2Vycm9ycygpKSA/IHZhbGlkYXRpb25fZXJyb3JzKCkgOiAkdGhpcy0+c2Vzc2lvbi0+Zmxhc2hkYXRhKCdtZXNzYWdlJyk7DQoNCiAgICAgICAgICAgICR0aGlzLT5kYXRhWydtaW5fcGFzc3dvcmRfbGVuZ3RoJ10gPSAkdGhpcy0+Y29uZmlnLT5pdGVtKCdtaW5fcGFzc3dvcmRfbGVuZ3RoJywgJ2lvbl9hdXRoJyk7DQogICAgICAgICAgICAkdGhpcy0+ZGF0YVsnb2xkX3Bhc3N3b3JkJ10gPSBbDQogICAgICAgICAgICAgICAgJ25hbWUnID0+ICdvbGQnLA0KICAgICAgICAgICAgICAgICdpZCcgPT4gJ29sZCcsDQogICAgICAgICAgICAgICAgJ3R5cGUnID0+ICdwYXNzd29yZCcsDQogICAgICAgICAgICBdOw0KICAgICAgICAgICAgJHRoaXMtPmRhdGFbJ25ld19wYXNzd29yZCddID0gWw0KICAgICAgICAgICAgICAgICduYW1lJyA9PiAnbmV3JywNCiAgICAgICAgICAgICAgICAnaWQnID0+ICduZXcnLA0KICAgICAgICAgICAgICAgICd0eXBlJyA9PiAncGFzc3dvcmQnLA0KICAgICAgICAgICAgICAgICdwYXR0ZXJuJyA9PiAnXi57JyAuICR0aGlzLT5kYXRhWydtaW5fcGFzc3dvcmRfbGVuZ3RoJ10gLiAnfS4qJCcsDQogICAgICAgICAgICBdOw0KICAgICAgICAgICAgJHRoaXMtPmRhdGFbJ25ld19wYXNzd29yZF9jb25maXJtJ10gPSBbDQogICAgICAgICAgICAgICAgJ25hbWUnID0+ICduZXdfY29uZmlybScsDQogICAgICAgICAgICAgICAgJ2lkJyA9PiAnbmV3X2NvbmZpcm0nLA0KICAgICAgICAgICAgICAgICd0eXBlJyA9PiAncGFzc3dvcmQnLA0KICAgICAgICAgICAgICAgICdwYXR0ZXJuJyA9PiAnXi57JyAuICR0aGlzLT5kYXRhWydtaW5fcGFzc3dvcmRfbGVuZ3RoJ10gLiAnfS4qJCcsDQogICAgICAgICAgICBdOw0KICAgICAgICAgICAgJHRoaXMtPmRhdGFbJ3VzZXJfaWQnXSA9IFsNCiAgICAgICAgICAgICAgICAnbmFtZScgPT4gJ3VzZXJfaWQnLA0KICAgICAgICAgICAgICAgICdpZCcgPT4gJ3VzZXJfaWQnLA0KICAgICAgICAgICAgICAgICd0eXBlJyA9PiAnaGlkZGVuJywNCiAgICAgICAgICAgICAgICAndmFsdWUnID0+ICR1c2VyLT5pZCwNCiAgICAgICAgICAgIF07DQoNCiAgICAgICAgICAgIC8vIHJlbmRlcg0KICAgICAgICAgICAgJHRoaXMtPl9yZW5kZXJfcGFnZSgnYXV0aCcgLiBESVJFQ1RPUllfU0VQQVJBVE9SIC4gJ2NoYW5nZV9wYXNzd29yZCcsICR0aGlzLT5kYXRhKTsNCiAgICAgICAgfQ0KICAgICAgICBlbHNlDQogICAgICAgIHsNCiAgICAgICAgICAgICRpZGVudGl0eSA9ICR0aGlzLT5zZXNzaW9uLT51c2VyZGF0YSgnaWRlbnRpdHknKTsNCg0KICAgICAgICAgICAgJGNoYW5nZSA9ICR0aGlzLT5pb25fYXV0aC0+Y2hhbmdlX3Bhc3N3b3JkKCRpZGVudGl0eSwgJHRoaXMtPmlucHV0LT5wb3N0KCdvbGQnKSwgJHRoaXMtPmlucHV0LT5wb3N0KCduZXcnKSk7DQoNCiAgICAgICAgICAgIGlmICgkY2hhbmdlKQ0KICAgICAgICAgICAgew0KICAgICAgICAgICAgICAgIC8vaWYgdGhlIHBhc3N3b3JkIHdhcyBzdWNjZXNzZnVsbHkgY2hhbmdlZA0KICAgICAgICAgICAgICAgICR0aGlzLT5zZXNzaW9uLT5zZXRfZmxhc2hkYXRhKCdtZXNzYWdlJywgJHRoaXMtPmlvbl9hdXRoLT5tZXNzYWdlcygpKTsNCiAgICAgICAgICAgICAgICAkdGhpcy0+bG9nb3V0KCk7DQogICAgICAgICAgICB9DQogICAgICAgICAgICBlbHNlDQogICAgICAgICAgICB7DQogICAgICAgICAgICAgICAgJHRoaXMtPnNlc3Npb24tPnNldF9mbGFzaGRhdGEoJ21lc3NhZ2UnLCAkdGhpcy0+aW9uX2F1dGgtPmVycm9ycygpKTsNCiAgICAgICAgICAgICAgICByZWRpcmVjdCgnYXV0aC9jaGFuZ2VfcGFzc3dvcmQnLCAncmVmcmVzaCcpOw0KICAgICAgICAgICAgfQ0KICAgICAgICB9DQogICAgfQ0KDQogICAgLyoqDQoJICogRm9yZ290IHBhc3N3b3JkDQoJICovDQoJcHVibGljIGZ1bmN0aW9uIGZvcmdvdF9wYXNzd29yZCgpDQoJew0KCQkkdGhpcy0+ZGF0YVsndGl0bGUnXSA9ICR0aGlzLT5sYW5nLT5saW5lKCdmb3Jnb3RfcGFzc3dvcmRfaGVhZGluZycpOw0KCQkNCgkJLy8gc2V0dGluZyB2YWxpZGF0aW9uIHJ1bGVzIGJ5IGNoZWNraW5nIHdoZXRoZXIgaWRlbnRpdHkgaXMgdXNlcm5hbWUgb3IgZW1haWwNCgkJaWYgKCR0aGlzLT5jb25maWctPml0ZW0oJ2lkZW50aXR5JywgJ2lvbl9hdXRoJykgIT0gJ2VtYWlsJykNCgkJew0KCQkJJHRoaXMtPmZvcm1fdmFsaWRhdGlvbi0+c2V0X3J1bGVzKCdpZGVudGl0eScsICR0aGlzLT5sYW5nLT5saW5lKCdmb3Jnb3RfcGFzc3dvcmRfaWRlbnRpdHlfbGFiZWwnKSwgJ3JlcXVpcmVkJyk7DQoJCX0NCgkJZWxzZQ0KCQl7DQoJCQkkdGhpcy0+Zm9ybV92YWxpZGF0aW9uLT5zZXRfcnVsZXMoJ2lkZW50aXR5JywgJHRoaXMtPmxhbmctPmxpbmUoJ2ZvcmdvdF9wYXNzd29yZF92YWxpZGF0aW9uX2VtYWlsX2xhYmVsJyksICdyZXF1aXJlZHx2YWxpZF9lbWFpbCcpOw0KCQl9DQoNCg0KCQlpZiAoJHRoaXMtPmZvcm1fdmFsaWRhdGlvbi0+cnVuKCkgPT09IEZBTFNFKQ0KCQl7DQoJCQkkdGhpcy0+ZGF0YVsndHlwZSddID0gJHRoaXMtPmNvbmZpZy0+aXRlbSgnaWRlbnRpdHknLCAnaW9uX2F1dGgnKTsNCgkJCS8vIHNldHVwIHRoZSBpbnB1dA0KCQkJJHRoaXMtPmRhdGFbJ2lkZW50aXR5J10gPSBbDQoJCQkJJ25hbWUnIAk9PiAnaWRlbnRpdHknLA0KCQkJCSdpZCcJPT4gJ2lkZW50aXR5JywNCgkJCQknY2xhc3MnCT0+ICdmb3JtLWNvbnRyb2wnLA0KCQkJCSdhdXRvY29tcGxldGUnCT0+ICdvZmYnLA0KCQkJCSdhdXRvZm9jdXMnCT0+ICdhdXRvZm9jdXMnDQoJCQldOw0KDQoJCQlpZiAoJHRoaXMtPmNvbmZpZy0+aXRlbSgnaWRlbnRpdHknLCAnaW9uX2F1dGgnKSAhPSAnZW1haWwnKQ0KCQkJew0KCQkJCSR0aGlzLT5kYXRhWydpZGVudGl0eV9sYWJlbCddID0gJHRoaXMtPmxhbmctPmxpbmUoJ2ZvcmdvdF9wYXNzd29yZF9pZGVudGl0eV9sYWJlbCcpOw0KCQkJfQ0KCQkJZWxzZQ0KCQkJew0KCQkJCSR0aGlzLT5kYXRhWydpZGVudGl0eV9sYWJlbCddID0gJHRoaXMtPmxhbmctPmxpbmUoJ2ZvcmdvdF9wYXNzd29yZF9lbWFpbF9pZGVudGl0eV9sYWJlbCcpOw0KCQkJfQ0KDQoJCQkvLyBzZXQgYW55IGVycm9ycyBhbmQgZGlzcGxheSB0aGUgZm9ybQ0KCQkJJHRoaXMtPmRhdGFbJ21lc3NhZ2UnXSA9ICh2YWxpZGF0aW9uX2Vycm9ycygpKSA/IHZhbGlkYXRpb25fZXJyb3JzKCkgOiAkdGhpcy0+c2Vzc2lvbi0+Zmxhc2hkYXRhKCdtZXNzYWdlJyk7DQoJCQkkdGhpcy0+bG9hZC0+dmlldygnX3RlbXBsYXRlcy9hdXRoL19oZWFkZXInLCAkdGhpcy0+ZGF0YSk7DQoJCQkkdGhpcy0+bG9hZC0+dmlldygnYXV0aC9mb3Jnb3RfcGFzc3dvcmQnKTsNCgkJCSR0aGlzLT5sb2FkLT52aWV3KCdfdGVtcGxhdGVzL2F1dGgvX2Zvb3RlcicpOw0KCQl9DQoJCWVsc2UNCgkJew0KCQkJJGlkZW50aXR5X2NvbHVtbiA9ICR0aGlzLT5jb25maWctPml0ZW0oJ2lkZW50aXR5JywgJ2lvbl9hdXRoJyk7DQoJCQkkaWRlbnRpdHkgPSAkdGhpcy0+aW9uX2F1dGgtPndoZXJlKCRpZGVudGl0eV9jb2x1bW4sICR0aGlzLT5pbnB1dC0+cG9zdCgnaWRlbnRpdHknKSktPnVzZXJzKCktPnJvdygpOw0KDQoJCQlpZiAoZW1wdHkoJGlkZW50aXR5KSkNCgkJCXsNCg0KCQkJCWlmICgkdGhpcy0+Y29uZmlnLT5pdGVtKCdpZGVudGl0eScsICdpb25fYXV0aCcpICE9ICdlbWFpbCcpDQoJCQkJew0KCQkJCQkkdGhpcy0+aW9uX2F1dGgtPnNldF9lcnJvcignZm9yZ290X3Bhc3N3b3JkX2lkZW50aXR5X25vdF9mb3VuZCcpOw0KCQkJCX0NCgkJCQllbHNlDQoJCQkJew0KCQkJCQkkdGhpcy0+aW9uX2F1dGgtPnNldF9lcnJvcignZm9yZ290X3Bhc3N3b3JkX2VtYWlsX25vdF9mb3VuZCcpOw0KCQkJCX0NCg0KCQkJCSR0aGlzLT5zZXNzaW9uLT5zZXRfZmxhc2hkYXRhKCdtZXNzYWdlJywgJHRoaXMtPmlvbl9hdXRoLT5lcnJvcnMoKSk7DQoJCQkJcmVkaXJlY3QoImF1dGgvZm9yZ290X3Bhc3N3b3JkIiwgJ3JlZnJlc2gnKTsNCgkJCX0NCg0KCQkJLy8gcnVuIHRoZSBmb3Jnb3R0ZW4gcGFzc3dvcmQgbWV0aG9kIHRvIGVtYWlsIGFuIGFjdGl2YXRpb24gY29kZSB0byB0aGUgdXNlcg0KCQkJJGZvcmdvdHRlbiA9ICR0aGlzLT5pb25fYXV0aC0+Zm9yZ290dGVuX3Bhc3N3b3JkKCRpZGVudGl0eS0+eyR0aGlzLT5jb25maWctPml0ZW0oJ2lkZW50aXR5JywgJ2lvbl9hdXRoJyl9KTsNCg0KCQkJaWYgKCRmb3Jnb3R0ZW4pDQoJCQl7DQoJCQkJLy8gaWYgdGhlcmUgd2VyZSBubyBlcnJvcnMNCgkJCQkkdGhpcy0+c2Vzc2lvbi0+c2V0X2ZsYXNoZGF0YSgnc3VjY2VzcycsICR0aGlzLT5pb25fYXV0aC0+bWVzc2FnZXMoKSk7DQoJCQkJcmVkaXJlY3QoImF1dGgvZm9yZ290X3Bhc3N3b3JkIiwgJ3JlZnJlc2gnKTsgLy93ZSBzaG91bGQgZGlzcGxheSBhIGNvbmZpcm1hdGlvbiBwYWdlIGhlcmUgaW5zdGVhZCBvZiB0aGUgbG9naW4gcGFnZQ0KCQkJfQ0KCQkJZWxzZQ0KCQkJew0KCQkJCSR0aGlzLT5zZXNzaW9uLT5zZXRfZmxhc2hkYXRhKCdtZXNzYWdlJywgJHRoaXMtPmlvbl9hdXRoLT5lcnJvcnMoKSk7DQoJCQkJcmVkaXJlY3QoImF1dGgvZm9yZ290X3Bhc3N3b3JkIiwgJ3JlZnJlc2gnKTsNCgkJCX0NCgkJfQ0KCX0NCg0KCS8qKg0KCSAqIFJlc2V0IHBhc3N3b3JkIC0gZmluYWwgc3RlcCBmb3IgZm9yZ290dGVuIHBhc3N3b3JkDQoJICoNCgkgKiBAcGFyYW0gc3RyaW5nfG51bGwgJGNvZGUgVGhlIHJlc2V0IGNvZGUNCgkgKi8NCglwdWJsaWMgZnVuY3Rpb24gcmVzZXRfcGFzc3dvcmQoJGNvZGUgPSBOVUxMKQ0KCXsNCgkJaWYgKCEkY29kZSkNCgkJew0KCQkJc2hvd180MDQoKTsNCgkJfQ0KDQoJCSR0aGlzLT5kYXRhWyd0aXRsZSddID0gJHRoaXMtPmxhbmctPmxpbmUoJ3Jlc2V0X3Bhc3N3b3JkX2hlYWRpbmcnKTsNCgkJDQoJCSR1c2VyID0gJHRoaXMtPmlvbl9hdXRoLT5mb3Jnb3R0ZW5fcGFzc3dvcmRfY2hlY2soJGNvZGUpOw0KDQoJCWlmICgkdXNlcikNCgkJew0KCQkJLy8gaWYgdGhlIGNvZGUgaXMgdmFsaWQgdGhlbiBkaXNwbGF5IHRoZSBwYXNzd29yZCByZXNldCBmb3JtDQoNCgkJCSR0aGlzLT5mb3JtX3ZhbGlkYXRpb24tPnNldF9ydWxlcygnbmV3JywgJHRoaXMtPmxhbmctPmxpbmUoJ3Jlc2V0X3Bhc3N3b3JkX3ZhbGlkYXRpb25fbmV3X3Bhc3N3b3JkX2xhYmVsJyksICdyZXF1aXJlZHxtaW5fbGVuZ3RoWycgLiAkdGhpcy0+Y29uZmlnLT5pdGVtKCdtaW5fcGFzc3dvcmRfbGVuZ3RoJywgJ2lvbl9hdXRoJykgLiAnXXxtYXRjaGVzW25ld19jb25maXJtXScpOw0KCQkJJHRoaXMtPmZvcm1fdmFsaWRhdGlvbi0+c2V0X3J1bGVzKCduZXdfY29uZmlybScsICR0aGlzLT5sYW5nLT5saW5lKCdyZXNldF9wYXNzd29yZF92YWxpZGF0aW9uX25ld19wYXNzd29yZF9jb25maXJtX2xhYmVsJyksICdyZXF1aXJlZCcpOw0KDQoJCQlpZiAoJHRoaXMtPmZvcm1fdmFsaWRhdGlvbi0+cnVuKCkgPT09IEZBTFNFKQ0KCQkJew0KCQkJCS8vIGRpc3BsYXkgdGhlIGZvcm0NCg0KCQkJCS8vIHNldCB0aGUgZmxhc2ggZGF0YSBlcnJvciBtZXNzYWdlIGlmIHRoZXJlIGlzIG9uZQ0KCQkJCSR0aGlzLT5kYXRhWydtZXNzYWdlJ10gPSAodmFsaWRhdGlvbl9lcnJvcnMoKSkgPyB2YWxpZGF0aW9uX2Vycm9ycygpIDogJHRoaXMtPnNlc3Npb24tPmZsYXNoZGF0YSgnbWVzc2FnZScpOw0KDQoJCQkJJHRoaXMtPmRhdGFbJ21pbl9wYXNzd29yZF9sZW5ndGgnXSA9ICR0aGlzLT5jb25maWctPml0ZW0oJ21pbl9wYXNzd29yZF9sZW5ndGgnLCAnaW9uX2F1dGgnKTsNCgkJCQkkdGhpcy0+ZGF0YVsnbmV3X3Bhc3N3b3JkJ10gPSBbDQoJCQkJCSduYW1lJyA9PiAnbmV3JywNCgkJCQkJJ2lkJyA9PiAnbmV3JywNCgkJCQkJJ3R5cGUnID0+ICdwYXNzd29yZCcsDQoJCQkJCSdwYXR0ZXJuJyA9PiAnXi57JyAuICR0aGlzLT5kYXRhWydtaW5fcGFzc3dvcmRfbGVuZ3RoJ10gLiAnfS4qJCcsDQoJCQkJXTsNCgkJCQkkdGhpcy0+ZGF0YVsnbmV3X3Bhc3N3b3JkX2NvbmZpcm0nXSA9IFsNCgkJCQkJJ25hbWUnID0+ICduZXdfY29uZmlybScsDQoJCQkJCSdpZCcgPT4gJ25ld19jb25maXJtJywNCgkJCQkJJ3R5cGUnID0+ICdwYXNzd29yZCcsDQoJCQkJCSdwYXR0ZXJuJyA9PiAnXi57JyAuICR0aGlzLT5kYXRhWydtaW5fcGFzc3dvcmRfbGVuZ3RoJ10gLiAnfS4qJCcsDQoJCQkJXTsNCgkJCQkkdGhpcy0+ZGF0YVsndXNlcl9pZCddID0gWw0KCQkJCQknbmFtZScgPT4gJ3VzZXJfaWQnLA0KCQkJCQknaWQnID0+ICd1c2VyX2lkJywNCgkJCQkJJ3R5cGUnID0+ICdoaWRkZW4nLA0KCQkJCQkndmFsdWUnID0+ICR1c2VyLT5pZCwNCgkJCQldOw0KCQkJCSR0aGlzLT5kYXRhWydjc3JmJ10gPSAkdGhpcy0+X2dldF9jc3JmX25vbmNlKCk7DQoJCQkJJHRoaXMtPmRhdGFbJ2NvZGUnXSA9ICRjb2RlOw0KDQoJCQkJLy8gcmVuZGVyDQoJCQkJJHRoaXMtPmxvYWQtPnZpZXcoJ190ZW1wbGF0ZXMvYXV0aC9faGVhZGVyJyk7DQoJCQkJJHRoaXMtPmxvYWQtPnZpZXcoJ2F1dGgvcmVzZXRfcGFzc3dvcmQnLCAkdGhpcy0+ZGF0YSk7DQoJCQkJJHRoaXMtPmxvYWQtPnZpZXcoJ190ZW1wbGF0ZXMvYXV0aC9fZm9vdGVyJyk7DQoJCQl9DQoJCQllbHNlDQoJCQl7DQoJCQkJJGlkZW50aXR5ID0gJHVzZXItPnskdGhpcy0+Y29uZmlnLT5pdGVtKCdpZGVudGl0eScsICdpb25fYXV0aCcpfTsNCg0KCQkJCS8vIGRvIHdlIGhhdmUgYSB2YWxpZCByZXF1ZXN0Pw0KCQkJCWlmICgkdGhpcy0+X3ZhbGlkX2NzcmZfbm9uY2UoKSA9PT0gRkFMU0UgfHwgJHVzZXItPmlkICE9ICR0aGlzLT5pbnB1dC0+cG9zdCgndXNlcl9pZCcpKQ0KCQkJCXsNCg0KCQkJCQkvLyBzb21ldGhpbmcgZmlzaHkgbWlnaHQgYmUgdXANCgkJCQkJJHRoaXMtPmlvbl9hdXRoLT5jbGVhcl9mb3Jnb3R0ZW5fcGFzc3dvcmRfY29kZSgkaWRlbnRpdHkpOw0KDQoJCQkJCXNob3dfZXJyb3IoJHRoaXMtPmxhbmctPmxpbmUoJ2Vycm9yX2NzcmYnKSk7DQoNCgkJCQl9DQoJCQkJZWxzZQ0KCQkJCXsNCgkJCQkJLy8gZmluYWxseSBjaGFuZ2UgdGhlIHBhc3N3b3JkDQoJCQkJCSRjaGFuZ2UgPSAkdGhpcy0+aW9uX2F1dGgtPnJlc2V0X3Bhc3N3b3JkKCRpZGVudGl0eSwgJHRoaXMtPmlucHV0LT5wb3N0KCduZXcnKSk7DQoNCgkJCQkJaWYgKCRjaGFuZ2UpDQoJCQkJCXsNCgkJCQkJCS8vIGlmIHRoZSBwYXNzd29yZCB3YXMgc3VjY2Vzc2Z1bGx5IGNoYW5nZWQNCgkJCQkJCSR0aGlzLT5zZXNzaW9uLT5zZXRfZmxhc2hkYXRhKCdtZXNzYWdlJywgJHRoaXMtPmlvbl9hdXRoLT5tZXNzYWdlcygpKTsNCgkJCQkJCXJlZGlyZWN0KCJhdXRoL2xvZ2luIiwgJ3JlZnJlc2gnKTsNCgkJCQkJfQ0KCQkJCQllbHNlDQoJCQkJCXsNCgkJCQkJCSR0aGlzLT5zZXNzaW9uLT5zZXRfZmxhc2hkYXRhKCdtZXNzYWdlJywgJHRoaXMtPmlvbl9hdXRoLT5lcnJvcnMoKSk7DQoJCQkJCQlyZWRpcmVjdCgnYXV0aC9yZXNldF9wYXNzd29yZC8nIC4gJGNvZGUsICdyZWZyZXNoJyk7DQoJCQkJCX0NCgkJCQl9DQoJCQl9DQoJCX0NCgkJZWxzZQ0KCQl7DQoJCQkvLyBpZiB0aGUgY29kZSBpcyBpbnZhbGlkIHRoZW4gc2VuZCB0aGVtIGJhY2sgdG8gdGhlIGZvcmdvdCBwYXNzd29yZCBwYWdlDQoJCQkkdGhpcy0+c2Vzc2lvbi0+c2V0X2ZsYXNoZGF0YSgnbWVzc2FnZScsICR0aGlzLT5pb25fYXV0aC0+ZXJyb3JzKCkpOw0KCQkJcmVkaXJlY3QoImF1dGgvZm9yZ290X3Bhc3N3b3JkIiwgJ3JlZnJlc2gnKTsNCgkJfQ0KCX0NCg0KCS8qKg0KCSAqIEFjdGl2YXRlIHRoZSB1c2VyDQoJICoNCgkgKiBAcGFyYW0gaW50ICAgICAgICAgJGlkICAgVGhlIHVzZXIgSUQNCgkgKiBAcGFyYW0gc3RyaW5nfGJvb2wgJGNvZGUgVGhlIGFjdGl2YXRpb24gY29kZQ0KCSAqLw0KCXB1YmxpYyBmdW5jdGlvbiBhY3RpdmF0ZSgkaWQsICRjb2RlID0gRkFMU0UpDQoJew0KCQkkYWN0aXZhdGlvbiA9IEZBTFNFOw0KDQoJCWlmICgkY29kZSAhPT0gRkFMU0UpDQoJCXsNCgkJCSRhY3RpdmF0aW9uID0gJHRoaXMtPmlvbl9hdXRoLT5hY3RpdmF0ZSgkaWQsICRjb2RlKTsNCgkJfQ0KCQllbHNlIGlmICgkdGhpcy0+aW9uX2F1dGgtPmlzX2FkbWluKCkpDQoJCXsNCgkJCSRhY3RpdmF0aW9uID0gJHRoaXMtPmlvbl9hdXRoLT5hY3RpdmF0ZSgkaWQpOw0KCQl9DQoNCgkJaWYgKCRhY3RpdmF0aW9uKQ0KCQl7DQoJCQkvLyByZWRpcmVjdCB0aGVtIHRvIHRoZSBhdXRoIHBhZ2UNCgkJCSR0aGlzLT5zZXNzaW9uLT5zZXRfZmxhc2hkYXRhKCdtZXNzYWdlJywgJHRoaXMtPmlvbl9hdXRoLT5tZXNzYWdlcygpKTsNCgkJCXJlZGlyZWN0KCJhdXRoIiwgJ3JlZnJlc2gnKTsNCgkJfQ0KCQllbHNlDQoJCXsNCgkJCS8vIHJlZGlyZWN0IHRoZW0gdG8gdGhlIGZvcmdvdCBwYXNzd29yZCBwYWdlDQoJCQkkdGhpcy0+c2Vzc2lvbi0+c2V0X2ZsYXNoZGF0YSgnbWVzc2FnZScsICR0aGlzLT5pb25fYXV0aC0+ZXJyb3JzKCkpOw0KCQkJcmVkaXJlY3QoImF1dGgvZm9yZ290X3Bhc3N3b3JkIiwgJ3JlZnJlc2gnKTsNCgkJfQ0KCX0NCg0KICAgIC8qKg0KICAgICAqIERlYWN0aXZhdGUgdGhlIHVzZXINCiAgICAgKg0KICAgICAqIEBwYXJhbSBpbnR8c3RyaW5nfG51bGwgJGlkIFRoZSB1c2VyIElEDQogICAgICovDQogICAgcHVibGljIGZ1bmN0aW9uIGRlYWN0aXZhdGUoJGlkID0gTlVMTCkNCiAgICB7DQogICAgICAgIGlmICghJHRoaXMtPmlvbl9hdXRoLT5sb2dnZWRfaW4oKSB8fCAhJHRoaXMtPmlvbl9hdXRoLT5pc19hZG1pbigpKQ0KICAgICAgICB7DQogICAgICAgICAgICAvLyByZWRpcmVjdCB0aGVtIHRvIHRoZSBob21lIHBhZ2UgYmVjYXVzZSB0aGV5IG11c3QgYmUgYW4gYWRtaW5pc3RyYXRvciB0byB2aWV3IHRoaXMNCiAgICAgICAgICAgIHNob3dfZXJyb3IoJ1lvdSBtdXN0IGJlIGFuIGFkbWluaXN0cmF0b3IgdG8gdmlldyB0aGlzIHBhZ2UuJyk7DQogICAgICAgIH0NCg0KICAgICAgICAkaWQgPSAoaW50KSRpZDsNCg0KICAgICAgICAkdGhpcy0+bG9hZC0+bGlicmFyeSgnZm9ybV92YWxpZGF0aW9uJyk7DQogICAgICAgICR0aGlzLT5mb3JtX3ZhbGlkYXRpb24tPnNldF9ydWxlcygnY29uZmlybScsICR0aGlzLT5sYW5nLT5saW5lKCdkZWFjdGl2YXRlX3ZhbGlkYXRpb25fY29uZmlybV9sYWJlbCcpLCAncmVxdWlyZWQnKTsNCiAgICAgICAgJHRoaXMtPmZvcm1fdmFsaWRhdGlvbi0+c2V0X3J1bGVzKCdpZCcsICR0aGlzLT5sYW5nLT5saW5lKCdkZWFjdGl2YXRlX3ZhbGlkYXRpb25fdXNlcl9pZF9sYWJlbCcpLCAncmVxdWlyZWR8YWxwaGFfbnVtZXJpYycpOw0KDQogICAgICAgIGlmICgkdGhpcy0+Zm9ybV92YWxpZGF0aW9uLT5ydW4oKSA9PT0gRkFMU0UpDQogICAgICAgIHsNCiAgICAgICAgICAgIC8vIGluc2VydCBjc3JmIGNoZWNrDQogICAgICAgICAgICAkdGhpcy0+ZGF0YVsnY3NyZiddID0gJHRoaXMtPl9nZXRfY3NyZl9ub25jZSgpOw0KICAgICAgICAgICAgJHRoaXMtPmRhdGFbJ3VzZXInXSA9ICR0aGlzLT5pb25fYXV0aC0+dXNlcigkaWQpLT5yb3coKTsNCg0KICAgICAgICAgICAgJHRoaXMtPl9yZW5kZXJfcGFnZSgnYXV0aCcgLiBESVJFQ1RPUllfU0VQQVJBVE9SIC4gJ2RlYWN0aXZhdGVfdXNlcicsICR0aGlzLT5kYXRhKTsNCiAgICAgICAgfQ0KICAgICAgICBlbHNlDQogICAgICAgIHsNCiAgICAgICAgICAgIC8vIGRvIHdlIHJlYWxseSB3YW50IHRvIGRlYWN0aXZhdGU/DQogICAgICAgICAgICBpZiAoJHRoaXMtPmlucHV0LT5wb3N0KCdjb25maXJtJykgPT0gJ3llcycpDQogICAgICAgICAgICB7DQogICAgICAgICAgICAgICAgLy8gZG8gd2UgaGF2ZSBhIHZhbGlkIHJlcXVlc3Q/DQogICAgICAgICAgICAgICAgaWYgKCR0aGlzLT5fdmFsaWRfY3NyZl9ub25jZSgpID09PSBGQUxTRSB8fCAkaWQgIT0gJHRoaXMtPmlucHV0LT5wb3N0KCdpZCcpKQ0KICAgICAgICAgICAgICAgIHsNCiAgICAgICAgICAgICAgICAgICAgc2hvd19lcnJvcigkdGhpcy0+bGFuZy0+bGluZSgnZXJyb3JfY3NyZicpKTsNCiAgICAgICAgICAgICAgICB9DQoNCiAgICAgICAgICAgICAgICAvLyBkbyB3ZSBoYXZlIHRoZSByaWdodCB1c2VybGV2ZWw/DQogICAgICAgICAgICAgICAgaWYgKCR0aGlzLT5pb25fYXV0aC0+bG9nZ2VkX2luKCkgJiYgJHRoaXMtPmlvbl9hdXRoLT5pc19hZG1pbigpKQ0KICAgICAgICAgICAgICAgIHsNCiAgICAgICAgICAgICAgICAgICAgJHRoaXMtPmlvbl9hdXRoLT5kZWFjdGl2YXRlKCRpZCk7DQogICAgICAgICAgICAgICAgfQ0KICAgICAgICAgICAgfQ0KDQogICAgICAgICAgICAvLyByZWRpcmVjdCB0aGVtIGJhY2sgdG8gdGhlIGF1dGggcGFnZQ0KICAgICAgICAgICAgcmVkaXJlY3QoJ2F1dGgnLCAncmVmcmVzaCcpOw0KICAgICAgICB9DQogICAgfQ0KDQogICAgLyoqDQogICAgICogQ3JlYXRlIGEgbmV3IHVzZXINCiAgICAgKi8NCiAgICBwdWJsaWMgZnVuY3Rpb24gY3JlYXRlX3VzZXIoKQ0KICAgIHsNCiAgICAgICAgJHRoaXMtPmRhdGFbJ3RpdGxlJ10gPSAkdGhpcy0+bGFuZy0+bGluZSgnY3JlYXRlX3VzZXJfaGVhZGluZycpOw0KDQogICAgICAgIGlmICghJHRoaXMtPmlvbl9hdXRoLT5sb2dnZWRfaW4oKSB8fCAhJHRoaXMtPmlvbl9hdXRoLT5pc19hZG1pbigpKQ0KICAgICAgICB7DQogICAgICAgICAgICByZWRpcmVjdCgnYXV0aCcsICdyZWZyZXNoJyk7DQogICAgICAgIH0NCg0KICAgICAgICAkdGFibGVzID0gJHRoaXMtPmNvbmZpZy0+aXRlbSgndGFibGVzJywgJ2lvbl9hdXRoJyk7DQogICAgICAgICRpZGVudGl0eV9jb2x1bW4gPSAkdGhpcy0+Y29uZmlnLT5pdGVtKCdpZGVudGl0eScsICdpb25fYXV0aCcpOw0KICAgICAgICAkdGhpcy0+ZGF0YVsnaWRlbnRpdHlfY29sdW1uJ10gPSAkaWRlbnRpdHlfY29sdW1uOw0KDQogICAgICAgIC8vIHZhbGlkYXRlIGZvcm0gaW5wdXQNCiAgICAgICAgJHRoaXMtPmZvcm1fdmFsaWRhdGlvbi0+c2V0X3J1bGVzKCdmaXJzdF9uYW1lJywgJHRoaXMtPmxhbmctPmxpbmUoJ2NyZWF0ZV91c2VyX3ZhbGlkYXRpb25fZm5hbWVfbGFiZWwnKSwgJ3RyaW18cmVxdWlyZWQnKTsNCiAgICAgICAgJHRoaXMtPmZvcm1fdmFsaWRhdGlvbi0+c2V0X3J1bGVzKCdsYXN0X25hbWUnLCAkdGhpcy0+bGFuZy0+bGluZSgnY3JlYXRlX3VzZXJfdmFsaWRhdGlvbl9sbmFtZV9sYWJlbCcpLCAndHJpbXxyZXF1aXJlZCcpOw0KICAgICAgICBpZiAoJGlkZW50aXR5X2NvbHVtbiAhPT0gJ2VtYWlsJykNCiAgICAgICAgew0KICAgICAgICAgICAgJHRoaXMtPmZvcm1fdmFsaWRhdGlvbi0+c2V0X3J1bGVzKCdpZGVudGl0eScsICR0aGlzLT5sYW5nLT5saW5lKCdjcmVhdGVfdXNlcl92YWxpZGF0aW9uX2lkZW50aXR5X2xhYmVsJyksICd0cmltfHJlcXVpcmVkfGlzX3VuaXF1ZVsnIC4gJHRhYmxlc1sndXNlcnMnXSAuICcuJyAuICRpZGVudGl0eV9jb2x1bW4gLiAnXScpOw0KICAgICAgICAgICAgJHRoaXMtPmZvcm1fdmFsaWRhdGlvbi0+c2V0X3J1bGVzKCdlbWFpbCcsICR0aGlzLT5sYW5nLT5saW5lKCdjcmVhdGVfdXNlcl92YWxpZGF0aW9uX2VtYWlsX2xhYmVsJyksICd0cmltfHJlcXVpcmVkfHZhbGlkX2VtYWlsJyk7DQogICAgICAgIH0NCiAgICAgICAgZWxzZQ0KICAgICAgICB7DQogICAgICAgICAgICAkdGhpcy0+Zm9ybV92YWxpZGF0aW9uLT5zZXRfcnVsZXMoJ2VtYWlsJywgJHRoaXMtPmxhbmctPmxpbmUoJ2NyZWF0ZV91c2VyX3ZhbGlkYXRpb25fZW1haWxfbGFiZWwnKSwgJ3RyaW18cmVxdWlyZWR8dmFsaWRfZW1haWx8aXNfdW5pcXVlWycgLiAkdGFibGVzWyd1c2VycyddIC4gJy5lbWFpbF0nKTsNCiAgICAgICAgfQ0KICAgICAgICAkdGhpcy0+Zm9ybV92YWxpZGF0aW9uLT5zZXRfcnVsZXMoJ3Bob25lJywgJHRoaXMtPmxhbmctPmxpbmUoJ2NyZWF0ZV91c2VyX3ZhbGlkYXRpb25fcGhvbmVfbGFiZWwnKSwgJ3RyaW0nKTsNCiAgICAgICAgJHRoaXMtPmZvcm1fdmFsaWRhdGlvbi0+c2V0X3J1bGVzKCdjb21wYW55JywgJHRoaXMtPmxhbmctPmxpbmUoJ2NyZWF0ZV91c2VyX3ZhbGlkYXRpb25fY29tcGFueV9sYWJlbCcpLCAndHJpbScpOw0KICAgICAgICAkdGhpcy0+Zm9ybV92YWxpZGF0aW9uLT5zZXRfcnVsZXMoJ3Bhc3N3b3JkJywgJHRoaXMtPmxhbmctPmxpbmUoJ2NyZWF0ZV91c2VyX3ZhbGlkYXRpb25fcGFzc3dvcmRfbGFiZWwnKSwgJ3JlcXVpcmVkfG1pbl9sZW5ndGhbJyAuICR0aGlzLT5jb25maWctPml0ZW0oJ21pbl9wYXNzd29yZF9sZW5ndGgnLCAnaW9uX2F1dGgnKSAuICddfG1hdGNoZXNbcGFzc3dvcmRfY29uZmlybV0nKTsNCiAgICAgICAgJHRoaXMtPmZvcm1fdmFsaWRhdGlvbi0+c2V0X3J1bGVzKCdwYXNzd29yZF9jb25maXJtJywgJHRoaXMtPmxhbmctPmxpbmUoJ2NyZWF0ZV91c2VyX3ZhbGlkYXRpb25fcGFzc3dvcmRfY29uZmlybV9sYWJlbCcpLCAncmVxdWlyZWQnKTsNCg0KICAgICAgICBpZiAoJHRoaXMtPmZvcm1fdmFsaWRhdGlvbi0+cnVuKCkgPT09IFRSVUUpDQogICAgICAgIHsNCiAgICAgICAgICAgICRlbWFpbCA9IHN0cnRvbG93ZXIoJHRoaXMtPmlucHV0LT5wb3N0KCdlbWFpbCcpKTsNCiAgICAgICAgICAgICRpZGVudGl0eSA9ICgkaWRlbnRpdHlfY29sdW1uID09PSAnZW1haWwnKSA/ICRlbWFpbCA6ICR0aGlzLT5pbnB1dC0+cG9zdCgnaWRlbnRpdHknKTsNCiAgICAgICAgICAgICRwYXNzd29yZCA9ICR0aGlzLT5pbnB1dC0+cG9zdCgncGFzc3dvcmQnKTsNCg0KICAgICAgICAgICAgJGFkZGl0aW9uYWxfZGF0YSA9IFsNCiAgICAgICAgICAgICAgICAnZmlyc3RfbmFtZScgPT4gJHRoaXMtPmlucHV0LT5wb3N0KCdmaXJzdF9uYW1lJyksDQogICAgICAgICAgICAgICAgJ2xhc3RfbmFtZScgPT4gJHRoaXMtPmlucHV0LT5wb3N0KCdsYXN0X25hbWUnKSwNCiAgICAgICAgICAgICAgICAnY29tcGFueScgPT4gJHRoaXMtPmlucHV0LT5wb3N0KCdjb21wYW55JyksDQogICAgICAgICAgICAgICAgJ3Bob25lJyA9PiAkdGhpcy0+aW5wdXQtPnBvc3QoJ3Bob25lJyksDQogICAgICAgICAgICBdOw0KICAgICAgICB9DQogICAgICAgIGlmICgkdGhpcy0+Zm9ybV92YWxpZGF0aW9uLT5ydW4oKSA9PT0gVFJVRSAmJiAkdGhpcy0+aW9uX2F1dGgtPnJlZ2lzdGVyKCRpZGVudGl0eSwgJHBhc3N3b3JkLCAkZW1haWwsICRhZGRpdGlvbmFsX2RhdGEpKQ0KICAgICAgICB7DQogICAgICAgICAgICAvLyBjaGVjayB0byBzZWUgaWYgd2UgYXJlIGNyZWF0aW5nIHRoZSB1c2VyDQogICAgICAgICAgICAvLyByZWRpcmVjdCB0aGVtIGJhY2sgdG8gdGhlIGFkbWluIHBhZ2UNCiAgICAgICAgICAgICR0aGlzLT5zZXNzaW9uLT5zZXRfZmxhc2hkYXRhKCdtZXNzYWdlJywgJHRoaXMtPmlvbl9hdXRoLT5tZXNzYWdlcygpKTsNCiAgICAgICAgICAgIHJlZGlyZWN0KCJhdXRoIiwgJ3JlZnJlc2gnKTsNCiAgICAgICAgfQ0KICAgICAgICBlbHNlDQogICAgICAgIHsNCiAgICAgICAgICAgIC8vIGRpc3BsYXkgdGhlIGNyZWF0ZSB1c2VyIGZvcm0NCiAgICAgICAgICAgIC8vIHNldCB0aGUgZmxhc2ggZGF0YSBlcnJvciBtZXNzYWdlIGlmIHRoZXJlIGlzIG9uZQ0KICAgICAgICAgICAgJHRoaXMtPmRhdGFbJ21lc3NhZ2UnXSA9ICh2YWxpZGF0aW9uX2Vycm9ycygpID8gdmFsaWRhdGlvbl9lcnJvcnMoKSA6ICgkdGhpcy0+aW9uX2F1dGgtPmVycm9ycygpID8gJHRoaXMtPmlvbl9hdXRoLT5lcnJvcnMoKSA6ICR0aGlzLT5zZXNzaW9uLT5mbGFzaGRhdGEoJ21lc3NhZ2UnKSkpOw0KDQogICAgICAgICAgICAkdGhpcy0+ZGF0YVsnZmlyc3RfbmFtZSddID0gWw0KICAgICAgICAgICAgICAgICduYW1lJyA9PiAnZmlyc3RfbmFtZScsDQogICAgICAgICAgICAgICAgJ2lkJyA9PiAnZmlyc3RfbmFtZScsDQogICAgICAgICAgICAgICAgJ3R5cGUnID0+ICd0ZXh0JywNCiAgICAgICAgICAgICAgICAndmFsdWUnID0+ICR0aGlzLT5mb3JtX3ZhbGlkYXRpb24tPnNldF92YWx1ZSgnZmlyc3RfbmFtZScpLA0KICAgICAgICAgICAgXTsNCiAgICAgICAgICAgICR0aGlzLT5kYXRhWydsYXN0X25hbWUnXSA9IFsNCiAgICAgICAgICAgICAgICAnbmFtZScgPT4gJ2xhc3RfbmFtZScsDQogICAgICAgICAgICAgICAgJ2lkJyA9PiAnbGFzdF9uYW1lJywNCiAgICAgICAgICAgICAgICAndHlwZScgPT4gJ3RleHQnLA0KICAgICAgICAgICAgICAgICd2YWx1ZScgPT4gJHRoaXMtPmZvcm1fdmFsaWRhdGlvbi0+c2V0X3ZhbHVlKCdsYXN0X25hbWUnKSwNCiAgICAgICAgICAgIF07DQogICAgICAgICAgICAkdGhpcy0+ZGF0YVsnaWRlbnRpdHknXSA9IFsNCiAgICAgICAgICAgICAgICAnbmFtZScgPT4gJ2lkZW50aXR5JywNCiAgICAgICAgICAgICAgICAnaWQnID0+ICdpZGVudGl0eScsDQogICAgICAgICAgICAgICAgJ3R5cGUnID0+ICd0ZXh0JywNCiAgICAgICAgICAgICAgICAndmFsdWUnID0+ICR0aGlzLT5mb3JtX3ZhbGlkYXRpb24tPnNldF92YWx1ZSgnaWRlbnRpdHknKSwNCiAgICAgICAgICAgIF07DQogICAgICAgICAgICAkdGhpcy0+ZGF0YVsnZW1haWwnXSA9IFsNCiAgICAgICAgICAgICAgICAnbmFtZScgPT4gJ2VtYWlsJywNCiAgICAgICAgICAgICAgICAnaWQnID0+ICdlbWFpbCcsDQogICAgICAgICAgICAgICAgJ3R5cGUnID0+ICd0ZXh0JywNCiAgICAgICAgICAgICAgICAndmFsdWUnID0+ICR0aGlzLT5mb3JtX3ZhbGlkYXRpb24tPnNldF92YWx1ZSgnZW1haWwnKSwNCiAgICAgICAgICAgIF07DQogICAgICAgICAgICAkdGhpcy0+ZGF0YVsnY29tcGFueSddID0gWw0KICAgICAgICAgICAgICAgICduYW1lJyA9PiAnY29tcGFueScsDQogICAgICAgICAgICAgICAgJ2lkJyA9PiAnY29tcGFueScsDQogICAgICAgICAgICAgICAgJ3R5cGUnID0+ICd0ZXh0JywNCiAgICAgICAgICAgICAgICAndmFsdWUnID0+ICR0aGlzLT5mb3JtX3ZhbGlkYXRpb24tPnNldF92YWx1ZSgnY29tcGFueScpLA0KICAgICAgICAgICAgXTsNCiAgICAgICAgICAgICR0aGlzLT5kYXRhWydwaG9uZSddID0gWw0KICAgICAgICAgICAgICAgICduYW1lJyA9PiAncGhvbmUnLA0KICAgICAgICAgICAgICAgICdpZCcgPT4gJ3Bob25lJywNCiAgICAgICAgICAgICAgICAndHlwZScgPT4gJ3RleHQnLA0KICAgICAgICAgICAgICAgICd2YWx1ZScgPT4gJHRoaXMtPmZvcm1fdmFsaWRhdGlvbi0+c2V0X3ZhbHVlKCdwaG9uZScpLA0KICAgICAgICAgICAgXTsNCiAgICAgICAgICAgICR0aGlzLT5kYXRhWydwYXNzd29yZCddID0gWw0KICAgICAgICAgICAgICAgICduYW1lJyA9PiAncGFzc3dvcmQnLA0KICAgICAgICAgICAgICAgICdpZCcgPT4gJ3Bhc3N3b3JkJywNCiAgICAgICAgICAgICAgICAndHlwZScgPT4gJ3Bhc3N3b3JkJywNCiAgICAgICAgICAgICAgICAndmFsdWUnID0+ICR0aGlzLT5mb3JtX3ZhbGlkYXRpb24tPnNldF92YWx1ZSgncGFzc3dvcmQnKSwNCiAgICAgICAgICAgIF07DQogICAgICAgICAgICAkdGhpcy0+ZGF0YVsncGFzc3dvcmRfY29uZmlybSddID0gWw0KICAgICAgICAgICAgICAgICduYW1lJyA9PiAncGFzc3dvcmRfY29uZmlybScsDQogICAgICAgICAgICAgICAgJ2lkJyA9PiAncGFzc3dvcmRfY29uZmlybScsDQogICAgICAgICAgICAgICAgJ3R5cGUnID0+ICdwYXNzd29yZCcsDQogICAgICAgICAgICAgICAgJ3ZhbHVlJyA9PiAkdGhpcy0+Zm9ybV92YWxpZGF0aW9uLT5zZXRfdmFsdWUoJ3Bhc3N3b3JkX2NvbmZpcm0nKSwNCiAgICAgICAgICAgIF07DQoNCiAgICAgICAgICAgICR0aGlzLT5fcmVuZGVyX3BhZ2UoJ2F1dGgnIC4gRElSRUNUT1JZX1NFUEFSQVRPUiAuICdjcmVhdGVfdXNlcicsICR0aGlzLT5kYXRhKTsNCiAgICAgICAgfQ0KICAgIH0NCg0KICAgIC8qKg0KICAgICAqIFJlZGlyZWN0IGEgdXNlciBjaGVja2luZyBpZiBpcyBhZG1pbg0KICAgICAqLw0KICAgIHB1YmxpYyBmdW5jdGlvbiByZWRpcmVjdFVzZXIoKXsNCiAgICAgICAgaWYgKCR0aGlzLT5pb25fYXV0aC0+aXNfYWRtaW4oKSl7DQogICAgICAgICAgICByZWRpcmVjdCgnYXV0aCcsICdyZWZyZXNoJyk7DQogICAgICAgIH0NCiAgICAgICAgcmVkaXJlY3QoJy8nLCAncmVmcmVzaCcpOw0KICAgIH0NCg0KICAgIC8qKg0KICAgICAqIEVkaXQgYSB1c2VyDQogICAgICoNCiAgICAgKiBAcGFyYW0gaW50fHN0cmluZyAkaWQNCiAgICAgKi8NCiAgICBwdWJsaWMgZnVuY3Rpb24gZWRpdF91c2VyKCRpZCkNCiAgICB7DQogICAgICAgICR0aGlzLT5kYXRhWyd0aXRsZSddID0gJHRoaXMtPmxhbmctPmxpbmUoJ2VkaXRfdXNlcl9oZWFkaW5nJyk7DQoNCiAgICAgICAgaWYgKCEkdGhpcy0+aW9uX2F1dGgtPmxvZ2dlZF9pbigpIHx8ICghJHRoaXMtPmlvbl9hdXRoLT5pc19hZG1pbigpICYmICEoJHRoaXMtPmlvbl9hdXRoLT51c2VyKCktPnJvdygpLT5pZCA9PSAkaWQpKSkNCiAgICAgICAgew0KICAgICAgICAgICAgcmVkaXJlY3QoJ2F1dGgnLCAncmVmcmVzaCcpOw0KICAgICAgICB9DQoNCiAgICAgICAgJHVzZXIgPSAkdGhpcy0+aW9uX2F1dGgtPnVzZXIoJGlkKS0+cm93KCk7DQogICAgICAgICRncm91cHMgPSAkdGhpcy0+aW9uX2F1dGgtPmdyb3VwcygpLT5yZXN1bHRfYXJyYXkoKTsNCiAgICAgICAgJGN1cnJlbnRHcm91cHMgPSAkdGhpcy0+aW9uX2F1dGgtPmdldF91c2Vyc19ncm91cHMoJGlkKS0+cmVzdWx0KCk7DQoNCiAgICAgICAgLy9VU0FHRSBOT1RFIC0geW91IGNhbiBkbyBtb3JlIGNvbXBsaWNhdGVkIHF1ZXJpZXMgbGlrZSB0aGlzDQogICAgICAgIC8vJGdyb3VwcyA9ICR0aGlzLT5pb25fYXV0aC0+d2hlcmUoWydmaWVsZCcgPT4gJ3ZhbHVlJ10pLT5ncm91cHMoKS0+cmVzdWx0X2FycmF5KCk7DQoNCg0KICAgICAgICAvLyB2YWxpZGF0ZSBmb3JtIGlucHV0DQogICAgICAgICR0aGlzLT5mb3JtX3ZhbGlkYXRpb24tPnNldF9ydWxlcygnZmlyc3RfbmFtZScsICR0aGlzLT5sYW5nLT5saW5lKCdlZGl0X3VzZXJfdmFsaWRhdGlvbl9mbmFtZV9sYWJlbCcpLCAndHJpbXxyZXF1aXJlZCcpOw0KICAgICAgICAkdGhpcy0+Zm9ybV92YWxpZGF0aW9uLT5zZXRfcnVsZXMoJ2xhc3RfbmFtZScsICR0aGlzLT5sYW5nLT5saW5lKCdlZGl0X3VzZXJfdmFsaWRhdGlvbl9sbmFtZV9sYWJlbCcpLCAndHJpbXxyZXF1aXJlZCcpOw0KICAgICAgICAkdGhpcy0+Zm9ybV92YWxpZGF0aW9uLT5zZXRfcnVsZXMoJ3Bob25lJywgJHRoaXMtPmxhbmctPmxpbmUoJ2VkaXRfdXNlcl92YWxpZGF0aW9uX3Bob25lX2xhYmVsJyksICd0cmltJyk7DQogICAgICAgICR0aGlzLT5mb3JtX3ZhbGlkYXRpb24tPnNldF9ydWxlcygnY29tcGFueScsICR0aGlzLT5sYW5nLT5saW5lKCdlZGl0X3VzZXJfdmFsaWRhdGlvbl9jb21wYW55X2xhYmVsJyksICd0cmltJyk7DQoNCiAgICAgICAgaWYgKGlzc2V0KCRfUE9TVCkgJiYgIWVtcHR5KCRfUE9TVCkpDQogICAgICAgIHsNCiAgICAgICAgICAgIC8vIGRvIHdlIGhhdmUgYSB2YWxpZCByZXF1ZXN0Pw0KICAgICAgICAgICAgaWYgKCR0aGlzLT5fdmFsaWRfY3NyZl9ub25jZSgpID09PSBGQUxTRSB8fCAkaWQgIT0gJHRoaXMtPmlucHV0LT5wb3N0KCdpZCcpKQ0KICAgICAgICAgICAgew0KICAgICAgICAgICAgICAgIHNob3dfZXJyb3IoJHRoaXMtPmxhbmctPmxpbmUoJ2Vycm9yX2NzcmYnKSk7DQogICAgICAgICAgICB9DQoNCiAgICAgICAgICAgIC8vIHVwZGF0ZSB0aGUgcGFzc3dvcmQgaWYgaXQgd2FzIHBvc3RlZA0KICAgICAgICAgICAgaWYgKCR0aGlzLT5pbnB1dC0+cG9zdCgncGFzc3dvcmQnKSkNCiAgICAgICAgICAgIHsNCiAgICAgICAgICAgICAgICAkdGhpcy0+Zm9ybV92YWxpZGF0aW9uLT5zZXRfcnVsZXMoJ3Bhc3N3b3JkJywgJHRoaXMtPmxhbmctPmxpbmUoJ2VkaXRfdXNlcl92YWxpZGF0aW9uX3Bhc3N3b3JkX2xhYmVsJyksICdyZXF1aXJlZHxtaW5fbGVuZ3RoWycgLiAkdGhpcy0+Y29uZmlnLT5pdGVtKCdtaW5fcGFzc3dvcmRfbGVuZ3RoJywgJ2lvbl9hdXRoJykgLiAnXXxtYXRjaGVzW3Bhc3N3b3JkX2NvbmZpcm1dJyk7DQogICAgICAgICAgICAgICAgJHRoaXMtPmZvcm1fdmFsaWRhdGlvbi0+c2V0X3J1bGVzKCdwYXNzd29yZF9jb25maXJtJywgJHRoaXMtPmxhbmctPmxpbmUoJ2VkaXRfdXNlcl92YWxpZGF0aW9uX3Bhc3N3b3JkX2NvbmZpcm1fbGFiZWwnKSwgJ3JlcXVpcmVkJyk7DQogICAgICAgICAgICB9DQoNCiAgICAgICAgICAgIGlmICgkdGhpcy0+Zm9ybV92YWxpZGF0aW9uLT5ydW4oKSA9PT0gVFJVRSkNCiAgICAgICAgICAgIHsNCiAgICAgICAgICAgICAgICAkZGF0YSA9IFsNCiAgICAgICAgICAgICAgICAgICAgJ2ZpcnN0X25hbWUnID0+ICR0aGlzLT5pbnB1dC0+cG9zdCgnZmlyc3RfbmFtZScpLA0KICAgICAgICAgICAgICAgICAgICAnbGFzdF9uYW1lJyA9PiAkdGhpcy0+aW5wdXQtPnBvc3QoJ2xhc3RfbmFtZScpLA0KICAgICAgICAgICAgICAgICAgICAnY29tcGFueScgPT4gJHRoaXMtPmlucHV0LT5wb3N0KCdjb21wYW55JyksDQogICAgICAgICAgICAgICAgICAgICdwaG9uZScgPT4gJHRoaXMtPmlucHV0LT5wb3N0KCdwaG9uZScpLA0KICAgICAgICAgICAgICAgIF07DQoNCiAgICAgICAgICAgICAgICAvLyB1cGRhdGUgdGhlIHBhc3N3b3JkIGlmIGl0IHdhcyBwb3N0ZWQNCiAgICAgICAgICAgICAgICBpZiAoJHRoaXMtPmlucHV0LT5wb3N0KCdwYXNzd29yZCcpKQ0KICAgICAgICAgICAgICAgIHsNCiAgICAgICAgICAgICAgICAgICAgJGRhdGFbJ3Bhc3N3b3JkJ10gPSAkdGhpcy0+aW5wdXQtPnBvc3QoJ3Bhc3N3b3JkJyk7DQogICAgICAgICAgICAgICAgfQ0KDQogICAgICAgICAgICAgICAgLy8gT25seSBhbGxvdyB1cGRhdGluZyBncm91cHMgaWYgdXNlciBpcyBhZG1pbg0KICAgICAgICAgICAgICAgIGlmICgkdGhpcy0+aW9uX2F1dGgtPmlzX2FkbWluKCkpDQogICAgICAgICAgICAgICAgew0KICAgICAgICAgICAgICAgICAgICAvLyBVcGRhdGUgdGhlIGdyb3VwcyB1c2VyIGJlbG9uZ3MgdG8NCiAgICAgICAgICAgICAgICAgICAgJHRoaXMtPmlvbl9hdXRoLT5yZW1vdmVfZnJvbV9ncm91cCgnJywgJGlkKTsNCg0KICAgICAgICAgICAgICAgICAgICAkZ3JvdXBEYXRhID0gJHRoaXMtPmlucHV0LT5wb3N0KCdncm91cHMnKTsNCiAgICAgICAgICAgICAgICAgICAgaWYgKGlzc2V0KCRncm91cERhdGEpICYmICFlbXB0eSgkZ3JvdXBEYXRhKSkNCiAgICAgICAgICAgICAgICAgICAgew0KICAgICAgICAgICAgICAgICAgICAgICAgZm9yZWFjaCAoJGdyb3VwRGF0YSBhcyAkZ3JwKQ0KICAgICAgICAgICAgICAgICAgICAgICAgew0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICR0aGlzLT5pb25fYXV0aC0+YWRkX3RvX2dyb3VwKCRncnAsICRpZCk7DQogICAgICAgICAgICAgICAgICAgICAgICB9DQoNCiAgICAgICAgICAgICAgICAgICAgfQ0KICAgICAgICAgICAgICAgIH0NCg0KICAgICAgICAgICAgICAgIC8vIGNoZWNrIHRvIHNlZSBpZiB3ZSBhcmUgdXBkYXRpbmcgdGhlIHVzZXINCiAgICAgICAgICAgICAgICBpZiAoJHRoaXMtPmlvbl9hdXRoLT51cGRhdGUoJHVzZXItPmlkLCAkZGF0YSkpDQogICAgICAgICAgICAgICAgew0KICAgICAgICAgICAgICAgICAgICAvLyByZWRpcmVjdCB0aGVtIGJhY2sgdG8gdGhlIGFkbWluIHBhZ2UgaWYgYWRtaW4sIG9yIHRvIHRoZSBiYXNlIHVybCBpZiBub24gYWRtaW4NCiAgICAgICAgICAgICAgICAgICAgJHRoaXMtPnNlc3Npb24tPnNldF9mbGFzaGRhdGEoJ21lc3NhZ2UnLCAkdGhpcy0+aW9uX2F1dGgtPm1lc3NhZ2VzKCkpOw0KICAgICAgICAgICAgICAgICAgICAkdGhpcy0+cmVkaXJlY3RVc2VyKCk7DQoNCiAgICAgICAgICAgICAgICB9DQogICAgICAgICAgICAgICAgZWxzZQ0KICAgICAgICAgICAgICAgIHsNCiAgICAgICAgICAgICAgICAgICAgLy8gcmVkaXJlY3QgdGhlbSBiYWNrIHRvIHRoZSBhZG1pbiBwYWdlIGlmIGFkbWluLCBvciB0byB0aGUgYmFzZSB1cmwgaWYgbm9uIGFkbWluDQogICAgICAgICAgICAgICAgICAgICR0aGlzLT5zZXNzaW9uLT5zZXRfZmxhc2hkYXRhKCdtZXNzYWdlJywgJHRoaXMtPmlvbl9hdXRoLT5lcnJvcnMoKSk7DQogICAgICAgICAgICAgICAgICAgICR0aGlzLT5yZWRpcmVjdFVzZXIoKTsNCg0KICAgICAgICAgICAgICAgIH0NCg0KICAgICAgICAgICAgfQ0KICAgICAgICB9DQoNCiAgICAgICAgLy8gZGlzcGxheSB0aGUgZWRpdCB1c2VyIGZvcm0NCiAgICAgICAgJHRoaXMtPmRhdGFbJ2NzcmYnXSA9ICR0aGlzLT5fZ2V0X2NzcmZfbm9uY2UoKTsNCg0KICAgICAgICAvLyBzZXQgdGhlIGZsYXNoIGRhdGEgZXJyb3IgbWVzc2FnZSBpZiB0aGVyZSBpcyBvbmUNCiAgICAgICAgJHRoaXMtPmRhdGFbJ21lc3NhZ2UnXSA9ICh2YWxpZGF0aW9uX2Vycm9ycygpID8gdmFsaWRhdGlvbl9lcnJvcnMoKSA6ICgkdGhpcy0+aW9uX2F1dGgtPmVycm9ycygpID8gJHRoaXMtPmlvbl9hdXRoLT5lcnJvcnMoKSA6ICR0aGlzLT5zZXNzaW9uLT5mbGFzaGRhdGEoJ21lc3NhZ2UnKSkpOw0KDQogICAgICAgIC8vIHBhc3MgdGhlIHVzZXIgdG8gdGhlIHZpZXcNCiAgICAgICAgJHRoaXMtPmRhdGFbJ3VzZXInXSA9ICR1c2VyOw0KICAgICAgICAkdGhpcy0+ZGF0YVsnZ3JvdXBzJ10gPSAkZ3JvdXBzOw0KICAgICAgICAkdGhpcy0+ZGF0YVsnY3VycmVudEdyb3VwcyddID0gJGN1cnJlbnRHcm91cHM7DQoNCiAgICAgICAgJHRoaXMtPmRhdGFbJ2ZpcnN0X25hbWUnXSA9IFsNCiAgICAgICAgICAgICduYW1lJyAgPT4gJ2ZpcnN0X25hbWUnLA0KICAgICAgICAgICAgJ2lkJyAgICA9PiAnZmlyc3RfbmFtZScsDQogICAgICAgICAgICAndHlwZScgID0+ICd0ZXh0JywNCiAgICAgICAgICAgICd2YWx1ZScgPT4gJHRoaXMtPmZvcm1fdmFsaWRhdGlvbi0+c2V0X3ZhbHVlKCdmaXJzdF9uYW1lJywgJHVzZXItPmZpcnN0X25hbWUpLA0KICAgICAgICBdOw0KICAgICAgICAkdGhpcy0+ZGF0YVsnbGFzdF9uYW1lJ10gPSBbDQogICAgICAgICAgICAnbmFtZScgID0+ICdsYXN0X25hbWUnLA0KICAgICAgICAgICAgJ2lkJyAgICA9PiAnbGFzdF9uYW1lJywNCiAgICAgICAgICAgICd0eXBlJyAgPT4gJ3RleHQnLA0KICAgICAgICAgICAgJ3ZhbHVlJyA9PiAkdGhpcy0+Zm9ybV92YWxpZGF0aW9uLT5zZXRfdmFsdWUoJ2xhc3RfbmFtZScsICR1c2VyLT5sYXN0X25hbWUpLA0KICAgICAgICBdOw0KICAgICAgICAkdGhpcy0+ZGF0YVsnY29tcGFueSddID0gWw0KICAgICAgICAgICAgJ25hbWUnICA9PiAnY29tcGFueScsDQogICAgICAgICAgICAnaWQnICAgID0+ICdjb21wYW55JywNCiAgICAgICAgICAgICd0eXBlJyAgPT4gJ3RleHQnLA0KICAgICAgICAgICAgJ3ZhbHVlJyA9PiAkdGhpcy0+Zm9ybV92YWxpZGF0aW9uLT5zZXRfdmFsdWUoJ2NvbXBhbnknLCAkdXNlci0+Y29tcGFueSksDQogICAgICAgIF07DQogICAgICAgICR0aGlzLT5kYXRhWydwaG9uZSddID0gWw0KICAgICAgICAgICAgJ25hbWUnICA9PiAncGhvbmUnLA0KICAgICAgICAgICAgJ2lkJyAgICA9PiAncGhvbmUnLA0KICAgICAgICAgICAgJ3R5cGUnICA9PiAndGV4dCcsDQogICAgICAgICAgICAndmFsdWUnID0+ICR0aGlzLT5mb3JtX3ZhbGlkYXRpb24tPnNldF92YWx1ZSgncGhvbmUnLCAkdXNlci0+cGhvbmUpLA0KICAgICAgICBdOw0KICAgICAgICAkdGhpcy0+ZGF0YVsncGFzc3dvcmQnXSA9IFsNCiAgICAgICAgICAgICduYW1lJyA9PiAncGFzc3dvcmQnLA0KICAgICAgICAgICAgJ2lkJyAgID0+ICdwYXNzd29yZCcsDQogICAgICAgICAgICAndHlwZScgPT4gJ3Bhc3N3b3JkJw0KICAgICAgICBdOw0KICAgICAgICAkdGhpcy0+ZGF0YVsncGFzc3dvcmRfY29uZmlybSddID0gWw0KICAgICAgICAgICAgJ25hbWUnID0+ICdwYXNzd29yZF9jb25maXJtJywNCiAgICAgICAgICAgICdpZCcgICA9PiAncGFzc3dvcmRfY29uZmlybScsDQogICAgICAgICAgICAndHlwZScgPT4gJ3Bhc3N3b3JkJw0KICAgICAgICBdOw0KDQogICAgICAgICR0aGlzLT5fcmVuZGVyX3BhZ2UoJ2F1dGgvZWRpdF91c2VyJywgJHRoaXMtPmRhdGEpOw0KICAgIH0NCg0KICAgIC8qKg0KICAgICAqIENyZWF0ZSBhIG5ldyBncm91cA0KICAgICAqLw0KICAgIHB1YmxpYyBmdW5jdGlvbiBjcmVhdGVfZ3JvdXAoKQ0KICAgIHsNCiAgICAgICAgJHRoaXMtPmRhdGFbJ3RpdGxlJ10gPSAkdGhpcy0+bGFuZy0+bGluZSgnY3JlYXRlX2dyb3VwX3RpdGxlJyk7DQoNCiAgICAgICAgaWYgKCEkdGhpcy0+aW9uX2F1dGgtPmxvZ2dlZF9pbigpIHx8ICEkdGhpcy0+aW9uX2F1dGgtPmlzX2FkbWluKCkpDQogICAgICAgIHsNCiAgICAgICAgICAgIHJlZGlyZWN0KCdhdXRoJywgJ3JlZnJlc2gnKTsNCiAgICAgICAgfQ0KDQogICAgICAgIC8vIHZhbGlkYXRlIGZvcm0gaW5wdXQNCiAgICAgICAgJHRoaXMtPmZvcm1fdmFsaWRhdGlvbi0+c2V0X3J1bGVzKCdncm91cF9uYW1lJywgJHRoaXMtPmxhbmctPmxpbmUoJ2NyZWF0ZV9ncm91cF92YWxpZGF0aW9uX25hbWVfbGFiZWwnKSwgJ3RyaW18cmVxdWlyZWR8YWxwaGFfZGFzaCcpOw0KDQogICAgICAgIGlmICgkdGhpcy0+Zm9ybV92YWxpZGF0aW9uLT5ydW4oKSA9PT0gVFJVRSkNCiAgICAgICAgew0KICAgICAgICAgICAgJG5ld19ncm91cF9pZCA9ICR0aGlzLT5pb25fYXV0aC0+Y3JlYXRlX2dyb3VwKCR0aGlzLT5pbnB1dC0+cG9zdCgnZ3JvdXBfbmFtZScpLCAkdGhpcy0+aW5wdXQtPnBvc3QoJ2Rlc2NyaXB0aW9uJykpOw0KICAgICAgICAgICAgaWYgKCRuZXdfZ3JvdXBfaWQpDQogICAgICAgICAgICB7DQogICAgICAgICAgICAgICAgLy8gY2hlY2sgdG8gc2VlIGlmIHdlIGFyZSBjcmVhdGluZyB0aGUgZ3JvdXANCiAgICAgICAgICAgICAgICAvLyByZWRpcmVjdCB0aGVtIGJhY2sgdG8gdGhlIGFkbWluIHBhZ2UNCiAgICAgICAgICAgICAgICAkdGhpcy0+c2Vzc2lvbi0+c2V0X2ZsYXNoZGF0YSgnbWVzc2FnZScsICR0aGlzLT5pb25fYXV0aC0+bWVzc2FnZXMoKSk7DQogICAgICAgICAgICAgICAgcmVkaXJlY3QoImF1dGgiLCAncmVmcmVzaCcpOw0KICAgICAgICAgICAgfQ0KICAgICAgICAgICAgZWxzZQ0KICAgICAgICAgICAgew0KICAgICAgICAgICAgICAgICR0aGlzLT5zZXNzaW9uLT5zZXRfZmxhc2hkYXRhKCdtZXNzYWdlJywgJHRoaXMtPmlvbl9hdXRoLT5lcnJvcnMoKSk7DQogICAgICAgICAgICB9DQogICAgICAgIH0NCg0KICAgICAgICAvLyBkaXNwbGF5IHRoZSBjcmVhdGUgZ3JvdXAgZm9ybQ0KICAgICAgICAvLyBzZXQgdGhlIGZsYXNoIGRhdGEgZXJyb3IgbWVzc2FnZSBpZiB0aGVyZSBpcyBvbmUNCiAgICAgICAgJHRoaXMtPmRhdGFbJ21lc3NhZ2UnXSA9ICh2YWxpZGF0aW9uX2Vycm9ycygpID8gdmFsaWRhdGlvbl9lcnJvcnMoKSA6ICgkdGhpcy0+aW9uX2F1dGgtPmVycm9ycygpID8gJHRoaXMtPmlvbl9hdXRoLT5lcnJvcnMoKSA6ICR0aGlzLT5zZXNzaW9uLT5mbGFzaGRhdGEoJ21lc3NhZ2UnKSkpOw0KDQogICAgICAgICR0aGlzLT5kYXRhWydncm91cF9uYW1lJ10gPSBbDQogICAgICAgICAgICAnbmFtZScgID0+ICdncm91cF9uYW1lJywNCiAgICAgICAgICAgICdpZCcgICAgPT4gJ2dyb3VwX25hbWUnLA0KICAgICAgICAgICAgJ3R5cGUnICA9PiAndGV4dCcsDQogICAgICAgICAgICAndmFsdWUnID0+ICR0aGlzLT5mb3JtX3ZhbGlkYXRpb24tPnNldF92YWx1ZSgnZ3JvdXBfbmFtZScpLA0KICAgICAgICBdOw0KICAgICAgICAkdGhpcy0+ZGF0YVsnZGVzY3JpcHRpb24nXSA9IFsNCiAgICAgICAgICAgICduYW1lJyAgPT4gJ2Rlc2NyaXB0aW9uJywNCiAgICAgICAgICAgICdpZCcgICAgPT4gJ2Rlc2NyaXB0aW9uJywNCiAgICAgICAgICAgICd0eXBlJyAgPT4gJ3RleHQnLA0KICAgICAgICAgICAgJ3ZhbHVlJyA9PiAkdGhpcy0+Zm9ybV92YWxpZGF0aW9uLT5zZXRfdmFsdWUoJ2Rlc2NyaXB0aW9uJyksDQogICAgICAgIF07DQoNCiAgICAgICAgJHRoaXMtPl9yZW5kZXJfcGFnZSgnYXV0aC9jcmVhdGVfZ3JvdXAnLCAkdGhpcy0+ZGF0YSk7DQoNCiAgICB9DQoNCiAgICAvKioNCiAgICAgKiBFZGl0IGEgZ3JvdXANCiAgICAgKg0KICAgICAqIEBwYXJhbSBpbnR8c3RyaW5nICRpZA0KICAgICAqLw0KICAgIHB1YmxpYyBmdW5jdGlvbiBlZGl0X2dyb3VwKCRpZCkNCiAgICB7DQogICAgICAgIC8vIGJhaWwgaWYgbm8gZ3JvdXAgaWQgZ2l2ZW4NCiAgICAgICAgaWYgKCEkaWQgfHwgZW1wdHkoJGlkKSkNCiAgICAgICAgew0KICAgICAgICAgICAgcmVkaXJlY3QoJ2F1dGgnLCAncmVmcmVzaCcpOw0KICAgICAgICB9DQoNCiAgICAgICAgJHRoaXMtPmRhdGFbJ3RpdGxlJ10gPSAkdGhpcy0+bGFuZy0+bGluZSgnZWRpdF9ncm91cF90aXRsZScpOw0KDQogICAgICAgIGlmICghJHRoaXMtPmlvbl9hdXRoLT5sb2dnZWRfaW4oKSB8fCAhJHRoaXMtPmlvbl9hdXRoLT5pc19hZG1pbigpKQ0KICAgICAgICB7DQogICAgICAgICAgICByZWRpcmVjdCgnYXV0aCcsICdyZWZyZXNoJyk7DQogICAgICAgIH0NCg0KICAgICAgICAkZ3JvdXAgPSAkdGhpcy0+aW9uX2F1dGgtPmdyb3VwKCRpZCktPnJvdygpOw0KDQogICAgICAgIC8vIHZhbGlkYXRlIGZvcm0gaW5wdXQNCiAgICAgICAgJHRoaXMtPmZvcm1fdmFsaWRhdGlvbi0+c2V0X3J1bGVzKCdncm91cF9uYW1lJywgJHRoaXMtPmxhbmctPmxpbmUoJ2VkaXRfZ3JvdXBfdmFsaWRhdGlvbl9uYW1lX2xhYmVsJyksICd0cmltfHJlcXVpcmVkfGFscGhhX2Rhc2gnKTsNCg0KICAgICAgICBpZiAoaXNzZXQoJF9QT1NUKSAmJiAhZW1wdHkoJF9QT1NUKSkNCiAgICAgICAgew0KICAgICAgICAgICAgaWYgKCR0aGlzLT5mb3JtX3ZhbGlkYXRpb24tPnJ1bigpID09PSBUUlVFKQ0KICAgICAgICAgICAgew0KICAgICAgICAgICAgICAgICRncm91cF91cGRhdGUgPSAkdGhpcy0+aW9uX2F1dGgtPnVwZGF0ZV9ncm91cCgkaWQsICRfUE9TVFsnZ3JvdXBfbmFtZSddLCBhcnJheSgNCiAgICAgICAgICAgICAgICAgICAgJ2Rlc2NyaXB0aW9uJyA9PiAkX1BPU1RbJ2dyb3VwX2Rlc2NyaXB0aW9uJ10NCiAgICAgICAgICAgICAgICApKTsNCg0KICAgICAgICAgICAgICAgIGlmICgkZ3JvdXBfdXBkYXRlKQ0KICAgICAgICAgICAgICAgIHsNCiAgICAgICAgICAgICAgICAgICAgJHRoaXMtPnNlc3Npb24tPnNldF9mbGFzaGRhdGEoJ21lc3NhZ2UnLCAkdGhpcy0+bGFuZy0+bGluZSgnZWRpdF9ncm91cF9zYXZlZCcpKTsNCiAgICAgICAgICAgICAgICAgICAgcmVkaXJlY3QoImF1dGgiLCAncmVmcmVzaCcpOw0KICAgICAgICAgICAgICAgIH0NCiAgICAgICAgICAgICAgICBlbHNlDQogICAgICAgICAgICAgICAgew0KICAgICAgICAgICAgICAgICAgICAkdGhpcy0+c2Vzc2lvbi0+c2V0X2ZsYXNoZGF0YSgnbWVzc2FnZScsICR0aGlzLT5pb25fYXV0aC0+ZXJyb3JzKCkpOw0KICAgICAgICAgICAgICAgIH0NCiAgICAgICAgICAgIH0NCiAgICAgICAgfQ0KDQogICAgICAgIC8vIHNldCB0aGUgZmxhc2ggZGF0YSBlcnJvciBtZXNzYWdlIGlmIHRoZXJlIGlzIG9uZQ0KICAgICAgICAkdGhpcy0+ZGF0YVsnbWVzc2FnZSddID0gKHZhbGlkYXRpb25fZXJyb3JzKCkgPyB2YWxpZGF0aW9uX2Vycm9ycygpIDogKCR0aGlzLT5pb25fYXV0aC0+ZXJyb3JzKCkgPyAkdGhpcy0+aW9uX2F1dGgtPmVycm9ycygpIDogJHRoaXMtPnNlc3Npb24tPmZsYXNoZGF0YSgnbWVzc2FnZScpKSk7DQoNCiAgICAgICAgLy8gcGFzcyB0aGUgdXNlciB0byB0aGUgdmlldw0KICAgICAgICAkdGhpcy0+ZGF0YVsnZ3JvdXAnXSA9ICRncm91cDsNCg0KICAgICAgICAkdGhpcy0+ZGF0YVsnZ3JvdXBfbmFtZSddID0gWw0KICAgICAgICAgICAgJ25hbWUnICAgID0+ICdncm91cF9uYW1lJywNCiAgICAgICAgICAgICdpZCcgICAgICA9PiAnZ3JvdXBfbmFtZScsDQogICAgICAgICAgICAndHlwZScgICAgPT4gJ3RleHQnLA0KICAgICAgICAgICAgJ3ZhbHVlJyAgID0+ICR0aGlzLT5mb3JtX3ZhbGlkYXRpb24tPnNldF92YWx1ZSgnZ3JvdXBfbmFtZScsICRncm91cC0+bmFtZSksDQogICAgICAgIF07DQogICAgICAgIGlmICgkdGhpcy0+Y29uZmlnLT5pdGVtKCdhZG1pbl9ncm91cCcsICdpb25fYXV0aCcpID09PSAkZ3JvdXAtPm5hbWUpIHsNCiAgICAgICAgICAgICR0aGlzLT5kYXRhWydncm91cF9uYW1lJ11bJ3JlYWRvbmx5J10gPSAncmVhZG9ubHknOw0KICAgICAgICB9DQoNCiAgICAgICAgJHRoaXMtPmRhdGFbJ2dyb3VwX2Rlc2NyaXB0aW9uJ10gPSBbDQogICAgICAgICAgICAnbmFtZScgID0+ICdncm91cF9kZXNjcmlwdGlvbicsDQogICAgICAgICAgICAnaWQnICAgID0+ICdncm91cF9kZXNjcmlwdGlvbicsDQogICAgICAgICAgICAndHlwZScgID0+ICd0ZXh0JywNCiAgICAgICAgICAgICd2YWx1ZScgPT4gJHRoaXMtPmZvcm1fdmFsaWRhdGlvbi0+c2V0X3ZhbHVlKCdncm91cF9kZXNjcmlwdGlvbicsICRncm91cC0+ZGVzY3JpcHRpb24pLA0KICAgICAgICBdOw0KDQogICAgICAgICR0aGlzLT5fcmVuZGVyX3BhZ2UoJ2F1dGgnIC4gRElSRUNUT1JZX1NFUEFSQVRPUiAuICdlZGl0X2dyb3VwJywgJHRoaXMtPmRhdGEpOw0KICAgIH0NCg0KICAgIC8qKg0KCSAqIEByZXR1cm4gYXJyYXkgQSBDU1JGIGtleS12YWx1ZSBwYWlyDQoJICovDQoJcHVibGljIGZ1bmN0aW9uIF9nZXRfY3NyZl9ub25jZSgpDQoJew0KCQkkdGhpcy0+bG9hZC0+aGVscGVyKCdzdHJpbmcnKTsNCgkJJGtleSA9IHJhbmRvbV9zdHJpbmcoJ2FsbnVtJywgOCk7DQoJCSR2YWx1ZSA9IHJhbmRvbV9zdHJpbmcoJ2FsbnVtJywgMjApOw0KCQkkdGhpcy0+c2Vzc2lvbi0+c2V0X2ZsYXNoZGF0YSgnY3NyZmtleScsICRrZXkpOw0KCQkkdGhpcy0+c2Vzc2lvbi0+c2V0X2ZsYXNoZGF0YSgnY3NyZnZhbHVlJywgJHZhbHVlKTsNCg0KCQlyZXR1cm4gWyRrZXkgPT4gJHZhbHVlXTsNCgl9DQoNCgkvKioNCgkgKiBAcmV0dXJuIGJvb2wgV2hldGhlciB0aGUgcG9zdGVkIENTUkYgdG9rZW4gbWF0Y2hlcw0KCSAqLw0KCXB1YmxpYyBmdW5jdGlvbiBfdmFsaWRfY3NyZl9ub25jZSgpew0KCQkkY3NyZmtleSA9ICR0aGlzLT5pbnB1dC0+cG9zdCgkdGhpcy0+c2Vzc2lvbi0+Zmxhc2hkYXRhKCdjc3Jma2V5JykpOw0KCQlpZiAoJGNzcmZrZXkgJiYgJGNzcmZrZXkgPT09ICR0aGlzLT5zZXNzaW9uLT5mbGFzaGRhdGEoJ2NzcmZ2YWx1ZScpKQ0KCQl7DQoJCQlyZXR1cm4gVFJVRTsNCgkJfQ0KCQkJcmV0dXJuIEZBTFNFOw0KCX0NCg0KCXB1YmxpYyBmdW5jdGlvbiBfcmVuZGVyX3BhZ2UoJHZpZXcsICRkYXRhID0gTlVMTCwgJHJldHVybmh0bWwgPSBGQUxTRSkvL0kgdGhpbmsgdGhpcyBtYWtlcyBtb3JlIHNlbnNlDQoJew0KDQoJCSR2aWV3ZGF0YSA9IChlbXB0eSgkZGF0YSkpID8gJHRoaXMtPmRhdGEgOiAkZGF0YTsNCg0KCQkkdmlld19odG1sID0gJHRoaXMtPmxvYWQtPnZpZXcoJHZpZXcsICR2aWV3ZGF0YSwgJHJldHVybmh0bWwpOw0KDQoJCS8vIFRoaXMgd2lsbCByZXR1cm4gaHRtbCBvbiAzcmQgYXJndW1lbnQgYmVpbmcgdHJ1ZQ0KCQlpZiAoJHJldHVybmh0bWwpDQoJCXsNCgkJCXJldHVybiAkdmlld19odG1sOw0KCQl9DQoJfQ0KDQp9DQo='))
Function Calls
base64_decode | 1 |
Stats
MD5 | ea6d3217fd2a57d7822cbde3c43e707c |
Eval Count | 1 |
Decode Time | 182 ms |