Charl van Niekerk » Blog

Main

Latest

Archives

Powered by Blogger

Fring

I tried Fring the other day and was generally quite impressed. However, there are a few issues that bother me.

It's cool that Fring supports Google Talk, but why can't I log in to any other XMPP server? Maybe I just did something wrong but I did not manage to sign into my jabber.co.za account at all. It's all the same protocol standard anyway so what's the difference? (I actually saw that this was asked before but got no replies.)

Then, the Twitter support... Basically it handles Twitter like any other chat window. Sure I want to have the phone make noise when I receive an actual private message but I don't want to have that for each incoming Twitter message too! My contacts are far too busy for that. I quickly disabled Twitter.

When using the "Fring Me" widget, because my phone doesn't have GPS now it won't display my location on the map. Why not just use triangulation?

Although the Skype support can sometimes be slow when logging on, I loved the ability to use VoIP from the phone!!

As a last thought, when are we getting a public REST API?

PHP ADSL Account Switcher

Screenshot of my ADSL Account Switcher

I have multiple ADSL accounts and a Netgear ADSL router and eventually I just got irritated of moving between them, copying and pasting into that boring Netgear web interface. So I wrote a little script to do the work for me:

<?php
  // Handy library function for so-called "screen scraping" (I call it "HTML hacking")
  function extractSingle($text, $startDelim, $endDelim) {
    $start = strpos($text, $startDelim);
    if ($start === false) return false;
    $start += strlen($startDelim);
    $end = strpos($text, $endDelim, $start);
    if ($end === false) return false;
    return substr($text, $start, $end - $start);
  }
  
  // Load the configuration
  $config = new SimpleXMLElement(file_get_contents('adsl-config.xml'));
  
  // Change the account details if necessary
  if (isset($_REQUEST['username']) && isset($_REQUEST['password'])) {
    $curl = curl_init();
    curl_setopt($curl, CURLOPT_URL, "http://$config->host/setup.cgi");
    curl_setopt($curl, CURLOPT_USERPWD, "$config->user:$config->pass");
    curl_setopt($curl, CURLOPT_POSTFIELDS, 'DSLencapsulation=pppoe&pppoeName=' . urlencode($_REQUEST['username']) . '&pppoePasswd=' . urlencode($_REQUEST['password']) . '&pppoeService=&pppoeIdleTime=0&WAN_ipType=Dynamic&DNStype=Dynamic&natEnable=enabled&apply=Apply&h_DSLencapsulation=pppoe&wan_login=setup.cgi%3Fnext_file%3Dpppoe.htm&h_natEnable=enabled&h_WANlogin=enable&h_WAN_ipType=Dynamic&c4_pppoeip=&h_DNStype=Dynamic&c4_DNS1address=&c4_DNS2address=&runtest=&todo=save&this_file=pppoe.htm&next_file=basic.htm');
    curl_setopt($curl, CURLOPT_RETURNTRANSFER, 1);
    curl_exec($curl);
    curl_close($curl);
    header("Location: $_SERVER[REQUEST_URI]");
    exit;
  }
  
  // Get the current username / password from the router
  $curl = curl_init();
  curl_setopt($curl, CURLOPT_URL, "http://$config->host/setup.cgi?next_file=pppoe.htm");
  curl_setopt($curl, CURLOPT_USERPWD, "$config->user:$config->pass");
  curl_setopt($curl, CURLOPT_RETURNTRANSFER, 1);
  $ret = curl_exec($curl);
  curl_close($curl);
  $username = extractSingle($ret, '<input type="text" name="pppoeName" size="15" maxlength="63" value="', '"></td>');
  //$password = extractSingle($ret, '<input type="password" name="pppoePasswd" size="15" maxlength="63" value="', '"></td>');
  
  // Determine the title of the current adsl account
  $title = 'Unknown';
  foreach ($config->account as $account) {
    if ($account->username == $username) {
      $title = $account->title;
      break;
    }
  }
  
  header("Content-Type: text/html; charset=UTF-8");
