<?php
/*========================================================================*\
|| ###################################################################### ||
|| # vBulletin 6.2.3 - Licence Number L3138846
|| # ------------------------------------------------------------------ # ||
|| # Copyright 2000-2026 MH Sub I, LLC dba vBulletin. All Rights Reserved.  # ||
|| # This file may not be redistributed in whole or significant part.   # ||
|| # ----------------- VBULLETIN IS NOT FREE SOFTWARE ----------------- # ||
|| # http://www.vbulletin.com | http://www.vbulletin.com/license.html   # ||
|| ###################################################################### ||
\*========================================================================*/

// ######################## SET PHP ENVIRONMENT ###########################

// ##################### DEFINE IMPORTANT CONSTANTS #######################
define('CVS_REVISION', '$RCSfile$ - $Revision: 111008 $');

// #################### PRE-CACHE TEMPLATES AND DATA ######################
global $phrasegroups, $specialtemplates, $vbphrase, $vbulletin;
$phrasegroups = ['cpglobal', 'cphome', 'cppermission',];
$specialtemplates = [];

// ########################## REQUIRE BACK-END ############################
require_once(dirname(__FILE__) . '/global.php');

// ######################## CHECK ADMIN PERMISSIONS #######################
if (!vB::getUserContext()->hasAdminPermission('canadminsettingsall'))
{
	print_cp_no_permission();
}

// ############################# LOG ACTION ###############################
log_admin_action();


// ########################################################################
// ######################### START MAIN SCRIPT ############################
// ########################################################################

print_cp_header($vbphrase['urlacesslist_manager'], [
	get_admincp_script_tag('vbulletin_paginate.js'),
]);


if (empty($_REQUEST['do']))
{
	$_REQUEST['do'] = 'list';
}

/** @var vB_Library_Urlcache */
$lib = vB_Library::instance('urlcache');
$assertor = vB::getDbAssertor();

// print_form_header2() always appends '.php?do'...
$thispagelink = 'admincp/urlaccesslist';
$thispagedo = 'list';

// Grab pagination params that's common to most pages.
$vbulletin->input->clean_array_gpc('r', [
	'page'	  => vB_Cleaner::TYPE_INT,
	'perpage' => vB_Cleaner::TYPE_INT,
]);
['p' => $page, 'pp' => $perpage] = getPageAndPerPage($vbulletin->GPC);


