How I made a Tweetie 2 Image Service

Recently, Gandi offered .im domains cheap and, being of puerile mind, I picked up myqu.im for a laugh. I put a jokey wordpress blog on there and called it My Quick Images. The joke was that anyone finding it would assume the site was designed without knowing Quim was an obscene word. Much hilarity ensued and it even made the B3ta newsletter.

The joke stopped being funny when Tweetie 2 came out for the iPhone and it allowed you to add custom image services. I took that as a challenge and assumed I could rip lots of functionality from my URL shortener, tw3.it and have something working in under a day. As it turned out, it was remarkably simple to get the basics up and running. All the code is below. Files may need fixing thanks to WordPress not being the best code repository.

The URL to POST to is http://myqu.im/u and it does exactly what the docs say to do. Oh, and if you don’t want it to return an image, you can add a trailing slash like http://myqu.im/u/ and it will return an HTML page instead.

If you notice anything like stupid cock-ups in my code, which isn’t unlikely in this early stage, please feel free to point it out in the comments. I’m not really a coder, so it’d not surprise me to find out I’ve made a massive oopsie.

Here are the settings for Tweetie 2 to use myqu.im:

Tweetie 2 settings for myqu.im

Here are the settings for Tweetie 2 to use tw3.it:

Tweetie 2 settings for tw3.it

?Download target.php
< ?php
include "db.inc.php";
include "functions.inc.php";
foreach ($_POST as $key => $value) {
    $_POST[$key] = mysql_real_escape_string($value);
  }
?>
 
< !DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
        "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
<head>
	<meta http-equiv="content-type" content="text/html; charset=iso-8859-1" />
	<title>posted</title>
	<meta name="generator" content="BBEdit 9.2" />
</head>
<body>
< ?php
$filename=basename($_FILES['media']['name']);
$extension = getExtension($filename);
$extension = strtolower($extension);
if (($extension != "jpg") && ($extension != "jpeg") && ($extension != "png") && ($extension != "gif"))
	{
	//print error message
	echo '<h1>Unknown extension!';
	}
else
	{
	if ($extension == "jpg") { $mime = "image/jpeg"; }
	if ($extension == "jpeg") { $mime = "image/jpeg"; }
	if ($extension == "png") { $mime = "image/png"; }
	if ($extension == "gif") { $mime = "image/gif"; }
 
	$image_name=time(). '_'. rand(0,9). rand(0,9). rand(0,9). rand(0,9). '.'.$extension;
	$target = $_SERVER['DOCUMENT_ROOT'] . "/imageupload/". $image_name;
	$ok=1;
	if(move_uploaded_file($_FILES['media']['tmp_name'], $target))
		{
		$last = mysql_query("SELECT uid FROM Images ORDER by uid DESC LIMIT 1",$db);
		$last = mysql_fetch_row($last);
		$next = dec2string($last[0] + 1);
		mysql_query("INSERT into Images (id, name, user, mime) values ('$next', '$image_name', '". $_POST['username']. "', '$mime')",$db);
 
		if (isset($_GET['slash'])) { $next .= "/"; }
		echo "<mediaurl>http://myqu.im/g/". $next. "</mediaurl>";
		echo "<br />Your file has been uploaded as http://myqu.im/g/". $next;
		}
	else {
	echo "Sorry, there was a problem uploading your file.";
	}
}
?>
</body>
</html>
?Download db_inc.php
< ?php
// Database Login
$db = mysql_connect("localhost", "login", "password");
mysql_select_db("databasename",$db);
< ?php
function string2dec ($string)
{
    global $error;
    $decimal = 0;
 
    $charset = '0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz';
    $charset = substr($charset, 0, 62);
 
    do {
 
       $char   = substr($string, 0, 1);
       $string = substr($string, 1);
 
       $pos = strpos($charset, $char);
       if ($pos === false) {
          $error[] = "Illegal character ($char) in INPUT string";
          return false;
       } // if 
 
       $decimal = ($decimal * 36) + $pos;
 
    } while($string <> null);
 
    return $decimal;
 
} // string2dec 
 
