A piggy bank of commands, fixes, succinct reviews, some mini articles and technical opinions from a (mostly) Perl developer.

Record and playback macros in vi

qN - start recording, where N is a-z
@N - play back your recording, where N is a-z
@@ play back the same recording again

Kill a process in Windows

taskkill /f /im AnnoyingProcess.exe

List all processes in Windows

wmic /output:c:\process.txt process get description,executablepath

Date/Time perl modules

  • Date::Manip - Big. Needs several step sto convert to/from eopch seconds. But you could just subtract 1 week's worth of seconds.
  • Date::Calc - Less big, simpler. Has Add_Delta_Days. Doesn't generate BST from epoch seconds (on Mac).
  • POSIX - has strftime. Can easily generate epoch seconds from the current time. Lacking in conversion to date?
  • DateTime - The best and easiest.

How to list differences between Perforce labels


#!/bin/bash

NOW="/tmp/now_tmp"
BEFORE="/tmp/before_tmp"
LABEL=$1

USAGE="usage: "${0%}" [label]"
if [ "x$LABEL" == "x" ]; then echo $USAGE; exit; fi

p4 changes -l -i ./... > $NOW
p4 changes -l -i ./...@$LABEL &gt $BEFORE
for change_num in $(diff $NOW $BEFORE | perl -lne'/. Change (\d+)/ && print $1');
do
p4 describe $change_num |perl -pne'do { print "-----------------------------------------------------------\n\n"; exit } if m{Differences \.\.\.}'
done


XML parsing fun with Perl

  • XML::Simple - No XPath, just simple nested hashrefs. Good options for collapsing keys. Useful for configuration files.
  • XML::Twig - Designed to handle sub-trees of very large documents, fast.
  • XML::XPath - find() method produces a nodelist, which is just an arrayref (see XML::XPath::XMLParser). It's dumb to have to "re-parse" nodes in order to look further down. Maybe I'm missing something?
  • XML::TreeBuilder or HTML::TreeBuilder - No XPath, but a splendid look_down() method. Returns objects on which you can also call look_down().
  • XML::LibXML and XML::LibXML::XPathContext - The best.
    • But HTML source often requires tidying into XML
    • And there is fun to be has converting entities
use XML::LibXML;
use XML::LibXML::XPathContext;
$parser = XML::LibXML->new();
$xml = $parser->parse_string($self->raw_xml);
$xpath = XML::LibXML::XPathContext->new($xml->documentElement);
$xpath->registerNs('atom', 'http://www.w3.org/2005/Atom');
print $xpath->findvalue("/atom:feed/atom:title");


Nothing seems good for testing XML paths, tags and attributes.

Misc Ruby stuff

  • Write to a file:
  • File.open(local_filename, 'w') {|f| f.write(doc) }
  • Read from a file:
  • File.open(local_filename, 'w') {|f| f.write(doc) }
  • stringify: .inspect

Simple Perl parallelisation


@waitlist = (10,20,16,12,8,22);

foreach $item (@waitlist) {
pipe *{$item},RETHAND;
unless ($pid = fork()) {
# Child process
sleep $item;
print RETHAND "Completed $item\n";
exit();
}
}

foreach $item (@waitlist) {
$response = <$item>;
$now = localtime();
print "$now - $response";
}


Replace sleep with a more useful command.

Apache::Registry / Perl config files

  • Apache::Reload causes more problems than it fixes
  • Apache::StatINC only works on the @INC path which is set by Apache before scripts are run
  • Apache::Registry - just don't bother
  • Don't use Apache's PerlFreshRestart On, it will break things
  • If parsing Perl syntax config files from Apache, remember it takes a few seconds for Perl to 'let go' after making changes.

Perl testing/profiling

  • Devel::DProf - subroutine profiler
  • Devel::NYTProf - the best one, apparently
  • Devel::SmallProf - line-by-line profiler
  • Devel::Cover - Test coverage
  • HTML::Mason::Plugin - manual method for Mason components

Log into a server using secure keys instead of typing a password

On the client:
  1. ssh-keygen -t rsa
  2. accept the default filename
  3. press enter for a blank password
  4. a private (id_rsa) and public key (id_rsa.pub) will be created
  5. copy the public key to the server
On the server
  1. cat id_rsa.pub >> ~/.ssh/authorized_keys
  2. chmod 700 ~/.ssh
  3. chmod 644 ~/.ssh/authorized_keys
Now back up your keys.

See also this and this.
(Upon error "Agent admitted failure to sign using the key", log out of the client and log back in again to fix).

How to customise the "content edit form" in Drupal

/**
* Catch the theme_node_form function, and redirect through the template api
* Allows us to customise the fields displayed on the "create content" form
*/
function phptemplate_node_form($form) {
$admin_role_id = 3;

if ((! $user->roles[ $admin_role_id ]) && ($user->uid != 1)) {
// user is not an admin, hide all the advanced fields

// Default Drupal fields
unset($form['attachments']);
unset($form['options']);
unset($form['author']);
unset($form['comment_settings']);
unset($form['revision_information']);
unset($form['menu']);
unset($form['body_field']['format']);
unset($form['path']);
//$form['format']['#title'] = 'Advanced setting: Input format'; // e.g. rename fields

// Ubercart fields
//unset($form['base']); // note: can't submit without this because display price and SKU are required
//unset($form['taxonomy']);
//unset($form['field_image_cache']);
//unset($form['google_checkout']);

// call the original function
return theme_node_form($form);
}

Set up sendmail on linux desktop

Setting up email sending (not receiving) for XAMPP in Ubuntu.

Install Postfix:
  • sudo apt-get install postfix
  • Choose satellite system
  • Choose example.com for the system mail name (it will mean the 'hidden' Return-Path address goes to nothing, not the visible From/Reply-to address)
  • Type your ISP's SMTP address
  • Type a user for incoming email
  • Just accept the defaults for other questions
If you need to reconfigure, do sudo dpkg-reconfigure postfix

To check the version, do postconf -d | grep mail_version

PHP/XAMPP settings:
  • In php.ini, add: sendmail_path = /usr/sbin/sendmail -t
Test like this:



$email = 'you@yourdomain.com';
$headers = "From: $email\r\n";
$headers .= "Reply-To: $email\r\n";
$subject = "test subject";
$message = "test body";
print mail($email,$subject,$message,$headers) . "\n";

?>

Simple PHP email form

The 'hidden' Return-Path header (not visible Reply-To) will be your name at your domain.

Email form:

<form method="post" action="s.php">
From: <input name="from" type="text" /><br />
To: <input name="to" type="text" /><br />
Subject: <input name="subject" type="text" /><br />
Body:<br />
<textarea name="body" rows="15" cols="40">
</textarea><br />
<input type="submit" value="send"/>
</form>


s.php:

<?php
$to = $_REQUEST['to'] ;
$from = $_REQUEST['from'] ;
$subject = $_REQUEST['subject'] ;
$body = $_REQUEST['body'] ;

$return = mail( $to, $subject, $body, "From: $from\r\nReply-To: $from" );

if ($return == 1) {
print "sent.";
}
else {
print "error.";
}
?>

Get all past podcasts in iTunes

  • Display the podcasts in list view (details view)
  • Ctrl-click on the triangle next to the podcasts
  • Voila! You will see a list of the past episodes to select