homepage Welcome to WebmasterWorld Guest from 54.227.146.68
register, free tools, login, search, pro membership, help, library, announcements, recent posts, open posts,
Become a Pro Member

Home / Forums Index / Code, Content, and Presentation / PHP Server Side Scripting
Forum Library, Charter, Moderators: coopster & jatar k

PHP Server Side Scripting Forum

    
Meta tags from a database
chrisguk




msg:4443822
 9:51 pm on Apr 21, 2012 (gmt 0)

Hi Guys,

This is my first post I think in this area.

I found the code below almost by accident on this forum.

Is anyone able to help me adapt it. for example, I want it to say "if the id matches the $page then use that row to populate the title, keywords etc etc

My requests are all made by the index.php at the moment using this:

$page = isset($_GET['page']) ? $_GET['page'] : 'home';

<?php

// Open database here...

// SQL
$sql = mysql_query("SELECT * FROM database WHERE id = '" . $id . "' LIMIT 1") or die (mysql_error());

while($row = mysql_fetch_array($sql)){
$title = $row['title']; // get title from database
$description = $row['description']; // get description from database
$keywords = substr($row['keywords'], 0, 250); // get keywords (250 characters) from database
}

// Close database here...
?>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
<html>
<head>
<title><?php echo $title?></title>
<meta http-equiv="content-type" content="text/html;charset=iso-8859-1">
<meta http-equiv="Content-Language" content="en">
<meta name="description" content="<?php echo $description?>">
<meta name="keywords" content="<?php echo $keywords?>">
</head>
<body>

<!-- HTML content goes here... -->

</body>
</html>

 

topr8




msg:4443883
 6:10 am on Apr 22, 2012 (gmt 0)

i'm not sure i understand your question, however i think you just want to change:

$sql = mysql_query("SELECT * FROM database WHERE id = '" . $id . "' LIMIT 1") or die (mysql_error());
to
$sql = mysql_query("SELECT * FROM database WHERE id = '" . $page . "' LIMIT 1") or die (mysql_error());

however you REALLY need to 'clean' the input, eg. check that $_GET['page'] is the kind of value you are expecting, or else it is only a matter of time before you are hacked and all the data in your database is compromised.

enigma1




msg:4443896
 9:02 am on Apr 22, 2012 (gmt 0)

You should be checking if there any rows returned from the query before inserting tags. You've set a limit to 1 so there is only one row maximum to be returned.

if( mysql_num_rows($sql) ) {
$row = mysql_fetch_array($sql);
$title = $row['title']; // get title from database
$description = $row['description']; // get description from database
$keywords = substr($row['keywords'], 0, 250); // get keywords (250 characters) from database
} else {
$title = 'Set Default Title';
$description = 'Set Default Description';
$keywords = 'Set Default Keywords';
}

chrisguk




msg:4443966
 5:28 pm on Apr 22, 2012 (gmt 0)

Okay this is what I have so far, will this work or not.

At the moment I get an error message saying "no database selected".

I have called the db - "mydb" and the table "url"

<?php
$localhost = 'localhost';
$dbuser = 'root';
$dbpass = 'password';
$dbname = 'mydb';

$connect = mysql_connect($localhost, $dbuser, $dbpass);
mysql_select_db('dbname', $connect);

$page = array('about','profiles','another_page');

$page = isset($_GET['page']) ? $_GET['page'] : 'home';

$sql = mysql_query("SELECT * FROM mydb WHERE id = '" . $page . "' LIMIT 1") or die (mysql_error());

if( mysql_num_rows($sql) ) {
$row = mysql_fetch_array($sql);
$title = $row['title']; // get title from database
$description = $row['description']; // get description from database
$keywords = substr($row['keywords'], 0, 250); // get keywords (250 characters) from database
} else {
$title = 'Set Default Title';
$description = 'Set Default Description';
$keywords = 'Set Default Keywords';
}


include($_SERVER['DOCUMENT_ROOT']. '/include/header.php');

include('content/'.$page.'.php');

include($_SERVER['DOCUMENT_ROOT']. "/include/footer.php");
?>


contents of my header.php

<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
<html>
<head>
<title><?php echo $title?></title>
<meta http-equiv="content-type" content="text/html;charset=iso-8859-1">
<meta http-equiv="Content-Language" content="en">
<meta name="description" content="<?php echo $description?>">
<meta name="keywords" content="<?php echo $keywords?>">
</head>
<body>

<!-- HTML content goes here... -->

</body>
</html>

chrisguk




msg:4443967
 5:34 pm on Apr 22, 2012 (gmt 0)

Cancel that, I fixed it and it works perfect:

changed mysql_select_db('dbname', $connect); to:

mysql_select_db($dbname, $connect);

rocknbil




msg:4444326
 4:59 pm on Apr 23, 2012 (gmt 0)

What is this bit about? You set page to an array and overwrite it in the next line.

