What is the mechanism of "using $_GET instead of a new file"? - php

I saw some websites that (for example):
if you want to view your message box, then it is: example.com/file.php?action=pm and also if you want to send a message again the address and the file is the same, but the $_GET is different : example.com/file.php?action=sendpm
How does it work?
Is it just:
if ($_GET['action'] == "pm")
{
//lots of html code(divs, forms, etc) paste here for action=pm.
}
else
{
//lots of html code paste here for action=send
}
instead of having files : pm.php, send.php ... ?Or the mechanism is different?
I saw that SMF use this mechanism and also I saw something like this for facebook.com/?ref=something.
How does it work?

The easiest way is this:
$action = isset($_GET['action']) ? $_GET['action'] : 'default';
if(!in_array($action, array('list', 'of', 'allowed', 'pages')))
$action = 'default';
include($action . '.php');
Note that the validation step is incredibly important. Not properly validating the value leads to nasty security holes from users being able to read any files your script can access to users being able to execute arbitrary code.
Putting all code in a single file like you suggested in your question is a bad idea since it results in unreadable code. Especially when mixing PHP and HTML in the same file like your question suggested (tip: use a template engine!).

This is called routing and allows a single entry point to many functions within an single application.
Requests are taken, processed and routed to the correction function. This routing pattern fits well into the Model View Controller (MVC) pattern for organizing code.
Take a look at how the Zend Framework describes MVC and Routing:
http://framework.zend.com/manual/en/learning.quickstart.intro.html#learning.quickstart.intro.mvc

You can have a switch statement. For example
example.com/file.php?action=pm or example.com/file.php?action=sendpm
if (isset($_REQUEST['action'])) {
$param = $_REQUEST['action'];
switch($param) {
case "pm":
// Code goes here
break;
case "sendpm":
// Do something here
break;
default:
// handle the default case
break;
}
} else {
// Handle it here
}
Well there are even other ways to do it !!
Switch is one of the easiest way !!

Related

Does files size slow down php response?

I currently use a one file design... where all my php code is in one index.php file, I have about 13,000 lines (~1mb) in one file, and it is starting to hang a little on load time... I was thinking it could be the file size, but I had always thought PHP is preprocessed on the server, so it doesn't matter what is in the other if statements, because it won't be rendered.
Below is an example of my index.php:
if ($_POST['action'] == 'view') {
// code
} else if ($_POST['action'] == 'something') {
// code
} else if ($_POST['action'] == 'otherthings') {
// code
} else {
// homepage
}
Questions:
Am I losing any speed by having my code in one file? or does this not affect the speed at all?
Are there any code layout/organizational styles that are more efficient for PHP? or does this not matter either?
As others have recommended, it's better to break this file into parts, for ease of maintainability as much as anything. One thing you might consider is using an opcode cache like APC as this will reduce the number of times the index.php file is parsed.
Every line you put needs to be parsed, so putting all code in a unique file affects to response time.
A very simple way to reorganize all it would be:
$action = $_POST['action'];
$path = 'path_to_your_application';
//you should put some validation about action, for example
$allowed_actions = (array of possible values of "action");
if(in_array($action, $allowed_actions) && file_exists($path.$action.".php"))) require($path.$action.".php");
else //homepage
or something like this :-)
No, the more consume time is I/O, as opening files. In your case,
server open and read an unique file, it's optimized
But, code is not maintenable, has cyclomatic complex, is not really
testable... It's recommended to organize your code in breaking it
into many files, with MVC Logic for example. You can also use a
micro framework to help you organize your code around conventions.
See http://silex.sensiolabs.org/ for example.

How to allow only specific pages to be included

