PHP
PHP Flaws
You saw it, you learned it, you programmed it, it’s everywhere. Well, I’m not talking about a Microsoft product, it is PHP.
Are you annoyed by the error messages of PHP? When something wrong happened, an error message will show up, which may break the HTML being generated. To remove the error messages, you must add error_reporting(0) in front of the code, or it won’t be portable. Talking about portability… PHP is a configurable programming language. The configuration makes PHP code must detect the configurations and perform actions based on it.
Can you imagine of the php.ini setting default_php_mode exists? By turning on default_php_mode, you can start writing PHP code without , for example:
include 'header.php' ?> <!DOCTYPE html> <html> <head> ......
You won’t be able to use PHP code to detect it. Of course, that configuration does exist, for good.
Magic quotes, originally used to help newbie programmers in security, made a hassle for experienced programmers and PHP5 newbies. You must add a boilerplate code like this
<?php
if (get_magic_quotes_gpc()) {
$_REQUEST = array_map('stripslashes', $_REQUEST);
$_GET = array_map('stripslashes', $_GET);
$_POST = array_map('stripslashes', $_POST);
$_COOKIE = array_map('stripslashes', $_COOKIE);
}
?>
to make sure the text that will be used in database queries will not be quad-slashed (like 'text here \\\\').
The flags are bad. I hate these things like file_put_contents('file.txt', 'Hello corrupted world', FILE_APPEND); preg_match($pattern, $subject, $matches, PREG_OFFSET_CAPTURE, 3);. Also, some functions use array references, for example, preg_match($pattern, $subject, $matches, PREG_OFFSET_CAPTURE, 3); will modify the variable $matches. It should be done like:
<?php
try {
$matches = preg_match_offset_capture($pattern, $subject, 3);
} catch (PregException $e) {
$matches = array();
}
?>
The variable scoping may confuse the newbie PHP programmers who had programming experience on other programming languages such as JavaScript. You can’t access global variables in the function scope. You must use $GLOBALS or global $g_variable. It’s a huge hassle.
Here is an example of PHP global variables:
<?php
$x = 0;
function f($n) {
$x += $n; // wrong, not accessing global $x
}
function g($n) {
global $x; // right
$x += $n;
}
function h($n) {
$GLOBALS['x'] += $n; // right
}
?>
Maybe you know, or maybe you don’t. There are alternative syntaxes for if and the for blocks.
<?php if ($x): else: endif; foreach ($a as $b): endforeach; ?>
Some people will use the brace syntax, and some people will use that alternative syntax, which will cause inconsistency in large coding projects. The alternative syntaxes should be removed.
Most low-class Web developers who do not know PHP, copy and paste small scripts from large script repositories, like copying full of JavaScript from DynamicDrive for vanity proposes. Because PHP attracts low-class developers, the syntax of PHP became messy to meet the needs for the low-class developers, then, more low-class developers will be attracted.
PHP needs a revolution. The revolution will change the PHP syntax to something clean, ECMAScript syntax could be fair. Yes, do break the backward compatibility, too much backward compatibility cause problems. If PHP revolution won’t start… <%= "Hello Ruby on Rails world!" %>
HTTP and HTML Forms
Before start learning PHP or other server-side scripting languages, you must know how do the browser and server transmit information over the HTTP (HyperText Transfer Protocol) and how the form data are extracted.
When you typed a HTTP URL into the address bar, for example, http://www.example.com/index.html . The browser will send a request to www.example.com over your computer’s network. The request will contain many headers telling the browser’s information and which page to request. The request will look like this:
GET /index.html [The browser wants the page index.html] Host: www.example.com [The hostname on the address bar] User-Agent: Mozilla/10.0 Firefox 5.2.5 [Your browser's identifier] Accept: text/html [Your browser is looking for text/html (HTML) document] Cookie: AAA=BBB; CCC=DDD; [Your cookies]
Then the server will parse the request and respond with the content of the page.
HTTP/1.1 200 OK [200 OK means the request is successful] Date: Tue, 15 Nov 1994 08:12:31 GMT [Time on the server] Content-Type: text/html [The type of the document, text/html is the MIME type for HTML] [After one empty line, the content of the page is outputted] <html><head><title>Example Web page</title></head> [......]
Please note that the [bracketed text] are explanations I added.
There are many more HTTP headers, I’m not going to teach you all of them, you can read more at http://en.wikipedia.org/wiki/List_of_HTTP_headers.
When you submitted a HTML form, some additional information will be added to request headers. There are two (and some rare ones such as PUT and DELETE) types of HTTP requests, GET and POST. When you clicked “Search” on Google, you will send a GET request to Google’s server and you will be taken to a result page. You can bookmark the result page, and the search query will appear in the URL (look at the address bar: “http://www.google.com/search?hl=en&q=SEARCH QUERY STRING“), that means the search form’s values appeared in the URL.
POST request is different. The form values do not show up on the URL. Instead, they show up inside the headers. You cannot bookmark a form result of a POST form. Normally, GET requests are used for GETting something, such as searching. Side effects, such as registration, purchase, transaction are sent as POST requests. If you submitted a POST form and you tried to refresh the page, the browser will say “Re-submit form data?”. If you clicked Yes, you will re-purchase something, performed a transaction twice, or anything else.
The form’s method is determined by the <form>’s method attribute, and the form’s target is determined by the action attribute. Set action to “#” if the target of the form is the form itself. Here is an example registration form.
<!-- Starts a new HTML form. The method is POST because a registration is a side effect, and you don't bookmark a registration form result. --> <form action="register.php" method="POST"> <div> <!-- A text field, its name, its value will be sent to the server under the name of 'username'. so the server will access it like $_POST['username'], Request.post['username'] depending on the type of the server software. --> Username: <input type='text' name='username' value='' /><br /> <!-- A password field that does not show up what the user typed. (it will only show "*********") A password field acts like a text field. --> Password: <input type='password' name='password' /><br /> <!-- A radio button. the name will determine the radio button group. The value will determine the value to be sent when it was selected. The checked attribute tells the browser if it should be selected by default. --> Gender: <input type='radio' name='gender' value='male' checked='checked'> Male <input type='radio' name='gender' value='female'> Female<br /> <!-- Submit button submits the form (duh) --> <input type='submit' value='Submit' name='Submit' /> <!-- There are many other types of form controls, such as drop-down, image buttons, lists, they all have a name and value attribute. Please go back to the HTML tutorial you've read to learn more about other form controls. --> </div> </form>
The form values will be included in the request, and the server will read it and take action. It will either register you, or send you back and show an error message.
Here is a pseudocode that will show how the server will handle the form.
// Request.post is all values from a POST request.
// check if the submit button was clicked. (the button's name is 'Submit')
if (Request.post.has('Submit')) {
// validate form
if (!(Request.post.has('username') || Request.post.has('password') || Request.post.has('gender'))) {
output ('<p>You must fill ALL form fields correctly.</p>');
} else {
// register user
registerUser(Request.post['username'], Request.post['password'], Request.post['gender']);
output ('You are registered.')
}
}
Cookies are used to store information to the browser (and they will be read by the server). On Google.com, you can click “Preferences” to change the search preferences, then, the preferences will be saved to your browser (only if cookies are enabled in your browser). The cookies are passed to the server by the Cookie HTTP header and the server will send the Set-Cookie HTTP header to tell the browser to set the cookie. Cookies can expire, determined by the expiry date when the cookie was set.
When you log in to a website, what keeps you logged in? Cookies. The server tells the browser to set the cookie containing the login information or session identifier to keep you logged in. On most login-enabled sites, there is a “Remember Me” option. Most of the sites will make the cookie never expire if you choose “Remember Me”.
Last day of April
This is the last day of April. In my place, it is 8:00 AM, before I’m going to school.
I wrote a PHP script that generates O’Reilly book covers, because I’ve seen many spoofs of it.
You can see it at http://uniteduniversemainsite.freehostia.com/files/covergenerator.php?
Here is the source code.
<?php
error_reporting(0);
if (isset($_REQUEST['submit'])) {
foreach ($_REQUEST as &$value) {
$value = htmlentities($value);
}
echo <<<EOF
<!DOCTYPE html>
<html lang="en">
<head>
<title>{$_REQUEST['title']}</title>
<style type="text/css" media="all">
div {
margin: 0;
padding: 0;
overflow: hidden;
}
#top, #msubtitle, #bright {
font-size: 0.18in;
font-family: "Times New Roman", Times, serif;
font-style: italic;
text-transform: capitalize;
}
#book {
width: 5in;
height: 6in;
border: 1px solid black;
page-break-inside: avoid;
size: portrait;
}
#top {
text-align: center;
height: 0.4in;
margin-left: 0.5in;
margin-right: 0.5in;
width: 4in;
}
#tbar {
background-color: #3388AA;
height: 0.1in;
}
#middle {
height: 5.25in;
}
#imagebox {
padding-left: 0.5em;
height: 3in;
width: 4.5in;
text-alighn right;
vertical-align: bottom;
}
#mimage {
min-height: 3in;
max-height: 3in;
max-width: 4.5in;
float: right;
}
#mtitle {
height: 1.5in;
margin-left: 0.5in;
margin-right: 0.5in;
padding: 0.05in 0in 0in 0.05in;
background-color: #3388AA;
font-size: 0.65in;
font-family: "Times New Roman", Times, serif;
color: white;
}
#msubtitle {
text-align: right;
margin-right: 0.5in;
font-size: 0.2in;
}
#bottom {
height: 0.3in;
}
#bleft, #bright {
display: inline;
padding-left: 0.1in;
padding-right: 0.1in;
}
#bleft {
font-weight: bold;
font-family: "Times New Roman", Times, serif;
font-size: 0.2in;
float: left;
}
#bright {
float: right;
}
</style>
</head>
<body>
<div id="book">
<div id="top">
<div id="tbar"></div>
<div id="ttitle">{$_REQUEST['toptitle']}</div>
</div>
<div id="middle">
<div id="imagebox">
<img src="{$_REQUEST['image']}" alt="" id="mimage" />
</div>
<div id="mtitle">{$_REQUEST['title']}</div>
<div id="msubtitle">{$_REQUEST['subtitle']}</div>
</div>
<div id="bottom">
<div id="bleft">{$_REQUEST['publisher']}</div>
<div id="bright">{$_REQUEST['author']}</div>
</div>
</div>
</body>
</html>
EOF;
} else {
?>
<!DOCTYPE html>
<html lang="en">
<head>
</head>
<body>
<div id="root">
<form method="post" action="?">
<div id="form">
<label for="title">
Title:
<input type='text' id='title' name='title' value='Lorem Ipsum' />
</label>
<br />
<label for="subtitle">
Sub-title:
<input type='text' id='subtitle' name='subtitle' value="Lorem ipsum dolor sit amet, consectetur adipiscing elit. " />
</label>
<br />
<label for="toptitle">
Top Title:
<input type='text' id='toptitle' name='toptitle' value="Nonsense that you don't understand. " />
</label>
<br />
<label for="image">
Image:
<input type='text' id='image' name='image' value="http://dss.ucar.edu/staff/davestep/camel.tr.gif" />
</label>
<br />
<label for="publisher">
Publisher:
<input type='text' id='publisher' name='publisher' value="O'RLY" />
</label>
<br />
<label for="author">
Author:
<input type='text' id='author' name='author' value='Lorem Ipsum' />
</label>
<br />
<input type='submit' value='Submit' name='submit' />
</div>
</form>
</div>
</body>
</html>
<?php
}
?>
Canvas Chat
Recently, I created a new PHP application, it is like a chat room, but you can send images instead of text.
To download the source code: http://www.mediafire.com/download.php?jgm2yn2qt5z.
To try it online, go to http://www.eeveeshq.com/canvaschat/, Kat uploaded it to her site, but that one is a custom build with integration to her website, so you need to register Eevee’s HQ to use it.
I originally posted in on Eevee’s HQ, and someone spammed it, at last, Nick said he did it.
asked Kat about it, In the next day, Kat said she was joking around.
YouTube is getting worse, big companies such as Disney were trying to make advertisement videos more visible on YouTube, YouTube is not for you, it is for THEM.
Let’s use Veoh.com if YouTube is getting bad.
PHP Math Expression Parser
I created a math expression parser that evaluates math expressions and functions such as “variable = 42 * (34 + 52 – sqrt(variable + 3))”.
<?php
/**
* A math expression parser, supports:
* <ol>
* <li>add, subtract, multiply and division</li>
* <li>brackets grouping</li>
* <li>functions, custom functions' prefix can be customized.</li>
* <li>variables</li>
* </ol>
* Does not support:
* <ol>
* <li>bitwise/logical operators.</li>
* <li>if/else/for statements</li>
* <li>arrays</li>
* </ol>
* Depends on BCMath library to gain arbitrary precision features.<br />
* BNF Grammar (quotes strings and ALL CAPs are terminals):
* <pre>
* expression ::= ( IDENT '=' expression | addexpr )
* addexpr ::= term ( ( '+' | '-' ) term )*
* term ::= primary ( ( '*'|'/' ) primary )*
* primary ::= ( NUMBER | IDENT | '(' expression ')' | IDENT ( '(' expression (',' expression)* ')' | '(' ')' ) )
* </pre>
* This class implements ArrayAccess, so <code>$expr['name']</code> will access variable <code>name</code>.
* To evaluate an expression, use the <code>evaluate(string $expr)</code> method.
* To set percision, use <code>bcscale(int $scale)</code> function.
* Example usage: <code>$expr = new Expression(); $expr->evaluate('a = 12 + 5'); echo $expr['a']; //prints 17</code>
* @author SpaceMan
* @version 1.0
*/
class Expression implements ArrayAccess {
private $tokens = array();
private $expr = '';
/**
* @var array List of all variables.
*/
public $variables = array();
/**
* @var string Prefix of all custom functions, for example, <code>sqrt(10)</code> will map
* to <code>bcsqrt(10)</code> if the prefix is <code>bc</code>.
*/
public $prefix = 'bc';
/**
* Constructs a new Expression object.
* @param string $expr The initial expression to be evaluated.
*/
public function __construct($expr = '') {
$this->expr = $expr;
}
/**
* Evaluates an expression.
* @param string $expr The expression to be evaluated.
* @return string The result in string of numbers.
*/
public function evaluate($expr) {
$this->expr = $expr;
$this->tokenize();
return $this->expression();
}
public function offsetSet($offset, $value) {
$this->variables[$offset] = $value;
}
public function offsetExists($offset) {
return isset($this->variables[$offset]);
}
public function offsetUnset($offset) {
unset($this->variables[$offset]);
}
public function offsetGet($offset) {
return isset($this->variables[$offset]) ? $this->variables[$offset] : null;
}
/**
* Tokenize the expression.
* @internal
*/
private function tokenize() {
$expr = $this->expr;
$i = 0;
$c = " ";
//while there are more string to be tokenized
while ($c) {
//exit if there are no more string.
if ($i >= strlen($expr)) {
return;
}
//the code to be scanned
$c = substr($expr, $i);
if (preg_match('/^\d+(\.\d+)?/', $c, $matches, PREG_OFFSET_CAPTURE)) {
//numbers
$i += strlen($matches[0][0]);
array_push($this->tokens, array('NUMBER', $matches[0][0]));
} else if (preg_match('/^[A-Za-z0-9_]+/', $c, $matches, PREG_OFFSET_CAPTURE)) {
//variables
$i += strlen($matches[0][0]);
array_push($this->tokens, array('IDENT', $matches[0][0]));
} else if ($c[0] == ' ' or $c[0] == '\t' or $c[0] == '\r' or $c[0] == '\n') {
//whitespaces
$i ++;
} else {
//operators
array_push($this->tokens, array($expr[$i], $expr[$i]));
$i ++;
}
}
}
/**
* Determines if the next token exists.
* This function takes multiple arguments.
* @internal
*/
private function has() {
$t = $this->tokens[0];
foreach (func_get_args() as $name) {
if ($t[0] == $name) {
return true;
}
}
return false;
}
/**
* Consume the next token.
*/
private function token() {
return array_shift($this->tokens);
}
/**
* Calls a function.
* @internal
*/
private function call($name, $values = array()) {
return eval('return ' . $this->prefix . $name . '(' . implode(',', $values) . ');');
}
private function primary() {
if ($this->has('NUMBER')) {
//numbers
$t = $this->token();
return $t[1];
} else if ($this->has('-')) {
//negative numbers
$this->token();
return -$this->primary();
} else if ($this->has('(')) {
//brackets
$this->token();
$v = $this->expression();
$this->token();
return $v;
} else if ($this->has('IDENT') && $this->tokens[1][0] == '(') {
//function call
$name = $this->token();
$name = $name[1];
$this->token();
$args = array();
if ($this->has(')')) {
//zero arguments
return $this->call($name);
} else {
//one or more arguments
$args[] = $this->expression();
while ($this->has(',')) {
$this->token();
$args[] = $args[] = $this->expression();
}
$v = $this->call($name, $args);
$this->token();
return $v;
}
} else if ($this->has('IDENT')) {
//get variable
$t = $this->token();
return $this->variables[$t[1]] or '0';
} else {
throw new RuntimeException('Syntax error.');
}
}
private function term() {
$v = $this->primary();
while ($this->has('*', '/')) {
$op = $this->token();
$right = $this->primary();
switch ($op[0]) {
case '*':
$v = bcmul($v, $right);
break;
case '/':
$v = bcdiv($v, $right);
break;
default:
throw new RuntimeException('Invalid operator, expection "*" or "/".');
}
}
return $v;
}
private function addexpr() {
$v = $this->term();
while ($this->has('+', '-')) {
$op = $this->token();
$right = $this->term();
switch ($op[0]) {
case '+':
$v = bcadd($v, $right);
break;
case '-':
$v = bcsub($v, $right);
break;
default:
throw new RuntimeException('Invalid operator, expection "+" or "-".');
}
}
return $v;
}
private function expression() {
if ($this->has('IDENT') and $this->tokens[1][0] == '=') {
$left = $this->token();
$left = $left[1];
$this->token();
$right = $this->expression();
$this->variables[$left] = $right;
return $right;
} else {
return $this->addexpr();
}
}
}
?>
To use it, include that file and create a new Expression object, then call the evaluate($expr) to evaluate expressions.
An example usage:
<?php
include ('expression.php');
$expr = new Expression();
$expr['variablename'] = 12; //pre-define a variable inside the object
echo $expr->evaluate($_GET['expression']);
echo 'The variable variablename is: ' . $expr['variablename'];
//to set a prefix for custom functions
$expr->prefix = 'myfuncs_';
?>
My Sites
Other Blogs
Twitter Updates
Tags
Recent Comments
- Pinoytech on Chrome OS Leaked
- Acchan on PHP Flaws
- admin on Finished Moving
- Calvin on Finished Moving
- admin on Colony
| M | T | W | T | F | S | S |
|---|---|---|---|---|---|---|
| « Oct | ||||||
| 1 | 2 | 3 | 4 | 5 | 6 | 7 |
| 8 | 9 | 10 | 11 | 12 | 13 | 14 |
| 15 | 16 | 17 | 18 | 19 | 20 | 21 |
| 22 | 23 | 24 | 25 | 26 | 27 | 28 |
| 29 | 30 | 31 | ||||
Categories
Creative Commons License