Using PHP url variables/php includes - php

What I'm trying to do is to create a URL, example:
article.php?00001
Then using the following code this will include 00001 as an article within article.php
if(isset($_GET['00001'])){
include('00001.php');
}else if(isset($_GET['00002'])){
include('00002.php');
} else {
include('noarticle.php');
}
Now, this works, and would be suitable for several articles if I just keep adding 00003-00010 etc, but if I intend to add MANY more articles, is there a better way of coding this without having to manually insert article numbers?

Use a database to store your articles. Have a look at http://www.freewebmasterhelp.com/tutorials/phpmysql for a guide on how to use MySQL with PHP.
With regards to your URLs, use article.php?id=### then use $_GET['id'] to determine which article is being viewed.
By including files based on user-supplied data, what if the user goes to article.php?article - it tries to load article.php which tries to load article.php which tries to ... you get the idea.

Just make it dynamic!
I would do something like this:
article.php?id=id_of_my_article
if(isset($_GET['id'])) include($_GET['id'].".php");
else include('noarticle.php');

First you need to know that it's insecure to include files simply based on url. There are other better means of doing so, as #Joe and #Angelo Cavallini wrote.
But if you are well aware of the consequences and determined to do so, you man try:
$id = current( $_GET );
$id && $id=intval($id);
if( $id ){
include( $id.'php' );
}

Related

Prevent end user manipulating URL to change content on website, method GET PHP