?>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
<html lang="en">
  <head>
    <title>ADSL Account Switcher</title>
    <style type="text/css">
      body {
        padding: 40px;
        font: 0.8em / 1.6 verdana, arial, sans-serif;
        text-align: center;
      }
      h1 {
        font: 2em verdana, arial, sans-serif;
        letter-spacing: 2px;
      }
      h2 {
        margin: 40px 0 0 0;
        padding: 0;
        font: 1.4em verdana, arial, sans-serif;
        letter-spacing: 4px;
      }
    </style>
  </head>
  <body>
    <h1>ADSL Account Switcher</h1>
    <h2>Current Account</h2>
    <p>
      <strong>Account: <?php echo $title; ?></strong><br>
      Username: <?php echo htmlspecialchars($username); ?>
    </p>
    <h2>Switch To</h2>
    <?php foreach ($config->account as $account): ?>
      <form method="post" action="">
        <p>
          <input type="hidden" name="username" value="<?php echo htmlspecialchars($account->username); ?>">
          <input type="hidden" name="password" value="<?php echo htmlspecialchars($account->password); ?>">
          <input type="submit" value="<?php echo htmlspecialchars($account->title); ?>">
        </p>
      </form>
    <?php endforeach; ?>
  </body>
</html>

This is obviously just a hack for my personal use so sorry if it isn't too clean but I thought I should post it here anyway in case somebody can find any benefit out of it some way or the other. It might or might not work on your setup but the firmware version I am using here is V3.01.25

I actually want to transform the core functionality into an XML API but I don't know where I would use something like that.

Oh yes, and you'll also need the following configuration file (obviously you'll have to customise):

<adsl>
 <host>10.0.0.1</host>
 <user>admin</user>
 <pass>password</pass>
 <account>
  <title>Local (isp123)</title>
  <username>isp123@dsl512.isdsl.net</username>
  <password>fubarnoob</password>
 </account>
 <account>
  <title>International (isp234)</title>
  <username>isp234@dsl512.isdsl.net</username>
  <password>eishbahlol</password>
 </account>
</adsl>

Browsing the Local Interwebs

I sometimes have some people telling me that there's no point behind local-only ADSL as all the worth-while sites are hosted overseas. Although many (if not most) South Africans opted for hosting their blogs and other sites overseas because of the ridiculous local bandwidth prices, there are still many great sites hosted inside of this country. Here is a short list of the ones I use most frequently.

My Broadband, the famous portal site for everything internet-related (and actually tech-related in general) in South Africa, is still one of my favourites. There's everything, news, forums, blogs, photos, etc. I also love the wug.za.net gallery.

The CLUG Park helps me to keep updated with what's happening in the geeksphere and the CLUG Wiki is also a handy point of reference every now and then. The Geek Dinner and WAPA are also good to watch. And of course, to me Tectonic is just unmissable!

As far as news (in general) is concerned, we are spoiled for choice. In no particular order:

You can also go to the WeatherSA site directly.

One of the best things about The Times for me is actually the multimedia section. Believe it or not, the videos are hosted locally. :)

Although I couldn't find that many "Web 2.0" sites and utilities specifically, there is of course TimesURL (complete with API) for shortening long URLs.

As far as communication goes, we definitely have some options. Although there used to be two public Jabber servers, there is currently only Jabber.co.za left (to my knowledge). The nice thing is that although you only connect to a local server, you can still chat to anybody on any of the other Jabber servers out there so you can easily communicate with friends and family overseas (including anybody using Google Talk). You can even Twitter using the Twitter Jabber bot.

We still have lots of IRC networks though (for those that still use it), including (my favourite) Atrum but there's also LagNet and the old ZAnet.

We also have some great download mirrors, which are obviously the best part of "local-only" as it's very bandwidth-intensive. Because I use ISDSL local, I normally first try ftp.is.co.za but if I can't find what I want I go directly to mirror.ac.za. Unfortunately their PHP mirror still seems broken but in general their mirrors are updated much quicker than ftp.is.co.za, especially their Ubuntu mirror which was ready with the latest ISOs at the time of the (official) Ubuntu Hardy release.

I'm sure there's many other servers out there I still have to discover but at least this gives you a good start. If you know of more (especially servers that host multimedia content), please comment! :)

Zend Framework OpenID Bug

I am setting up an OpenID provider tonight using Zend Framework's OpenID library but ran into strange issues when it came to passing "extension" variables. On the consumer side, the variables were passed back but they all had a value of 1 instead of the full string value for some reason. After quite a bit of searching, I found a "small" bug in Zend/OpenId/Extension/Sreg.php. After I added exactly 7 characters to the file, everything worked as expected. Here is my diff:

