Finally migrated to Mephisto

Big sigh of relief…

… and yes, everything went fine. Well, mostly. If something looks amiss, please use the brand new feedback page (thanks Rick!) to let me know. I’ve tried to redirect most existing urls to their new ones as Mephisto and Typo slightly differ on how they generate the permalink portion, but may have missed a few (so if you get an error page when something used to work, please do let me know!).

After much hesitation, and having dreaded the minutiae of the conversion, I’ve finally made it!

In fact it was the switch to a brand new VPS with a 1Gb of memory that was the trigger. Since I was reinstalling everything from scratch (more on that shortly), I figured now was the time to bite the bullet. And it went much easier than I expected :). I’ll try to put down some notes on some the pitfalls to avoid within a few days.

Suffice it to say that I’m quite happy with the result and this blog is now running with nginx (yeah!!!) and a cluster of mongrels on a fined tune gentoo vps (I’ve kept detailed notes that I will share soon).

I’ve also ported the Brighthouse theme by Richard White to Mephisto and will add it to the Mephisto Theme Gallery as soon as I get to clean it up and remove the nano RAILS specific stuff. In fact, I’m curious as to whether you would rather have the theme with AdSense and TextLinkAds:http://www.text-link-ads.com/?ref=14245 (aff) included, or maybe the ability to turn them on/off?

Also new is the Archives page, and hopefully the new error page will help people find what they were looking for.

in News | 293 Words

A new Rails plugin for TextLinkAds (including support for Feedvertising)

Change of Strategy

Instead of updating my constantly breaking Typo sidebar plugin, and to implement Feedvertising from TextLinkAds, I’ve changed gears and chosen to implement just a regular plugin (very close to the new way of doing sidebar plugins in typo 4.1). This approach should work in all versions of typo, as well as any other Ruby on Rails’s application.

The support for feedvertising is slightly different than the one from the WordPress plugin that is the only option offered so far, but should be fairly close.

Installation

Get the plugin from subversion:

script/plugin install http://svn.nanorails.com/plugins/textlinkads/

or to use svn:externals and get future updates via svn update

script/plugin install -x http://svn.nanorails.com/plugins/textlinkads/

The installation will copy a file textlinkads.yml into your config directory.

The file looks like this:

key: TLA_KEY
affiliateid: 0
title: Sponsors
advertisehere: Advertise here!
testing: false
caching: true

Replace TLA_KEY with the one provided by TextLinkAds, set your affiliateid if you’d like to have a link to TextLinkAds with your affiliate id (so you can get credit if someone signs up for a TextLinkAds account). Change the title and advertisehere messages if you don’t like the defaults.

Set testing to false once you’ve verified it works (while testing=true, the plugin will use a special page provided by TextLinkAds that displays to links. However, that page does not contain any RSS links)

Finally, if the caching done by Rails is not enough, the plugin can cache the calls to retrieve the links. See the caching section for explanations on how to setup caching.

Integrating with Typo

Adding the display of regular links

To add the regular TextLinkAds links, you need to add a call to render_TLA anywhere in the rendering code. In typo, the most likely place is in your template’s default.rhtml

Here’s what my template looks like


<div id="sidebar">
  ...
  <div class="sidebar-node"><%= render_TLA %></div>
  <% response.lifetime = 6.hour %>
  <%= render_sidebars %>
</div>

to replace the original:


<div id="sidebar">
  <%= render_sidebars %>
</div>

Add the RSS links

For RSS2.0 for example, edit the file app/views/xml/_rss20_item_article.rxml to add a call to render_TLA_RSS(post_id)

here’s the original file:


  xm.item do
    xm.title post_title(item)
    if this_blog.show_extended_on_rss
      content = item.full_html
    else
      content = item.body_html
    end
    xm.description content
    xm.pubDate pub_date(item.published_at)
    ...

