ElbertF http://elbertf.com Insights and Updates from a Tech Geek Wed, 08 Feb 2012 05:43:09 +0000 en hourly 1 http://wordpress.org/?v=3.3.1 Swiftlet 3.0 http://elbertf.com/2012/01/swiftlet-3-0-easy-mvc-framework/ http://elbertf.com/2012/01/swiftlet-3-0-easy-mvc-framework/#comments Thu, 26 Jan 2012 05:38:00 +0000 ElbertF http://elbertf.com/?p=1027 Three years ago I released an early version of Swiftlet, a light-weight PHP framework built for speed and security. Over time however, a lot of functionality was added and started to suffer from feature creep. My original intention of creating a maintainable framework that was easy to pick up was a bit lost.

Last Sunday I had a spur of inspiration and decided to start over. With a slightly different vision, a better understanding of MVC and experience gained with the project I managed to finish it the same day. The result is about 150kB of code including documentation.

If you’re unfamiliar with the model-view-controller approach to programming Swiftlet might be a good starting point. The code is quite simple and hopefully the documentation makes the concept understandable.

Source code

Swiftlet on GitHub

Swiftlet is released under the GNU Public License.

]]>
http://elbertf.com/2012/01/swiftlet-3-0-easy-mvc-framework/feed/ 0
Free transform plugin for Raphaël JS http://elbertf.com/2011/12/free-transform-plugin-for-raphael-js/ http://elbertf.com/2011/12/free-transform-plugin-for-raphael-js/#comments Sun, 04 Dec 2011 04:35:32 +0000 ElbertF http://elbertf.com/?p=992 After doing some research for work involving client-side image manipulation I decided to dive into Raphaël, a JavaScript library that simplifies working with vector graphics on the web.

One thing I struggled with was applying multiple transformations to an element. When rotating an object the coordinate plane rotates with it which means dragging no longer works as one might expect (e.g. right becomes up). Raphaël’s creator Dmitri Baranovskiy indicated this is the correct behavior.

I worked out a solution and released it as a plugin. It supports snap-to-grid dragging, scaling and rotating and handles sets. Like Raphaël itself, the plugin is licensed under the MIT license.

Source code

Raphaël.FreeTransform on GitHub

Demo

elbertf.com/raphael/free_transform/

See also…

These are a couple of other plugins I created recently.

Raphaël.JSON

Serialize Raphaël elements and back.

Raphaël.Export

Cross-browser solution to export Raphaël elements to SVG, works in Internet Explorer 6, 7 and 8. Can be used to convert Raphaël drawings to PNG or PDF server-side using ImageMagick or Batik.

]]>
http://elbertf.com/2011/12/free-transform-plugin-for-raphael-js/feed/ 2
Resolve scoping issues in jQuery with anonymous functions http://elbertf.com/2011/05/resolve-scoping-issues-in-jquery-with-anonymous-functions/ http://elbertf.com/2011/05/resolve-scoping-issues-in-jquery-with-anonymous-functions/#comments Sat, 21 May 2011 05:56:37 +0000 ElbertF http://elbertf.com/?p=943 I had a bit of a head-scratching moment recently when I was using jQuery to bind event handlers to elements in a loop. Usually I would just use jQuery’s .each() method but in this specific case that wasn’t an option. Consider the following (simplified) code:

1
2
3
4
5
6
7
8
9
10
11
12
13
<ul>
	<li id="item-1">Item 1</li>
	<li id="item-2">Item 2</li>
	<li id="item-3">Item 3</li>
</ul>
 
<script type="text/javascript">
	for ( var i = 1; i <= 3; i ++ ) {
		$('#item-' + i).click(function() {
			alert('You clicked item ' + i);
		});
	}
</script>

Against my intuition, clicking any of the three li elements would return return “You clicked item 4”. I then realized that i was being read after the for-loop had finished. To solve this, wrap the function in another anonymous function passing i as an argument:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
<ul>
	<li id="item-1">Item 1</li>
	<li id="item-2">Item 2</li>
	<li id="item-3">Item 3</li>
</ul>
 
<script type="text/javascript">
	for ( var i = 1; i <= 3; i ++ ) {
		(function(i) {
			$('#item-' + i).click(function() {
				alert('You clicked item ' + i);
			});
		}(i));
	}
</script>

This way the second i lives in the same scope as the alert() function which will now return the correct value.

]]>
http://elbertf.com/2011/05/resolve-scoping-issues-in-jquery-with-anonymous-functions/feed/ 0
Escaping and sanitizing user input in PHP http://elbertf.com/2010/07/escaping-and-sanitizing-user-input-in-php/ http://elbertf.com/2010/07/escaping-and-sanitizing-user-input-in-php/#comments Fri, 23 Jul 2010 09:12:09 +0000 ElbertF http://elbertf.com/?p=606 I recently answered a question on Quora, a questions and answers website that I frequent. The poster asked “what are best practices for escaping or sanitizing user input in PHP?” People seemed to appreciate the answer I wrote so I’ll post it here and elaborate on it a bit more.

