Peter's Blog

Redefining the Impossible

Posts made during October 2004


If you have a file on an ssh enabled server that you want to edit with VIM and you don't want to mess around with ftp you can use VIM's ftp support.

However, I find the support for scp to be more useful. Having installed Cygwin and open ssh I have also acquired the scp command. VIM knows about this and can use it to edit files.

Suppose I want to edit the file 'interesting.txt' on the server 'stuff.com'? I use the VIM command:

:e scp://peter@stuff.com/interesting.txt

and start editing. When I am finished I just write the file normally:

:w

Because I have already created an ssh key on stuff.com (as shown here) I am not hastled for passwords.

Very nice for quick .css tweeks, editing drupal modules etc. I can edit the file locally in a windows GUI and upload it to nice secure linux server. Best of both worlds.

Downsides?

  1. Win32 vim leaves a silly dos box with a 'Hit any key to close this window...' message on it when reading the file.
  2. Have to know the exact path to the file.

7 Comments

I wanted a means to print Drupal nodes in a fairly simple form: just the node title and body, no blocks, no search buttons, etc. I tried the Print Page module but that does not strip the peripherals. I tried the pdfview but that gave very crudely formatted results.

I knew that the book module had a 'printable page' option so I decided to look see how it did it and knock up a module myself. Here it is:

<?php
/*
 * Add option to show printable page without embellishments.
 */

function printablepage_help($section = 'admin/help#printablepage') {
  $output = "";

  switch ($section) {
    case 'admin/system/modules#description':
      $output = t("Print page");
      break;
  }
  return $output;
}

function printablepage_link($type, $node=0, $main) {
    global $user;

    $links = array();

    if (($type == "system")) {
    // URL, page title, func called for page content, weight, 1 = don't disp menu
        menu("printablepage", t("Printable Page"), "printablepage_page", 1, MENU_HIDE);
    }

    $links[] = l(t("Printable Page"), "printablepage/$node->nid",
                                            array("title" => t("Printable Page.")));

    return $links;
}