Yesterday I asked a question about how to include files passed in via the URL, and someone give me this:
if (isset($_GET['file'])){
include($_GET['file'].'.php');
}
But one of the answers told me to do something with this to avoid possible attacks from hackers or something like that. The problem is that I don't understand how to do it myself.
He said I should do something like this:
$pages_array=('home','services','contact').
And then check the GET var:
if(!in_array($_GET['page'], $pages_array) { die(); }
What does this do, and how do I integrate it into my original code above?
Your original code is looking for a file parameter in the URL, and then including whatever file was passed in. So if somebody goes to your PHP page and adds ?file=something.txt to the URL, you'll include the contents of something.txt in your output.
The problem with this is that anybody can manually modify the URL to try to include whatever file they want - letting them see files on your system that should be private.
The solution is to have a list of allowed filenames, like this:
$pages = array('home', 'services', 'contact');
And then before you include the file, check that it's one of the allowed filenames first.
$pages = array('home', 'services', 'contact');
if (isset($_GET['file'])){
if (!in_array($_GET['file'], $pages_array)) {
exit('Not permitted to view this page');
}
include($_GET['file'].'.php');
}
We're using a PHP array to define the list of allowed pages, checking if our page is in the list with the in_array() function, and then stopping all script execution if it's not in the list with the exit() function.
The code checks the GET information passed from the browser to your PHP page by making sure that the page name is present in your $pages_array.
As long as you list all of the pages in your $pages_array, the code will execute. If the page is not in your array list, then it will die and not be executed.
When using GET it is always beneficial to validate the code sent in this way, as arbitrary statements can be sent and executed without validation.
The code, in this instance, is being validated - so you have taken the necessary steps; as long as there is nothing more to the code that you haven't submitted.
Correct code
$pages_array=array('home','services','contact');
You almost answered your own question...
Except this line becomes...
$pages_array=array('home','services','contact');
Instead of what you had...
$pages_array=('home','services','contact').
//change the variable array declaration
$newArray = array('home','services','contact');
Just do an else statement in your if like
else {
//include your file
include($_GET['page'].'.php');
}
Basically, Your syntax for an array definition is wrong, but also why die() if $_GET['file'] is not set? would it not be better if you reverted to a default so as to fail silently.
Using in_array()
<?php
$pages_array = array('home','services','contact');
if(isset($_GET['file']) && in_array($_GET['file'], $pages_array)){
include($_GET['file'].'.php');
}else{
include('home.php');
}
?>
Or even using switch() with hard coded values.
<?php
$page = isset($_GET['file']) ? $_GET['file'] : 'home';
switch($page){
case "home" : include($page.'.php'); break;
case "services" : include($page.'.php'); break;
case "contact" : include($page.'.php'); break;
default:
include('home.php');
break;
}
?>
$pages=array('home','services','contact');
if(isset($_GET['page']))
{
$page=$_GET['page'];
if(!in_array($page,$pages))
{
die ('');
}
else {
include($page.'.php');
}
}
So, your links will look like:
yoursite.com/index.php?page=home -> with this tool:
http://www.generateit.net/mod-rewrite/
you can make nicer URL's.

How do I make a php if/switch statement according to the PHP lang of the site?

My site has a way of changing its language, and each time I change it I see something like this at the top of the source code:
<html dir="ltr" lang="en-US">
<html dir="ltr" lang="zh-TW">
I think using the URL may also work:
http://alexchen.info/en
http://alexchen.info/tw
or maybe this:
?lang=es
?lang=en
because this works too:
http://alexchen.info/?lang=es
http://alexchen.info/?lang=en
I would like to know what's the best way of using that to make a php if statement (or switch statement).
For instance:
if(lang=en) {
// do this
}
if(lang=tw) {
// do this
}
If you have ?lang=en you can simply get via the $_GET global variable. However, you should first encapsulate the logic within a function.
function getLang()
{
return $_GET['lang'];
}
// ...
if (getLang() == 'en') {
// ...
}
To write a switch (which could have easily been looked up in their documentation):
switch($lang) {
case 'en-US':
// do this
break;
case 'zh-TW':
// do this
break;
}
Although this probably isn't the best approach to doing site translation. I haven't done much multi-language stuff myself, but I see a lot of frameworks wrap blocks of text in functions like
echo T("sample text");
And then the T function would replace that text with the translated text. That way you don't have you entire site littered with switch statements. The translations can be stored in a database. If there's a missing translation, that can be logged or inserted as a blank entry into your DB so that you know what you need to fill in/translate later without digging through your site trying to find all the places where text needs to be translated.

Sanitizing/validating user supplied values in php

I have a function called InputFilter that I use for validating/sanitizing form data and I want to know how to implement it correctly into this? I need to run it through $_GET['media']. The file that the function InputFilter is in is clean.php and if I try to include clean.php into this it makes my result pages not show when a search is performed. This script below is my search.php. Even when I paste the contents of clean.php into search.php it will make my result pages blank and I am not sure why. Is there any easy way to get this to work or a simple way to sanitize/validate $_GET['media']?
$media = isset($_GET['media']) ? $_GET['media'] : 'no_media';
switch($media) {
case 'all':
include("all_media.php");
break;
case 'only':
include("only_media.php");
break;
default:
include("def_search.php");
}
I am open to any other way of securing $_GET['media'].
The switch makes your script very save! No matter what anybody sets as media, there will be no security hole in this code.
To sanitize $_GET check the PHP method filter_input().

Dynamic Include Safety

Is there any way to safely include pages without putting them all in an array?
if (preg_match('/^[a-z0-9]+/', $_GET['page'])) {
$page = $_GET['page'].".php";
$tpl = $_GET['page'].".html";
if (file_exists($page)) include($page);
if (file_exists($tpl)) include($tpl);
}
What should I add to make this pretty safe?
I'm doing it this way bacause I don't like having to include stuff that has to be included on all pages. The "include header > content > include footer"-way. I don't wanna use any template engines/frameworks neither.
Thanks.
The weakness in your current implementation is that …
the regular expression just tests the beginning of the string, so “images/../../secret” would pass, and
without further validation, “index” would also be a valid value and would cause a recursion.
To make your implementation safe, it’s a good practice to put everything, that’s intended to be included, in its own directory (e.g. “includes” and “templates”). Based on this, you just have to ensure that there is no way out of this directory.
if (preg_match('/^[a-z0-9]+$/', $_GET['page'])) {
$page = realpath('includes/'.$_GET['page'].'.php');
$tpl = realpath('templates/'.$_GET['page'].'.html');
if ($page && $tpl) {
include $page;
include $tpl;
} else {
// log error!
}
} else {
// log error!
}
Note: realpath returns the absolute path to the given relative path if file exists and false otherwise. So file_exists is not necessary.
Despite what you stated about not wanting to store a list of available pages in an array it is likely going to be the best, non-db, solution.
$availFiles = array('index.php', 'forum.php');
if(in_array($_GET['page'].".php", $availFiles))
{
//Good
}
else
{
//Not Good
}
You could easily build the array dynamicly with either DB queries or by reading a file, or even reading the contents of a directory and filtering out the things you don't want available.
You should never use user supplied information for includes. You should always have some sort of request handler that does this for you. While a regular expression may filter somethings it will not filter everything.
If you do not want your site to get hacked you do not allow your users to control the flow of the application by designating an include.
I agree with Unkwntech. This is such an insecure way to include files into your website, I wish PHP programmers would do away with it altogether. Even so, an array with all possible matches is certainly safer. However, You'll find that the MVC pattern works better and it is more secure. I'd download code igniter and take a tutorial or two, you'll love it for the same reason you wanna use dynamic includes.

Categories