Why is it important to sanitize user input?

If you’re not careful with user input your website might be open to code injection, directory traversal or similar attacks. Information supplied by users can never be assumed safe.

Examples of user input are submitted forms (e.g. comments), URL parameters (?q=example) and server-side scripts pulling in third-party data, such as an RSS feed importer.

HTML and JavaScript

To make strings safe for HTML (without breaking Unicode text) use htmlentities().

1
<?php $safe = htmlentities($unsafe, ENT_QUOTES, 'UTF-8'); ?>

This will encode all special HTML characters. This method is better than black-listing specific elements such as <script> or just opening tags (<). Do not use strip_tags(), str_replace() or regular expressions to filter HTML and JavaScript, it is easy to miss obscure vulnerabilities and leave them exploitable.

When automatically parsing a URL to display a clickable link, check if URL starts with a protocol like “http://” (regex: /[a-z]:\/\//i) and make sure javascript: links never work. Also be careful with quotes and closing angle brackets as they can break HTML.

These examples demonstrate how unfiltered links can be dangerous:

1
2
3
4
5
6
7
<?php
$url = 'javascript:alert(\'XSS\');';
$url = 'http://example.com" onclick="alert(\'XSS\');';
$url = 'example.com"><script>alert(\'XSS\');</script>';
?>
 
<a href="<?php echo $url ?>">Click here</a>

URLs

To pass values as a parameter to a URL, use rawurlencode().

1
<?php $url = 'http://example.com/?k=' . rawurlencode($v); ?>

This function is nearly identical to urlencode() but follows the RFC 1738 specification.

MySQL database queries

When storing strings in a MySQL database, use mysql_real_escape_string().

1
<?php $safe mysql_real_escape_string($unsafe); ?>

Often addslashes() is used instead but this is not enough to prevent SQL injection attacks. If you want to learn why I recommend reading this blog post by Chris Shiflett and the third chapter of the guide to PHP security by Ilia Alshanetsky (PDF, 130KB).

This function requires a MySQL connection.

Magic Quotes

If your web app suffers from unwanted backslashes appearing in content this is probably due to double escaping (e.g. “today\’s weather”). This is likely caused by PHP’s now deprecated Magic Quotes.

Magic Quotes is a feature automatically escapes user input, intended to help beginners write more secure code. Because it’s not always on or needed this affects portability and requires excessive use of stripslashes() to undo.

To recursively undo the affects of Magic Quotes use this function at the beginning of your scripts:

1
2
3
4
5
6
7
8
9
10
11
12
13
<?php
function undo_magic_quotes($v)
{
    return is_array($v) ? array_map('undo_magic_quotes', $v) : stripslashes($v);
}
 
if ( function_exists('get_magic_quotes_gpc') && get_magic_quotes_gpc() )
{
    $_GET    = array_map('undo_magic_quotes', $_GET);
    $_POST   = array_map('undo_magic_quotes', $_POST);
    $_COOKIE = array_map('undo_magic_quotes', $_COOKIE);
}
?>

Directories

And finally, be careful with including files using user input.

1
2
3
4
5
6
7
<?php
// Don't do this
require($_GET['file']);
 
// And especially not this
echo file_get_contents($_GET['file']);
?>

This is dangerous because a user can request any file from the server and execute or view the code (e.g. “?file=../../config.php”, this is called a path traversal attack). One solution is to use basename() which strips off the path of a file name.

These were just a few basics, there is a lot more to web application security. OWASP is a great resource if you want to learn more.

]]>
http://elbertf.com/2010/07/escaping-and-sanitizing-user-input-in-php/feed/ 4
Install Firefox 3.6 add-ons in Firefox 4 beta, disable compatibility check http://elbertf.com/2010/06/how-to-install-firefox-3-6-add-ons-in-firefox-4-beta-avoid-compatibility-check/ http://elbertf.com/2010/06/how-to-install-firefox-3-6-add-ons-in-firefox-4-beta-avoid-compatibility-check/#comments Wed, 30 Jun 2010 09:54:02 +0000 ElbertF http://elbertf.com/wp/?p=530 Update (March 22, 2011): this post also applies to Firefox 4 final. Just use extensions.checkCompatibility.4.0 instead of extensions.checkCompatibility.4.0b.

Firefox 4 beta is available. I installed the 64bit version on Linux today, it’s notably faster than previous versions and includes several other improvements such as tabs on top. Now, I don’t want to go back to 3.6.

