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.

Posted in geek
  • http://twitter.com/tarasis/status/4805165753 Robert McGovern

    Nice way to avoid Twitpic cockups :) RT @jearle: New blog post: How I made a Tweetie 2 Image Service: http://blog.23x.net/153 – comments?

  • http://twitter.com/kovshenin/status/4805197240 kovshenin

    How I made a Tweetie 2 Image Service: http://blog.23x.net/153 (via @jearle)

  • Pingback: Using Tweetie 2 with My Quick Images | myqu.im()

  • http://advlist.info/ Kroyj

    I’d passion to be au courant that too!

  • http://twitter.com/yamasas/status/6194654056 yamasas

    [twitter] How I made a Tweetie 2 Image Service | The 23x blog http://bit.ly/7DKoXU

  • http://www.fuckbethetopofgoogle.com Adrian @ fuck be the top of google . com

    Bookmarked :)

    (Edited by 23x – this kind of comment spam is how “bethetopofgoogle” will try to promote your site. Good SEO doesn’t require comment spam, fucktard.)

  • http://www.iphonespyapp.com/ Scott

    If you are going to do GOOD SEO, you should try the method that works for all the really big players! They don’t keep it a secret, but it is something that they seem to have left off the SEO curriculum, so let me be the person to tell the SEOtards how to get your site seen by as many people as possible, and as a result, appear at the top of all the best search engines.

    Here goes:

    Write something that people want to read.

    I know what you are thinking: “woah, what’s the catch?” or “who does this guy think he is, telling me how to do my job? I spammed 10,000 blogs today, and of those links 500 of them are still up, and I am building this awesome link farm.”

    But what do I know? Look at all the REALLY HEAVY page-ranked sites, and the ones that appear at the top of all your Google searches. What do they contain?

    CONTENT.

    When you do a search for yourself (I am not talking about the ones you do for your SEO crap), you put in terms that you think will narrow down the results to something you want to read, and Google is *really good* – most of the time, it gives you the result you want, right on the front page! What the parasitic SEOtards try to do is break that.

    So screw you, SEOtards. You want to appear at the top of Google? You write something that people want to read, and there it will be.