--- Sreg.php.bak        2008-04-27 02:07:31.000000000 +0200
+++ Sreg.php    2008-04-27 02:10:24.000000000 +0200
@@ -189,7 +189,7 @@
         $props2 = array();
         foreach (self::getSregProperties() as $prop) {
             if (isset($props[$prop])) {
-                $props2[$prop] = $props[$prop];
+                $props2[$prop] = $this->_props[$prop];
             }
         }

I tried to submit this bug on the issue tracker but I have to wait for them to authorise me first.

Ubuntu 8.04 (Hardy Heron) Released!

The stable version of Ubuntu 8.04 Hardy Heron has just been released a couple of minutes ago. It's the first Long Term Support (LTS) release since Ubuntu 6.04 Dapper Drake.

What we saw with the last major Ubuntu release we are seeing now again. Major amounts of bandwidth are being pumped everywhere in the world. In South Africa, the mirrors also seem to be taking the strain but luckily people like Andrew Alston are keeping a close eye on the situation. In an e-mail to the Ubuntu South African Local Community List, he mentioned:

Currently the combined outbound bandwidth to Ubuntu Users is pushing in excess of 500mbit between the two locations.

For South Africa, that's pretty hectic, but it just comes to show how many Ubuntu-loving Linux users there are in this country. After all, the name "ubuntu" means much more to us than to most people of the world!

Garden Route WUG

If there is one thing that has been on the local open source community's minds for the last few years it has been creating a WUG in George and eventually expanding that to the whole Garden Route area. This was actually one of the first things that was on the agenda of the now-defunct Garden Route LUG called "GROSSUG" but, as is typical in George and particularly the GROSSUG, there was a whole lot of talking and some really great ideas but little to no action. It was actually so bad we probably could have joined the national government.

Anyway, getting back to the wireless stuff. Justin Miles restarted the discussion and I'm now starting to think that it could finally be the time for something like this to run. Pretty-much everybody I spoke to over the last few years are pro the idea but now we need to start to translate words into actions.

The advantages of such a network is immense to the local community. For example, the ability to make free and unlimited voice calls to anywhere in the area; free and unlimited VPN access into your company's network from home; free and unlimited access to local FTP servers to download your favourite Linux ISOs, etc.

We will be holding a meeting about this soon, probably combine it with the same meeting as the Garden Route ID meeting. I am currently talking to various people so will let you all know ASAP of the date and time and location.

Garden Route ID

I just landed back in George on Sunday and had a good rest yesterday morning. Yesterday afternoon I had a very interesting discussion with Greg Roodt of HandMade SoftWare.

There has been a lot said around the web the last few months about creating trust relationships, closed (non-anonymous groups) on the web as well as improving on the signal-to-noise ratio. We don't want to spend more time online, we want to spend quality time.

One of the things that have made the web great is the ability to be anonymous and have a certain level of freedom that isn't always accepted in society in general. However, along with this you also got a huge amount of abuse, especially by spammers and stalkers. These days, many people are starting to believe that anonymity is not everything in life and sometimes the ability to trust and be trusted is better.

Therefore, we are starting with our latest (local) initiative. For lack of a better name, I call it the Garden Route ID for the moment...

Essentially, this is the way I see it:

We have a website that allow users to log on, but not to register. We have a list of verifiers and their locations on the site. The user must go to one of the verifiers, who are generally trusted in the community, to physically identify themselves and show that they are a "real person". The verifier would take down their contact information (telephone number(s), physical address, etc) and allow them to choose a unique username together with a password.

After this, users can log in and update their own information as they need. However, being the Garden Route ID, they need to stay within the Garden Route area to continue to make use of the service.

The Garden Route ID site can then effectively function as an OpenID provider. If the user has a Garden Route ID account, you know they are part of the network and can probably be trusted. And if they generate abuse, it should be reasonably easy to track them down and/or remove their account and ban them out of joining back into the system.

There are cases where a third-party site might decide to allow only Garden Route ID "holders". There are also cases where it would simply be a single sign-on alternative. After all, the site is a full OpenID provider so it can be used for any OpenID enabled site. In some cases however it can even work in a kind of a "we'll give you special treatment if you have a Garden Route ID" scenario. You could get access to more services, quicker. For example, if you submit a classified ad or comment, instead of having to wait for it to be approved by the site administrator, it could be published immediately because you're now part of the "trusted" network.