function printablepage_page() {
    /*
     * In initial link nid is in the url
     */
    $nid = arg(1);

    $html = "<html><head><title>$node->title</title>";
    $html .= "<base href=\"$base_url/\" />";
    $html .= "<style type=\"text/css\">\n@import url(misc/print.css);\n</style>";
    $html .= "</head><body>";

    /*
     * Search db for nodes.
     */
    if( $nid != "term") {
        $nodes = db_query("SELECT nid, title, teaser, created FROM {node} WHERE nid = %d", $nid);
    } else {
        $termID = arg(2);
        $nodes = db_query("SELECT n.* FROM {term_node} t INNER JOIN {node} n ON t.nid = n.nid
                                 WHERE t.tid = $termID ORDER BY n.nid");
    }

    while ($node = db_fetch_object($nodes)) {
        /*
        ** Load the specified node:
        */
        $item = node_load(array('nid' => $node->nid));

        /*
         * Add the title and the body to the output under construction.
         */
        $html .= "<h1>$item->title</h1>\n";
        $body = str_replace( '<!--break-->', '', $item->body);
        $body = str_replace( 'h3', 'h4', $item->body);
        $body = str_replace( 'h2', 'h3', $item->body);
        $body = str_replace( 'h1', 'h2', $item->body);
        /* Pass body through filters to create html */
        $html .= check_output( $body);
        $html .= "<hr/>";
    }

    $html .= "</body></html>";

    print $html;
}

?>

Save as modules/printablepage.module, enable the module and enjoy.

This adds a 'Printable Page' like to every node display. Clicking the link shows the page without the Drupallish embellishments: headers, blocks, search boxes, footers, breadcrumbs etc, just the raw html, ready for print preview (something the 'Print Page' module lacked) and printing.

Not very sophisticated and probably breaking all known Drupal coding guidelines but it works for me with Drupal 4.4.0.

Update: the script now supports dumping all the nodes with a particular taxonomy term in order of node id which is approximately the same as chronological order. To use it, link to:

printablepage/term/<nid>

where <nid> is the node id, e.g. printablepage/term/15


Filed under: drupal php

6 Comments

I was reading this post and was moved to have a play with Technorati. I did a search for my blog and found a couple of other folks have linked to articles in it! This is news to me and has made me happy. I've created a Technorati account and added Technorati to my plugs box on the right. The Quote bubble thing opens up the Technorati search for this site.

The article mentioned how Technorati's performance has suddenly improved and I can vouch for that: it is now almost google-quick.

On a related popularity note, my access logs are showing that the most frequent referrers from google are people looking for the word "MS Draw" (without the space: I don't want the search to find this post) and finding this entry. If you do a google search for that word then my posting comes out top. I seem to be an expert on this particular Word foible.


Filed under: blog google technorati

Add a comment

I have mentioned before about using VIM with embedded Python but I didn't mention what it is. Its a version of VIM specially compiled with built in python. Its a bit of a pain to set up as the main VIM site does not ship such a version and you have to build it yourself. This involves downloading the VIM source and the Python source and building VIM in such a way as to tell it where the python libraries can be found.

Once this is done it is quite cool. From within VIM I can type something like:

:py print dir("")

and remind myself of what methods a string object has. I can remind myself how to append arrays to arrays by typing

:py print [1, 2, 3] + [4, 5, 6]

and seeing how this compares to using append (it's different).

To manipulate the vim buffer it is possible to go:

:py import vim
:py vim.current.buffer[0] = 'hello peter'

to change the first line of the buffer to 'hello peter'

I think any other VIM/Python enthusiasts out there will already have their mouths watering by now and will be off downloading so I will just refer them to

:help py

VIM has similar support for perl and ruby and other sundry languages.


Filed under: python vim

3 Comments

I was thinking today how cool and hip I was using Bloglines as an RSS aggregator compared to people who just go through a list of favourite web sites every day. So 1995. Go RSS, join the 21st century.

Then I thought about it some more and this is essentially what I am doing with bloglines: I have a list of feeds that I go through one by one, looking through the articles. No real difference to going through a sidebar full of bookmarks, looking at websites.

If I am going to evangelise RSS aggregation, what am I going to say are the advantages? Why bother?

  • Uniform presentation
  • No adverts (for now: I cannot imagine this will forever be true)
  • Um

I'm going to continue with bloglines as the reasons above are enough for me, I just won't try to evangelise. As it happens I am not a good evangelist: I have yet to convert anyone to FireFox for example which should be pretty easy. Even after I removed the adware from my boss's PC he showed no interest in FireFox.

Maybe I should examine my RSSing habits and figure out if I am missing the point in some way.

The only people I know who are at all interested in gmail are those of a geeky persuasion.


4 Comments

My Site5 hosting service allows me to download access logs which I find enlessly fascinating. The netadmin administration tool offers AwStats which shows incredibly detailed statistics but it is slightly skewed by showing my own access.

So I wrote a python script to parse the log and dump out anything interesting. It filters out IP addresses I am likely to connect from. This is crude in that I have hard wired the log file name. Note that the log file I download is gzipped but that is no problem for python.

This dumps out:

  • suspicious looking attempts to hack in (extremely long strings etc)
  • a list of various user agents and the IP addresses they are coming from
  • a list of referrer strings

Things I find interesting in the dumps:

  • There are 171 different types of user agents listed. Most claim to be mozilla type browsers which is probably rarely true but even so, there are a lot of things crawling around out there. Someone out there is using lynx. Hi there.
  • I get at least one known spam email address harvester visiting (DTS Agent). Be warned. This particular one does not really bother to hide itself.
  • Referrers from drupal.org seem to arrive from random pages on that site. I think folk are browsing around, see something from me in the 'Drupal Talk block and come here for a read. Drupal generates a misleading referrer string.
  • The referrer strings from google give the search terms. I get a number of people looking for r-s-y-n-c w-i-n-2-k (obscured to hide from google) and when I do that search this post somes in at #7 with it's enticing title. Moral: give postings enticing titles.
  • Yahoo Slurp crawls the site about as much as google but gave me one referral compared to 81 from google.

These statistics are for a 7 day period.

import gzip
import re

#
# Open log file. Crude but effective. Reads directly from gzipped log file.
#
oFile = gzip.GzipFile( 'C:\\Tmp\\accesslog-bisiand.me.uk-9-28-2004.gz')

def Sorted( oArray):
    "Return sorted array"
    oTmp = oArray[:]
    oTmp.sort()
    return oTmp

#
# Scan through the log file.
# Use regular expression to split the entries up.
#
# Pattern is thus:
#
# 56.98.204.40 - - [09/Sep/2004:03:50:01 -0400] "GET / HTTP/1.0" 200 643 "-" "
#Mozilla/5.0 (Windows; U; Windows NT 5.0; en-US; rv:1.7) Gecko/20040803 Firefox/0.9.3"
#
oRE = re.compile( r'(\d+\.\d+\.\d+\.\d+).*(\[.*\])\s+"(GET|POST|HEAD|SEARCH|PUT)\s+([^"]+)
                       "\s+([\d-]+)\s+([\d-]+)\s+"([^"]+)"\s+"([^"]+)"')

#
# Here build map of IP addresses to the log file entries.
#
oHits = {}

#
# Build map of unique referrers and how many folk they sent my way.
#
oReferrers = {}

#
# Go though file.
#
for strLine in oFile.readlines():
    print strLine[:-1]
    oMatch = oRE.search( strLine)
    if oMatch:
        #
        # These things seem to be used by hackers trying  to break in.
        #
        if oMatch.group(3) in ("PUT", "SEARCH"):
            print strLine
            continue

        #
        # Get the IP address.
        #
        strIP = oMatch.group(1)

        #
        # Ignore the entry if it is me.
        #
        if strIP in ('76.54.32.10', '12.3.45.67'):
            continue

        #
        # Get interesting fields from log file.
        #
        strAccess = oMatch.group( 3) + oMatch.group(4)
        strReferrer = oMatch.group(7)
        strAgent = oMatch.group( 8 )

        #
        # Build up hit map.
        #
        if oHits.has_key( strIP):
            oHits[strIP].append( (strAccess, strReferrer, strAgent))
        else:
            oHits[strIP] = [( strAccess, strReferrer, strAgent)]

        #
        # Build up referred map.
        #
        if oReferrers.has_key( strReferrer):
            oReferrers[strReferrer] += 1
        else:
            oReferrers[strReferrer] = 1
    else:
        #
        # Did not match the regular expression. Just dump the line.
        #
        print "Miss:" + strLine

#
# Determine which user agents originate from which IP.
#
strAgents = {}

for strIP in Sorted(oHits.keys()):
    oHit = oHits[strIP]
    if strAgents.has_key(oHit[0][2]):
        strAgents[oHit[0][2]].append( strIP)
    else:
        strAgents[oHit[0][2]] = [strIP]

#
# Display the unique User Agents and the IPs using them.
# This shows things like googlebot.
#
for strAgent in Sorted( strAgents.keys()):
    strIPs = strAgents[strAgent]
    print strAgent
    for strIP in strIPs:
        print "   %s %d" % (strIP.ljust( 15), len( oHits[strIP]))

#
# How did they get here? Show the referred name.
#
for strReferrer in Sorted( oReferrers.keys()):
    if strReferrer.find( '209.59.159.21') >= 0:
        continue
    if strReferrer.find( 'bisiand.me.uk') >= 0:
        continue
    if len(strReferrer) < 60:
        print strReferrer.ljust( 60) + str(oReferrers[strReferrer])
    else:
        print strReferrer + "\n" + (' ' * 60) + str(oReferrers[strReferrer])

Add a comment

One of my daily chores is to try out various search terms on google to see how popular this site is. Yes it's sad but it's also tedious, especially if this site is only found on the 6th page. Today I knocked up this quick script to do this for me. This will search through up to 10 pages for the first reference to this site.

As usual in my scripts I'm too lazy to put in support for command line parameters and I edit the script directly to set it up.

Apart from Python this needs a google api developer key and the pygoogle library. You can sign up for the developer key here and put it in the code. Google let you query their server 1000 times a day provided you give them this key.

Even if nobody else is vain or attention seeking enough to need this script it is interesting to see how easy programmatically searching google can be.

This script does give a warning about using a deprecated soap library.


#
# How cool am I?
#

import google

google.LICENSE_KEY = "censored"

strTerm = 'hello world'
strSite = 'bisiand.me.uk'
#
# Proxy server: set to None if not needed
#
strProxy = 'firewall:8080'

bFound = False

for nPage in range(10):
   oSearchResult = google.doGoogleSearch( strTerm,
                                               start = nPage * 10,
                                               maxResults = 10,
                                               http_proxy = strProxy)
   if len(oSearchResult.results) == 0:
       break

   nResult = 0
   for oResult in oSearchResult.results:
       nResult += 1
       if oResult.URL.find( strSite) >= 0:
           print "Found on page %d item %d" % (nPage + 1, nResult)
           print oResult.snippet.encode( 'ascii', 'ignore')
           bFound = True
           break

   if bFound:
       break

if not bFound:
   print "Beneath contempt"


Filed under: google python

Add a comment

The google pagerank for this site has gone from 0 to 1. The tooltip in the google bar defines pagerank as google's measure of the the importance of the site on a scale of 0 to 10. This means that this site is not totally unimportant.


Filed under: google pagerank

10 Comments

Decided to uninstall WindowsBlinds, partly because I am bored with it and partly in preparation for Windows XP SP2. I ran the uninstallation and rebooted but the logoff and logon screens were still the windowblinds versions.

I looked through control panel/add remove programs and found something called 'login studio' so I uninstalled that. No joy, still showed customised shutdown and login screens.

After a google trawl I found the trick. Find this registry item:

 [HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Winlogon]
    "UIHost"="C:\WINDOWS\System32\logonuiX.exe"

And change it to:

 [HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Winlogon]
    "UIHost"="C:\WINDOWS\System32\logonui.exe"

(i.e. remove the X) which is the microsoft version of the logout/login program. The C:\WINDOWS\System32\logonuiX.exe file can then be sent to hell.

The customised login.logout display was always a little odd anyway: user names were transparent and at an odd place on screen.


Filed under: google windowblinds windows

Add a comment

I don't have a motorbike any more but here's a motorbike tip anyway. Winter is approaching and bikes are going into hibernation till next spring. This is England and around this time of year being in a safe warm car is preferable to sliding down the road beside your motorbike.

The first year I had my old CBR600fx I left it in the garage all winter. By spring the battery was knackered and refused to hold a charge. The factory fitted immobilizer had drained the battery all winter and ruined it. I had to buy a new one.

I did't want to buy a new battery every year so I bought a trickle charger designed to keep motorbike or car batteries healthy. Just plug it in and leave it for however many months. The one I bought was by a company called oxford, I think it was called an Oximiser. It came with connecters to permanently wire to the bike so it could be plugged in whenever it was needed without having to take the battery out. It was a wonder, in the last year I had the bike I didn't ride it yet it started quite easily when I got around to selling it.


Filed under: untagged

1 Comment