// ###################### Start List #######################
if ($_REQUEST['do'] == 'list')
{
	$totalcount = $assertor->getField('urlcache_accesslist', [
		vB_dB_Query::TYPE_KEY => vB_dB_Query::QUERY_SUMMARY,
		vB_dB_Query::COLUMNS_KEY => ['COUNT(*)'],
	]);
	// allow perpage = 0 to be show all
	$conditions = [];
	if ($perpage > 0)
	{
		$conditions = [
			vB_dB_Query::PARAM_LIMIT => $perpage,
			vB_dB_Query::PARAM_LIMITSTART => ($page - 1) * $perpage,
		];
	}
	$sort = [
		'field' => ['host', ],
		'direction' => [vB_dB_Query::SORT_ASC, ],
	];
	$list = $assertor->assertQuery('urlcache_accesslist', $conditions, $sort);

	$paginationParams = [
		'page' => $page,
		'perpage' => $perpage,
	];
	print_pagination_form($thispagelink, $thispagedo, $paginationParams, $totalcount);

	// Note, the .h-flex-left here is to ensure the checkbox & "All" labels stay on a single line in the initial case there are no holidays defined.
	$checkall = "
		<label class=\"h-pointer h-flex-left\">
			<span class=\"h-checkbox-label h-align-middle \">
				<input class=\"h-pointer js-checkbox-master\" data-child=\"js-checkbox-child\" type=\"checkbox\" name=\"checkall\" value=\"1\">
			</span>
			{$vbphrase['all']}
		</label>";
	$headers = [
		$checkall,
		// Can't get this to look nicely for the manually entered "allow" atm... going to hide them for now.
		// "<span class=\"h-center-content\">" .( $vbphrase['last_url'] ?? 'PHRASE:LAST_URL:PHRASE' ). "</span>",
		// "<span class=\"h-center-content\">" .( $vbphrase['lastfetch'] ?? 'PHRASE:lastfetch:PHRASE' ). "</span>",
		"<span class=\"h-center-content\">" . $vbphrase['accesstype'] . "</span>",
		"<span class=\"h-center-content\">" . $vbphrase['controls'] . "</span>",
	];
	$colSpan = count($headers);

	// We want the left column left-aligned, everything else center aligned. We may want to push this to the print_cells_row2 function if this config
	// turns out to be common.
	$aligns = array_fill(0, $colSpan, 'vbcenter');
	$aligns[0] = 'vbleft';

	print_form_header2($thispagelink, 'bulk_delete');
	print_table_start();
	print_description_row($vbphrase['urlaccesslist_desc'], false, $colSpan);
	print_table_header($vbphrase['domains'], $colSpan);
	$bgClasses = array_fill(0, $colSpan, 'thead thead--v-centered');
	$bgClasses[0] = 'thead thead--v-centered h-fixed-width-32';
	print_cells_row2($headers, $bgClasses, $aligns);

	construct_hidden_code('page', $page);
	construct_hidden_code('perpage', $perpage);

	//print_cells_row2($firstRow, [], $aligns);
	// Hack to pre-increment the global counter for our fetch_prev_row_bgclass() use below.
	fetch_row_bgclass();
	$strUtil = vB::getString();
	foreach ($list AS $__row)
	{
		$__id = $__row['hostid'];
		$__url = get_admincp_url('urlaccesslist', ['do' => 'edit', 'hostid' => $__id]);
		$__editLink = construct_link_code2($vbphrase['edit'], $__url, false, '', 'h-center-content');
		$__host = ($__row['scheme'] ? $__row['scheme'] . '://' : '') . $__row['host'];
		// prevent any intentional or accidental xss.. though URLs generally shouldn't be able to have html code, this can be
		// manually entered (by an admin)
		$__host = $strUtil->htmlSpecialChars($__host);

		// put the checkbox next to the title (inside the label).
		$__checkbox =  "<label class=\"h-pointer h-flex-left h-gap-4\">
				<span class=\"h-checkbox-label  \">
					<input class=\"h-pointer js-checkbox-child\" type=\"checkbox\" name=\"hostid[]\" value=\"$__id\">
				</span>
				$__host
			</label>";
		$rowCells = [
			$__checkbox,
			// $__row['url'],
			// $__row['lastfetch'],
			// Grep help: accesstype_deny, accesstype_allow
			$vbphrase['accesstype_' . $__row['accesstype']] ?? $__row['accesstype'],
			$__editLink,
		];

		// print_cells_row2() will always call fetch_row_bgclass() which increments the global counter. fetch_prev..() does not increment the counter.
		$__defaultBgClass = fetch_prev_row_bgclass();
		// vertically align every column (i.e. checkboxes vs text labels) to look a bit neater.
		$__bgClasses = array_fill(0, $colSpan, $__defaultBgClass . ' h-align-middle--only');
		print_cells_row2($rowCells, $__bgClasses, $aligns);
	}

	$args = [
		'do' => 'edit',
		'page' => $page,
		'perpage' => $perpage,
	];
	$editUrl = get_admincp_url('urlaccesslist', $args);
	$actionPrefix = 'admincp/urlaccesslist.php';
	$buttons = [
		// We have several "bulk" actions that we need to carry the hostids over to. We switch the form action via the .js-alternate-submit handler.
		// Default is already bulk_delete but just keeping it consistent with the other submits.
		construct_submit_button($vbphrase['domains_bulk_delete'], ['js-alternate-submit',], ['data-action' => $actionPrefix, 'data-do' => 'bulk_delete']),
		construct_submit_button($vbphrase['domains_bulk_allow'], ['js-alternate-submit',], ['data-action' => $actionPrefix, 'data-do' => 'bulk_allow']),
		construct_submit_button($vbphrase['domains_bulk_deny'], ['js-alternate-submit',], ['data-action' => $actionPrefix, 'data-do' => 'bulk_deny']),
		construct_link_button($vbphrase['add_new_domain_access'] , $editUrl),
		//['submit', $vbphrase['reactions_save_options']],
	];


	print_table_button_footer($buttons, $colSpan);

	print_pagination_form($thispagelink, $thispagedo, $paginationParams, $totalcount);
}

