Profiling AppleScript code

This looks promising. Shark is a tool that can be used to profile code. I haven’t done any serious profiling since some python script I was working on years ago on BeOS. Daniel Jalkut has a nice post, Shark Bites Script up on his blog, on how to use Shark to profile AppleScript code. Since I’ve been doing a bit of AppleScripting lately, and I have some code that is in serious need of optimisation, this might be worth a second look.

Random Post Link

Another Blogsome user wanted a Random Post to be displayed on the home page. I haven’t quite figured out how to get the actual post displayed, but a link to a random post should be pretty easy. Luckily, WP-MU uses post ids. If we can get the latest post id, then we should be able to get a random number between 1 and this. We can then check to see if the post exists (it may have been deleted: WP does not reuse post ids), and if it doesn’t, get another random number, and keep doing this until we find a post id that is still valid. It’s then a simple step to create the permalink. The first problem arises when we try to get the latest post. We could use {the_author_posts}, but this will give us the number of posts, which means if the user has deleted n posts, the last n posts will not be in the selection of random posts. This is not necessarily such a bad thing, as it will mean that older posts are likely to be used. The next problem of {the_author_posts} is that it must be used within The Loop. If we are planning to put the link before we have been through ‘The Loop’, then we should be alright. The third issue of {the_author_posts} is that with a multi-author blog, the random number will be much lower than the total number of posts, meaning even older posts are only likely to be selected from. Another option would be to say “Okay, I want a random post lower in id (ie, older than) every other post on the page.” This makes things much easier, but is limited to the same problem of not being able to be placed before the loop, as we’ll set a variable to the post id on each post as we come to it, and since most blogs are ordered in descending order, the last post visited will (or should) have the lowest id. The problem here is that a category view may have a very low post count, and it’s oldest visible post may be a very early post. The third option would be to say “I want a post that is older than the newest post on the page.” Again, the limit as to where this must appear is present. However, an additional problem is that we may get a link to a post that’s already visible. This third one to me seems to be the best compromise. So how do we get this post id? We’ll need to modify our post.html file under Blogsome. {capture name=max_id}{the_ID}{/capture} {if $smarty.capture.max_id > $max_id}{assign var=max_id value=$smarty.capture.max_id}{/if} This code can go anywhere: I stuck it right at the bottom, out of the way. The next part should only be done once: {math} is quite processor intensive, so do it just where you want the object to appear: {math equation="rand(1,n)" assign=rand_post n=$max_id} Our final code is to grab the permalink and title for this post. However, I cannot yet find a way to get the title, so we are stuck not knowing the post title: Random Post I’ve tried using {get_post} and {get_postdata}, but since the latter returns an Array, it’s not much use. Returned Arrays are no good - the value needs to be assigned to a variable for us to be able to access it. It’s probably possible to alter the query, or rerun a new query, but I’m getting to tired to do this right now.

Limiting Smarty {foreach}

A user on the Blogsome forums wanted to be able to reduce the number of items that appeared in a Smarty generated list. Since the original code was using {foreach}, and I know {section} has a max=n attribute, I thought I’d try that. The problem was that the Array in question: {popularposts} generates $pposts; is not an array that can be accessed by indices. It’s key instead is the number of hits on the pages, so that’s not much good to us. However, it’s possible to use a simple {if} clause, and the {counter} function, to _effectively _limit the number of iterations.

1
2
3
4
5
6
7
    {counter assign=idx print=0}
    {foreach from=$array key=key item=item}
        {counter}
        {if $idx < = n}
            Data to be repeated goes in here.
        {/if}
    {/foreach}

Replacing n with a number will cause n-1 iterations to be displayed. I said effectively above, as the other iterations will actually occur, but no data will actually be printed on the screen, as there is no {else} clause.

Related Stories.

After hacking through the source, I finally figured out how to make {relatedstories} work. The trick is that it stores the date in a variable called $relatedstories.

    {relatedstories}
    {if $relatedstories}
      <h2>Related Stories</h2>
      <ul>
      {foreach from=$relatedstories key=key item=story}
        <li> <a href="{get_permalink id=$story->ID}" >
            {$story->post_title}</a>
        </li>
      {/foreach}
      </ul>
    {/if}

I’ve got it set up in my sidebar at the moment. It’s smart enough to figure out when it’s not a single post page, and won’t show then, so you don’t need any fancy extra Smarty Tags to only show in single post view. Oh, and it also sets the variable $relatedstoriesWords, so it’s possible to do something like: <h2 title="{$relatedstoriesWords}">Related Stories</h2> and when you hover over the title, it tells you the words it’s looking for. I’m still working on how to truncate the title. {$story->post_title|truncate} fails dismally. Quite annoying.

Blogsome Forum RSS feed.

Blogsome has implemented RSS feeds in the forums: RSS: click if your RSS syndicator can handle feed: URIs. RSS: an http: link to the feed.

Tiger kills Acrobat Distiller 5 (Classic)

Since upgrading to Tiger, Jaq obviously hadn’t done any creating PDFs in Distiller. It still uses Classic, and Tiger upgrades stop it from actually producing the PDF files. However, there is a solution: open up Distiller, and change the Job Options... settings for all of the profiles, so that _Fast Web Vie_w, and Embed Thumbnails are both unchecked. Bingo, works again.

