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

Variables

None

Stats

MD5 ea6d3217fd2a57d7822cbde3c43e707c
Eval Count 1
Decode Time 182 ms