$page = array('about','profiles','another_page');
$page = isset($_GET['page']) ? $_GET['page'] : 'home';

The answer is not important, as I'll make use of this later. :-)

will this work or not.


In terms of absolutes, it should work. But will it work well? Or safely, or without "what happened there" moments? Questionable.

First look at this. I'm a little confused, you have a select querying "id" which is usually numeric, but it looks like it's a text string (e.g., if it's not present set it to 'home').

$sql = mysql_query("SELECT * FROM mydb WHERE id = '" . $page . "' LIMIT 1") or die (mysql_error());

What if, for whatever reason, $page is set but empty? What you get is

SELECT * FROM mydb WHERE id = '' LIMIT 1

Which is perfectly valid and won't error. But you won't know what has happened.

You're also taking raw input and doing a direct uncleansed query on a database, which opens you to mySQL injection. Worst yet: now you're taking that raw uncleansed variable and using it in an include:

include('content/'.$page.'.php');

Although that's limited to the content directory, hackers are very creative and can do stuff I've never dreamed of with this. I'd give a little more attention to making sure that's uber clean. Aside, I'd also use the same approach you use on the previous two includes.

include($_SERVER['DOCUMENT_ROOT']. '/content/'.$page.'.php');

Solution: This returns to my question about the array. One simple approach could be (note I've changed the name to pageS on the array)

$pages = array('home','about','profiles','another_page');
$page = isset($_GET['page']) ? $_GET['page'] : 'home';

if (in_array($page,$pages)) {
// OK! it's an acceptable query. All your code here
}
else { echo "There is no page with that name on this site."; exit; }

Simple and straightforward: anything else a hacker attempts to input doesn't match the allowed set of pages. On a large site this really isn't practical, but smaller ones it's fine.

chrisguk




msg:4444327
 5:03 pm on Apr 23, 2012 (gmt 0)

The array part was an error I left that in there by accident.

Going back to your comment about larger and smaler sites. My site will be a large site so what is your recommendations?

topr8




msg:4444417
 10:30 pm on Apr 23, 2012 (gmt 0)

this is the only book i ever recommend, and no i'm not the author

Essential PHP Security published by o'reilly

it's one of their smallest books and the most important/useful one i've ever read.

buy it or get it from your local library library.

chrisguk




msg:4444440
 11:11 pm on Apr 23, 2012 (gmt 0)

I rewrote the script completely and added some prepare statements for security.

Thanks for the recommendation of the book.

g1smd




msg:4444449
 11:26 pm on Apr 23, 2012 (gmt 0)

At the very top of the script you should look at the value of the page variable and return 404 status if the format isn't even valid.

Before the place where the !DOCTYPE is emitted, you should check whether anything was returned from the datebase for this query and return 404 status if not.

A surprisingly large number of database driven sites fail to do this and return infinite blank-template duplicate content with "200 OK" status for non-valid requests.

chrisguk




msg:4444455
 11:41 pm on Apr 23, 2012 (gmt 0)

Sorry guys I should have closed this thread down, the script has been completely re-written with most if not all security stuff taken care of,

@g1

I'll share it with you over the next day or so.

enigma1




msg:4444702
 3:42 pm on Apr 24, 2012 (gmt 0)

infinite blank-template duplicate content with "200 OK" status for non-valid requests.

Let me guess. You're going to write specific code if the page parameter is invalid and return 404? How about parameter qwerdhfj? It's also invalid.

rocknbil




msg:4444733
 4:19 pm on Apr 24, 2012 (gmt 0)

My site will be a large site so what is your recommendations?


Don't run away, no one's picking on you. :-) It's all about assisting with what we know (which helps us learn more . . . .)

There's a number of ways, and the first place to look is what the successful CMS's do. All of them store a seo-freindly URL along side the rest of the data. So you look up the requested URL and if it's not found, output a 404 page.

A simple way to filter that URL: if it's a url, you're only going to allow letters, numbers, and dashes, right?

$url = preg_replace('/[^a-z\d\-]/i','',$url);

That's one way that would do nicely. "Replace anything not a letter or number or dash with an empty string."

chrisguk




msg:4444753
 5:05 pm on Apr 24, 2012 (gmt 0)

Run away lol, nah im just knee deep in code. Im attempting to develop a backend CMS for my project site, so far its going okay but with my lack of knowledge in some areas I need assistance which you guys have kindly offered :)

SIDE NOTE: This forum layout would be far better if we could use [PHP][/PHP] tags in the BB codes?

Im a little lost as to what the answers to my questions relate to now so here goes, I have pasted the latest code in and then I will tell you what I am trying to achieve:

This is my code so far, at the moment I get an error:

Fatal error: Cannot use object of type stdClass as array in /var/www/test/index.php on line 30

<?php require_once($_SERVER['DOCUMENT_ROOT']. "/include/config.php");