As usual the only thing holding me back from upgrading is add-on compatibility. Luckily it’s possible to disable the compatibility check so Firefox 4 will let you install add-ons built for older versions, I found that many add-ons work just fine in Firefox 4.

Disable compatibility check

If you’re willing to take your chances, navigate to about:config in your browser, promise not to break anything and right to window click to add a new boolean. In the preference name field, add extensions.checkCompatibility.4.0b and set the value to false. Firefox will now let you install any add-on.

If anything breaks, try disabling add-ons or delete them completely. You can always go back to 3.6 if nothing works, and wait for a new stable release.

I’ve tested it with AdBlock Plus, Firebug, Flashblock and Wappalyzer.

]]>
http://elbertf.com/2010/06/how-to-install-firefox-3-6-add-ons-in-firefox-4-beta-avoid-compatibility-check/feed/ 5
Launching reversegif.com http://elbertf.com/2010/06/launching-reversegif-com/ http://elbertf.com/2010/06/launching-reversegif-com/#comments Sun, 06 Jun 2010 06:05:52 +0000 ElbertF http://elbertf.com/wp/?p=522 Animated GIFs are better in reverse. For me this was reason enough to spend a weekend coding and avoid doing anything useful. I created a simple service where you can upload animated GIF images and it will reverse them. To my surprise the domain name reversegif.com was still available so I quickly grabbed it and today I put the website up.

A few examples:

Enjoy!

]]>
http://elbertf.com/2010/06/launching-reversegif-com/feed/ 2
How to store passwords safely with PHP and MySQL http://elbertf.com/2010/01/store-passwords-safely-with-php-and-mysql/ http://elbertf.com/2010/01/store-passwords-safely-with-php-and-mysql/#comments Sun, 31 Jan 2010 08:43:27 +0000 ElbertF http://ElbertF.com/?p=447 First, let me tell you how not to store passwords and why.

Do not store password as plain text

This should be obvious. If someone gains access to your database then all user accounts are compromised. And not only that, people tend to use the same password on different sites so those accounts will be compromised as well. Your site doesn’t even need to be hacked; a system administrator could easily browse your database.

Do not try to invent your own password security

Chances are that you’re no security expert. You’re better off using a solution that has been proven to work instead of coming up with something yourself.

Do not encrypt passwords

Encryption may seem like a good idea but the process is reversible. Anyone with access to your code would have no trouble transforming the passwords back to their originals. Security through obscurity is not sufficient!

Do not use MD5

Storing password hashes is a step in the right direction. Cryptographic hashing functions like MD5 are irreversible which makes it difficult to figure out the original password. To validate a hashed password, simply hash the password again when a user logs in and compare the hashes.

1
2
3
4
5
<?php
$password = 'swordfish';
 
$hash = md5($password); // Value: 15b29ffdce66e10527a65bc6d71ad94d
?>

Note that this makes it impossible to retrieve a password from the database. If a user forgets his password, simply generate a new one.

So why not MD5? It is quite easy to make a list of millions of hashed passwords (a rainbow table) and compare the hashes to find the original passwords (the same goes for other hashing functions like SHA-1).

MD5 is also prone to brute forcing (trying out all combinations with an automated script) because of collisions. This means that different passwords can have the same hash, making it even easier to find one that works.

MD5 collision demo: mscs.dal.ca/~selinger/md5collision

Do not use a single site-wide salt

A salt is a string that is hashed together with a password so that most rainbow tables (or dictionary attacks) won’t work.

1
2
3
4
5
6
<?php
$password = 'swordfish';
$salt = 'something random';
 
$hash = md5($salt . $password); // Value: db4968a3db5f6ed2f60073c747bb4fb5
?>

This is better then using just MD5 but someone with access to your code can find the salt a generate a new rainbow table.

What you should do

  • Use a cryptographically strong hashing function like SHA-1 or even SHA-256 (see PHP’s hash() function).
  • Use a long and random salt for each password.
  • Use a slow hashing algorithm to make brute force attacks near impossible.
  • Regenerate the hash every time a users logs in.
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
<?php
$username = 'Admin';
$password = 'gf45_gdf#4hg';
 
// Create a 256 bit (64 characters) long random salt
// Let's add 'something random' and the username
// to the salt as well for added security
$salt = hash('sha256', uniqid(mt_rand(), true) . 'something random' . strtolower($username));
 
// Prefix the password with the salt
$hash = $salt . $password;
 
// Hash the salted password a bunch of times
for ( $i = 0; $i < 100000; $i ++ )
{
    $hash = hash('sha256', $hash);
}
 
