While working on the project they gave us in college, I came across yet another fun example of the difference between the big browsers.
Firefox 3.6.2: Firefox Screenshot
Opera 10.50: Opera Screenshot
Chrome 5.0.322.2: Chrome Screenshot
IE8 gave the same result as Chrome.
Save this code and open the file in those 3 browsers if you wanna try for yourself.
Or click this link: Link
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN" "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en">
<head>
<title>Test</title>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<style type="text/css">
/* CSS RESET*/
html, body, div, h1, h2, h3, h4, ul, ol, li, form, fieldset,
input, textarea {
margin: 0;
padding: 0;
font-size: 100%;
}
ul {list-style: none;}
img, fieldset {border: 0;}
h1, h2, h3, h4 {font-weight: normal;}
em {font-style: italic;}
strong {font-weight: bold;}
#header{
outline: solid 2px red;
}
#headertext{
max-width: 200px;
height: 40px;
border: dotted 3px green;
float: left;
font-weight: bold;
font-size: 1.8em;
}
</style>
</head>
<body>
<div id="main">
<div id="header">
<div id="headertext">
<h2>Foo in the bar</h2>
</div>
<div id="navbar">
<h3>Foo in the bar</h3>
</div>
</div>
</div>
</body>
</html>
Posted by WebDevHobo at 3:22 AM 2 comments Links to this post
Labels: browsers, chrome, firefox, opera
Querying the servers
Friday, January 8, 2010
When you build a website, you'll probably be using these pieces of technology:
Client-side languages like HTML, CSS and JavaScript
Server-side languages like PHP, ASP.NET, etc...
A relational database like MySQL, MSSQL, PostreGreSQL, etc...
Depending on how active a certain website is, the database will get more or less queries. Some fellow students of mine appear to think that this is completely dependent on the activity of the user. I am here to show that it is not.
Let's take a look at this drawing I made:
A short display of how multiple queries for each piece of data are more stressful than one query to get multiple pieces of data
Granted, the query for the 5 pieces of data at once might be a tiny bit bigger, but it makes no significant difference. And this is only 5 times. Suppose it were 20, or 100. The difference would be a lot bigger. And that's not taking into account that this is only one user doing one thing. The one user can spend hours doing many more things and besides that one user, many other users will also be doing this. The implications are enormous.
One might think this is all very straightforward. The logic is simple and there's no refuting it. Yet it keeps happening. Because in a lab-environment, performance is not an issue. Testing remains limited to functionality and endurance is mostly ignored. The remarks I've heard from various students and people on the internet boils down to: it's working under this condition, so I'm not going to bother with it anymore
In conclusion, I think the drawing speaks for itself. Performance is always an issue, and taking the stress of your system can certainly improve it.
Posted by WebDevHobo at 6:24 AM 0 comments Links to this post
Labels: database, performance, simplicity
Variable variables
Friday, September 25, 2009
Since I'm not researching new things right now, due to my total lack of initiative, I'm gonna post something on things I already know which I believe to be useful.
Variables
To explain this, I need the reader to get into a certain state of mind.
To be brief, think of a variable as a cardboard box in which you put things. You can have many boxes like this, the "variable" thing about them being the name you give the box.
And that's what I'm gonna be working with here. Putting a box inside a box inside a box... and so on.
Variable variables
Which is a fancy name for what I said just now. Every variable has 2 basic things in common with all other variables:
A name, by which it can be identified. We need to know which box we need.
Content. You need to put something in the box(you can leave it empty if you want).
PHP example:
$number = 6;
echo $number //outputs 6 on the screen
Simple enough. Now watch this:
$a = 'test';
$$a = 'testing this test';
echo $test; // This will output: "testing this test"
You might be asking: "but where did the $test variable come from?"
That is what variable variables is all about.
To understand this, remember what I said earlier about "a box inside a box inside a box...". We have 2 dollar signs, so we have 2 boxes. Starting from left to right, you have the biggest and final box, then the box just a bit smaller, and so on, until you reach the last box. What happened is that I removed the smallest box and used its content to name the next box.
Note: You can't pick a random order. You can use an infinite amount of dollar signs(boxes), but when you're going to determine what the final variable will be, you have to start doing the replacement from right to left. The smallest box gets deleted first and it keeps going like that until you finally reach the biggest box.
I defined the variable $a = 'test';. So the content of $a is test
Since we removed a box, we have to remove a dollar sign and the variable-name connected to it. We then replace it with the content of that variable. And thus birth is given to the $test variable.
Note: The smart reader will have asked him/herself this already: "what happens if I do this with many variables, but in the middle of the line, there's a typo?"
To be honest, I'm not entirely sure. In PHP, an unknown variable is treated as an empty string. So if you make a typo somewhere and you get a reference to a variable that hasn't been created yet, it should be replaced with an empty string of text. That will probably create an error or a warning, I'm not sure. Either way, since the variable that you'll be calling in the end doesn't exist, that too will be replaced by an empty string of text.
Functions too
You can pull this trick with functions as well. How? Because functions are never preceded by dollar signs. If php sees the () signs, it knows there's a function. But what if this happens:
$function_name();
Well, the parser will assume there's a variable somewhere name "function_name". It will look up the content and replace it, same way you've witnessed before.
So if you have this:
function test() {
echo "hello world";
}
$function_name = 'test';
$function_name();//outputs "hello world"
The parser will look for a function called test(). Simple as that. And once again, you can keep going with this. The depth is unlimited(theoretically).
What do you use it for
You can do anything you want with it really.
Something I use this for is easy creation of variables to represent the content of database entries.
For instance, suppose you have a database table with these columns:
username | email | gender |age | married | number_of_children | street | province | etc
And you're viewing the profile of a single person. Image having to type all the variables. Seems normal? Now check this:
$vars = array('username','email','gender','age','married','number_of_children','street','province','etc');//or some function that calls the column names for you
foreach($vars as $var) {
$$var = $sql->getUserInfo($user_id,$var);//user_id to be obtained at some earlier point
}
A bunch of variables will be created for the specific user_id.
This principle becomes more and more useful with every extra column you need. If you have a function that can call all the columns of a certain table, you'll have the variables for all the columns you need (and those you don't need too, keep that in mind).
That's about all I have to say on the subject. Thanks for reading.
Posted by WebDevHobo at 10:42 PM 0 comments Links to this post
Labels: php
escaping characters in PHP
Monday, August 17, 2009
Recently this PHP function was introduced to me:
mysql_real_escape_string()
I hadn't heard of it before.
To escape strings, I'm used to using
addslashes()
I'm told that the difference in the mysql function is that it is dependent on the MySQL server settings.
I have a standard install on this machine, with no settings altered whatsoever. I decided to do a simple test, with all the characters my keyboard can produce:
$link = mysql_connect($dbhost, $dbuser, $dbpw);
mysql_select_db($dbname, $link);
$test = "|@#[^{}³1234567890°_-)àç!è§('\"é&²AZERTYUIOP¨*$^poiuytreza€[]£%MLKJHGFDSQqsdfghjklmùµ´`>WXCVBN?./+=:;,nbvcxw<\~";
echo addslashes($test);
echo mysql_real_escape_string($test);
The output for both functions is identical. Here's a screenshot:
Screenshot containing the output of both functions
I have no knowledge of extra settings that might influence the function. So I'm stumped. If anybody ever reads this and knows of a way to influence the behavior of this function, feel free to let me know.
Posted by WebDevHobo at 2:48 PM 4 comments Links to this post
Labels: mysql, php, string_escaping
Formchecking in PHP
Sunday, August 16, 2009
I recently asked a question on Stackoverflow
I was a bit confused over a concept in programming/web-development I had never seen before, which turned out to be "Abstraction". I was provided with some good answers.
Several people mentioned that my code didn't look like it was checked for errors pretty well. The post has some long answers and my original one got pretty long too, so I decided to elaborate here.
I should note that my native language is Dutch. Most variable names will be in dutch, though some resemble their English counter-part. Though I'll be re-writting some of it in English randomly.
register.php
The HTML of this page contains a hidden field with the name 'postback'.
<input type="hidden" name="postback" value="" />
<input type="submit" name="btnOk" id="btnOk" value="Register" />
<input type="reset" name="reset" value="Reset" />
In the source code, you'll find this:
if(isset($_REQUEST['postback'])) {
$allOk = true;
...
This is where the formchecking begins. What we were taught to do, let's leave whether this is a good or bad practice out of it for a second, is to control the input of every field for possible SQL injection, XSS and other stuff.
The basic idea is that the moment something bad is detected, the allOk variable is set to false and can never be set to true again.
Here are a couple of examples of SQL injections we got from our instructor:
admin'--
' OR 1=1--
' UNION SELECT 1, 'hackerX', 'letmein', 1--
' HAVING 1=1--
' GROUP BY users.id HAVING 1=1--
' GROUP BY users.id, users.login HAVING 1=1--
' UNION SELECT SUM(login) FROM users--
'; INSERT INTO users VALUES(666, 'hacker', 'letmein', 0xffff)--
' UNION SELECT @@version,'1','1','1'--
' UNION SELECT MIN(login),1,1,1 FROM users WHERE login>'a'--
' UNION SELECT MIN(login),1,1,1 FROM users WHERE login>'admin'--
' UNION SELECT password,1,1,1 FROM users WHERE login='admin'--
So how do I check my forms? The way I remember doing it most. And this is how:
Step 1
Using $_POST[], I make all the variables I need.
Example:
$naam = addPostSlashes($_POST['naam']);
$straat = addPostSlashes($_POST['straat']);
$paswoord = addPostSlashes($_POST['pasw']);
...
addPostSlashes() is a function that checks if the php.ini file has magic quotes enabled or not. If not it applies the addslashes() method and in the other case it's been done already.
I saw people mentioning the mysql_real_escape_string() function. I looked it up on PHP.net and compared it to the addslashes() method. The documentation itself doesn't show a lot of difference and some debugging didn't either, though I haven't tried the SQL injections yet. I doubt they'd have created mysql_real_escape_string() if it does the exact same thing as an existing function.
Part 2 - Regular Expressions
I use a couple of regular expressions to test the variables.
$rexSafety = '/^[^<,"@$?=>|;#]+$/i';
$rexMail = '/^[a-z0-9\._]+@([a-z0-9-_]+\.)+[a-z]{2,3}$/i';
I'd like to mention that the Regular Expressions you see here have been tested and work. The only tiny problem I'm having is with the first one, which doesn't seem to allow empty strings. Which can be a pain for non-required fields in a registration form.
The first one is used as follows:
if(!preg_match($rexSafety,stripslashes($naam))){
$allOk = false;
$naamError = ' please don\'t use < , @ # - > $ ; = | or "';
}
I'm checking if any of these characters are present in the received string and if there is even one, the entire registration gets canceled. Next to the field where the error was found appears a message explaining what went wrong to the user. In this case, asking to please not use any of the following characters.
Rest assured, a potential customer accidentally filling in something wrong won't have to re-write the whole thing. The page is reloaded not only with the explanations, but also has all the previously entered text in the correct place, with the exception of passwords not being reloaded.
Thinking about this, I realize that anyone with a @ in their password is gonna be pretty miffed at me for doing this. As far as I'm aware, you can't escape a @ or a # sign and they can both be used in SQL injection. Please correct me if I'm wrong. And should you do so, please refrain from such comments as: "what a horrible piece of coding" and other such comments. I'm here to learn, not to get insulted.
Part 3 - All Ok!
Once everything is checked and no errors are found, I call upon the SQL class and the User class. They respectively represent the SQL actions I want to perform and the actions on the User I wish to perform. I should perhaps mention that the register.php file has a require statement for both classes at the top of the file.
So this happens:
$sql = new SqlObject();
$newUser = new User('',$naam,sha1($passw),...);
$sql->addUser($newUser);
All of those are escaped. Just have to remember it's all stored with escaped characters, as to make sure logging in works.
Let's look at an example of what the User.class.php file looks like:
<?php
class User {
// members
var $id;
var $name;
var $password;
// constructor
function User($id=-1,$name='',$password='') {
$this->id = $id;
$this->name = $name;
$this->password = $password;
}
}
?>
This is shortened, but you get the general idea I hope.
The SQL class has
require "User.class.php";
written on the first line, which enables it to use instances of the User class.
Which brings us to the addUser() function:
function addUser($user){
$insQuery = 'INSERT INTO users(naam,paswoord,...)';
$insQuery.= " VALUES ('".$user->naam."', '".$user->paswoord."')";
@mysql_query($insQuery) or showError("user insert failed");
}
I highly doubt this but I'll mention it anyway: the ... are meant to indicate more fields, not actual input.
So that's how we've been taught to do it. That is to say, we were shown the basics and were allowed to choose our own way of implementing it.
I read the term "prepared statement" a few times. I looked it up and it looks interesting enough.
To answer Mr. Vinko's example: the string John O'Donell will be entered into the database as John O\'Donell, that is true. Your concern seems to be that the escaping of the characters should happen at the insertion, and not during the checking for SQL injections(and similar stuff). To be honest, I've never considered doing this, because of the simple reason that it's not the way I did it the first time I did this type of formchecking. The fact that it worked, was enough for me untill now. This whole ordeal has gotten me thinking, and I'm beginning to believe I'm mixing up a few things.
EDIT:
I read all the things most of you said and it's starting to make sense. I can divide it all into 2 basic steps now
Check for faulty input/possible injections without escaping anything
If everything checks out, send it to the PHP that handle database insertion and escape it there.
That's what I think this all comes down to. I hope I got it right this time...
I hope this wasn't too long and I realise this was more of an explanation to certain people than a proper blog entry, but I did what I said I'd be doing when I made my first post on this blog: learning. If anyone has any pointers or tips on the subject of formchecking or prepared statements, feel free to tell me.
Though if you choose to do so, please don't say stuff like "That's a bad practice, the way I do it is better!" and the walk off without even offering an example. If you're gonna say I'm wrong or it could be better, then take the time to prove it. Offer me a good reasoning and I will listen/read. I'm not the kind of guy who sticks to what he believes no matter what for fear of new things, I just hope the rest of you out there aren't either.
Posted by WebDevHobo at 10:51 PM 0 comments Links to this post
Labels: formchecking, php, sql, sql injection