Pigsy says:

Better bury a priest alive than stop him getting his fill.

Strangest Spam

I received the strangest Spam today. Gmail didn’t flag it as Spam, but that’s because there isn’t much to it:

X-Gmail-Received: 207621b91521d8580702cc6b8f5dc303db882c71
Delivered-To: xxx@gmail.com
Received: by 10.70.73.14 with SMTP id v14cs27376wxa;
        Sun, 16 Oct 2005 21:21:02 -0700 (PDT)
Received: by 10.36.105.16 with SMTP id d16mr2452237nzc;
        Sun, 16 Oct 2005 21:21:02 -0700 (PDT)
Return-Path: <onisimvfdi@aucklandnz.com>
Received: from m1.dnsix.com (m1.dnsix.com [63.251.171.164])
        by mx.gmail.com with ESMTP id e1si1376069nzd.2005.10.16.21.21.02;
        Sun, 16 Oct 2005 21:21:02 -0700 (PDT)
Received-SPF: neutral (gmail.com: 63.251.171.164 is neither permitted nor denied by best guess record for domain of onisimvfdi@aucklandnz.com)
Date: Sun, 16 Oct 2005 21:21:02 -0700 (PDT)
Message-Id: <435326ae.1e47a7b1.2e3f.ffffea7aSMTPIN_ADDED@mx.gmail.com>
Received: from [221.169.78.40] (helo=aucklandnz.com)
	by m1.dnsix.com with smtp (Exim 4.44)
	id 1ERF09-0008R3-2k
	for xxx@xxx.com; Sun, 16 Oct 2005 13:21:01 -0700

<!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML 2.0//EN">
<HTML><HEAD>
<TITLE>404 Not Found</TITLE>
</HEAD><BODY>
<H1>Not Found</H1>
The requested URL was not found on this server.<P>
<HR>
<ADDRESS>Apache/1.3.31</ADDRESS>
</BODY></HTML>

No web addresses, one email. I think maybe this Spammer had a problem… The two IP addresses listed as the first sources, those Received: headers that appear first, are both Private Range IP addresses, but the m1.dnsix.com one seems like the service provider. Oh well, no biggie.

(kind of) Fix for XMLRPC bug.

I’ve been playing around with the version of the WP-mu source that’s used on Blogsome’s servers, trying to find the exact point where the bug is that escapes apostrophes and quotes.

Basically, the XMLRPC client contacts the server, and sends the data in. According to the console, the content of the post is actually in a field called description.

Searching through the XMLRPC file I find only five references to the word description. Two of these are in functions to do with posting. Both are basically the same, one is for blogger, the other metaweblog type connections:

1
    $post_content = apply_filters('content_save_pre', $content_struct['description']);

Now, a bit of research showed up that apply_filters is a function that allows plugins and their ilk to access the data before it gets saved to the database. Now, I’m fairly sure it is not a plugin doing this.

I also discovered that it is likely that the update to XMLRPC.php that happened was accompanied by a change to another file, that calls stripslashes(), another WP function. The XMLRPC update was, after all, a fix that removed the ability for XMLRPC calls to run unescaped code. So it makes sense that it escapes stuff.

In the short term, I discovered ecto has the ability to automatically run a script as you post: in the New Post window, make sure Options are showing, and choose the Formatting tab. (Incidentally, if you are only using double-quotes, it seems the Smarten Quotes will help, but it may mess with code).

I use a script that is like this to fix everything up:

1
2
3
4
5
6
7
import sys
data = open(sys.argv[1]).read()

data = data.replace(“'”,“'”)
data = data.replace('“',”“”)

open(sys.argv[1],'w').write(data)

This on its own is not enough - I seemed to have to go into the HTML editing mode before it would work. I think ecto does its own conversion of certain HTML entities to real characters.

This post is a test post to see how it all goes with <pre> tags and the like.

Interactionless Catchpa

Over on this site, I read about a system that seems to be a bit like mine (only perhaps more complicated). It did give me one idea though: I could automatically populate the value into the box. Or even more simply, have the JavaScript simply fix up the action="" attribute. Then the user just needs to set the action attribute to a whitespace string, and then the JavaScript will make it possible for the reader to submit comments. I’m not sure if this would really be all is needed to prevent Spam comments. Requiring JavaScript to be on… • And trackbacking it gave me another idea: setting the action on a trackback URI to copy the URI to the clipboard. That would be cool. Or making the ‘LinkThis’ bookmarklet get the trackback URI from the page. Should be able to look for a link with rel="trackback", and use the href from this. Okay, this bit works, but again I’ve run into the problem that I’m trying access an ‘off-site’ document. And I cannot do that with JavaScript.

1
2
3
4
5
    var a = document.getElementsByTagName('a');
    var tb = '';
    for (var i=0;i<a.length;i++){
        if (a[i].rel=="trackback") 
            tb=a[i].href;};

That code fragment will get the trackback URI. But there’s no argument I can pass to the bookmarklet.php file that will insert this automatically. Something to add to the Blogsome wishlist, I guess.