A blend of programming and seo

How to use the digg API

digg How to use the digg API

This article will show you how to use the digg API using PHP. I have also written a library in PHP that maps all of the endpoints documented in the API to easily accessible functions (it is also compatible with PHP 4).

What can you do with the digg API?

  • Get all popular stories submitted after January 1, 2007 sorted by promotion date
  • Get the most recent 100 upcoming stories in the topic “Apple”
  • Get the first 20 stories that were promoted on or after December 25, 2005
  • Determine whether a story, identified by its URL, has been submitted to Digg and, if so, get details like the number of Diggs and comments it has received
  • Get the details of a story, identified by its URL on Digg
  • Get all stories submitted today from nytimes.com
  • Get all stories submitted by Kevin Rose (or another Digger)

How it works

Requests are sent to the digg servers through URLS that are described in the API doc (here).

Here is an example:

http://services.digg.com/stories?appkey=http%3A%2F%2Fexample.com

This will return all stories. By default only 10 will be returned at a time (which can be increased to a maximum of 100). Also, you may notice an appkey=XXX argument. This is a unique identifier required by the digg servers. It is recommended to use the urlencoded refereral URL. Other return types are also available, which can make parsing easier depending on the language used.

response types:

  • XML: Easily parsed in many languages on many platforms. It is particularly easy to use in Flash applications.
  • JSON: May be directly eval’d in Javascript, and also can be parsed in many languages.
  • Javascript: Useful as the source of a script tag, it passes JSON response to the Javascript callback function you specify.
  • Serialized PHP: Easily unserialized in PHP to create objects, to which the programmer can attach custom methods. Or the programmer can directly access the response data through the public properties of the objects.

example:

http://services.digg.com/stories?appkey=http%3A%2F%2Fexample.com (will return XML by default)
http://services.digg.com/stories?appkey=http%3A%2F%2Fexample.com&type=json
http://services.digg.com/stories?appkey=http%3A%2F%2Fexample.com&type=php
http://services.digg.com/stories?appkey=http%3A%2F%2Fexample.com&type=javascript

Other basic arguments

    count
    Number of events to retrieve.
    Event count integer
    Default: 10, Maximum: 100.
    offset
    Offset in complete events list.
    Event offset integer.
    Default: 0.

PHP code

The following is a function that will allow you to connect to the digg service and parse the results. It also will automatically generate the appid based on the current location of the script.


function connect($hostname) {
    //this is an ID that is unique to your app.  It is auto-generated, based on the calling URL
    $appid = urlencode("http://".$_SERVER["HTTP_HOST"].$_SERVER["REQUEST_URI"]);
   
    $host = $hostname."&appkey=".$appid;
    echo $host;
    $ch = curl_init();
    curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
    curl_setopt ($ch, CURLOPT_URL,$host);
    curl_setopt ($ch,CURLOPT_USERAGENT,"Test library");
    curl_setopt ($ch,CURLOPT_CONNECTTIMEOUT,60);
    $response = curl_exec ( $ch );
    curl_close($ch);
   
    return $response;
}


Download

The digg API toolkit can be downloaded Here

May 6, 2009   7 Comments

2-way encryption in PHP

For most php applications, a 1-way hash such as md5 or sha1 is sufficient for storing passwords in a database. This is more secure, because passwords aren’t stored in plaintext and when a user does type in a password to login to the application, it is compared to a hash rather than the actual password. A problem with this method is that there is no way to get the original password. So if a user forgets their password, the only thing that you can do is reset (by generating a new one) it and send them this new password.

Reasons you might need the original password:

  • You are communicating with an external service such as twitter
  • It is more convenient to your users to send them their original password (although, this is slightly more insecure, because email is plain-text, and many users use the same password for multiple apps)

Built-in functions (requires mcrypt extension)

PHP has built-in functions for 2-way hashing called mcrypt. It supports: DES, TripleDES, Blowfish (default), 3-WAY, SAFER-SK64, SAFER-SK128, TWOFISH, TEA, RC2 and GOST in CBC, OFB, CFB and ECB cipher modes,RC6 and IDEA.

Example of usage:

<?php
$key = "your key";
$input = "data to be encrypted";

$encrypted_data = mcrypt_ecb (MCRYPT_3DES, $key, $input, MCRYPT_ENCRYPT);
?>

The following is a class written all in PHP that supports AES 128 2-way encryption. The nice part, is that you don’t need any external libraries to use it.

Here is an example:

<?php
 require_once('aes128.php');
 $aes=new aes128();
 
$cipher=$aes->makeKey("0123456789abcdef");

//encrypt data using above cipher
 $encPassword=$aes->blockEncrypt("secretpass",$cipher);

//decrypt password using above cipher
 $decPassoword=$aes->blockDecrypt($encPassword,$cipher);   
 echo $decPassoword;
?>

Download here

May 5, 2009   6 Comments

How to improve PHP session security

Sessions in PHP are pretty easy to use. Here is a simple example on how to start a session:

<?php
session_start();
$_SESSION['my_variable'] = 'test';
?>