// Prefix the hash with the salt so we can find it back later
$hash = $salt . $hash;
 
/* Value:
 * e31f453ab964ec17e1e68faacbb64f05bccceb179858b4c482c1b182ff1e440e
 * f1e10feb5b86c6d367e4eb8f90f2cde5648a7db3df8526878f20a77eed00c703
 */
 
?>

In the above example we turned a reasonably strong password into a 128 characters long hash that we can store in a database. The next time the user logs in we can validate the password as follows:

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
32
<?php
$username = 'Admin';
$password = 'gf45_gdf#4hg';
 
$sql = '
    SELECT
        `hash`
    FROM `users`
        WHERE `username` = "' . mysql_real_escape_string($username) . '"
    LIMIT 1
    ;';
 
$r = mysql_fetch_assoc(mysql_query($sql));
 
// The first 64 characters of the hash is the salt
$salt = substr($r['hash'], 0, 64);
 
$hash = $salt . $password;
 
// Hash the password as we did before
for ( $i = 0; $i < 100000; $i ++ )
{
    $hash = hash('sha256', $hash);
}
 
$hash = $salt . $hash;
 
if ( $hash == $r['hash'] )
{
    // Ok!
}
?>

A few additional tips to prevent user accounts from being hacked:

  • Limit the number of failed login attempts.
  • Require strong passwords.
  • Do not limit passwords to a certain length (remember, you’re only storing a hash so length doesn’t matter).
  • Allow special characters in passwords, there is no reason not to.

That’s it, happy coding!

]]>
http://elbertf.com/2010/01/store-passwords-safely-with-php-and-mysql/feed/ 32
Swiftlet 1.1 Stable http://elbertf.com/2010/01/swiftlet-1-1-stable/ http://elbertf.com/2010/01/swiftlet-1-1-stable/#comments Tue, 05 Jan 2010 04:36:28 +0000 ElbertF http://ElbertF.com/?p=418 I released a new stable version of Swiftlet a few days ago together with a new web page at swiftlet.org. Swiftlet is a light-weight framework written in PHP aimed to make website development faster and easier.

Version 1.1 comes with a few new plugins that bring CMS-like features to Swiftlet. See the changelog for the full list of changes.

The documentation has also been updated and can now be found at swiftlet.org/docs. If you need support or have any requests, feel free to start a thread at swiftlet.org/community.

]]>
http://elbertf.com/2010/01/swiftlet-1-1-stable/feed/ 0
Safer web forms with security tokens http://elbertf.com/2009/11/safer-web-forms-with-security-tokens/ http://elbertf.com/2009/11/safer-web-forms-with-security-tokens/#comments Sun, 15 Nov 2009 08:24:31 +0000 ElbertF http://ElbertF.com/?p=367 A common issue with many web applications is their vulnerability for Cross-Site Request Forgery, or XSRF. It allows a hacker to send a malicious request to a website with an other user’s privileges. Here’s how it works:

  • A hacker creates a page with a form that submits data to example.com.
  • An administrator from example.com is tricked into visiting the page, the form is submitted using JavaScript.
  • The data is handled by example.com as if it came from the administrator (because it did).

This allows a hacker to perform administrative tasks on example.com like editing pages or deleting users.

Solution

Probably the best solution to this problem is using a security token. This is a code (usually a hash) that is send with the form in a hidden field and is only valid for a specific user and a certain period of time.

I recommend using a SHA1 hash created from these components:

  • Information about the user (IP address, user agent, username).
  • Information about the server (hostname, software version).
  • Information about the website (database name, table prefix).
  • Information that expires (user’s session id).

This will result in an unpredictable and seemingly random hash that is still verifiable by the server and difficult to fake.

After the form is submitted the hash is re-created and compared to the token that was send with the form. Only if the hashes match the form is processed, otherwise an error message is displayed. This way even if a hacker manages to find the user’s token the request will fail.

Example (PHP/HTML):

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
32
33
<?php
$authToken = sha1(
  session_id() .
  phpversion() .
  $dbName .
  $_SERVER['REMOTE_ADDR'] .
  $_SERVER['HTTP_USER_AGENT']
  );
 
if ( isset($_POST['submit']) )
{
  if ( isset($_POST['auth_token']) && $_POST['auth_token'] == $authToken )
  {
    // Process form
  }
  else
  {
    // Display error message
  }
}
?>
 
<form id="form" method="post" action="./">
  <fieldset>
    <label for="name">Name:</label>
    <input type="text" name="name" id="name" value=""/>
  </fieldset>
  <fieldset>
    <input type="hidden" name="auth_token" value="<?php echo $authToken ?>"/>
 
    <input type="submit" name="submit" value="Submit"/>
  </fieldset>
</form>

