Archive for the ‘Computers’ Category

Twitter from PHP

Tuesday, June 16th, 2009

A few months ago I broke down and joined Twitter. Pretty much the only reason is that I wanted to learn how to integrate Twitter into PHP web applications. Here’s what I found:

Twitter has a URL http://www.twitter.com/statuses/update.xml where you can POST a twitter update. The following HTML form will update your twitter status after asking you for your username and password:

<form action="http://twitter.com/statuses/update.xml" method="POST">
	<input type="text" name="status" />
	<input type="submit" value=""Tweet!" />
</form>

This is cool, but it would be nice to circumvent the password protection in a web application where you probably already have a user logged in and validated? Fortunately this is possible using HTTP headers: (please make sure you read my SECURITY NOTE below)

<form action='twitter.php' method='post'>
	<input type='text' name='status' />
	<input type='submit' value='tweet' />
</form>
<?php
	if($_POST['status']!="") {

		$data = "status=".stripslashes($_POST['status']);
		$fp = fsockopen("www.twitter.com", 80);
		$user = "twitter_username";
		$pass = "twitter_password";

		fputs($fp, "POST /statuses/update.xml HTTP/1.1\r\n");
		fputs($fp, "Host: www.twitter.com\r\n");
		fputs($fp, "Referer: None\r\n");
		fputs($fp, "Authorization: Basic ".
			base64_encode($user.":".$pass)."\r\n");
		fputs($fp, "Content-type: ".
			"application/x-www-form-urlencoded\r\n");
		fputs($fp, "Content-length: ". strlen($data) ."\r\n");
		fputs($fp, "Connection: close\r\n\r\n");
		fputs($fp, $data);

		while(!feof($fp))$str .= fgets($fp, 128);
		if(!strstr(" OK ",$str))
			echo "There was a problem posting your twitter update.";
		else echo "twitter update posted successfully!";
	}
?>

SECURITY NOTE:

Please notice that the code above sends the username and password hash unencrypted over a plaintext HTTP pipe. The password hash is thus vulnerable to rainbow table attacks.

A better solution uses HTTPS with cURL. This way, the username & password hash info don’t have to be sent plaintext:

<form action='twitter.php' method='post'>
	<input type='text' name='status' /> <input type='submit' value='tweet' />
</form>
<?php
	if($_POST['status']!="") {
		$url = "https://twitter.com/statuses/update.xml";
		$user = "twitter_username";
		$pass = "twitter_password";

		$ch = curl_init();
		curl_setopt($ch, CURLOPT_URL, $url);
		curl_setopt($ch, CURLOPT_POST, true);
		curl_setopt($ch, CURLOPT_HEADER, true);
		curl_setopt($ch, CURLOPT_USERPWD, $user.":".$pass);
		curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
		curl_setopt($ch, CURLOPT_POSTFIELDS,
			"status=".stripslashes($_POST['status']));

		ob_start();
		curl_exec($ch);
		$str = ob_get_contents();
		ob_end_clean();
		curl_close($ch);

		if($str=="" || strstr($str,"<error>"))
			echo "There was a problem posting your twitter update.";
		else echo "twitter update posted successfully!";
	}
?>

Since I’ve started using twitter I’ve found that it’s very useful for companies and organizations that want to get messages out to lots of people quickly. You can even get twitter updates by phone using SMS!

Happy tweeting!

  • Share/Bookmark

PHP ICO to PNG conversion

Tuesday, February 17th, 2009

A few posts ago I wrote about using a PHP class to convert an ICO image to a PNG (or GIF or JPG). I just discovered a bug in the class.

I ran into a problem where some red and orange ICO images turned blue during the conversion. Reading this forum post made me realize that the red and blue values were switched somewhere in class.ico.php. With some experimentation I found it:

In class.ico.php, lines 264-267 need to be changed from