$page = isset($_GET['page']) ? $_GET['page'] : 'home';

$sql = $mysqli->query("SELECT * FROM admin WHERE id = '" . $page . "' LIMIT 1");
if ($mysqli->connect_errno) {
printf("Connect failed: %s\n", $mysqli->connect_error);
exit();
}

if ($sql->num_rows > 0) {
$row = $sql->fetch_object();
$title = $row['title']; // get title from database
$description = $row['description']; // get description from database
$keywords = substr($row['keywords'], 0, 250); // get keywords (250 characters) from database
} else {
$title = 'Administration Panel';
$description = 'description';
$keywords = '';
}

$sqlb = $mysqli->query("SELECT * FROM config");
if ($mysqli->connect_errno) {
printf("Connect failed: %s\n", $mysqli->connect_error);
exit();
}

if ($sqlb->num_rows > 0) {
$rowa = $sqlb->fetch_object();
$url = $rowa['adminurl'];
$email = $rowa['support_email'];
$legal = $rowa['legal'];

}


include($_SERVER['DOCUMENT_ROOT']. "include/header.php");

include('content/'.$page.'.php');

include($_SERVER['DOCUMENT_ROOT']. "include/footer.php");


?>


Im willing to learn and listen at the same time. I have got this far on my own so hopefully im learning something.

Any ideas how to improve or fix it will be gratefully received :)

enigma1




msg:4444772
 6:01 pm on Apr 24, 2012 (gmt 0)

That's because you're fetching an object and you treat it as an array

$rowa = $sqlb->fetch_object();
$url = $rowa['adminurl'];

should be
$url = $rowa->adminurl;

If you want to use arrays, use the fetch_array instead

g1smd




msg:4444780
 6:40 pm on Apr 24, 2012 (gmt 0)

Let me guess. You're going to write specific code if the page parameter is invalid and return 404? How about parameter qwerdhfj? It's also invalid.

In the site I am working on now, if the requested value isn't a single letter followed by a five digit number then 404 is returned immediately because the request doesn't even get rewritten to the PHP script.

For requests in the right format, the database is then queried using the page number as the key. If there is no entry in the database for this query then 404 is returned by the PHP script.


A simple way to filter that URL: if it's a url, you're only going to allow letters, numbers, and dashes, right?

The code shown below has served well on many occasions for generating the text part of a friendly URL from the page title:
$text = preg_replace('/[^a-z0-9]+$/', '', (preg_replace('/[^a-z0-9-]+/', '-', (preg_replace('/[\']+/', '', (preg_replace('/\ ?&amp;\ ?/', '-', strtolower($this->pageName))))))));

It goes like this: take the page name -> lower-case it -> replace
&amp; with hyphen -> remove apostrophes -> replace non-a-z non-0-9 non-hyphen with a hyphen.

There's probably a more efficient way to write it, but it works OK. This for URLs like
example.com/page434-the-page-name-is-here

[edited by: g1smd at 7:24 pm (utc) on Apr 24, 2012]

enigma1




msg:4444784
 6:50 pm on Apr 24, 2012 (gmt 0)

My point is friendly url or not, any page can basically respond with an infinite number of 200s.

example.com/friendly-link?invalid=5

It's not a problem as long as that exact link is not found within the domain or it doesn't injected in some way.

chrisguk




msg:4444786
 7:07 pm on Apr 24, 2012 (gmt 0)

The code shown below has served well on many occasions for generating the text part of a priendly URL from the page title:
$text = preg_replace('/[^a-z0-9]+$/', '', (preg_replace('/[^a-z0-9-]+/', '-', (preg_replace('/[\']+/', '', (preg_replace('/\ ?&amp;\ ?/', '-', strtolower($this->pageName)))))))));


@g1smd
How would I implement this in my code above?

rocknbil




msg:4445404
 4:25 pm on Apr 25, 2012 (gmt 0)

The code shown below has served well on many occasions for generating the text part of a friendly URL from the page title:


To clarify, I was just showing a simple way to allow only specific page URL's as input - not convert them from page titles. You don't want

example.com/pagename=<script src="badsite.com"></script>

lame example, but, yeah. . .

Page titles converted to URL's have proven themselves as too slippery for me, and often the URL needs to be something independent from the title. This also allows you to change the title without having to add 301's for the old URL's every time you do. I'm guessing that's why everyone uses a separate field for the URL. :-)

Global Options:
 top home search open messages active posts  
 

Home / Forums Index / Code, Content, and Presentation / PHP Server Side Scripting
rss feed

All trademarks and copyrights held by respective owners. Member comments are owned by the poster.
Home ¦ Free Tools ¦ Terms of Service ¦ Privacy Policy ¦ Report Problem ¦ About ¦ Library ¦ Newsletter
WebmasterWorld is a Developer Shed Community owned by Jim Boykin.
© Webmaster World 1996-2014 all rights reserved