There are benefits for everybody in this and I think it'll be a very interesting experiment. We will be holding a physical meeting about this in the next week or two but dates have yet to be confirmed. It is likely to be combined with some other stuff all in one evening, at least for the initial talks, but I'll publish the information here as it becomes available.

Syndicated Content on Facebook

Facebook started out as a social networking platform but has since evolved into a more complete "portal" environment (dare I use that word - it got badly associated with bloat the last few years). Pretty-much everything is syndicated into Facebook these days - links, photos, videos, news, you name it!

The other day we had an extremely interesting discussion in the comments on a post on iMod about a new Facebook news application.

One of the pretty common things I see around South African news syndication applications is that they particularly focus on placing information onto the profiles of the users who add them. This does not really make sense to me at all; profile pages are for information relating to a particular user surely, not for general syndicated content?

My solution has been to syndicate stuff onto a separate canvas page up to thus far. However, as Chris put it on one of his comments:

[...] I stick to my limitation of select applications on my profile, so I don’t have to click around so much [...]

That makes a lot of sense to me as well. For example, think about iGoogle. It allows you to get a good overview of the day's happenings without going to a lot of separate pages.

So, essentially we want the ability to have separate boxes on one page, but not necessarily on somebody's profile. What's the point of placing stuff on your own profile if it's mainly for you to read? Isn't your profile for other people primarily? You don't want to see all of your own personal information (which you already know, I presume?) and other people don't want to read all your favourite newsfeeds necessarily. If they come to your profile page, they probably want to find out more about you.

Reducing bloat on profile pages is definitely on the list of priorities for Facebook and this really points out a limitation in Facebook's framework that would help. Obviously this is a use that has evolved over time so there was no way they could have foreseen this. The fact is that Facebook is starting to replace the function of services such as iGoogle in some ways. It allows you the functionality of being able to read your news and interact with your friends all on one site and even integrate the two activities (like with "share this" buttons and who knows what else into the future).

Ideally the user needs a separate page, a bit like the homepage with all their friends' activities, but filled with individual boxes that can be added and populated by different applications much in the same way as on profiles.

Then, we can make the profile pages much cleaner and more focused, and let the user have their own page for their choice of syndicated content.

Obviously we can also allow the user to easily publish a list of their favourite news sources on their profile pages and even expose this new "news" page (or parts thereof) to other people. "What does Charl like to read?"

Read the comments on iMod for more discussion about this.

GardenRoute.com Facebook App Profile Badges

Finally I have a chance to relax again so I thought I would finish off some loose ends. I added some options for profile badges to the GardenRoute.com Facebook App. Syndicating news to somebody's profile page is actually a very silly idea in my opinion. I got the idea from another app and was copying that but actually it was pretty stupid of me. At least this concept makes some sense (I hope).

Muti Wordpress 2.5 Plugin

After some discussion via mail I created my first Wordpress plugin this afternoon. It's very simple and will add a little "Muti This" button to the bottom of your posts.

<?php
/*
Plugin Name: Muti
Plugin URI: http://muti.co.za
Description: Adds a muti button at the bottom of each post.
Author: Charl van Niekerk
Version: 1.0
Author URI: http://charlvn.za.net
*/
function muti($c) {
  return $c . '<p><a href="http://muti.co.za/submit?url=' . urlencode(get_permalink()) . '&amp;title=' . urlencode(the_title('', '', false)) . '"><img src="' . get_option('siteurl') . '/wp-content/plugins/muti/muti.gif" alt="Muti This" title="Muti This" /></a></p>';
}
add_action('the_content', 'muti');

To install it get muti.zip and put the muti directory inside of your wp-content/plugins directory. Then just open your Wordpress admin back-end and enable the plugin as usual.

This has been created for and tested on Wordpress 2.5; it may or may not work on older versions.

Please let me know what you think and if you have any suggestions for improvements!

OAuth: Good or bad?

After my recent mashup idea I started thinking about the actual implementation. The only thing that bothers me about this particular project is the API integration and the security.

The calls to Muti for submitting posts and voting posts up (or down, if that is ever enabled again) will require some user authentication. The same goes for the API call to Afrigator to get the user's MyGator posts.

