<?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.
Related
I'm having a little problem. I want to securely include files based on the $_GET Parameter from a subdirectory + handle if the parameter is not valid.
<?php
if(isset($_GET['p']) && $_GET['p'] == 'fahrzeuge'){
include 'includes/cars.php';
}
if(isset($_GET['p']) && $_GET['p'] == 'impressum'){
include 'includes/impressum.php';
}
if(isset($_GET['p']) && $_GET['p'] == 'home'){
include 'includes/home.php';
}
if(isset($_GET['p']) && $_GET['p'] == 'anfahrt'){
include 'includes/anfahrt.php';
}
if(isset($_GET['p']) && $_GET['p'] == 'about'){
include 'includes/about.php';
}
?>
This is my Code. Sorry I know it is a noob way of solving this. How can I improve it? Any Suggestions/Help would be highly appreciated
This is the fastes and best way, i am a fan of short codes
and found this from (HACKBUGZ PHP).
You have an array with array keys and array values.
EXAMPLE 1
<?php
$PAGES = array();
$PAGES = [
'home' => 'home.html'
,'about' => 'about.php'
,'contact' => 'somedir/contact.php'
];
#include(substr($PAGES[$_GET['p']] ?? ('home'), 0, 255));
exit;
?>
You can have different query names, filenames, filetypes and directorys.
the # catch the include error if file not exists.
substr($PAGES, 0, 255) cuts the uri to 255 chars(if you dont like that
just do it without)
($PAGES[$_GET['p']] ?? ('home')) checks if query (array_key) exists in array if not 'home' will be the default
EXAMPLE 2(without substr)
<?php
$PAGES = array();
$PAGES = [
'home' => 'home.html'
,'about' => 'about.php'
,'contact' => 'somedir/contact.php'
];
#include($PAGES[$_GET['p']] ?? ('home'));
exit;
?>
Set an array of legit pages. Check once if $_GET['p'] is set and if so assign its value (after escaping it) to a variable $p.
Then check if the requested page ($p) is defined in your pages array, if so - include it.
$pages = array('about','contact','home');
$p = 'home'; //Default page
if(isset($_GET['p'])) {
$p = $_GET['p']; //no need to escape as we compare it to predefined values as #Yoshi suggested
}
if(in_array($p, $pages)){
include 'includes/'.$p.'.php';
} else {
include 'includes/home.php';
}
I would use a ternary to set a variable that tells the page what to include.
This is very similar to Ofir Baruch's answer, except much shorter.
$pages = array('about','contact','home');
$p = isset($_GET['p']) && in_array($_GET['p'], $pages)? $_GET['p'] : 'home';
include "includes/{$p}.php";
Basically, you have an array of pages that are possible. In the ternary, we check if $_GET['p'] is set (isset()), AND we check if the value it contains is in the array. If it is, we use $_GET['p'] as $p, if it is not, we set $p to home, this means that home will always be the default if $_GET['p'] is not set, or not a valid page as per the array.
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');
I'm just trying to figure out which would be better, in the long term, as well as if there is a performance difference between these two scenarios.
We're maintaining a site we did not create, and we're trying to add something dynamically to the sidebar on certain pages, and trying to decide if there's a reason to use a foreach loop or multiple if/else statements.
We're going to end up with a lot more pages than the 6 shown here, so performance could be considered a concern.
The foreach loop looks like this:
$rb_enabled = false;
$RURLs = array(
'/cambridge.php' => 'cambridge',
'/milton.php' => 'milton',
'/kitchener_waterloo.php' => 'kw',
'/hamilton_dundas.php' => 'hd',
'/oakville.php' => 'oakville',
'/brantford.php' => 'brantford'
);
foreach( $RURLs as $rurl => $engine_location ){
if($_SERVER['REQUEST_URI'] == $ru){
$rb_url == $engine_location;
$rb_enabled == true;
}
}
if($rb_enabled === true){ //create a div with information based on engine location }
The sidebar php file this gets loaded into is on many pages, some of which need this div created specifically for it, other pages need to not have it at all, hence the $rb_enabled.
Is there a reason that foreach loop is better or worse than this:
if($_SERVER['REQUEST_URI'] == '/cambridge.php'){ $rb_url = 'cambridge'; $rb_enabled = true; }
else if($_SERVER['REQUEST_URI'] == '/milton.php'){ $rb_url = 'milton'; $rb_enabled = true; }
else if($_SERVER['REQUEST_URI'] == '/kitchener_waterloo.php'){ $rb_url = 'kw'; $rb_enabled = true; }
else if($_SERVER['REQUEST_URI'] == '/hamilton_dundas.php'){ $rb_url = 'hd'; $rb_enabled = true; }
else if($_SERVER['REQUEST_URI'] == '/oakville.php'){ $rb_url = 'oakville'; $rb_enabled = true; }
else if($_SERVER['REQUEST_URI'] == '/brantford.php'){ $rb_url = 'brantford'; $rb_enabled = true; }
The if statements are a bit redundant with the $rb_enabled, but wondering if there's any reason to use one way over the other, even if it's only "which code you would rather take over if you were the next one with hands on this project" if that's the only reason.
Also open to a new idea entirely!
You already have an array with the URI's as key, so why not use array_key_exists()?
if(array_key_exists($_SERVER['REQUEST_URI'], $RURLS)) {
$rb_enabled = true;
$rb_url = $RURLS[$_SERVER['REQUEST_URI']];
}
There is no need to loop through the array, or provide multiple if or switch/case statements. The performance for this lookup will not degrade as the size of your URI array increases (well within reason at least - if you have a huge array that takes up lots of memory, that could be a problem.)
You should use switch/case syntax for what you asking for:
switch( $_SERVER['REQUEST_URI'] ) {
case '/milton.php':
$rb_url = 'milton';
$rb_enabled = true;
break;
....
}
One line:
list($rb_enabled,$rb_url) = ($url=$RURLs[$_SERVER['REQUEST_URI']])? array(true,$url) : null ;
I'm trying to use the break concept, but I am also am using some built in PHP functions to only allow certain values into the get function.
$allowedKeys = array(
'route'
);
$options = array(
'chapter_1' => 'chapter_1',
'chapter_2' => 'chapter_2',
'chapter_3' => 'chapter_3'
);
$_GET = array_intersect_key($_GET, array_flip($allowedKeys));
if($_GET[$allowedKeys[0]] && array_key_exists($_GET[$allowedKeys[0]], $options)) {
if($_GET[$allowedKeys[0]] == $options[0]) {
/* This is where I'm trying to see if route=chapter_1 then do something.
The logic I'm trying to write is if the route is chapter_1 then print
out the content from chapter 1 How can determine this? */
echo "Hello";
}
}
Why isn't this code echoing "hello"?
Why make it more complex than it needs to be?
//check you have a route
$route = isset( $_GET['route'] ) ? $_GET['route'] : '';
switch( $route ) {
case 'chapter_1':
//do chapter one stuff
echo 'Chapter 1';
break;
case 'chapter_2':
//do chapter two stuff
echo 'Chapter 2';
break;
default:
echo 'Intro';
}
I'll answer your question directly for you. 'Hello' isn't showing because it is inside an if statement that isn't being triggered because either "if($_GET[$allowedKeys[0]] && array_key_exists($_GET[$allowedKeys[0]], $options))" or "if($_GET[$allowedKeys[0]] == $options[0])" is returning false.
I have a bit of a problem with my PHP code, I am assigning values to variables in different states of the flow depending on what I receive, but for some reason it keeps getting stuck at one point, here is the code.
if (isset($session)) {
//if the user is in the database
if ($row == 1) {
$from = $_GET['from'];
if (isset($from)) {
$page = $_GET['page'];
switch ($page) {
case "game":
$page = "game";
sendVars($page);//send the variable
break;
case "gallery":
$page = "gallery";
sendVars($page);//send the variable
break;
case "leaderboard":
$page = "leaderboard";
sendVars($page);//send the Variable
break;
}
}else {
$page = "game";
sendVars($page);//send the variable
}
//if the user is not in the database
}else {
//do this
}
} else {
//register
}
Now for some odd reason, it keeps setting the value of $page to game, even though I set the page variable to gallery like so http://www.mydomai.com/?from=set&page=gallery . the only reason for this that I can think of is that my switch is not working as it should? or it is bypassing the switch somehow?
Thanx in advance!
I just ran your code after removing a few of the unessersary variable assignments:
<?php
// I added this function just for testing
function sendVars($page) {
echo $page;
}
if (isset($_GET['from'])) {
$page = $_GET['page'];
switch ($page) {
case "game":
sendVars($page); //send the variable
break;
case "gallery":
sendVars($page); //send the variable
break;
case "leaderboard":
sendVars($page); //send the Variable
break;
}
} else {
$page = "game";
sendVars($page); //send the variable
}
And it all seems fine, xxx.php?from=1&page=gallery echos out "gallery", try doing a print_r($_GET) at the top of your script and see what it prints out and let us know.
On a side note I think the below may be shorter for you and still do the same thing:
if (isset($_GET['from'])) {
// Check if $_GET['page'] exsists and is either game, gallery or leaderboard
if (isset($_GET['page']) && in_array($_GET['page'], array('game', 'gallery', 'leaderboard')))
sendVars($_GET['page']);
}
else
sendVars('game');
I hope this helps
Cheers
Luke
Try doing a var_dump($page);exit; before the switch and see what it spits out.
Also you can do a var_dump($from) and see what that is spitting out - it may be that it goes to the else, so it may not even be getting to the switch.
If this is inside a function, I personally prefer guard-style clauses than constantly increasing the levels of indentation. The idea is you pick out the bad conditions (ie if something is going wrong) to "protect" the larger block of logic.
In your case that's the switch statement.
if (!isset($session))
return ...; // register
if ($row != 1)
return ...; // do this
$from = $_GET['from'];
$page = $_GET['page'];
if (isset($from)) switch ($page) {
case "game":
$page = "game";
break;
case "gallery":
$page = "gallery";
break;
case "leaderboard":
$page = "leaderboard";
break;
}
else $page = "game";
return sendVars($page);// don't need to repeat this if all cases do it!
It's just a style of code and it's not going to fix all (if any) of your problems. You actually don't need the switch block in there for this code. I can't see that it's doing anything.
You don't necessarily need the switch statement. I can't see an obvious problem with your logic but I think this will do the same thing:
if (isset($session))
{
//if the user is in the database
if ($row == 1)
{
$page = (in_array($_GET['page'],array('game','gallery','leaderboard'))) ? $_GET['page'] : "game";
sendVars($page); //send the variable
}
else //if the user is not in the database
{
//do this
}
}
else
{
//register
}
Just saw Luke used the same in_array method but 25 mins before me. Serves me right for being slow!