random walk through fields of musings

Wednesday, December 24, 2008

photos side-by-side aka montages

I seem to do this infrequently enough that I need to make myself a reminder, luckily I wrote a script that is pretty self-explanatory -- in this example it puts two photos side by side (similar method can be used to make 6 2"x2" passport photographs print on a single 4x6 print -- much cheaper than going to one of those passport places).


use strict;
local($|) = 1;

use Image::Magick;
my(@file) = @ARGV;



$rv = $image->Read(@file);
warn "$rv" if $rv;

my($montage) = $image->Montage(
mattecolor=>'#FFFFFF', #does not take?

$rv = $montage->Write('mp.jpg');
warn "$rv" if "$rv";

If you have ImageMagick installed but not the perl bindings, you can do this on the command line too.

Tuesday, December 23, 2008

terminal reset and why enter doesn't return

occasionally, if for some reason, my ssh session to a remote machine, probably running screen, doesn't terminate cleanly, and I have to return-~. to kill it, my Mac OSX terminal gets "screwed up" -- the number of rows gets reduced, the characters don't all echo, etc.. Usually, running the reset command will fix things, but sometimes it doesn't help. Of course I can't find the reference now, but some site suggested entering ^jreset^j (ctrl-j reset ctrl-j) repeatedly till it works. Incredulous, I tried it, and indeed it does work!

Monday, December 15, 2008

searching UMOD with JNDI

For some of the support tools I've been writing for CTools (in JSP with JSTL) I need to authorize against a group in the LDAP interface to UMOD. JNDI is very complete, so it should have been an easy task, but searching to see if a given logged-in (via Cosign) user was in the requisite group wasn't working. I had some example code in Perl that a colleague had once sent out, and a 1-to-1 transcription into Java using JNDI didn't work. It turns out that the scope for searches in JNDI does not default to "SUB" AND if you try to bind (even anonymously) the query tries to ADD the attribute instead of searching for it, and so had to be explicitly set. To help you (and remind me) avoid this pain, here is the requisite code:

private boolean isMember(String grp, String un) throws Exception {
   boolean isMem = false;
   Hashtable env = new Hashtable();
   env.put(Context.INITIAL_CONTEXT_FACTORY, "com.sun.jndi.ldap.LdapCtxFactory");
   env.put(Context.PROVIDER_URL, "ldap://ldap.itd.umich.edu:389/dc=umich,dc=edu");

   try {
     javax.naming.directory.DirContext ctx = new javax.naming.directory.InitialDirContext(env);
     String[] attrIDs = {"member"};

     javax.naming.directory.SearchControls ctls = new javax.naming.directory.SearchControls();
     String filter = "(&(cn=" + grp + ") (objectclass=rfc822MailGroup))";
     String searchBase = "ou=Groups";
     javax.naming.NamingEnumeration s = ctx.search(searchBase, filter, ctls);
     String positiveMatch = "uid=" + un + ",";
     while (s.hasMore()) {
     javax.naming.directory.SearchResult sr = (javax.naming.directory.SearchResult)s.next();
     javax.naming.NamingEnumeration e = (sr.getAttributes()).getAll();
     while (e.hasMoreElements()){
       javax.naming.directory.Attribute attr = (javax.naming.directory.Attribute) e.nextElement();
       javax.naming.NamingEnumeration a = attr.getAll();
       while (a.hasMoreElements()){
         String val = (String) a.nextElement();
         if(val.indexOf(positiveMatch) != -1){
           isMem = true;
   return isMem;
  } catch (javax.naming.NamingException e) {
    System.err.println("Problem getting attribute:" + e);
    return false;

There must be a better way of formatting code in HTML without JS.