There are obviously various different ways to do this authentication. I could request that the user give me both their Afrigator and Muti usernames and passwords. However, that will mean I have to store it on my side somehow. Users will not want to input this every single time surely so I'll probably have to keep it in persistent storage. However even keeping it in temporary storage is risky. Obviously I'm not unethical and will go to every length to ensure the security of this information but I also don't want to be burdened with this confidential information. The web server(s) I will be running the mashup on will probably be shared and there's anyway no way for me to guarantee perfect security (or even come close to it) even if I ran it on a dedicated host.

This is one of the issues I have with Twitter at the moment. I don't like it one bit but for each Twitter mashup that requires authentication I will have to give it my original Twitter username and password as that's what the API calls require.

The most common solution to this is to use a "shared secret". This is basically like a randomly generated password that gets used only between two different sites to authenticate API calls. Therefore the user's original username and password on either site does not have to be shared with the other.

In my previous post I hinted at OAuth as that seems to be the upcoming industry standard for API authentication just like OpenID became the industry standard for cross-site user logins.

Although there are quite a few library implementations out there, there are not that many actual implementations. The only place I actually saw it in action so far (although I have to admit that I did not do a lot of searching around the interwebs) in a production environment is between Magnolia and Nsyght. Twitter has been working on it for a long time now but apparently the actual implementation is somewhat more tricky.

Anyway, on the one side I would really like to see both Afrigator and Muti implement OAuth for their API authentication as I figure we would be quite well ahead internationally if we were to do that. On the other side I would not blame Neville nor Stii if they were somewhat reluctant to implement OAuth as it seems to have yet to "prove" itself. The standard is also not one of the simplest and writing your own library might take some time. Using a third-party library that is not too well "settled in" yet might also have its risks.

I was about to send them private mail but then thought it's best to actually do this discussion in public as I think this is of general importance to the industry (internationally) at the moment. I am also looking to use OAuth for various of my own products shortly but I'm somewhat unsure so I would love to hear what other developers out there think. Please let's get a discussion going; blog, comment, go wild. Should we go with OAuth? Invent a simpler specification? Just use plain old usernames and passwords? Would love to hear your thoughts! :)

tert-Butylhydroquinone Cytotoxicity

Tertiary butylhydroquinone (TBHQ) is very often used as an antioxidant in food in South Africa. It's been outlawed in some countries, for example Japan.

Although results are inconclusive, there is reason for worry. From 898. Butylhydroquinone, tert- (TBHQ) (WHO Food Additives Series 40):

The potential of BHA and it primary metabolites TBHQ and TBQ to induce oxidative DNA damage and cell proliferation in human lymphocytes cultured in vitro was investigated. Analysis of the culture medium and lysed cell fractions indicated that TBHQ was actively metabolized in whole blood. No conjugation of TBHQ to glucuronic acid or sulfate was observed. Addition of BHA, TBHQ and TBQ to lymphocytes resulted in a dose-dependent increase in cytotoxicity. TBHQ appeared more cytotoxic than TBQ and TBQ more than BHA. At non-cytotoxic doses, TBHQ induced a dose-dependent increase in cell proliferation as estimated by incorporation of BrdU. TBHQ was also shown to induce the formation of 8-oxodG at non-cytotoxic doses. Of the compounds tested, TBHQ appeared to be the best inducer of both cell proliferation and 8-oxodG formation. These effects were inhibited by co-administration of acetylsalicylic acid, which inhibits prostaglandin H synthetase, thus preventing oxidation of TBHQ to 2- tert-butyl-semiquinone (Schilderman et al., 1995).

So what if this was in vitro, this is still not good. TBHQ and TBQ have long been associated with DNA damage. Damaging lymphocytes? Now that is just plain evil in an area where AIDS is already a major problem. Bah!

Afrigator / Muti Mashup Idea #1

Now with Afrigator and Muti both getting APIs, I thought I should jump the gun and basically throw my first idea out there.

What I want to do is this. I want to let a user log in (using OpenID of course) and then let him associate his account (ideally using OAuth) with both his Afrigator account and his Muti account.

Then I want to retrieve a list of his latest MyGator posts from Afrigator and for each one of them check if that post has been submitted to Muti. If so, I want to use the amount of votes it received and order according to those votes.