function dec2string ($decimal)
{
    global $error;
    $string = null;
 
    $charset = '0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz';
    $charset = substr($charset, 0, 62);
 
    if (!ereg('(^[0-9]{1,16}$)', trim($decimal))) {
       $error['dec_input'] = 'Value must be a positive integer';
       return false;
    } // if
    $decimal = (int)$decimal;
 
    do {
 
       $remainder = ($decimal % 36);
 
       $char   = substr($charset, $remainder, 1);
       $string = "$char$string";
 
       $decimal   = ($decimal - $remainder) / 36;
 
    } while ($decimal > 0);
 
    return $string;
 
} // dec2string 
 
function getExtension($str) {
	$i = strrpos($str,".");
	if (!$i) { return ""; }
	$l = strlen($str) - $i;
	$ext = substr($str,$i+1,$l);
	return $ext;
}
?Download g.php
< ?php
include "db.inc.php";
include "functions.inc.php";
foreach ($_GET as $key => $value) {
	$_GET[$key] = mysql_real_escape_string($value);
}
if (isset($_GET['id'])) {
	$id = $_GET['id'];
	$check = mysql_query("SELECT * FROM Images where id = '".$id."'",$db);
	$check = mysql_fetch_row($check);
	if ($check) {
		header("Accept-Ranges: bytes");
		header("Content-Length: ". filesize("imageupload/".$check[3]) );
		header("Content-type:".$check[4]);
		readfile("imageupload/".$check[3]);
		}
	} elseif (isset($_GET['page'])) {
	$id = $_GET['page'];
	$check = mysql_query("SELECT * FROM Images where id = '".$id."'",$db);
	$check = mysql_fetch_row($check);
	if ($check) {
		$image = "imageupload/".$check[3];
		$info = getimagesize($image);
		echo '< !DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
        "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
<head>
	<meta http-equiv="content-type" content="text/html; charset=iso-8859-1" />
	<title>My Quick Image - posted by @'. $check[1]. '</title>
	<meta name="generator" content="BBEdit 9.2" />
	<meta name="viewport" content="width='.$info[0]. ', user-scalable=yes" />
</head>
<body style="margin:0px;">
';
		echo '<img src="/'. $image. '" '. $info[3]. '/><br />';
		echo "\n<br />";
		echo 'Uploaded by <a href="http://twitter.com/'. $check[1]. '">'. $check[1]. '</a>';
?>
 
<script type="text/javascript">
	var gaJsHost = (("https:" == document.location.protocol) ? "https://ssl." : "http://www.");
	document.write(unescape("%3Cscript src='" + gaJsHost + "google-analytics.com/ga.js' type='text/javascript'%3E%3C/script%3E"));
</script>
 
<script type="text/javascript">
	try {
		var pageTracker = _gat._getTracker("UA-10491025-1");
		pageTracker._initData();
		pageTracker._trackPageview();
	} catch(err) {}</script>
<script type="text/javascript">
	var analyticsFileTypes = [''];
	var analyticsEventTracking = 'enabled';
</script>
< ?php
		echo '</body>
</body></html>';
		}
	}
?Download .htaccess
# BEGIN WordPress
<ifmodule mod_rewrite.c>
RewriteEngine On
RewriteBase /
RewriteRule ^g/([a-zA-Z0-9]*)/$ /g.php?page=$1 [L]
RewriteRule ^g/([a-zA-Z0-9]*)$ /g.php?id=$1 [L]
RewriteRule ^u$ /target.php [L]
RewriteRule ^u/$ /target.php?slash=yes [L]
 
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule . /index.php [L]
</ifmodule>
 
# END WordPress
?Download database.sql
CREATE TABLE `Images` (
  `uid` int(11) NOT NULL auto_increment,
  `user` text NOT NULL,
  `id` text NOT NULL,
  `name` text NOT NULL,
  `mime` text NOT NULL,
  PRIMARY KEY  (`uid`)
)

Download all files here.

Please note, the code here is not necessarily the final code on the site as I’m one of those constant fiddlers. I’ll try to keep this post up to date with changes, but I may just open the svn repository up publicly if there’s any demand.

Jared Earle is a writer, photographer and systems administrator. You can find him on Twitter most of the time.