Note that this only really works for POST requests. For this reason GET (regular links) should never be used to pass information that is used for administrative tasks. AJAX requests should also always use POST.

]]>
http://elbertf.com/2009/11/safer-web-forms-with-security-tokens/feed/ 5
Using Internet Explorer 8 for IE6 and IE7 testing http://elbertf.com/2009/10/using-internet-explorer-8-for-ie6-and-ie7-testing/ http://elbertf.com/2009/10/using-internet-explorer-8-for-ie6-and-ie7-testing/#comments Thu, 01 Oct 2009 23:06:54 +0000 ElbertF http://ElbertF.com/?p=342 I personally don’t care what my websites look like in IE6 or 7 (or 8) but for those who do there is neat little trick to test your site for these browsers.

The hard way

If you’re on Windows XP or older you can use a standalone version of IE6. If you’re on Windows 7 (not the beta though), you can use Microsoft’s free “IE Application Compatibility VPC Image” to run XP with IE6 or 7 in a virtual machine. If you’re on any other operating system (Windows Vista, Mac OS, Linux) and have a Windows XP license you can run it using a VM like VirtualBox.

The easy way

If you’re already running IE8 there is an easier way. Compatibility View will render pages as IE7, and a missing doctype will cause pages to be rendered as IE6 in quirks mode.

You can simply remove the doctype from your pages when you’re testing for IE6 or ― if you’re using PHP ― add a simple switch:

1
2
3
4
<?php if ( !isset($_GET['ie6']) ): ?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-
strict.dtd">
<?php endif ?>

Now you can simply add “?ie6” to the URL in IE8 to see what your page looks like in IE6. You can even keep several tabs open to make sure it works with all versions.

]]>
http://elbertf.com/2009/10/using-internet-explorer-8-for-ie6-and-ie7-testing/feed/ 7
Swiftlet documentation update http://elbertf.com/2009/07/swiftlet-documentation-update/ http://elbertf.com/2009/07/swiftlet-documentation-update/#comments Thu, 23 Jul 2009 22:41:47 +0000 ElbertF http://ElbertF.com/?p=334 Swiftlet logoThe documentation for Swiftlet 1.0, a light-weight PHP framework I’ve been working on, is now pretty much complete.

I’ve already begun working on Swiftlet 1.1 which is now in Alpha (unstable and not suited for live environments).

]]>
http://elbertf.com/2009/07/swiftlet-documentation-update/feed/ 0
Automated direct messages on Twitter http://elbertf.com/2009/07/automated-direct-messages-on-twitter/ http://elbertf.com/2009/07/automated-direct-messages-on-twitter/#comments Mon, 06 Jul 2009 00:36:39 +0000 ElbertF http://ElbertF.com/?p=292 I’m a bit over the amount of spam I receive through Twitter’s messaging system. I get a fair number of direct messages every day and most of them are automated. I do read them all in case someone sends me a genuine message.

It shouldn’t be to hard for Twitter to detect automated messages, they could give me an option to block messages that have been send out more then ten times by a single user (I could create an application to do this myself but simply don’t have the bandwidth to handle that many messages, it would need thousands of active users to be effective).

Instead, I created a Twitter app to report users who send auto DMs to. Just tweet “@stopautodm @username” and they will be placed on the Hall of Shame. Perhaps at some point I could add an option to automatically unfollow the most reported users.

Website: elbertf.com/stopautodm
Twitter: @stopautodm

]]>
http://elbertf.com/2009/07/automated-direct-messages-on-twitter/feed/ 4
IE6ify Bookmarklet http://elbertf.com/2009/06/ie6ify-bookmarklet/ http://elbertf.com/2009/06/ie6ify-bookmarklet/#comments Fri, 26 Jun 2009 08:22:32 +0000 ElbertF http://ElbertF.com/?p=267 Today I created yet another utterly useless (but hopefully mildly entertaining) application; IE6ify.

It’s a bookmarklet that brings the joy of browsing the web with Microsoft Internet Explorer 6 to modern browsers. For almost a decade IE6 has managed to intrigue me by breaking standards-compliant websites in the most unpredictable ways. Whatever you did to fix a problem only made things worst, like an ugly dragon that grows two heads every time you cut one off.

Since it’s not possible to run IE6 natively on Windows Vista or 7 and IE6 in Linux Wine is a nightmare, I figured a lot of you would miss the old days. With IE6ify you can break any website in true IE6 fashion.