if ($_REQUEST['do'] == 'edit')
{
	$vbulletin->input->clean_array_gpc('r', [
		'hostid'	  => vB_Cleaner::TYPE_INT,
	]);
	$hostid = $vbulletin->GPC['hostid'];
	if ($hostid)
	{
		$assertor = vB::getDbAssertor();
		$domain = $assertor->getRow('urlcache_accesslist', ['hostid' => $hostid]);
	}
	else
	{
		$domain = [
			'scheme' => 'https',
			'host' => '',
			'accesstype' => vB_Library_UrlCache::ACCESS_TYPE_DENY,
		];
	}

	print_form_header2($thispagelink, 'save');
	construct_hidden_code('page', $vbulletin->GPC['page']);
	construct_hidden_code('perpage', $vbulletin->GPC['perpage']);
	if ($hostid)
	{
		construct_hidden_code('hostid', $hostid);
	}
	print_table_start();
	$title = $hostid ? 'edit_domain_access' : 'add_domain_access';
	print_table_header($vbphrase[$title]);
	print_description_row($vbphrase['urlaccess_add_desc'], false);

	print_input_row($vbphrase['scheme_desc'], 'scheme', $domain['scheme']);
	print_input_row($vbphrase['domain_desc'], 'host', $domain['host'] ?? '');
	$selectOptions = [
		vB_Library_UrlCache::ACCESS_TYPE_DENY => $vbphrase['accesstype_deny'],
		vB_Library_UrlCache::ACCESS_TYPE_ALLOW => $vbphrase['accesstype_allow'],
	];
	print_select_row($vbphrase['accesstype'], 'accesstype', $selectOptions, $domain['accesstype']);

	print_table_default_footer($vbphrase['save']);
}

if ($_REQUEST['do'] == 'save')
{
	$vbulletin->input->clean_array_gpc('r', [
		'hostid'	  => vB_Cleaner::TYPE_INT,
		'scheme'	  => vB_Cleaner::TYPE_STR,
		'host'	      => vB_Cleaner::TYPE_STR,
		'accesstype'  => vB_Cleaner::TYPE_STR,
	]);
	$hostid = $vbulletin->GPC['hostid'];
	// We might want to do some light validation here, but also not sure what's warranted since URLs can get weird.
	$scheme = $vbulletin->GPC['scheme'];
	$host = $vbulletin->GPC['host'];

	$accesstype = $vbulletin->GPC['accesstype'];
	if (!in_array($accesstype, [vB_Library_UrlCache::ACCESS_TYPE_DENY, vB_Library_UrlCache::ACCESS_TYPE_ALLOW]))
	{
		$accesstype = vB_Library_UrlCache::ACCESS_TYPE_DENY;
	}

	$assertor = vB::getDbAssertor();
	$check = $assertor->getRow('urlcache_accesslist', ['host' => $host, 'scheme' => $scheme]);
	if ($hostid OR $check)
	{
		if (!$hostid AND $check)
		{
			$hostid = $check['hostid'];
		}

		$assertor->update('urlcache_accesslist', [
			'scheme' => $scheme,
			'host' => $host,
			'accesstype' => $accesstype,
		], ['hostid' => $hostid]);
	}
	else
	{
		$assertor->insert('urlcache_accesslist', [
			'scheme' => $scheme,
			'host' => $host,
			'accesstype' => $accesstype,
		]);
	}

	// We may want to "search" for the new page that will include the above record and redirect to that page instead...
	// for now just going back to the original page.
	$args = [
		'do' => 'list',
		'page' => $vbulletin->GPC['page'],
		'perpage' => $vbulletin->GPC['perpage'],
	];
	$url = get_admincp_url('urlaccesslist', $args);
	print_cp_redirect($url, 2);
}


// Some common validation for the bulk actions.
if (
	$_REQUEST['do'] == 'bulk_delete' OR
	$_REQUEST['do'] == 'bulk_allow' OR
	$_REQUEST['do'] == 'bulk_deny'
)
{
	$vbulletin->input->clean_array_gpc('r', [
		'hostid'	  => vB_Cleaner::TYPE_ARRAY_INT,
	]);
	$hostids = $vbulletin->GPC['hostid'];
	$assertor = vB::getDbAssertor();
	$list = $assertor->getRows('urlcache_accesslist', ['hostid' => $hostids]);
	if (empty($list))
	{
		print_stop_message('please_select_at_least_one_domain');
	}
}

if ($_REQUEST['do'] == 'bulk_delete')
{
	$tableTitle = 'confirm_domain_delete';
	$description = 'are_you_sure_delete_domains';
	print_bulk_confirm($vbphrase, $tableTitle, $description, $list, 'do_delete', $page, $perpage);
}

if ($_REQUEST['do'] == 'bulk_allow')
{
	$tableTitle = 'confirm_domain_access_changes';
	$description = 'are_you_sure_allow_domains';
	print_bulk_confirm($vbphrase, $tableTitle, $description, $list, 'do_allow', $page, $perpage);
}

if ($_REQUEST['do'] == 'bulk_deny')
{
	$tableTitle = 'confirm_domain_access_changes';
	$description = 'are_you_sure_deny_domains';
	print_bulk_confirm($vbphrase, $tableTitle, $description, $list, 'do_deny', $page, $perpage);
}