For example, say there are five posts. Post A received -2 votes on Muti, post B received 1 vote on Muti, and post C and post D have both not been Muti'd at all, and post E received 5 votes. Post C was published after post D however.

In that case, post E would appear first because it has the most votes. Then post B would appear since it has at least 1 vote so somebody submitted it and it has not been voted down (yet). Then post C and post D would appear because they were not Muti'd so we will assume their score is 0 (no votes). C will appear ahead of D however because the two have the same score we will fall back on chronological order. Then post A would come in last since it has been Muti'd but has been voted down quite badly.

Of course for each post you would be able to see the status (Muti'd or not Muti'd), be able to Muti it if it hasn't been already and be able to vote it up or down if it has, and if it has been Muti'd the actual score.

Any thoughts?

hKit and Tidy

Tonight I was using hKit to parse some hCards but I was trying to use it together with PHP's Tidy extension and I ran into some issues. I had to replace references to a function dom_import_simplexml which actually does not seem to exist with a function simplexml_import_dom which does actually exist. There were also some issues in the actual use of Tidy.

Anyway, here comes my subversion diff on the latest checkout from the subversion trunk at time of writing.

Index: hkit.class.php
===================================================================
--- hkit.class.php (revision 14)
+++ hkit.class.php (working copy)
@@ -86,7 +86,7 @@
   {
    // pre-flight checks
    $pass   = true; 
-   $required = array('dom_import_simplexml', 'file_get_contents', 'simplexml_load_string');
+   $required = array('simplexml_import_dom', 'file_get_contents', 'simplexml_load_string');
    $missing = array();
    
    foreach ($required as $f){
@@ -192,7 +192,7 @@
         }
        
         // td@headers pattern
-        if (strtoupper(dom_import_simplexml($result)->tagName)== "TD" && $result['headers']){
+        if (strtoupper(simplexml_import_dom($result)->tagName)== "TD" && $result['headers']){
          $include_ids = explode(' ', $result['headers']);
          $doc   = $this->doc;
          foreach ($include_ids as $id){
@@ -217,7 +217,7 @@
     
      if ($results){
       foreach ($results as $result){
-       $tagName = strtoupper(dom_import_simplexml($result)->tagName);
+       $tagName = strtoupper(simplexml_import_dom($result)->tagName);
        if ((($tagName == "OBJECT" && $result['data']) || ($tagName == "A" && $result['href'])) 
          && preg_match('/\binclude\b/', $result['class'])){ 
         $att  = ($tagName == "OBJECT" ? 'data' : 'href');      
@@ -250,7 +250,7 @@
   private function getNodeValue($node, $className)
   {
 
-   $tag_name = strtoupper(dom_import_simplexml($node)->tagName);
+   $tag_name = strtoupper(simplexml_import_dom($node)->tagName);
    $s   = false;
    
    // ignore DEL tags
@@ -314,8 +314,9 @@
     break;
     
     case 'php':
-     $tidy  = tidy_parse_string($source);
-     return tidy_clean_repair($tidy);
+     $tidy = tidy_parse_string($source, array('output-xhtml' => true));
+     $tidy->cleanRepair();
+     return $tidy;
     break;
       
     default:

Hope this helps somebody. :)

I named the robot (and other stuff)

Name That Robot

Name That Code

How Much Do You Hate Myspace?

The Blog-O-Cuss Meter - Do you cuss a lot in your blog or website?

Twitter Public Timeline Caching

I need to create a Twitter application that receives a copy of all the messages in the public timeline for indexing. I quickly noticed that the public timeline is rather busy and that I'll probably have to poll once every 5 seconds. Then I discovered that the public timeline isn't even updated every 5 seconds. So I wrote a quick script to test this.

<?php
$prevLast = null;
$duplicates = 0;
for ($i = 0; $i < 1000; $i++) {
  $ch = curl_init('http://twitter.com/statuses/public_timeline.xml');
  curl_setopt($ch, CURLOPT_FORBID_REUSE, 1);
  curl_setopt($ch, CURLOPT_FRESH_CONNECT, 1);
  curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
  $s = curl_exec($ch);
  curl_close($ch);
  $xml = new SimpleXMLElement($s);
  $first = (string) $xml->status[19]->id;
  $last = (string) $xml->status[0]->id;
  if ($last == $prevLast) {
    $duplicates++;
  }
  elseif ($prevLast && $first > ($prevLast + 1)) {
    echo "Miss: " . ($first - $prevLast - 1) . " (Duplicates: $duplicates)<br>";
    ob_flush();
    flush();
    $duplicates = 0;
  }
  $prevLast = (string) $last;
  sleep(1);
}
if ($duplicates) {
  echo "Duplicates: $duplicates";
}

The results looked pretty bad.

Miss: 387 (Duplicates: 27)
Miss: 451 (Duplicates: 28)
Miss: 370 (Duplicates: 40)
Miss: 370 (Duplicates: 37)
Miss: 306 (Duplicates: 35)
Miss: 312 (Duplicates: 41)
Miss: 376 (Duplicates: 38)
Miss: 387 (Duplicates: 28)
Miss: 339 (Duplicates: 30)
Miss: 379 (Duplicates: 27)
Miss: 347 (Duplicates: 39)
Miss: 335 (Duplicates: 29)
Miss: 312 (Duplicates: 29)
Miss: 317 (Duplicates: 34)
Miss: 314 (Duplicates: 38)

That's just the first part, I don't need to paste all the output.

Goodness gracious! Luckily there is a solution. Alex Payne said on Twitter Development Talk that one can e-mail him and he would be able to set you up to syndicate all the latest Tweets to your own Jabber bot via XMPP. That's my project then for next weekend perhaps.

Afrigator: Give us an API!!

Note for non-techies: Basically the short version is that I am suggesting that Afrigator provide the ability for third-party developers to extend its functionality and integrate it into their own applications like Twitter and many other web services.

I'm up in Botswana with Neville at the moment and it's going pretty hectic so please consider this an update "from the road". :)

Basically the idea is that I need to give one idea that I would like to see implemented in Afrigator according to Mike's post so here we go.

Obviously I would like to see a lot of things relating to the semantic web, more Microformats integration, FOAF/RDF, OPML, etc.

A Facebook application that allows you to link up your Facebook Profile with your Afrigator account and syndicate your blog posts to your Facebook profile would also be cool. You could have messages popping up in your Minilog when you post something new and even an Afrigator box on your profile listing your blogs. This means you don't need to use another service to pull in your RSS/Atom feeds separately. You add each of your blogs in Afrigator and that automatically reflects on your Facebook profile.

Also, I know they have OpenID going, but how do I log in using it? What is the trick?

A better search feature... now that would be cool. For example, let's say somebody types in "charl van niekerk", they should get a list of all my blogs. At the moment they will just get crap. So some intelligence there would be awesome.

And what about some XMPP integration. Syndicate stuff over it, save a lot of bandwidth because you're using a push technology and not a pull technology. Cover Jabber, Google Talk, Fring, Yeigo, MXit, all in one go with an open standard like XMPP. Then if a new entry gets posted on one of your favourite blogs, you immediately get an instant message as soon as Afrigator detects it! This could even work for other protocols like MSN, IRC and perhaps Skype.

But now hold on for a second... That is already quite a list. I need to pick one thing that I would like to see. I don't like compromising here so I managed to figure it out. What I want is a full API.

But, why? Well, let's think about Twitter. The service itself is dead simple. It's almost frightening to think how little functionality it offers relative to something like Jaiku. So then, why is it so popular? Well stuff Twitter, that's just a base platform. I almost never go to twitter.com and use the actual site unless I'm changing my account details.

The nice thing about Twitter is that there are a huge amount of third-party applications built around its API. You have an idea, a feature you would like to see in Twitter? No problem, you write your own system that integrates with the Twitter API and you can have whatever you like - the sky is the limit.

So in other words, I don't need to beg and wait them to implement stuff. I can go and do it myself.

Ok, so WTF has this got to do with Afrigator? Simple: if they follow Twitter's lead and get a good powerful API going, then I can go and create my own mashups myself. I can go and hack some code together to do whatever I like. Also, lots of the stuff that I mentioned at the start of this post.

So the choice is obvious. I picked my one thing: an API. Twitter's success can largely be attributed to it I believe, and I'm sure this will work for Afrigator as well.

So, come on Stii, what do I need to bribe you with? Coffee? Beer? Pizza??? ;)

Copyright © 2004-2008 Charl van Niekerk. All articles are released under the Creative Commons Attribution 2.5 South Africa licence, unless where otherwise stated.