Apache Error Codes
With the function below you can add your own custom actions to error statuses of Apache.
Lets say you want a custom 404 error page. You could redirect a user upon a 404 error or show a complete different layout.
/** * HTTP Protocol defined status codes * @param int $num */ function HTTPStatus($num) { static $http = array ( 100 => "HTTP/1.1 100 Continue", 101 => "HTTP/1.1 101 Switching Protocols", 200 => "HTTP/1.1 200 OK", 201 => "HTTP/1.1 201 Created", 202 => "HTTP/1.1 202 Accepted", 203 => "HTTP/1.1 203 Non-Authoritative Information", 204 => "HTTP/1.1 204 No Content", 205 => "HTTP/1.1 205 Reset Content", 206 => "HTTP/1.1 206 Partial Content", 300 => "HTTP/1.1 300 Multiple Choices", 301 => "HTTP/1.1 301 Moved Permanently", 302 => "HTTP/1.1 302 Found", 303 => "HTTP/1.1 303 See Other", 304 => "HTTP/1.1 304 Not Modified", 305 => "HTTP/1.1 305 Use Proxy", 307 => "HTTP/1.1 307 Temporary Redirect", 400 => "HTTP/1.1 400 Bad Request", 401 => "HTTP/1.1 401 Unauthorized", 402 => "HTTP/1.1 402 Payment Required", 403 => "HTTP/1.1 403 Forbidden", 404 => "HTTP/1.1 404 Not Found", 405 => "HTTP/1.1 405 Method Not Allowed", 406 => "HTTP/1.1 406 Not Acceptable", 407 => "HTTP/1.1 407 Proxy Authentication Required", 408 => "HTTP/1.1 408 Request Time-out", 409 => "HTTP/1.1 409 Conflict", 410 => "HTTP/1.1 410 Gone", 411 => "HTTP/1.1 411 Length Required", 412 => "HTTP/1.1 412 Precondition Failed", 413 => "HTTP/1.1 413 Request Entity Too Large", 414 => "HTTP/1.1 414 Request-URI Too Large", 415 => "HTTP/1.1 415 Unsupported Media Type", 416 => "HTTP/1.1 416 Requested range not satisfiable", 417 => "HTTP/1.1 417 Expectation Failed", 500 => "HTTP/1.1 500 Internal Server Error", 501 => "HTTP/1.1 501 Not Implemented", 502 => "HTTP/1.1 502 Bad Gateway", 503 => "HTTP/1.1 503 Service Unavailable", 504 => "HTTP/1.1 504 Gateway Time-out" ); header($http[$num]); } ?>
You can download this 404 error page example to play with.
PHP Performance – isset() versus empty() versus PHP Notices
I’m cleaning up a lot of PHP code and always program with PHP error_reporting set to E_ALL and display_errors turned on so that I make sure to catch any PHP messages that come up. Since starting on this site, I have fixed literally hundreds (maybe thousands) of PHP Notices about using uninitialized variables and non-existent array indexes.
I have been fixing problems like this where $somevar is sometimes undefined:
if ($somevar)
by changing it to:
if (isset($somevar) && $somevar)
This successfully gets rid of the NOTICEs, but adds some overhead because PHP has to perform two checks. After fixing a lot of this in this manner, I’ve noticed that the pages seem to be generated a little slower.
So, to provide some conclusive results to myself, I wrote up a quick benchmarking script - available at php_empty_benchmark.php. It goes through 1,000,000 tests using each of these methods:
- if ($a) - This generates a notice if $a is not set
- if (isset($a)) - A simple clean way to check if the variable is set (note that it is not equivalent to the one above)
- if (isset($a) && ($a) - The one that I have been using which is equivalent to if($a), but doesn’t generate a notice.
- if (!empty($a)) - This is functionally equivalent to if($a), but doesn’t generate a notice.
It measures the time to perform 1 million tests using a defined percentage of values that are set. It then computes the difference as a percentage of the time taken for the original test (the one that generates the notices). A ‘diff’ of 100 means that the execution time is the same, greater than 100 means that it is faster, and less than 100 means that it is slower. A typical test produced these results:
With NOTICE: 0.19779300689697 With isset: 0.19768500328064 / Diff: 100.05463419811 With both: 0.21704912185669 / Diff: 91.128222590815 With !empty: 0.19779801368713 / Diff: 99.997468735875
In summary, using the if (isset($a) && $a) syntax is about 8-10% slower than generating the PHP Notice. Using !empty() should be a drop-in replacement that doesn’t generate the notice and has virtually no performance impact. Using ifset() also has no performance impact, but is not exactly the same as ‘if($a)’ since isset() will return true if the variable is set to a false value. I included it here, because it often make the code a little more readable than the !empty($a) syntax. For example:
$myvalue = !empty($_REQUEST['myvalue']) ? $_REQUEST['myvalue'] : '';
Versus
$myvalue = isset($_REQUEST['myvalue']) ? $_REQUEST['myvalue'] : '';
Source:
http://www.brandonchecketts.com/archives/php-performance-isset-versus-empty-versus-php-notices
How to check if a key exists in an array with in_array for Bash
When working with Bash it might become handy to have a way to check if a record exists in an array. In PHP you have in_array for this... The below code adds a function similar to the PHP variant.
function in_array() { local x ENTRY=$1 shift 1 ARRAY=( "$@" ) [ -z "${ARRAY}" ] && return 1 [ -z "${ENTRY}" ] && return 1 for x in ${ARRAY[@]}; do [ "${x}" == "${ENTRY}" ] && return 0 done return 1 } MASTER=() CURRENT=() FIRST=1 for SERVER in ${SERVERS}; do # collect all builds from server and populate CURRENT list COMMAND="${LS} -1fd ${WEBROOT}/${SITE}.*" BUILDS=`${SSH} ${SSHOPTS} root@${SERVER} "${COMMAND}"` for BUILD in ${BUILDS}; do CURRENT=( ${CURRENT[@]-} ${BUILD} ) done # if this is our first time around, copy CURRENT to MASTER if [ ${FIRST} -eq 1 ]; then MASTER=( ${CURRENT[@]} ) FIRST=0 fi # now we do a compare between MASTER and CURRENT to see what builds # are common INTERSECT=() for ENTRY in ${CURRENT[@]}; do in_array "${ENTRY}" "${MASTER[@]}" RET=$? if [ "${RET}" -eq 0 ]; then INTERSECT=( ${INTERSECT[@]-} ${ENTRY} ) fi done MASTER=( ${INTERSECT[@]} ) # clear the CURRENT array CURRENT=() done
Source: http://mykospark.net/tag/in_array/
How to modify HTTP headers with PHP header() function
Many examples that show how to use the header() function of PHP.
Hint:
If you want to check your headers, you can use web based tools like: web-sniffer.net, web-browser extensions (e.g. LiveHTTPHeaders, ieHTTPHeaders) or another third-party software tool.
// See related links for more status codes // Use this header instruction to fix 404 headers // produced by url rewriting... header('HTTP/1.1 200 OK'); // Page was not found: header('HTTP/1.1 404 Not Found'); // Access forbidden: header('HTTP/1.1 403 Forbidden'); // The page moved permanently should be used for // all redrictions, because search engines know // what's going on and can easily update their urls. header('HTTP/1.1 301 Moved Permanently'); header('Location: ' . $url); exit(); // Server error header('HTTP/1.1 500 Internal Server Error'); // Redirect to a new location: header('Location: http://www.example.org/'); // Redriect with a delay: header('Refresh: 10; url=http://www.example.org/'); print 'You will be redirected in 10 seconds'; // you can also use the HTML syntax: // <meta http-equiv="refresh" content="10;http://www.example.org/ /> // override X-Powered-By value header('X-Powered-By: PHP/4.4.0'); header('X-Powered-By: Brain/0.6b'); // content language (en = English) header('Content-language: en'); // last modified (good for caching) $time = time() - 60; // or filemtime($fn), etc header('Last-Modified: '.gmdate('D, d M Y H:i:s', $time).' GMT'); // header for telling the browser that the content // did not get changed header('HTTP/1.1 304 Not Modified'); // set content length (good for caching): header('Content-Length: 1234'); // Headers for an download: header('Content-Type: application/octet-stream'); header('Content-Disposition: attachment; filename="example.zip"'); header('Content-Transfer-Encoding: binary'); // load the file to send: readfile('example.zip'); // Disable caching of the current document: header('Cache-Control: no-cache, no-store, max-age=0, must-revalidate'); header('Expires: Mon, 26 Jul 1997 05:00:00 GMT'); // Date in the past header('Pragma: no-cache'); // set content type: header('Content-Type: text/html; charset=iso-8859-1'); header('Content-Type: text/html; charset=utf-8'); header('Content-Type: text/plain'); // plain text file header('Content-Type: image/jpeg'); // JPG picture header('Content-Type: application/zip'); // ZIP file header('Content-Type: application/pdf'); // PDF file header('Content-Type: audio/mpeg'); // Audio MPEG (MP3,...) file header('Content-Type: application/x-shockwave-flash'); // Flash animation // show sign in box header('HTTP/1.1 401 Unauthorized'); header('WWW-Authenticate: Basic realm="Top Secret"'); print 'Text that will be displayed if the user hits cancel or '; print 'enters wrong login data';
Source: http://www.jonasjohn.de/snippets/php/headers.htm
Related links:
http://en.wikipedia.org/wiki/List_of_HTTP_status_codes
http://www.web-caching.com/mnot_tutorial/
http://reeg.junetz.de/DSP/node16.html
How to generate a .htaccess and .htpasswd with PHP
Ever had a moment where you needed to secure a directory but didn't have the htpasswd tool available?
The following script simply generates a .htaccess and .htpasswd file to secure a directory.
<!DOCTYPE html> <html> <body> <?php if (!empty($_POST['username']) && !empty($_POST['password'])): ?> <strong>.htaccess</strong><br> <pre> AuthName "Members only" AuthType Basic AuthUserFile /srv/www/domain.tld/.htpasswd require valid-user </pre> Save the above file in the directory you want to secure.<br> <br> <strong>.htpasswd</strong><br> <pre> <?php echo $_POST['username'] . ':' . crypt($_POST['password'], base64_encode($_POST['password'])); ?> </pre> Save the above file as <strong>/srv/www/domain.tld/.htpasswd</strong>.<br> <br> <a href="<?php echo $_SERVER['PHP_SELF']; ?>">« BACK «</a> <?php else: ?> <form method="post"> Username: <input type="text" name="username"><br> Password: <input type="text" name="password"><br> <input type="submit"> </form> </form> <?php endif; ?> </body> </html>
How to generate a Windows Live Messenger or MSN Messenger contactlist file with PHP
If you would like to generate a contact list with PHP to import email addresses into your contact list use the following...
PHP contactlist generator
mysql_connect('localhost', 'username', 'password'); mysql_select_db('database'); $doc = new DOMDocument('1.0'); $doc->formatOutput = true; $node = $doc->createElement('messenger'); $messenger = $doc->appendChild($node); $node = $doc->createElement('service'); $node->setAttribute('name', '.NET Messenger Service'); $service = $messenger->appendChild($node); $node = $doc->createElement('contactlist'); $contactlist = $service->appendChild($node); $result = mysql_query("SELECT `email` FROM `contacts`"); while ($data = mysql_fetch_assoc($result)) { $node = $doc->createElement('contact', $data['email']); $contactlist->appendChild($node); } header('Content-type: text/xml'); header('Content-Disposition: attachment; filename=contacts.xml'); echo $doc->saveXML();
Output
<?xml version="1.0"?> <messenger> <service name=".NET Messenger Service"> <contactlist> <contact>email1@domain.tld</contact> <contact>email2@domain.tld</contact> <contact>email3@domain.tld</contact> <contact>email4@domain.tld</contact> <contact>email5@domain.tld</contact> </contactlist> </service> </messenger>
Some useful information about PHP RegEx
This information can be handy with the following PHP functions:
* preg_filter
* preg_grep
* preg_last_error
* preg_match_all
* preg_match
* preg_quote
* preg_replace_callback
* preg_replace
* preg_split
What is a regex?
At its most basic level, a regex can be considered a method of pattern matching or matching patterns within a string. In PHP the most oft used is PCRE or "Perl Compatible Regular Expressions". Here we will try to decypher the meaningless hieroglyphics and set you on your way to a powerful tool for use in your applications. Do not try to understand all this in a single sitting. Instead, take in a little and come back as you grasp various concepts.
Where do I begin?
At the beginning.
Lets create a string.
<?php // create a string $string = 'abcdefghijklmnopqrstuvwxyz0123456789'; // echo our string echo $string; ?>
If we simply wanted to see if the pattern 'abc' was within our larger string we could easily do something like this:
<?php // create a string $string = 'abcdefghijklmnopqrstuvwxyz0123456789'; echo preg_match("/abc/", $string); ?>
The code above will echo '1'. This is because it has found 1 match for the regex. That means it has found the pattern 'abc' once in the larger string. [[http://www.php.net/preg-match|preg_match()]] will count zero if there is no matches, or one if it finds a match. This function will stop searching after the first match. Of course, you would not do this in a real world situation as php has functions for this such as [[http://www.php.net/strpos|strpos()]] and [[http://www.php.net/strstr|strstr()]] which will do this much faster.
Match beginning of a string
Now we wish to see if the string begins with abc. The regex character for beginning is the caret ^. To see if our string begins with abc, we use it like this:
<?php // create a string $string = 'abcdefghijklmnopqrstuvwxyz0123456789'; // try to match the beginning of the string if(preg_match("/^abc/", $string)) { // if it matches we echo this line echo 'The string begins with abc'; } else { // if no match is found echo this line echo 'No match found'; } ?>
From the code above we see that it echo's the line ''The string begins with abc''. The forward slashes are a delimeter that hold our regex pattern. The quotations are used to 'wrap it all up'. So we see that using the caret(^) will give us the beginning of the string, but NOT whatever is after it.
What if I want case insensitive?
If you used the above code to find the pattern ABC like this:
if(preg_match("/^ABC/", $string))
the script would have returned the message:
No match found
This is because the search is case sensitive. The pattern 'abc' is not the same as 'ABC'. To match both 'abc' and 'ABC' we need to use a modifier to make the search case in-sensitive. With php regex, like most regex, is use 'i' for insensitive. So now our script might look like this:
<?php // create a string $string = 'abcdefghijklmnopqrstuvwxyz0123456789'; // try to match our pattern if(preg_match("/^ABC/i", $string)) { // echo this is it matches echo 'The string begins with abc'; } else { // if not match is found echo this line echo 'No match found'; } ?>
Now the script will find the pattern abc. It would also match any case in-sensitive combination of abc, ABC, Abc, aBc, and so on.
More on [[http://php.net/manual/en/reference.pcre.pattern.modifiers.php|modifiers]] later.
How do I find a pattern at the end of a string?
This is done in much the same way as with finding a a pattern at the beginning of a string. A common mistake made by many is to use the $ character to match the end of a string. This is incorrect and \z should be used. Consider this..
preg_match("/^foo$/", "foo\n")
This will return true as $ is like \Z which is like (?=\z|\n\z). So when a newline is not wanted, $ should not be used. Also $ will match multiple times with the /m modifier whereas \z will not. Lets make a small change to the code from above by removing the caret(^) at the beginning of the pattern and putting \z at the end of the pattern, we will keep the case in-sensitive modifier in to match any case.
<?php // create a string $string = 'abcdefghijklmnopqrstuvwxyz0123456789'; // try to match our pattern at the end of the string if(preg_match("/89\z/i", $string)) { // if our pattern matches we echo this echo 'The string ends with 89'; } else { // if no match is found we echo this line echo 'No match found'; } ?>
The script now will show the line
''The string ends with 89''
because we have matched the end of the string with the pattern 89. Pretty easy stuff so far.
Meta characters
During our first look at regex we did some simple pattern matching. We also introduced the caret(^) and the dollar($). These characters have special meaning. As we saw, the caret(^) matched the beginning of a string and the dollar matched the end of a string. These characters, along with others are called Meta characters. Here is a list of the Meta characters used for regex:
* . (Full stop)
* ^ (Carat)
* * (Asterix)
* + (Plus)
* ? (Question Mark)
* { (Opening curly brace)
* [ (Opening brace)
* ] (Closing brace)
* \ (Backslash)
* | (Pipe)
* ( (Opening parens)
* ) (Closing parens)
* } (Closing curly brace)
We will look at each of these during this tutorial, but it is important that you know what they are. If you wish to search a string that contains one of these characters, eg: "1+1" then you need to escape the the meta character with a backslash like this:
<?php // create a string $string = '1+1=2'; // try to match our pattern if(preg_match("/^1\+1/i", $string)) { // if the pattern matches we echo this echo 'The string begins with 1+1'; } else { // if no match is found we echo this line echo 'No match found'; } ?>
From the code above you will see the script print:
''The string begins with 1+1''
because it found the pattern 1+1 and ignored or escaped the special meaning of the + symbol. If you were to not escape the meta character and use the regex
preg_match("/^1+1/i", $string)
you would not find a match.
If you are looking for a backslash, you need to escape that also. But, we also need to escape the control character too, which is itself a backslash, hence we need to escape twice like this
\\\\
What do the other Meta characters do?
We have already seen the caret **^** and the dollar **$** in action, so now lets look at the others, beginning with the square braces [ ]. These Meta characters are used for specifying a character class.
A what?
A Character Class. This is just a set of characters you wish to match. They can be listed individually like:
[abcdef]
or as a range seperated by a **-** symbol like:
[a-f]
<?php // create a string $string = 'big'; // Search for a match echo preg_match("/b[aoiu]g/", $string, $matches); ?>
Source: http://www.phpro.org/tutorials/Introduction-to-PHP-Regex.html
How to recursive delete files and directories with PHP
This is an example how you could recursive delete directories with PHP.
Keep in mind that you ALWAYS define a root where this function should do its action.
This can seriously remove all your files.
define('UPLOADFILES', dirname(dirname(__FILE__)) . '/uploadfiles'); function recursiveDelete($path) { if (strpos($path, UPLOADFILES) === false) { exit('Trying to remove from wrong path to uploadfiles!'); } if (is_file($path)) { return unlink($path); } elseif ( is_dir($path) ){ $objects = scandir($path); foreach ($objects as $object) { if($object != '.' && $object != '..'){ recursiveDelete($path . '/' . $object); } } reset($objects); return rmdir($path); } }
How to send a message to your iPhone via Pushme.to with PHP or Bash and Curl
After having Pushme.to installed on my iPhone for over 3 months now I finally had the time to work on some scrips to make it work in different languages for use on servers that I manage.
The PHP version is the less version I use but may be handy for some people.
PHP Version:
function pushMeTo($username, $message, $signature) { $curl = curl_init(); curl_setopt($curl, CURLOPT_URL, 'http://pushme.to/' . $username . '/'); curl_setopt($curl, CURLOPT_RETURNTRANSFER, true); curl_setopt($curl, CURLOPT_POST, true); curl_setopt($curl, CURLOPT_POSTFIELDS, 'message=' . urlencode($message) . '&signature=' . urlencode($signature)); curl_exec($curl); curl_close($curl); } pushMeTo('username', 'Hello world!', 'God');
A more used version is the commandline (Bash) version:
Bash version:
#!/bin/bash username="username" message="Hello world" signature="God" /usr/local/bin/curl -F "message=$message" -F "signature=$signature" "http://pushme.to/$username/"
I currently use these for server monitoring on FreeBSD like the GEOM Raid bay and S.M.A.R.T. status of the disks and website monitoring which works quite nice. And in case the internet connection drops I have a backup via SMS with a serial connected cellphone. So this should be quite failsafe
If you have any other language that you want to use such as Perl just let me know and I could write it for you.
I hope you find these scripts useful. Happy texting!
Download Redtube movies with a simple PHP class
For donations I build everything...
Simply put this file on a server where you want and start downloading
class RedTube { function form() { echo '<form method="post"><input type="text" name="url"><input type="submit"></form>'; } function download($url = null) { if ($this->validate($url)) { $content = $this->fetch($url); preg_match('#<h1 class="videoTitle">(.*)</h1>#', $content, $d1); //preg_match('#<source src=\'(.*)\' type=\\\"video/mp4\\\">#', $content, $d2); preg_match('#<source src=\'(.*)\' type=\'video/mp4\'>#', $content, $d2); if (!empty($d1[1]) && !empty($d2[1])) { header("Content-type: application/octet-stream"); header('Content-Disposition: attachment; filename="' . addslashes($d1[1] . '.mp4') . '"'); $this->fetch($d2[1], true); } } } private function validate($url = null) { if (preg_match('#^http://(www.)?redtube.com/[0-9]+$#', $url)) { return true; } return false; } private function fetch($url = null, $stream = false) { $handle = fopen($url, 'r'); $buffer = null; if ($handle) { if ($stream) { while (!feof($handle)) { echo fgets($handle, 4096); } } else { while (!feof($handle)) { $buffer .= fgets($handle, 4096); } } fclose($handle); } return $buffer; } } $rt = new RedTube; if (!empty($_POST['url'])) { $rt->download($_POST['url']); } else { $rt->form(); }