What is this actually doing?

PHP is an easy language to use and many details are hidden from the programmer. When you store variables in a session, a cookie is dropped on the user’s system (you don’t need to use cookies, but the details are the same) with a unique identifier (this is highly randomized and difficult to reproduce). All of the actual data is stored on your server in a file (which is the default) or a specific database table. The random/unique identifier stored in the user’s cookie is then used as a key to their data.

Insecurities

There are a couple of different ways someone could possibly get access to a session. They are:

  • Guessing the session identifier
  • Session hijacking
  • Session sniffing
  • Session storage

Guessing the session identifier: PHP’s built-in session id generator is very random and it is unlikely that someone would be able to guess it.

Session Hijacking:
A valid session id is all that is needed to successfully hijack a session. In order to improve this, we need to see if there is anything extra in an HTTP request that we can use for extra identification. At first glance, and IP address sounds like a good piece of information to use to identifier a user. However, since http is a stateless protocol, you may have users that have a different IP address with every request (I’m not sure how common this is these days, but I used to see this with visitors that were using AOL networks).

A better idea is to use something like the userAgent.

session_start();

if ($_SESSION['HTTP_USER_AGENT'] != md5($_SERVER['HTTP_USER_AGENT'])) {
        //redirect user back to login page for authentication
       exit;
} else {
    $_SESSION['HTTP_USER_AGENT'] = md5($_SERVER['HTTP_USER_AGENT']);
}

Session Sniffing: Cookies and all other information between a client and server are sent in clear text (meaning someone between a client and the server could grab info such as a session id). So, if are running a site that involves sensitive information, it’s always a good idea to use SSL.

Session storage: If you are on a shared web-server, anyone on the system could potentially access the data stored in your sessions (PHP by default stores all session data in files..usually in the /tmp directory).

An alternative to storing them on the filesystem is to store them in a database (I have written a simple class that does just this. You can download it here.

Also, if you are going to store sensitive data in your sessions, you might want to use a 2-way encryption library such as RC4 (available here)

April 23, 2009   6 Comments

Using iframes for cross-site scripting

Here is an easy way to communicate different domains using frames:

Step 1: Create a file called iframe_remote.htm with the following:

<html>
    <script type="text/javascript">
      window.name="my test data";
    </script>
  </html>

The above code contains the data that you want to return to your calling script. I used a simple example with static data. Instead, a PHP (or any other programming language) script could be used to dynamically return data depending on the parameters (this data could also be JSON or XML).

Step 2: create a file called iframe.htm with the following:

<html>
<head>
<script language="javascript">
function loadFrame()
{
    var crossData = "";
    try
    {
    crossData = document.getElementById('cframe').contentWindow.name;
    alert("data: "+crossData);
    } catch(err) {}
}

function setFrame()
{
    document.getElementById('cframe').src = 'iframe_dummy.htm';
}
</script>
</head>
<body>
<iframe id="cframe" name="test" src="http://yourdomain.com/iframe_remote.htm" onLoad="loadFrame()" style="display:none"></iframe>
<input type="button" value="Get Remote data" onclick="setFrame()">
</body>
</html>

Set the iframe src to the full path of iframe_remote.htm. This file should also be placed on the domain that is retrieving the remote data. You should also create a file on the same server as iframe.htm called iframe_dummy.htm.

This technique currently works in all major browsers.

How it works

Under normal circumstances, you can’t access remote data or properties in a frame across different domains due to security measures in place by your browser. The iframe name is the key to retrieving cross-domain data. The above code first loads an iframe with javascript that sets the iframe’s window.name property. After this, the iframe src is dynamically changed to a local file, the windows.name property is not changed, and your browser sees this as a file on the same domain.

April 21, 2009   4 Comments

How to secure a web contact form

Many people have “contact us” forms on their website (or some other kind of form that sends email out using PHP).

contact How to secure a web contact form
A solution to send out the form by email might be the following:

<?php
 $from =$_POST[from_address'];
 $message=$_POST['
message'];
 $to = "webmaster@mydomain.com";

 mail($to,'
web contact form',$message,"From: $from\n");

?>

The problem with the above code is that it allows spammers to inject headers into the email, giving them the ability to send email anyone.

It can be done through the From field:

spam@email.com%0Acc:spam2@email.com

Your script will see the %0A as a newline and the headers will be sent like this:

To: you@yourcompany.com
From: spam@email.com
cc: spam2@email.com

The fix

A way to fix this potential issue is to validate the from address with a regular expression:

<?php

 $from =$_POST[from_address'];
 $message=$_POST['
message'];
 $to = "webmaster@mydomain.com";

if (!preg_match("/^([_a-z0-9-]+)(\.[_a-z0-9-]+)*@([a-z0-9-]+)(\.[a-z0-9-]+)*(\.[a-z]{2,6})$/",$from))
  {
      echo "not a valid email address";
      exit;
  }

 mail($to,'
web contact form',$message,"From: $from\n");
?>

April 20, 2009   1 Comment