I want url's like index.php?showuser=512, index.php?shownews=317 for pages i get content from db... and for regular pages index.php?page=about and so on WITHOUT mod-rewrite.
Invision Power Board has urls like this. I have looked through their code but I can't figure out how they do it.
I could do it like this:
if (ctype_digit($_GET['shownews'])) include('shownews.php');
elseif (ctype_digit($_GET['showuser'])) include('showuser.php');
// regular pages
elseif ($_GET['page'] == 'about') include('about.php');
elseif ($_GET['page'] == 'help') include('help.php');
elseif ($_GET['page'] == 'login') include('login.php');
But this feels too messy.
Just curious how IPB does this. Is there a better way do to this? WITHOUT any mod-rewrite. Any one know? I doubt they do it like the above.
I can't do:
if (preg_match('/^[a-z0-9]+$/', $_GET['page'])) include('$_GET['page']');
Then I would get links like index.php?showuser&id=512 and that I dont like. (i know its not safe just showing the princip)
I like it this way, it's not the best but i like it so please be quiet about template engines, frameworks etc. Just be kind and answer my question... I just want to know how IPB does this.
Thanks
Tomek
I don't know how IPB does this, let's get that out of the way. But, this is how I would approach this problem:
First, I recognize that there are two kinds of GET parameters: page/identifier, and just page. These would get tested separately.
Second, I recognize that all all get parameters match their filenames sans the php-suffix, so we can use this to our advantage.
One of the most important things to remember is to never let GET-parameters affect our code unsanitized. In this case, we know which types of pages we can and want to show, so we can create a white-list out of these.
So, onto the pseudo-y dispatcher code:
$pagesWithId = array("shownews", "showuser", "showwhatever");
$justPages = array("about", "help", "login");
foreach ($pagesWithId as $page) {
if (isset($_GET[$page])) {
$id = (int)$_GET[$page];
include($page.'.php');
die();
}
}
if (in_array($_GET['page'], $justPages)) {
include($_GET['page'].'.php');
die();
}
// page not found
show404OrHandleOtherwise();
For pages you just use a simple array.
if (isset($pages[$_GET['page']])) include $pages[$_GET['page']];
For shownews=317 You could make a simple conversion in your app. Depending on how you want to prioritize page or shownews etc:
if (isset($pages[$_GET['page']])) {
include $pages[$_GET['page']];
} else {
$possiblePages = array_filter(array_intersect_key($_GET, $pagesWithId), 'ctype_digit');
if (!empty($possiblePages)) {
$id = reset($possiblePages);
$pageName = key($possiblePages);
$page = $pagesWithId[$pageName];
include $page;
} else {
//no valid pages
}
}
Note: page "names" are array keys, and the value is the path, file and extension to include. More customizable.
Related
I am having an issue using isset to display content on a page.
My PHP file is called messages.php
I am directing my users with links to this URL: messages.php?inbox using if(isset($_GET['inbox']))
{ } to display the users inbox. Same principle with the other users options such as compose message is: messages.php?compose again using isset
The only problem I have is that I cannot stop people from manually typing stuff like domain.com/messages.php or domain.com/messages.php?somethingrandom.
Is there a way to direct users to messages.php?inbox when they type in the address bar something that isnt assigned to isset?
I did try to use switch but couldnt seem to get it to work properly with how ive laid out my HTML.
An example of the whole file is here http://pastebin.com/SfqN2L7g
I am fairly new to PHP and think I may have gone down the complicated route.
Any advice would be appreciated.
Thanks
The answer you added already would work, but I usually like having an array of valid options which I could maybe check against later on.
$validPages = array('inbox', 'compose');
$pageFound = false;
foreach ($validPages as $validPage) {
if (isset($_GET[$validPage])) {
$pageFound = true;
break;
}
}
if (! $pageFound) {
header('Location: /messages.php?inbox');
}
Thanks to the help of Marcos PĂ©rez Gude, the answer is as follows:
if(isset($_GET['inbox']) || isset($_GET['compose'])){
//Then do below
}else{
header("Location: messages.php?inbox");
exit;
}
For instance, I have viewpost.php and it's set up as needed and I only need to change the content within divs in there.
For example, I'm going to have to do viewpost.php?id=1,2,3 etc. But should I do EVERYTHING off index.php using index.php?action=viewpost&id=1?
Then also, do I use if statements, or do I communicate with my database using those get requests?
Overall, I plan to use modrewrite anyway, but I am clueless on the proper way to set up loading multiple pages off one, or a few php files.
I have a template and I just need to fill it using database data.
Easiest way is something very basic like this (Not very secure though)
$page = $_GET["action"];
if($page == null)
{
$page = "main";
}
if (file_exists("content/$page.php"))
{
include ("content/$page.php");
}
else
{
include ("includes/404.php");
}
A better solution is to use something like http://www.smarty.net/ to handle templating and content loading. Slightly more complicated, but most likely worth the extra effort if you're doing anything beyond a very simple website.
index.php?action=viewpost&id=1 this code in index:
if(isset($_GET['action']) && isset($_GET['id']))
{
$id = $_GET['id'];
if($action == "viewpost")
{
// action is viewpost
if(!ctype_digit($id))
{
// id isnt digit
die();
}
else
{
// viewpost
include('viewpost.php');
}
}
viewpost.php could look like:
just to be sure nothing bad happens when going right to viewpost.php you could see in the url if viewpost.php exists, or just do the security here (!ctype_digit($_GET['id']))
// since its already been secured with !ctype_digit, we can run queries right away
$q_findPost = mysqli_query($mysqli, "SELECT * FROM posts WHERE id=$id");
$r = mysqli_fetch_assoc($q_findPost);
// div stuff
Im doing a game and i created an "administration" panel for it.
it works like this:
admin.php
admin/code1.php
admin/code2.php
admin.php:
<?php
include("lib.php");
$player = check_user($secret_key, $db);
if($player->rank != "Administrador")
{
header("Location: personagem.php");
exit;
}
include("templates/private_header.php");
head("Admin Panel","adminpanel.png");
startbox();
if(isset($_GET['page']))
{
include("admin/" . $_GET['page'] . ".php");
}
else
{
?>
Kill Players<br>
Heal Players<br>
<?php
}
endbox();
include("templates/footer.php");
?>
i want to know if im prone to hacking.
the code1.php and code2.php uses a custom query library that is included in lib.php so there is no way to execute them directly without falling in to an error.
Also in My template i have:
if($player->rank == "Administrador")
{
echo "<a href='admin.php'>Admin Panel</a>";
}
so i can access the panel more quickly.There is risk in there too?
Just note that $player is a object created from a query to the player Database that represents the actual player. In my thoughts the only way to hack this is changing they "rank" status in the table to "Administrador" am i right? or there is something i let pass?
Thanks in advance
include("admin/" . $_GET['page'] . ".php");
This is a huge security hole.
Something like blah.php?page=../../../../etc/passwd%00 would include /etc/password and of course you can also do this with other files - maybe even some files uploaded by the user that contain PHP code (could be even an image as long as it contains <?php [code] somewhere)
And even if only you are administrator, not closing holes like that would not be wise - you might have other administrators at some point.
Never trust user input
Never work with any of $_GET $_POST, $_COOKIE without verifying them first (or anything else user-generated for that matter, even stuff from your own database might be dangerous).
include("admin/" . $_GET['page'] . ".php");
Don't do this. otherwise you can include any file you want. I suggest you whitelist all allowed pages to be included like so:
$allowed = array("admin_index", "page1", "page2");
if(in_array($_GET['page'], $allowed)){
include("admin/" . $_GET['page'] . ".php");
}
else{
// perform error handling
}
Here's a useful function that you could take a look at, if you don't want to whitelist all pages: basename() - this will always only return the filename part, without any directory-changing part.
Furthermore, I do not recommend you work with includes like this at all, but rather have some Controller-hierarchy that can decide what to do on each request.
What about the authentication?
Show us your code for the authentication. That's a crucial part of your system that needs to be secure.
I don't know how to easily describe this, here goes nothing...
I am writing a PHP script to perform an action if the URL is a specific URL, however, the URL is /ref/[VISITOR_USERNAME]. I want to set it so that anytime the URL is /ref/[ANY_TEXT], the action will perform.
if($_SERVER['REQUEST_URI'] == '/ref/' . string . '') {
...perform action...
}
How do I tell the script that if the URL is /ref/ and anything following that to perform the action?
Also, I realize there are other, probably better ways to do this, but for the sake of what I am trying to do, I need to do it this way.
Thanks in advance.
if(substr($_SERVER['REQUEST_URI'], 0, 5) == '/ref/') {
...
}
If you want to check for more you can build a regex:
if(preg_match('/\/ref\/.+/', $_SERVER['REQUEST_URI'])) {
...
}
You may just want to revise your Conditional Statement like so:
<?php
// CHECK THAT THE REQUEST URL CONTAINS "ref/[ANY_STRING_AT_ALL_INCLUDING_SLASHES]"
if( preg_match("#ref\/.*#", $_SERVER['REQUEST_URI'])) {
// NOW,GET TO WORK CODER... ;-)
}
So basically i am struggling with the need of optimizing my code for some project of mine.
Currently i have pages like add_company.php, view_company.php, edit_company.php.
What i would like to do is to serve all content from just 1 PHP file company.php.
So to speak company.php?action=view, company.php?action=edit etc. Is the only way to do this with massive if else statements? That would make my company.php like mega huge.
Or maybe even better how could I serve all my pages just using index.php ?
So what would be the best way to accomplish this? I am not php guru and i don't have much experience with MVC or any other pattern.
Thanks.
You could make company.php
<?php
$allowed = array('add', 'view', 'edit');
if ( ! isset($_GET['action'])) {
die('missing param');
}
$action = $_GET['action'];
if ( ! in_array($action, $allowed)) {
die('invalid');
}
require $action . '_' . __FILE__;
Quick and dirty, but should work :) You could place this code in any file, and it will work straight away.
With a bit of modification, you could make this your front controller with index.php.
I always prefer using a switch statement for the $_GET variable. Its my personal preference to put all the logic pertaining to one entity (in this case company) in a single PHP file because I generally deal with tons of entities. If you want a MVC model, this might not be what you are looking for. Just my 2 cents.
// Common page header
// Other stuff common in the pages
$page_to_load = $_GET[view];
switch($page_to_load) {
case 'view':
//Logic to view or HTML for view
break;
case 'add':
//Logic to add or HTML for add
break;
}
// Common footer etc..
This is pretty simple stuff. It should look something like this:
//index.php
if (!isset($_GET['page']))
{
require('index_contents.php');
}
else if ($_GET['page'] == 'company')
{
if (!isset($_GET['action']))
{
require('company_contents.php');
}
else if ($_GET['action'] == 'edit')
{
require('edit_company.php');
}
else if ($_GET['action'] == 'add')
{
require('add_company.php');
}
else
{
require('company_contents.php');
}
}
else
{
require('index_contents.php');
}
A very easy solution would be to just use includes.
if ($_GET["action"] == "view") {
require("action_view.php");
} else if ...
(of course, you might want to use a switch statement, if you have lots of different page types)
Then action_view.php contains just the code for the specific page.
Better, but also more complicated solutions, would be an object oriented approach (abstract Page class with Factory Pattern) or forthright a good framework and template engine.
You could use POST instead of GET with index.php:
<?php
require($_POST['action'] . ".php");
?>
This would hide the action type from the user, acting as though it is a single page. However, it may require using a form in your navigation as opposed to linking direct to "company.php?action=edit".