Wednesday, December 13, 2006

element.getAttribute("class")

Why are even the simple things sometimes hard? Attempting to get a element attribute. Here is a table of what the various browsers return when trying to get the class attribute having already found an element:
var element = document.getElementById("theSpan");
in a document containing the HTML:
<span id="theSpan" class="something">
Browser element. getAttribute( "class" ); element. getAttribute( "CLASS" ); element. getAttribute( "className" ); element. attributes[ "class" ]; element. className;
Firefox 2.0 something something null [object Attr] something
Opera 9.0 something something null [object Attr] something
Safari 1.3.2 something something null undefined something
IE 5.5 (Mac) null null something something something
IE 7.0 null null something [object] something

Updated: Thanks to anonymous for pointing out that you can just use element.className to get the class name used and it seems to work correctly across all browsers I tested.

It seems that there is no simple way to get the class attribute across browsers. The solution seems to be to get the class attribute and if it undefined try the className attribute. Most other attributes should work fine, it is just that IE doesn't like the class attribute that throws the spanner in the works. Here is the quick testing page.

Tuesday, December 12, 2006

Label Based Feeds

When I was at the Sakai conference I was asked if I wanted my blog added to Sakai Planet, the thing is that I blog about more than just Sakai and so only the posts for Sakai should end up in the planet. After a little googling I discovered you can have feeds for labels and it seems that my sakai feed works. I wonder why Google don't make this the default RSS feed when viewing all the posts for a tag?

Tuesday, November 28, 2006

Marketing through last.fm

I have had an account on last.fm for a while now. I send most of music listening to it. A few days ago I got a friend invite from TheHijacker. Looking at the profile it seems this is the profile for a previous member of Dodgy called Nigel Clark who decided to send me a friend invite because I was one of the top listeners to Dodgy in a last week (25 listens). I also a day later got a private message from him saying I should visit his website. I believe he it trying to promote his new album 21st Century Man. To be honest I don't mind this sort of promotion much, as it is obvious that I will quite happily listen to Dodgy and so will probably like his new album. This sort of promotion also isn't at the moment automated and so he obviously feels it is worth his time sending me the message. However I signed up with last.fm because it allows me to find other music rather than have it pushed on me. Although I'm guessing that Nigel Clark hasn't yet reached a big enough critical mass opn last.fm to be recommended to me as other people aren't yet listening to it.

Friday, November 03, 2006

Sakai Site.equals()

Took a little while to figure this one out but in Sakai the org.sakaiproject.site.api.Site equals() method will return true when passed a string if it matches the ID of the site. The reason they do this is so that they can save a list of site IDs and then have a collection of sites and call siteList.removeAll(stringList);. This can be seen is action in the CharonPortal where is is used to hide sites that the user isn't interested in.

Wednesday, November 01, 2006

Starting Rhythmbox in the Notification Area

I normally have Rhythmbox running on my desktop to provide me with music. However normally when you start up Rhythmbox it displays its window, now as I added Rhythmbox to the list of programs to automatically startup when I login I wanted it in the notification area (tray). The trick for doing this is to start Rhythmbox with the command: rhythmbox-client --hide Now if only gaim would have some way todo the same thing.

Friday, October 27, 2006

Terta & Bodington "Review"

Michael Feldstein has written a couple of very good posts about the Bodington VLE following the Tetra annoucement. His posts aren't a "review" of Bodington but more of an exploration of how Bodington does access control which is often over simplified in other tools.
Here at Oxford we use WebAuth for web based Single Sign On (SSO) and when looking at tools we like to see how easily they can be WebAuth enabled. Thankfully Sakai makes it all pretty easy. Sakai has the ability to support two authentication methods at the same time so we can have a login route for both Oxford users (WebAuth) and for internal Sakai users.

Previously we have used the Apache WebAuth module but this time I decided to attempt to use the Java WebAuth Filter developed as part of the SIPE project here at Oxford. One note is that the Standford WebAuth download pages have a newer version of the Java WebAuth filter than the SIPE pages. The Java WebAuth implementation only works with Java 1.5.

The first thing is to configure Kerberos on the machine so that it points to the correct servers, on my Linux box at Oxford this means having a configuration file called /etc/krb5.conf containing:

[libdefaults]
default_realm = OX.AC.UK

[realms]
OX.AC.UK = {
kdc = kdc0.ox.ac.uk
kdc = kdc2.ox.ac.uk
kdc = kdc1.ox.ac.uk
admin_server = kdc-admin.ox.ac.uk
}

[domain_realm]
.ox.ac.uk = OX.AC.UK
ox.ac.uk = OX.AC.UK


I also needed the kerberos tools too, on Ubuntu these come as part of the krb5-user package (sudo apt-get install krb5-user). Once my machine was running with Kerboros I needed to visit the systems development team and get a kerberos principal, this involved saying hello to the nice people upstairs and then typing a password for my new principal (buckett/itss). This principal then had rights over my webauth principal (webauth/oucs-matthewb.oucs.ox.ac.uk) so that I could key a keytab for my webauth principal. I get a keytab with the commands:

buckett@oucs-matthewb:~ $ kadmin -p buckett/itss
Authenticating as principal buckett/itss with password.
Password for buckett/itss@OX.AC.UK:
kadmin: ktadd -k /home/buckett/.webauth.keytab webauth/oucs-matthewb.oucs.ox.ac.uk
Entry for principal webauth/oucs-matthewb.oucs.ox.ac.uk with kvno 4, encryption type Triple DES cbc mode with HMAC/sha1 added to keytab WRFILE:/home/buckett/.webauth.keytab.
Entry for principal webauth/oucs-matthewb.oucs.ox.ac.uk with kvno 4, encryption type DES cbc mode with CRC-32 added to keytab WRFILE:/home/buckett/.webauth.keytab.

This gives me a keytab file that allows the WebAuth filter to authenticate with the Kerberos server without having to ask me for a password every time I start it up. I also need to create a keyring file.

touch /home/buckett/.webauth.keyring

and set the permissions on both of the files to be as restrictive as possible (chmod 400 ~/.webauth.*).

The the sakai login tool needs to be changed to include the WebAuth filter.
This means dropping all the JARs from the WebAuth distribution (bcprov-jdk15-132.jar, commons-httpclient-3.0.jar, commons-logging-api-1.0.4.jar, commons-codec-1.3.jar, commons-logging-1.0.4.jar, webauth-java-1.2.jar) into the WEB-INF/lib folder.
The web.xml then needs some extra sections added (in bold).

  <description>Sakai 2 sample tools: login</description>

  <!-- Webauth Filter Start -->
  <filter>
   <filter-name>Webauth Filter</filter-name>
   <filter-class>uk.ac.ox.webauth.Filter</filter-class>
   <init-param>
     <param-name>WebAuthDebug</param-name>
     <param-value>true</param-value>
   </init-param>
   <init-param>
       <param-name>WebAuthServicePrincipal</param-name>
       <param-value>webauth/oucs-matthewb.oucs.ox.ac.uk</param-value>
   </init-param>
   <init-param>
       <param-name>WebAuthKeytab</param-name>
       <param-value>/home/buckett/.webauth.keytab</param-value>
   </init-param>
   <init-param>
       <param-name>WebAuthWebKdcPrincipal</param-name>
       <param-value>service/webkdc@OX.AC.UK</param-value>
   </init-param>
   <init-param>
       <param-name>WebAuthWebKdcURL</param-name>
       <param-value>https://webauth.ox.ac.uk:8443/webkdc-service/</param-value>
   </init-param>
   <init-param>
       <param-name>WebAuthLoginURL</param-name>
       <param-value>https://webauth.ox.ac.uk/login</param-value>
   </init-param>
   <init-param>
       <param-name>WebAuthKeyring</param-name>
       <param-value>/home/buckett/.webauth.keyring</param-value>
   </init-param>
   <init-param>
       <param-name>AutoAddKeys</param-name>
       <param-value>true</param-value>
   </init-param>
   <init-param>
       <param-name>AutoRemoveKeys</param-name>
       <param-value>true</param-value>
   </init-param>
   <init-param>
       <param-name>WebAuthExtraRedirect</param-name>
       <param-value>true</param-value>
   </init-param>
 </filter>
 <!-- Webauth filter end -->

   <filter>
       <filter-name>sakai.request</filter-name>
       <filter-class>org.sakaiproject.util.RequestFilter</filter-class>
   </filter>

   <filter>
       <filter-name>sakai.request.container</filter-name>
       <filter-class>org.sakaiproject.util.RequestFilter</filter-class>
      <init-param>
           <param-name>tool.placement</param-name>
           <param-value>true</param-value>
       </init-param>
       <init-param>
           <param-name>remote.user</param-name>
           <param-value>false</param-value>
       </init-param>
   </filter>

   <filter-mapping>
       <filter-name>sakai.request</filter-name>
       <servlet-name>sakai.login</servlet-name>
       <dispatcher>REQUEST</dispatcher>
       <dispatcher>FORWARD</dispatcher>
       <dispatcher>INCLUDE</dispatcher>
   </filter-mapping>

   <filter-mapping>
       <filter-name>sakai.request.container</filter-name>
       <servlet-name>sakai.login.container</servlet-name>
       <dispatcher>REQUEST</dispatcher>
   </filter-mapping>
 

   <!-- Webauth Filter Mapping Start -->
   <filter-mapping>
       <filter-name>Webauth Filter</filter-name>
       <servlet-name>sakai.login.container</servlet-name>
   </filter-mapping>
   <!-- Webauth Filter Mapping End -->

   <servlet>
       <servlet-name>sakai.login</servlet-name>
       <servlet-class>org.sakaiproject.login.tool.LoginTool</servlet-class>
       <init-param>
           <param-name>container</param-name>
           <param-value>/sakai-login-tool/container</param-value>
       </init-param>
       <load-on-startup>1</load-on-startup>
   </servlet>


You will probably need to change the WebAuth filter configuration to point to the correct keyring/keytab files for you local installation.

The just edit your sakai.properties, making sure these are set.

# LOGIN/LOGOUT

# to include the user id and password for login on the gateway site
top.login=false

# to let the container handle login or not (set to true for single-signon type setups, false for just internal login)
container.login=true

xlogin.enabled=true
xlogin.text=Guests

Now if you startup Sakai it should provide you with two login buttons in the top right of the portal. One that uses WebAuth and one that uses the internal Sakai authentication.