xm.item do
  xm.title post_title(item)
  if this_blog.show_extended_on_rss
    content = item.full_html
  else
    content = item.body_html
  end
  content += render_TLA_RSS(item.id)
  response.lifetime = 6.hour
  xm.description content
  xm.pubDate pub_date(item.published_at)

Depending of which format you need, you may need to edit a different file.

That’s it.

Integrating with other apps

For other apps, just take a similar approach and add calls to render_TLA and render_TLA_RSS where most appropriate. Both calls are accessible from any Controller or Helper class.

Caching

Set “caching: true” in textlinkads.yml. Make sure Rails is configured with some caching. Typically, you need to have


config.action_controller.perform_caching = true
config.action_controller.fragment_cache_store = :file_store, "#{RAILS_ROOT}/tmp/cache"

either set from config/environment.rb or config/environment/[CURRENT ENVIRONMENT].rb

This will cache the pages where the ads appear, and cache the feed pages. But to make sure these pages will update properly if the TextLinkAds ads inventory is updated, you must ensure the cache will expire.

The best way to do that is to use the expiring_cache_action plugin. To install:

script/plugin install http://typosphere.org/trac/browser/trunk/vendor/plugins/expiring_action_cache

Then where you added calls to render_TLA, just add:

response.lifetime = 6.hour

This way, the cached page will expire 6 hours later so that would be the lapse of time to wait to see the updated ads.

No need to expire the cache for RSS, it should get expired automatically every time an article is added.

If you use this plugin in other applications, add a comment or send me a not (psq_0×40_nanorails_0×2e_com) and I’ll add a link to your instructions or code.

Adding CodeHighlighter to Typo

Recently, I ran across CodeHighlighter by Dan Webb. This looked like a pretty cool javascript, and I thought a better way than to do it on the server side.

Adding it to typo is fairly straightforward, baring a small patch.

Get the code

Get it from Dan’s site via subversion: http://svn.danwebb.net/external/CodeHighlighter/trunk

svn co http://svn.danwebb.net/external/CodeHighlighter/trunk

Adding CodeHightlighter to your template

Add to your template (themes/[YOUR THEME]/layouts/default.rhtml)

<%= javascript_include_tag "code_highlighter" %>
<%= javascript_include_tag "javascript" %>
<%= javascript_include_tag "css" %>
<%= javascript_include_tag "html" %>
<%= javascript_include_tag "ruby" %>

The code as provided by Dan has a small incompatibility with prototype used by Ruby on Rails. The following line

for (var i in this.styleSets) highlightCode(this.styleSets[i]);

behaves quite strangely and will pretty much kill your browser (Firefox runs out of memory and displays a bunch of “undefined” after several minutes) because it ends up calling hightlightCode way too many time because of all the methods added to all objects.

To make codehighlighter.js play nicely with prototype.js, replace that last line with:

if (this.styleSets.each) {
  this.styleSets.each(highlightCode)
} else {
    for (var i in this.styleSets) {
      highlightCode(this.styleSets[i]);
    }
}

Essentially, if prototype is present, we can use each to iterate on the styles, otherwise it is safe to used the old code.

Using Codehightlighter

Now, addng styling is easy. Using Textile, you can just put your code around a <pre> and a <code> block. If you have a javascript snippet, use a class of “javascript”.

For example:


<pre><code class="javascript">
if (this.styleSets.each) {
  this.styleSets.each(highlightCode)
} else {
    for (var i in this.styleSets) {
      highlightCode(this.styleSets[i]);
    }
</code></pre>

The other available styles are “html”, “css” and “ruby”.

For example, here’s how ruby would look like:

  def display_article(article = nil)
    begin
      @article      = block_given? ? yield : article
      @comment      = Comment.new
      @page_title   = @article.title
      auto_discovery_feed :type => 'article', :id => @article.id
      render :action => 'read'
    rescue ActiveRecord::RecordNotFound, NoMethodError => e
      error("Post not found...")
    end
  end

And it looks easy to create other styles. See the stylesetguide.html file for details.

Update: Turns out Dan already had a fix, so if you grab the trunk, you will be fine.

Here’s his version of the patch:

    for (var i=0; i < this.styleSets.length; i++) {
        highlightCode(this.styleSets[i]);
    }

Upgraded to Typo 4.0

Well, the upgrade to Typo 4.0 didn’t go so well. No data loss though, so everything’s cool.

At least most pages seem to be functional, so this is not so bad. Combined with having custom sidebar plugins that no longer work, the fact that the merge between the new code and my old one did not quite go as planned, it was not a too pleasant (most of it my own fault I guess).

Anyway, it is getting really late and I’ll finish the rest of the migration tomorrow.

If you tried to access the site while this was going on and you were inconvenienced, pleas accept my most sincere apologies!

If you notice anything weird, please send me a mail at psq _at_ nanorails _dot_ com.

Update, about 20h later, some sleep…: It seems that everything is back up, I migrated my custom plugins to typo 4.0 (about removing 1 file, removing half of the code linked to configuration and adding a few lines) and it seems that everything has been working smoothly :)

And the best of all of that: no more trackback spam! Well, not that it went away, it caught about 25 since last night, but they don’t get published anymore. Just for that, it was all worth it. Thank you everyone in the typo team!

Update 2: Well rails 1.1.5 came out, and it was not enough, so rails 1.1.6 came out and seems to be strong enough to fill in the security issues

And in the process, I also upgraded to Typo 4.0.2

That last upgrade went very smoothly!

However, I’ve had a few annoying cases of nanoRAILS hanging and not responding for hours on hand till I killed the processes. I don’t know yet at this point whether it is due to the new version of rails, the new version of typo, or pehaps some settings that changes on dreamhost. In any case, I’ve installed my own version of ruby and the full set of gems, so we’ll see if that helps!

TextLinkAds Typo Sidebar Plugin

Based on “Displaying ads from TextLinkAds in a rails application”, here’s the first release of my typo sidebar plugin to display ads from TextLinkAds. The plugin uses typo built-in caching as I explained before.

Download

Download either textlinkadssidebar.zip or textlinkadssidebar.tgz.

Installation

Unzip (unzip textlinkadssidebar.zip) or untar (tar xzvf textlinkadssidebar.tgz) directly into the components/sidebars/ directory of your typo installation.

Configuration

Using the sidebar tab of the admin section of typo, you’ll find an Item named “Text-Link-Ads” on the left hand side.

Simply drag it to the right side where at the desired location (the higher the better!).

Enter a title for that section (here I use nanoRAILS Sponsors).

Fill in your XML KEY from the “Get ad code” section on TextLinkAds.

Enter your affiliate ID (so you can get paid for referrals).

Enter the text for the referral link (I have “Advertise on nanoRails”).

Click on the Publish Changes button.

Once you refresh your blog, you will have a TextLinkAds section.

Text Link Ads

6/15/06 update: to use in the trunk of typo (1055 currently), you will need textlinkadssidebar-1055.zip or textlinkadssidebar-1055.tgz.

The short of it is that sidebar plugins have changed quite a bit! You may be better off recreating from scratch using one of the available ones.

The longer story is that you no longer need a configure.rhtml. Instead, you use the setting helper to describe each setting. You need to subclass Sidebars::ComponentPlugin instead of Sidebars::Plugin. You also need to remove the configure method and the way you specify the display name and and the description is also done with a helper.

Oh yeah, the file content.rhtml is unchanged :D

Typo trackback Spam

Taking a look at lib/spam_protection.rb, and scan_uri called when adding a trackback, scan_uri only checks against the RBL database.

So I’ve added the following to scan_uri:

# Pattern scanning
BlacklistPattern.find_all.each do |pattern|
  logger.info(&#8220;[SP] Scanning domain for #{pattern.class} #{pattern.pattern}&#8221;)

  if pattern.kind_of?(RegexPattern)
    throw :hit, &#8220;Regex #{pattern.pattern} matched on host&#8221; if domain.join(&#8216;.&#8217;).match(/#{pattern.pattern}/)
  else
    throw :hit, &#8220;String #{pattern.pattern} matched on host&#8221; if domain.join(&#8216;.&#8217;).match(/\b#{Regexp.quote(pattern.pattern)}\b/)
  end
end

Ultimately, this code should be factored out and called from scan_text and scan_uri.

So here’s the full version:

def scan_uri(host)
return scan_ip(host) if host =~ Format::IP_ADDRESS

host_parts = host.split(&#8216;.&#8217;).reverse
domain = Array.new

# Check for two level TLD
(SECOND_LEVEL.include?(host_parts[1]) ? 3:2).times do
  domain.unshift(host_parts.shift)
end

# Pattern scanning
BlacklistPattern.find_all.each do |pattern|
  logger.info(&#8220;[SP] Scanning domain for #{pattern.class} #{pattern.pattern}&#8221;)

  if pattern.kind_of?(RegexPattern)
    throw :hit, &#8220;Regex #{pattern.pattern} matched on host&#8221; if domain.join(&#8216;.&#8217;).match(/#{pattern.pattern}/)
  else
    throw :hit, &#8220;String #{pattern.pattern} matched on host&#8221; if domain.join(&#8216;.&#8217;).match(/\b#{Regexp.quote(pattern.pattern)}\b/)
  end
end
logger.info(&#8220;[SP] Scanning domain #{domain.join(&#8216;.&#8217;)}&#8221;)
query_rbls(HOST_RBLS, host, domain.join(&#8216;.&#8217;))
end

I’ll run this for a few days, and if it works, I will add a patch to the typo trac database.

So far, with the right pattern in the blacklist, it has been able to fend off one attack. So far, so good :)

[SP] Scanning for StringPattern HIDDEN
[SP] Scanning for StringPattern HIDDEN
[SP] Scanning IP 193.219.28.245
[SP] Scanning domain for StringPattern HIDDEN
[SP] Hit: String HIDDENmatched on host

I’ve replaced the pattern with HIDDEN just not to give this guy more publicity than he deserves.

Release 0.2 of BookmarkIt! Sidebar Plugin for Typo

Well, version 0.1 was shortlived. There was a critical difference between running with WEBrick and running in production environment with fastcgi.
The value of env[“REQUEST_URI”] did not contain “http://host”. So I found a quick solution and we’ll see if there is a better solution tomorrow.

Current solution consists of replacing

@article_url = request.env[&#8220;REQUEST_URI&#8221;]

with

@article_url = &#8216;http://&#8217;+request.env[&#8220;HTTP_HOST&#8221;]+
  request.env[&#8220;REQUEST_URI&#8221;]
  if @article_url.eql?(@article_url.gsub(/http:/,&#8221;).gsub(/HTTP:/,&#8221;))

You live and learn…

bookmarkit-0.2.zip and
bookmarkit-0.2.tgz

Release 0.1 of BookmarkIt! Plugin for Typo

First release (0.1) of BookmarkIt! for typo. Check back for new releases here on blog.nanorails.com

BookmarkIt! is a sidebar plugin for typo. With it, you can let people directly bookmark your blog, or an article dependending on the context. Try it for yourself on the right side of this page.

Installation
uncompress into a temporaty location and move the components and public directory onto your typo installation. On all OS I know, this will add the files in the right location. Then next time you go in the Sidebar section of Typo, you will be able to drag and drop the BookmarkIt! Item onto your Active items. Set the desired title and select the desired services, and then Publish your changes

Compatibility
Tested with typo revision 884. Should work with Typo 2.6.

Not all bookmarking services have been tested yet. I believe that the pages where I got the format for the links to be accurate, but I transcription could be flowed. Only the ones I had an account with. Post a comment on blog.nanorails.com if something doesn’t work.

Download the zip or the tgz file.