Website: elbertf.com/ie6ify.

]]>
http://elbertf.com/2009/06/ie6ify-bookmarklet/feed/ 9
JavaScript Tetris http://elbertf.com/2009/06/javascript-tetris/ http://elbertf.com/2009/06/javascript-tetris/#comments Fri, 12 Jun 2009 02:11:08 +0000 ElbertF http://ElbertF.com/?p=246 Because I have nothing better to do with my time I wrote a Tetris game in JavaScript. I know there are plenty out there already but it was fun to make and it brought back some memories (I wrote my first Tetris game in DOS when I was 14). Coincidentally, Tetris just turned 25.

I released it under GPL, feel free to grab the code from the source and do whatever you like with it.

Play the game at elbertf.com/tetris

]]>
http://elbertf.com/2009/06/javascript-tetris/feed/ 4
Object Oriented CSS http://elbertf.com/2009/05/object-oriented-css/ http://elbertf.com/2009/05/object-oriented-css/#comments Sat, 16 May 2009 03:56:20 +0000 ElbertF http://ElbertF.com/?p=186 Okay, there is no such thing as object oriented CSS. But there are advantages in OO programming that we can use in CSS.

1
2
3
4
5
6
7
p {
    margin: 0;
}
 
#content p {
    margin: 1em 0;
}

In this example p would be a class and #content p would be an instance of that class. Let’s say the margin set in p is a method and we got the basic concepts of OOP.

Practicle example

A single HTML element can serve different purposes on a page. A list element for example can be used as a navigational menu (styled horizontally) and as a regular list in content (styled vertically). Sometimes it’s difficult to change one without changing the other.

1
2
3
4
5
6
7
8
9
10
11
12
13
li {
    list-style: none inside;
}
 
#menu li {
    display: block;
    float: left;
}
 
#content li {
    /* We only want bullets if a list appears in content */
    list-style: outside disc;
}

Here I created two instances of the li object. If you change either one it won’t effect the other.

CSS Reset

It’s useful to reset all style properties first using a CSS reset. In the above example I simply applied list-style: none inside; to the li element so you won’t see bullets (•) unless you specify it. It’s easier to just reset everything at once, like this:

1
2
3
4
5
6
7
8
9
10
11
12
13
* {
	background-color: transparent;
	border: none;
	font-size: 1em;
	font-weight: inherit;
	font-family: 'Trebuchet MS', Verdana, Arial;
	line-height: 1.4em;
	list-style: none inside;
	margin: 0;
	padding: 0;
	text-align: inherit;
	text-decoration: none;
}

Adding this code on top of your CSS file will give you full control over your code.

As a bonus this will probably solve a lot of your cross-browser compatibility problems. This is because every browser applies different default CSS to elements.

]]>
http://elbertf.com/2009/05/object-oriented-css/feed/ 0
Swiftlet 1.0.0 Stable http://elbertf.com/2009/05/swiftlet-100-stable/ http://elbertf.com/2009/05/swiftlet-100-stable/#comments Fri, 08 May 2009 02:51:32 +0000 ElbertF http://ElbertF.com/?p=164 Swiftlet logoSwiftlet, the light-weight PHP framework that I’ve been working on for a while, is now stable.

Feature-wise not much has changed since the Beta and Release Candidate cycles but the code has been thoroughly tested and improved where possible. If you’re planning on building a PHP website, give Swiftlet a try.

I moved the project page and documentation away from Google Code, if you go to swiftlet.org you’ll find the new page. It’s powered by a documentation system that I custom coded (dubbed Pintail). If there is any interest I will release the code behind it as Open-Source as well.

]]>
http://elbertf.com/2009/05/swiftlet-100-stable/feed/ 8
Swiftlet Beta http://elbertf.com/2009/05/swiftlet-beta/ http://elbertf.com/2009/05/swiftlet-beta/#comments Sat, 02 May 2009 08:17:52 +0000 ElbertF http://ElbertF.com/?p=156 Swiftlet logoSwiftlet is now in beta, after 15 alpha cycles I’m confident that it’s now pretty much feature complete (there core that is, there will be plenty more plug-ins) and relatively stable.

One of the most important recently added features is the plug-in installer. It checks for compatibility with the core code and creates and populates database tables with a click of the mouse. Plug-ins that don’t require a database connection don’t need to be installed; they’re plug-and-play (and Swiftlet runs fine without a database).

I also added plug-ins to handle user sessions and authorization. This should make it easy to create a website that requires a login system.

Download: code.google.com/p/swiftlet/downloads/list

]]>
http://elbertf.com/2009/05/swiftlet-beta/feed/ 5
Swiftlet — light-weight PHP framework http://elbertf.com/2009/04/swiftlet-%e2%80%94-light-weight-php-framework/ http://elbertf.com/2009/04/swiftlet-%e2%80%94-light-weight-php-framework/#comments Sat, 25 Apr 2009 03:48:55 +0000 ElbertF http://ElbertF.com/?p=132 Swiftlet logoI just released an early alpha version of Swiftlet, an Open Source, light-weight PHP framework released under the GPL license.