// Some common validation for the bulk actions.
if ($_REQUEST['do'] == 'do_delete')
{
	$vbulletin->input->clean_array_gpc('r', [
		'hostid'	  => vB_Cleaner::TYPE_ARRAY_INT,
	]);
	$hostids = $vbulletin->GPC['hostid'];
	$assertor = vB::getDbAssertor();
	$assertor->delete('urlcache_accesslist', ['hostid' => $hostids]);

	$args = [
		'do' => 'list',
		'page' => $vbulletin->GPC['page'],
		'perpage' => $vbulletin->GPC['perpage'],
	];
	$url = get_admincp_url('urlaccesslist', $args);
	print_cp_redirect($url, 2);
}

// Some common validation for the bulk actions.
if ($_REQUEST['do'] == 'do_allow')
{
	$vbulletin->input->clean_array_gpc('r', [
		'hostid'	  => vB_Cleaner::TYPE_ARRAY_INT,
	]);
	$hostids = $vbulletin->GPC['hostid'];
	$assertor = vB::getDbAssertor();
	$assertor->update('urlcache_accesslist', ['accesstype' => vB_Library_UrlCache::ACCESS_TYPE_ALLOW], ['hostid' => $hostids]);

	$args = [
		'do' => 'list',
		'page' => $vbulletin->GPC['page'],
		'perpage' => $vbulletin->GPC['perpage'],
	];
	$url = get_admincp_url('urlaccesslist', $args);
	print_cp_redirect($url, 2);
}

// Some common validation for the bulk actions.
if ($_REQUEST['do'] == 'do_deny')
{
	$vbulletin->input->clean_array_gpc('r', [
		'hostid'	  => vB_Cleaner::TYPE_ARRAY_INT,
	]);
	$hostids = $vbulletin->GPC['hostid'];
	$assertor = vB::getDbAssertor();
	$assertor->update('urlcache_accesslist', ['accesstype' => vB_Library_UrlCache::ACCESS_TYPE_DENY], ['hostid' => $hostids]);

	$args = [
		'do' => 'list',
		'page' => $vbulletin->GPC['page'],
		'perpage' => $vbulletin->GPC['perpage'],
	];
	$url = get_admincp_url('urlaccesslist', $args);
	print_cp_redirect($url, 2);
}

// function(s) should be considered private to this script

function print_bulk_confirm(
	array $vbphrase,
	string $phraseKeyForTableTitle,
	?string $phraseKeyForDescription,
	array $domainslist,
	string $doaction,
	// These are passthroughs from the original list domains page so we end up back on the same page when we redirect.
	int $page,
	int $perpage) : void
{
	$colSpan = 2;
	print_form_header2('admincp/urlaccesslist', $doaction);
	print_table_start();
	print_table_header($vbphrase[$phraseKeyForTableTitle], $colSpan);
	if ($phraseKeyForDescription)
	{
		print_description_row($vbphrase[$phraseKeyForDescription], false, $colSpan);
	}
	$bgClasses = array_fill(0, $colSpan, 'thead thead--v-centered');
	$bgClasses[0] = 'thead thead--v-centered h-fixed-width-32';
	//print_cells_row2($headers, $bgClasses, $aligns);

	construct_hidden_code('page', $page);
	construct_hidden_code('perpage', $perpage);

	$strUtil = vB::getString();
	foreach ($domainslist AS $__row)
	{
		$__id = $__row['hostid'];
		$__host = ($__row['scheme'] ? $__row['scheme'] . '://' : '') . $__row['host'];
		// prevent any intentional or accidental xss.. though URLs generally shouldn't be able to have html code, this can be
		// manually entered (by an admin)
		$__host = $strUtil->htmlSpecialChars($__host);

		$__input = "<input type=\"hidden\" name=\"hostid[]\" value=\"{$__id}\">\n";
		//construct_hidden_code('hostid[]', $__id);

		$rowCells = [
			$__input . $__host,
			$vbphrase['accesstype_' . $__row['accesstype']] ?? $__row['accesstype'],
		];

		print_cells_row2($rowCells);
	}

	print_table_button_footer([['submit', $vbphrase['confirm']], ['goback', $vbphrase['cancel']]]);

}

/*=========================================================================*\
|| #######################################################################
|| # Downloaded: 13:27, Sun Aug 30th 2026
|| # CVS: $RCSfile$ - $Revision: 111008 $
|| #######################################################################
\*=========================================================================*/
