php $_GET['page'] several pages - php

if (!$_GET['page'] || preg_match('/\W/', $_GET['page']) || !file_exists('./intl/tpl/tpl_source/' . $_GET['page'] . '.tpl'))
$_GET['page'] = 'index';
if ($_GET['page'] && $_GET['page'] != 'index') {
$smarty->assign("pg_" . $_GET['page'], true);
$smarty->display($_GET['page'] . ".tpl");
die();
}
This code let me open any page (?page=1, ?page=2 and so on, also it's mean if no page give, open index)
but i need specify which one user can open, so, code should look like:
if ($_GET['page'] = '21' || preg_match('/\W/', $_GET['page']) || file_exists('./intl/tpl/tpl_source/' . $_GET['page'] . '.tpl')) {
//my stuff
}
In short, i need specify which addresses user can open with $_GET['page'] (?page=21 ?page=22 and so on).
Sorry if question not clear.

You can simplify your code by using a typecast (for filtering!) and a simpler list of allowed pages:
$allowed_pages = array(1, 12, 21, 25, 32);
$page = (int)$_GET["page"]
and in_array($page, $allowed_pages)
and file_exists("./intl/tpl/tpl_source/$page.tpl")
or $page = "index";
$smarty->assign("pg_$page", true);
$smarty->display("$page.tpl");
die();

You can create a white list:
var $pages = array(
21 => true,
22 => true
);
// or
var $pages = array_flip(array(21, 22));
and test whether the page is in there:
if(isset($pages[$_GET['page']])) {
}

Related

Is it OK to use an Array Check instead of Switch Statement for dynamic page content?

I'm trying to create a simple static website, but my lesser knowledge in back-end code had me question my abilities. Is there any kind of security risk or anything else I might be overseeing to use an array check instead of switch statement?
For example this is the code I've been using until recently
// Default page
$current_page = 'home';
if(array_key_exists('page', $_GET)) {
$current_page = $_GET['page'];
}
switch ($current_page) {
case 'home':
$page = 'pages/home.php';
break;
case 'about':
$page = 'pages/about.php';
break;
case 'contacts':
$page = 'pages/contacts.php';
break;
default:
$page = 'pages/404.php';
}
and this is the code I've replaced it with. It just makes more sense to me to have the code that would expand in the future (as more pages are added later on) separate from the actual check that never changes, on top of that I think it looks nicer.
$pages = array(
'home' => 'pages/home.php',
'about' => 'pages/about.php',
'contacts' => 'pages/contacts.php',
'404' => 'pages/404.php',
);
// Default page
$page = $pages['home'];
if(array_key_exists('page', $_GET)) {
$current_page = $_GET['page'];
if(array_key_exists($current_page, $pages)){
$page = $pages[$current_page];
} else {
$page = $pages['404'];
}
}
They are both safe, but the second is a bit easier to manage.
Another approach would be something like this:
$subFolder = 'pages';
$current_page = $subFolder . DIRECTORY_SEPARATOR . 'home';
if (array_key_exists('page', $_GET)) {
$current_page = $subFolder . DIRECTORY_SEPARATOR . $_GET['page'] . '.php';
}
if (file_exists(__DIR__ . DIRECTORY_SEPARATOR . $current_page)) {
$page = $current_page;
} else {
$page = $subFolder . DIRECTORY_SEPARATOR . '404.php';
}
echo $page;
This does not require you to edit your code every time you add a new page. The code itself checks if the requested page exists in the pages directory.

Error with if statement to include pages in php

I have a group of pages, and I want to include one of them dependent on a variable in url, but the page is always appear is dashboard
link1 : index.php?pth=&page=dashboard
link2 : index.php?pth=modules/institution&page=inst_classification
if statement :
if (isset($page) && !empty($page)) {
$page = htmlspecialchars($_GET["page"]);
$pth = htmlspecialchars($_GET["pth"]);
}else{
$page ='dashboard';
$pth = '';
}
include ('../admin/template/'.$template_fldr.'/html/'.$pth.$page.'.php');
thanks!
You access $page before you write to it. You also never check for the existance of your pth value. Try:
if (empty($_GET['page']) || empty($_GET['pth'])) {
$page ='dashboard';
$pth = '';
}else{
$page = htmlspecialchars($_GET["page"]);
$pth = htmlspecialchars($_GET["pth"]);
}
include ('../admin/template/'.$template_fldr.'/html/'.$pth.$page.'.php');
You probably also need a / here in your include, if modules/institution/inst_classification.php is the file you are looking for:
include('../admin/template/'.$template_fldr.'/html/'.$pth.'/'.$page.'.php'); - but that is not clear from your question.
if (isset($_GET["page"]) && isset($_GET["pth"])) {
$page = htmlspecialchars($_GET["page"]);
$pth = htmlspecialchars($_GET["pth"]);
} else {
$page = 'dashboard';
$pth = '';
}
include ('../admin/template/'.$template_fldr.'/html/'.$pth.'/'.$page.'.php');

scandir for files for users

I've created a pages dashboard for my content management system, and well I am trying to iterate the scandir method and my conditions are not working. Can someone explain why?
$pages = scandir('../',0);
foreach($pages as $page){
if($page !== "." OR $page !== ".." OR $page !== "admin" OR $page !== "admin.php" OR $page !== "kms_kontent" OR !is_dir('../'.$page)){
$extension = explode('.',$page);
$extension = end($extension);
$page = str_replace('.'.$extension,'',$page);
echo '<div class="row"><ul><li class="fifths">'.$page.'</li><li class="fifths"></li></ul></div>';
}
}
It's echoing all contents
--public_html
-admin.php #don't show
-admin #don't show
-kms_content #don'tshow
-index.php #show
-shop.php #show
Also it's showing . and .. which I don't want to show either.
The logic is flawed. To see why, let's assume you have just this comparison:
$page !== "." OR $page !== ".."
The condition is satisfied if page isn't . or if page isn't ..; if the page is . it will not be equal to .. and vice versa. In other words, the condition is always satisfied.
What you want is that the condition is satisfied only if page is neither . nor ..; so:
!($page === '.' || $page === '..')
Following DeMorgan's law:
$page !== '.' && $page !== '..'
An array of possible values could be used to simplify the code even more:
$invalid_pages = [".", "..", "admin", "admin.php", "kms_kontent"];
if (!in_array($page, $invalid_pages) && !is_dir('../'.$page)) {
}
if (
$page !== "." OR
$page !== ".." OR
$page !== "admin" OR
$page !== "admin.php" OR
$page !== "kms_kontent" OR
!is_dir('../'.$page)
) {
Because you are using OR, the if will go true when any of the conditions is true. So if $page is admin it will go false for $page !== "admin" but true to all others, and it won't work. You should use && or AND.
But instead, you could clean up that code a little bit using arrays. For instance:
$filter = ['.', '..', 'admin', 'admin.php', 'kms_kontent'];
$pages = scandir('../', 0);
foreach ($pages as $page) {
if (!in_array($page, $filter) && !is_dir("../$page")) {
...
}
}
It does the same thing, but the code looks cleaner and more items can be added more easily.
Using AND or && instead of OR!

?page=index $_GET

For this moment using this code:
if ($_GET['page'] == 'index'
and file_exists('./intl/tpl/' . $_GET['page'] . '.tpl')
or !file_exists('./intl/tpl/' . $_GET['page'] . '.tpl')
or !$_GET['page']) {
//code
} elseif ($_GET['page'] == 'multi'
and file_exists('./intl/tpl/' . $_GET['page'] . '.tpl')) {
//code 2
}
and so on...
Question 1: Does this code "good" ? Doesn't need any escaping or something ?
Question 2: ?page=logout doens't work, so i created logout.php which looks like:
<?php
require_once "./intl/config.php";
SessionDelete('logged_in');
SessionDelete('username');
SessionDelete('userid');
if ($user_admin != null) {
SessionDelete('inadmin');
if (SessionGet('s_order') != null or SessionGet('s_page_show_all') != null) {
SessionDelete('s_order');
SessionDelete('s_page_show_all');
}
}
header('Location: '.$config['indexurl'].'index.php');
?>
Maybe before sessions delete need session start and it's possible do that with ?page=logout ?
The code certainly can be improved:
Reorder the tests so that it will not generate E_NOTICE errors
Parenthesize so that operator precedence is immediately obvious
Use the && and || boolean operators (as garvey's comment says)
Doing this, you 'd have:
if (empty($_GET['page']) ||
!file_exists('./intl/tpl/' . $_GET['page'] . '.tpl') ||
($_GET['page'] == 'index' && file_exists('./intl/tpl/' . $_GET['page'] . '.tpl')) {
//code
}
} elseif ($_GET['page'] == 'multi' && file_exists('./intl/tpl/' . $_GET['page'] . '.tpl')) {
//code 2
}
Then, rewrite it some more to make it clear why you are doing what you do. This will also allow you to write simpler code. Simple is good.
// This way it's obvious that 'index' is the default page
$page = !empty($_GET['page']) ? $_GET['page'] : 'index';
if (!file_exists('./intl/tpl/' . $page . '.tpl')) {
$page = 'index'; // comment here saying that if a non-existing page is requested, we display the index instead
}
$template = './intl/tpl/' . $page . '.tpl';
// At this point, we know that $page has a value, and we know that $template exists, so:
switch($page) {
case 'index':
// code
break;
case 'multi':
// code2
break;
}
As for the second question: yes, you need to start the session before you are able to modify or destroy it.

Dynamic include

<?php
// Default page
if (!$_SERVER['QUERY_STRING']) $Page = "news";
// View
elseif (isset($_GET['newsID'])) $Page = "newsView";
elseif (isset($_GET['userID'])) $Page = "profile";
elseif (isset($_GET['messageID'])) $Page = "message";
elseif (isset($_GET['threadID'])) $Page = "thread";
elseif (isset($_GET['forumID'])) $Page = "forum";
elseif (isset($_GET['imgID'])) $Page = "imageView";
// Pages
elseif ($_GET['content'] == "search") $Page = "search";
elseif ($_GET['content'] == "gallery") $Page = "gallery";
elseif ($_GET['content'] == "forums") $Page = "forums";
elseif ($_GET['content'] == "messages") $Page = "messages";
many more...
// If page don't exist
else $Page = "error";
// Output page
include($config['PAGE_PATH'].$Page.'.php');
include($config['TEMPLATE_PATH'].$Page.'.html');
?>
This is some code my friend wrote years ago...
I'm wondering how safe this is and if I could make it a little cleaner?
Thanks.
As it is you who defines what pages are allowed to be included (white list), I cannot see any way to poison the $Page variable. So this seems pretty safe.
But you could clean it up using arrays such as:
$argToPage = array(
'newsID' => 'newsView',
'userID' => 'profile',
'messageID' => 'message',
'threadID' => 'thread',
'forumID' => 'forum',
'imgID' => 'imageView'
);
$contents = array(
'search',
'gallery',
'forums',
'messages'
);
$Page = null;
if (trim($_SERVER['QUERY_STRING']) == '') {
$Page = 'news';
} else {
foreach ($_GET as $key => $val) {
if (isset($argToPage[$key])) {
$Page = $argToPage[$key];
break;
}
}
}
if (is_null($Page) && isset($_GET['content']) && in_array($_GET['content'], $contents)) {
$Page = $contents[$_GET['content']];
} else {
$Page = 'error';
}
But that’s not much cleaner.
Well it's safe in the sense that the code sanitizes the parameter. People often do that (to disastrous results usually).
I'm not a big fan of this pattern however. By that I mean a single controller that includes files passed on a parameter. I much prefer to have a script per page and just include what's needed. Structurally I think it's better.
That being said, there's nothing fundamentally wrong with the above approach.
Just make sure you treat any data that comes from the user with extreme paranoia.
I'd be very cautious about cleaning this up any more than it is. Using a variable provided by user input in an include is a major security flaw. I would leave this as it is.
You could make an array with GET options as key and pages as values.. then use switch() statement. This should make the code cleaner. But as Cletus said, this isn't the best way to make a controller.

Categories