It’s targeted at developers who want to built simple websites that don’t require large and complex frameworks, but do want a solid base to work from. Swiftlet provides basic security features such as user input sanitizing, is highly extensible thanks to the deeply integrated hook system, completely Object Oriented and separates logic from design (MVC).

Even the most basic features such as connecting to a database and output buffering are implemented as plug-ins. This means they can be modified, extended and removed without hacking into the core code.

Website: http://swiftlet.org

]]>
http://elbertf.com/2009/04/swiftlet-%e2%80%94-light-weight-php-framework/feed/ 0
First Twitchance winner announced http://elbertf.com/2009/04/first-twitchance-winner-announced/ http://elbertf.com/2009/04/first-twitchance-winner-announced/#comments Mon, 06 Apr 2009 01:32:35 +0000 ElbertF http://ElbertF.com/?p=96 I just announced the first winner on Twitchance: @benjaminluk gets the $500!

6S Marketing made a bold move supporting Twitchance by being the first sponsor. The concept was unproven and perhaps a bit controversial but they were curious and decided is was worth a try. I encourage you to follow them on Twitter.

The next draw is on April 20, this time sponsored by Hover who provided another $500 and 20 smaller prizes.

We decided to make a small concept change: instead of randomly selecting a winner the sponsor and I pick the most creative message on Twitter and award the author with the prize.

To join, simply follow the instructions on the Twitchance website.

]]>
http://elbertf.com/2009/04/first-twitchance-winner-announced/feed/ 0
PHP: How not to pollute the global scope http://elbertf.com/2009/03/php-how-not-to-pollute-the-global-scope/ http://elbertf.com/2009/03/php-how-not-to-pollute-the-global-scope/#comments Sat, 28 Mar 2009 04:04:27 +0000 ElbertF http://ElbertF.com/?p=62 An emerging trend in JavaScript is to wrap entire programs in a single object to prevent conflicts with other scripts. The same can be done with PHP, something I haven’t seen done very often.

If you ever want to combine frameworks you may discover that they use similar names for some variables and functions. This can lead to unexpected output and security holes. If you’re planning on writing a framework of your own, consider wrapping it in an object.

In PHP5 it’s possible to pass objects by reference which means you can send an instance of a class to another class. This way you can nest classes and access the parent.

core.php:

class core
{
    public
        $var = 'This is a global variable.';
 
    const
        CONST_VAR = 'This is a constant.';
 
    // This function is executed when core is initialized.
    function __construct()
    {
        include('classes/foo.php');
 
        $this->foo = new foo($this);
    }
 
    // All the main functions go here.
}

foo.php:

class foo
{
    private $core;
 
    function __construct($core)
    {
        // Reference to the core object.
        $this->core = $core;
    }
 
    function hello_world()
    {
        echo $this->core->var;
    }
}

In this example “core” is the site’s main object containing global variables and functions. When we create an instance of class “foo”, we send a reference to the core object (“$this”) as a parameter. On a regular page the classes, variables and function can be accessed like this:

page.php

include('classes/core.php');
 
$core = new core();
 
echo $core->var; // output: This is a global variable.
echo core::CONST_VAR; // output: This is a constant.
 
$core->foo->hello_world(); // output: This is a global variable.

This way there is only one variable in the global scope: $core. Another advantage is that all variables declared in core are global and accessible throughout the whole program.

]]>
http://elbertf.com/2009/03/php-how-not-to-pollute-the-global-scope/feed/ 9
Tips for writing compact PHP code http://elbertf.com/2009/03/tips-for-writing-compact-php-code/ http://elbertf.com/2009/03/tips-for-writing-compact-php-code/#comments Wed, 25 Mar 2009 08:34:16 +0000 ElbertF http://ElbertF.com/?p=30 Writing compact code can save you time. It’s not always recommended and often even strongly discouraged as it makes your code less readable, but for simple operations it can be more efficient. In this post I will give a few examples.

1. Drop braces

Braces aren’t required in control structures with only one expression. Sometimes it makes sense to drop them. It’s very easy to make mistakes if you ever add code to the structure, I recommend only to do this when the expression is short and fits on a single line.

Long:

1
2
3
4
5
6
7
8
if ( $module == TRUE )
{
    load($module);
}
else
{
    error('No module');
}

Short:

1
2
if ( $module ) load($module);
else           error('No module');

2. Use ternary operators

The above example can be made even more compact using ternary operators:

$module ? load($module) : error('No module');

3. Use “OR” instead of “IF”

“OR” is the same as “or” and ”||”.

Long:

1
2
3
4
5
6
7
8
if ( $foo )
{
   echo $foo;
}
else
{
   echo $bar;
}

Short:

1
echo $foo || $bar;

4. Don’t compare variables to booleans

“if ( $foo == TRUE )” is the same as “if ( $foo )”. This shortcut can make your life as a programmer much easier:

Long:

1
2
3
4
5
6
7
8
9
10
11
function has_value($var)
{
    if ( $var == TRUE )
    {
        return TRUE;
    }
    else
    {
        return FALSE;
    }
}

Short:

1
2
3
4
function has_value($var)
{
    return ( bool ) $var;
}

5. Use default values for variables

It’s usually a good idea to define important variables at the beginning of your script, instead of inside control structures (this could result in undefined variables later on). Another advantage is that you can often save an entire else-block as demonstrated in this example:

Long:

1
2
3
4
5
6
7
8
if ( $foo > 3 )
{
    $message = '$foo is greater then 3.';
}
else
{
    $message = '$foo is lower than or equal to 3.';
}

Short:

1
2
3
4
5
6
$message = '$foo is lower than or equal to 3.';
 
if ( $foo > 3 )
{
    $message = '$foo is greater then 3.';
}

6. Assign variables inside conditions

Long:

1
2
3
4
5
6
$contents = file_get_contents($file);
 
if ( $contents )
{
    echo $contents;
}

Short:

1
2
3
4
if ( $contents = file_get_contents($file) )
{
    echo $contents;
}

7. Group variable declarations

Instead of prefixing every single variable declaration in a class with “public”, “protected” or “private” keywords, group them:

Long:

1
2
3
4
5
class db
{
    public $query;
    public $result;
    public $tables;

Short:

1
2
3
4
5
6
7
class db
{
    public
        $query,
        $result,
        $tables
        ;

Something similar can be done with regular variable declarations if they need to assign them the same value:

Long:

1
2
3
$foo    = TRUE;
$bar    = TRUE;
$foobar = TRUE;

Short:

1
2
3
$foo    =
$bar    =
$foobar = TRUE;

8. Merge arrays instead of assigning individual keys

Long:

1
2
3
4
5
$items = array('item 1', 'item 2');
 
$items[] = 'item 3';
$items[] = 'item 4';
$items[] = 'item 5';

Short:

1
2
3
4
5
6
7
$items = array('item 1', 'item 2');
 
$items = array_merge($items, array(
    'item 3',
    'item 4',
    'item 5'
    ));

Even shorter:

1
2
3
4
5
6
7
$items = array('item 1', 'item 2');
 
$items += array(
    'item 3',
    'item 4',
    'item 5'
    );

That’s it! Please share this post if you found it useful.

]]>
http://elbertf.com/2009/03/tips-for-writing-compact-php-code/feed/ 6
Twitchance http://elbertf.com/2009/03/twitchance/ http://elbertf.com/2009/03/twitchance/#comments Tue, 24 Mar 2009 05:55:18 +0000 ElbertF http://ElbertF.com/?p=25 A few days ago I launched Twitchance, a free Twitter lottery. It’s a viral marketing experiment where I’m going to give away some cash ($500.- on the first draw).

The concept is simple; participants post a message from a sponsor on Twitter. After some time a winner is randomly selected and awarded the prize. The sponsor receives amplified outreach to the online world.

Many companies offer services for free on the internet, often powered by advertisements. I figured the same could be done with a lottery. Twitter has a huge user base and tracking specific messages is easy, making it the perfect place for a project like this.

Anyone can join, all you need is a Twitter and Paypal account.

]]>
http://elbertf.com/2009/03/twitchance/feed/ 3
“Just another WordPress weblog” http://elbertf.com/2009/03/just-another-wordpress-webblog/ http://elbertf.com/2009/03/just-another-wordpress-webblog/#comments Tue, 24 Mar 2009 00:12:12 +0000 ElbertF http://elbertf.com/?p=16 I started this blog to write about my on-line projects and share insights and interesting finds on the web. Occasionally I might post a few tips and tricks for programmers and designers.

I’m a programmer myself, I write most of my applications in PHP and JavaScript. I built websites for a living and often work on experimental projects on the side.

This is my first WordPress blog, I used to share science and technology related articles on Blogger but never published any unique content. I also have a discontinued blog on Tumblr where I posted updates about one of my apps, Wappalyzer. I’m going to post the updates here from now on.

WordPress Theme

I started off with the Modicus theme from Upstart Blogger and turned it into something completely different. It’s a work in progress.

Plugins in use

If you’re interested in what I have to say, please subscribe to my feed and follow me on Twitter.

]]>
http://elbertf.com/2009/03/just-another-wordpress-webblog/feed/ 0