$c[$i] = $this->AllocateColor($im, $this->formats[$index]['colors'][$i]['red'],
         $this->formats[$index]['colors'][$i]['green'],
         $this->formats[$index]['colors'][$i]['blue'],
         round($this->formats[$index]['colors'][$i]['reserved'] / 255 * 127));

to

$c[$i] = $this->AllocateColor($im, $this->formats[$index]['colors'][$i]['blue'],
         $this->formats[$index]['colors'][$i]['green'],
         $this->formats[$index]['colors'][$i]['red'],
         round($this->formats[$index]['colors'][$i]['reserved'] / 255 * 127));

(Note that the blue and red values are indeed switched.) After changing this, it works like a charm for me.

  • Share/Bookmark

Facebook profile box tips

Tuesday, February 17th, 2009

As mentioned in my previous post, I’ve been finishing up a facebook application, My Sites. Now that it’s done, I thought I’d post a few tips on how to add profile boxes to your facebook application, since I found it maddeningly complicated.

For the non-facebook-savy, a profile box is a small box that applications can add to your profile’s “wall” or “boxes” tabs. They’re meant to provide a quick glimpse of what’s happening with the application.

I’m assuming that you keep a database of Facebook users, and you want to display something about them in the profile box.

The basic code for adding a profile box is below, annotated with copious comments. This is in PHP code, you can do it in other languages, but it’s what I use. Pop this code into a daily cron for example, and you’re good to go.

<?php
// This code connects to the facebook API.
@require_once 'facebook-platform/php/facebook.php';
$appapikey = 'facebook app api key';
$appsecret = 'facebook app api secret';
$facebook = new Facebook($appapikey, $appsecret);

// This code connects to your own database.
$BASEURL = "http://example.com/path/to/facebook/app";
$connection = @mysql_connect("server","username","password");
if(!$connection)die("Can't connect to the database at this time.");
$res = @mysql_select_db("database");
if(!$res)die("Site database doesn't seem to exist.");

// This code cycles through each user in the database
$sql="SELECT * FROM users";
$data=@mysql_query($sql);
while($user=mysql_fetch_assoc($data)) {
     // You can, of course, query your database to build these strings
     $WideBox = "Whatever you want a profile box on the 'boxes' tab to say.";
     $MobileBox = "Whatever you want a profile box accessed by a mobile device to say.";
     $NarrowBox = "Whatever you want a profile box on the 'wall' tab to say.";

     // This is the API call, it sets the user's profile box content:
     $facebook->api_client->profile_setFBML(
          NULL,        // This is the markup, set to NULL for 'FBML'
          $user['id'],  // ID number of the user whose profile box you want to set
          $WideBox,    // Wide box content for 'boxes' tab
          NULL,        // Deprecated, should always be NULL
          $MobileBox,  // Box content for mobile devices
          $NarrowBox   // Narrow box content for 'wall' tab
     );
}
// Clean up the connection
@mysql_close($connection);
?>
  • Share/Bookmark

ICO images in FaceBook profile boxes

Monday, February 9th, 2009

So I’ve been developing a FaceBook application, My Sites. It let’s you bookmark websites you like and share them with your friends.

The Problem

When a FaceBook application tries to add HTML to someone’s profile box, it can add images, but only in JPG, GIF, or PNG formats. For most uses this is fine, but I needed to add a favicon next to each website in a list, and ICO format isn’t allowed.

The Solution

Using a free php class that can import ICO images to a GD image resource, I converted the favicons to PNGs. Now FaceBook is all happy. Download a ZIP of the icon class here, or directly from PHPclasses.org.

[EDIT: please see my post on the important bug fix]

The Code

Here’s how you use the class:


<?php
error_reporting(0);
require("ico.class.php");
$f = "http://www.google.com/favicon.ico";
$i = new Ico($f);
if(!($r=$i->GetIcon(0))) die("Could not load ICO.");
else {
          header("Content-Type: image/png");
          imagepng($r);
}
?>
  • Share/Bookmark