I have a personal search site project I'm building, at the moment the only data that is being displayed on the website is data that is retrieved using SELECT queries and the GET method using the super global $_GET['example']. Now I don't know if I'm doing this wrong but some parts of my page are only displayed if certain GET variables in the URL are set or not empty. Below shows how my URL looks
EXAMPLE: index.php?search_category=guitar&main_category=9&postcode_val1=NP22&distance_default=100&submit=search
I have a lot of these if(isset($_GET['search_category']) type conditions in my website which are replied upon and show particular parts of content depending whether or not these are either true or false.
I have been on a lot of other websites that have similar URL's, I have tried to alter and manipulate these and the content does not break, alter or change in any way yet when i try this with my url it breaks my page and only certain parts of content gets displayed by being based on what is set. Is there some other layer of protection I should add, would using something like a rewrite rule help? The code below shows how I have wrote a drop down box based on what has been set In the URL but if a user edits the URL this is easily broken.
if(isset($_GET['search_category']) && isset($_GET['main_category']) &&
isset($_GET['postcode_val1']) && isset($_GET['distance_default']))
{
$stmt = $getFromUi->dispCategories();
echo "<option value='0'>All</option>";
echo "<option value='#'>-------------</option>";
while($row = $stmt->fetch(PDO::FETCH_OBJ))
{
$selected = '';
if(!empty($_GET['main_category']) && $_GET['main_category'] == $row->cat_id)
{
$selected = ' selected="selected"';
}
echo '<option value="'.htmlentities($row->cat_id).'"'.$selected.'>'.htmlentities($row->cat_title).'</option>';
}
}
It will break because the strict nature of logic you use on your code. The && mark with isset mean any parameter you define not set will not evaluate to true. If the parameter is quite flexible why not ||.
If you need it to still evaluate all parameter try to do limit first if condition to main determiner. like $_GET['search_category'] and use the remaining $_GET['other_parameter'] as needed inside the block code of main if.
You would need to use a post method, so that this goes through as a request instead. In my experiance, get will only fetch the url you open - not actually pass anything through unless its in the URL.
Not sure if that made any sense, but check post out.
https://www.w3schools.com/tags/ref_httpmethods.asp is a good place to start to see the difference of get vs post.

query string in php url which fetches values from files in directories

for security reasons we need to disable a php/mysql for a non-profit site as it has a lot of vulnerabilities. It's a small site so we want to just rebuild the site without database and bypass the vulnerability of an admin page.
The website just needs to stay alive and remain dormant. We do not need to keep updating the site in future so we're looking for a static-ish design.
Our current URL structure is such that it has query strings in the url which fetches values from the database.
e.g. artist.php?id=2
I'm looking for a easy and quick way change artist.php so instead of fetching values from a database it would just include data from a flat html file so.
artist.php?id=1 = fetch data from /artist/1.html
artist.php?id=2 = fetch data from /artist/2.html
artist.php?id=3 = fetch data from /artist/3.html
artist.php?id=4 = fetch data from /artist/4.html
artist.php?id=5 = fetch data from /artist/5.html
The reason for doing it this way is that we need to preserve the URL structure for SEO purposes. So I do not want to use the html files for the public.
What basic php code would I need to achieve this?
To do it exactly as you ask would be like this:
$id = intval($_GET['id']);
$page = file_get_contents("/artist/$id.html");
In case $id === 0 there was something else besides numbers in the query parameter. You could also have the artist information in an array:
// datafile.php
return array(
1 => "Artist 1 is this and that",
2 => "Artist 2..."
)
And then in your artist.php
$data = include('datafile.php');
if (array_key_exists($_GET['id'], $data)) {
$page = $data[$_GET['id']];
} else {
// 404
}
HTML isn't your best option, but its cousin is THE BEST for static data files.
Let me introduce you to XML! (documentation to PHP parser)
XML is similar to HTML as structure, but it's made to store data rather than webpages.
If instead your html pages are already completed and you just need to serve them, you can use the url rewriting from your webserver (if you're using Apache, see mod_rewrite)
At last, a pure PHP solution (which I don't recommend)
<?php
//protect from displaying unwanted webpages or other vulnerabilities:
//we NEVER trust user input, and we NEVER use it directly without checking it up.
$valid_ids = array(1,2,3,4,5 /*etc*/);
if(in_array($_REQUEST['id'])){
$id = $_REQUEST['id'];
} else {
echo "missing artist!"; die;
}
//read the html file
$html_page = file_get_contents("/artist/$id.html");
//display the html file
echo $html_page;

pass a value from one page to another outside querystring and without javascript?

One solution to automatically building navigation for a site is by scanning a folder for documents like this:
foreach(glob('pages/*.pg.php') as $_SITE_NAV_filePath):
$_SITE_NAV_filePath = explode('.pg',pathinfo($_SITE_NAV_filePath,PATHINFO_FILENAME));
$_SITE_NAV_fileName = $_SITE_NAV_filePath[0];
$_SITE_NAV_qv = preg_replace('/([A-Z])/','-$1',$_SITE_NAV_fileName); $_SITE_NAV_qv = trim($_SITE_NAV_qv,'-');
$_SITE_NAV_name = preg_replace('/([A-Z])/',' $1',$_SITE_NAV_fileName);
?>
<li><?=$_SITE_NAV_name?></li>
<?php
endforeach;
This code will turn "AnAwesomePage.pg.php" into a menu item like this :
<li>An Awesome Page</li>
This might be bad practice (?).
Anyway; I don't use this method very often since most of the time the sites have a database, and with that comes better solutions...
But my question is this:
Is there a way to prefix the filename with a integer followed by and underscore (3_AnAwesomePage.pg.php), for sorting order purposes, and pass it somehow to the destination page outside of the querystring and without any async javascript?
I could just explode the filename once again on "_" to get the sort order and store it somewhere, somehow?
This is the code for handeling the page query request:
$_SITE_PAGE['qv'] = $_GET['page'];
if (empty($_SITE_PAGE['qv'])){ $_SITE_PAGE['qv'] = explode('-','Home'); }
else { $_SITE_PAGE['qv'] = explode('-',$_GET['page']); }
$_SITE_PAGE['file'] = 'pages/'.implode($_SITE_PAGE['qv']).'.pg.php';
This code turns "An-Awesome-Page" back into "AnAwesomePage.pg.php" so it's possible to include it with php.
But with a prefix, it's not so easy.
The probliem is; Now there's no way to know what prefix number there was before since it has been stripped away from the query string. So I need to send it somehow along in the "background".
One very bad solution I came up with was to transform the navigation link into a form button and just _POST the prefix interger along with the form. At fist it sounded like a nice solution, but then I realized that once a user refreshes their page, it didn't look very good. And after all, that's not what forms are for either...
Any good solutions out there?
Or some other and better way for dealing with this?
There are two ways to keep that number saved, you can use cookies or php session variables.
But in this case, if user first enter the url in the browser or in a new browser, then he should be taken to default number.
Like you have:
1_first-page.php
2_first-page.php
3_first-page.php
If user enter the url like: domain.com/?page=first-page, you have to take him to 1_first-page.php to any number which you want to be default.

PHP Zend_Paginator on mySql query using GET

I am trying to call pages using Zend_Paginate() on a query that loads based on a GET search string the query essentially does the following:
SELECT * FROM table WHERE column LIKE '%searchstring%' OR alt_column LIKE '%searchstring%';
The query works fine when called via search/submit text form and the URL returns something similar to
URLINK.php?search=searchstring
However when trying to move onto the next page the program dumps me back to the paginate alternate URL (used for errors or no page display)-- hope this last line makes sense it is late and am doing my best to type this up with transparency.
What is the best method when using paginate against URL.php?search=searchstring"?
A bit more on the call to the url
//search query
$search = searchQuery('search', 'list_sql_rows.php');
$results - searchTable($dbRead, $search);
search method using the variables above in the order below
if(isset($_POST['submit_search'])) { $searchstring = $_POST['searchstring'];
if($searchstring) { header('Location: results.php?search=' . $searchstring); } }
This bit works well, but when I try to call the results.php?page=2 with paginator the system reverts me to the fall back URL list_sql_rows.php as mentioned above. Any thoughts/comments are appreciated.
Just to clarify a search field/form from the search.php page sends the $searchstring to the results.php page via $_POST && $_GET as fail safe. The get method sends the $searchstring in the URL header so the results of the search DO work on the first page results.php?search=$searchstring. This works just fine. The pagination seems to lose the $searchstring, and I wonder if this is due to a loss of the $_POST/$_GET when paginator begins to 'paginate' it returns URL results.php?page=2 so it seems $_GET may not be the method of choice?
UPDATE
On the write track now paginate works it is my link structure that is broken.
_results_samples.php?search=robert&page=4_ will in fact return page 4 of the paginated results using the word ROBERT
SOLUTION FOUND VIA variant suggestion by ROCKYFORD
variant of recommended method by first persisting $searchstring
change to paginate links as shown below
<a href='" . $_SERVER['PHP_SELF'] . "?search=" . $searchstring . "&page={$page}'>$page</a>
Here is the example of correct using of pagination:
in action-method:
$select = $clients->getAll();
$paginator = new Zend_Paginator(new Zend_Paginator_Adapter_DbSelect($select));
$paginator->setCurrentPageNumber($this->_getParam('page'));
$paginator->setItemCountPerPage(20);
$this->view->clients = $paginator;
in a view script:
<?php if (count($this->clients) > 0): ?>
...
<?php echo $this->paginationControl($this->clients, 'Sliding', 'partials/paginator.phtml'); ?>
<?php else: ?>
<h3 class="notice">No registered clients found!</h3>
<?php endif; ?>
But even if you will fail with this variant, you can always try to compose your own component, Zend only aids us in solving some tasks.
you need to make sure you preserve the query strings between requests, use Zend_Session_Namespace or Zend_registry.
Everytime Zend_Paginator loads a page when using the DbTableSelect or DbSelect adapters it has to hit the db with the query, it just changes the limit option.
Or you could just dump the whole query result into a Zend_Paginator_Adapter_Array and it will page through the array.
[edit]
you are going to have to persist the query string between requests someway so you can put it back in the url string, I usually use Zend_Registry, but then I use the whole MVC stack. You don't seem to be using the whole stack so you'll need another method, probably $_SESSION would work. I'm sure there are many other ways to persist this data.
P.S. you didn't mention which adapter you are using so I'm making some assumptions.
[edit]
Personally I always use $_post for this when possible to avoid all this, only seem to have this problem with $_get.

How do I create dynamic URLs?

I have a social network that allows users to write blogs and ask questions. I am wanting to create dynamic URLs that post the title of the blog or question on the end of the URL via PHP.
Example:
www.blah.com/the_title_here
Looking for the cleanest most efficient way to accomplish this.
You would usually store the URL-friendly "slug" in the database row, and then have a PHP script that finds posts matching that slug.
For example, if you have a script called index.php that took a parameter called slug...
<?php
if (isset($_GET['slug'])) {
$sql = "SELECT * FROM `your_table` WHERE slug = ? LIMIT 1";
$smt = $pdo->prepare($sql);
$smt->execute(array($_GET['slug']));
$row = $smt->fetchObject();
// do something with the matching record here...
}
else {
// display home page
}
...You could then re-write requests using .htaccess:
RewriteEngine on
RewriteRule ^(.+)$ index.php?slug=$1
Using the database to do this would be sad :(
There may be many cases where you do not need to lookup the database and you will with this method. eg:- www.blah.com/signup (no point here). And db connections eats up resources, serious resources...
RewriteEngine on
RewriteRule ^(.+)$ index.php?slug=$1
as shown by martin gets you the path or slug.
Most frameworks use filesystem to achieve cleaner URLs.
One folder to hold all files and
something which is similar in theory to
<?php
$default = "home";
//function to make sure the slug is clean i.e. doesnot contain ../ or something
if(isset($_GET['slug'])) $slug = clean($_GET['slug']);
if(!isset($slug)) $slug = $default;
$files = explode('/',$slug);// or any other function according to your choice
$file = "./commands/".$files[0].".php";
if(file_exists($file))
require_once($file);
else
require_once("./commands/".$default.".php");
You can make this as simple to as complicated as you want. You can even use the database to determine the default case like what Martin did, but that should be in the $default and not the first logic you use...
Advantages of doing it this way
It is way faster than querying the database
You can scale this a lot. Vertically eg: site.com/users/piyushmishra and site.com/forums/mykickassforum or even on deeper levels like site.com/category/category-name/post-name/comments/page-3
You can setup libraries and packages easier.Scaling horizontally (add more directories to check and each directory can have one/more modules setup) eg : ./ACLcommands/users.php , ./XMLRPC/ping.php
There are lots of open source software that do this, you can look at WordPress.org or MediaWiki.org to do this. You'll need a combination of .htaccess or Apache configuration settings to add mod_rewrite rules to them.
Next, you'll want a controller file as Martin Bean wrote to look up the post... but make sure you escape/sanitize/validate input properly, otherwise you can be vulnerable to SQL injection or XSS if you have JavaScript on your site.
So it's better to use the id method and only use the slug for pretty-url purposes. WordPress.org software also suggests that going only by the slug makes it slow once you have a lot of posts. So, you can use a combination of www.blah.com/slug-phrase-goes-before-the-numeric_id and write a RegExp to match: .*(\d+)$
"www.blah.com/$id/".preg_replace('/^[a-z-]+/','',preg_replace('/[ ,;.]+/','-',strtolower($title)))
and use only $id
from title
"How do I create dynamic URLs?"
it creates url
www.blah.com/15/how-do-i-create-dynamic-urls

Categories