magπ

A crafty, nommy, occassionally geeky blog-thing.

Hacking Owl Intranet

Owl Intranet Engine may bill itself as a intranet application, but really its just a swishy web-based file repository. “Just”, not because it doesn’t do the job well, but because that’s really all it does, and in my world an “intranet engine” should do more than just provide a place for colleagues to upload shared files.

I work with a number of NPOs who need something a little more full-featured than a pretty FTP server, and with the possible exception of Plone (which we can’t get running on the server until its next incarnation), there is a whole lot of nothing which quite makes it. Think Yahoo!Groups, but without the spammy crap, and without their hosting it. A clean integration of mailing list, filesharing, “database” widgets (i.e., a basic spreadsheet), wiki, and chat, all behind a common login, all administered through a website, and allowing for flexible group memberships.

Some sort of file repository, of course, is always the most pressing. So invariably I give them an installation of Owl, a Mailman mailing list and call it a day, while I dream of finding the time to write some custom in-house solution.

Over the years, one of those NPOs has been asking for little additions and tweaks here and there, which I’ve been gradually hacking into Owl. This is all one-off, short-notice additions. Hacks, literally. But, they’ve been getting the job done, and have resulted in a rather useful Owl installation. I still dream of the custom app, but in the meantime, this Owl-monster is something that I can now whip together in relatively short order, and meet most of those intranet needs.

Thus, notes to self!

Creating Committees

Our organization is divided into a number of committees. Each committee requires its own, protected workspace including a fileshare, ML, chat, db, and wiki. A given user may be a member of more than one committee, and an “administrator” should have access to all committee workspaces.

Owl uses “groups” for its permissions granting scheme. A user is added to a group. A group is given access to a given folder. The Administrator group has access to all folders, plus the administrative control panel.

In our case, a committee matches up roughly with the concept of a “group” paired with a folder. So, we create a user group, with the committee name, and fileshare folder with the user name, which is owned the the committee’s group. Which is easy enough, but it involves flipping back and forth between the Admin UI and the Fileshare UI, and far too many clicks in between.

By editing admin/index.php to display a “Create Fileshare?” checkbox in the “Add Group” form, I managed to save a fe wof those steps. The HTML itself consisted of adding the following rows to the table printed in the printnewgroup function:

           <tr> 
           <td>Create Fileshare?</td>
            <td><input type=checkbox name=fileshare></td>
           </tr> 

The form itself is processed by admin/admin_dbmodify.php

near the bottom of the file, directly after it inserts our new group into the groups database

$sql->query("INSERT INTO $default->owl_groups_table (name,maillist) 
VALUES ('$name','$maillist')");

I added a check for $_POST[‘fileshare’]. If the variable does not exist, the script will redirect the browser back to the defaul admin index page (as it originally did). However, if the variable does exist, then I instead want the browser to be redirected to the “Add Folder” form in the Fileshare UI. More, I want that form to be pre-populated with the Committee Name in the “name” field, and the Committee name in the “ownership” field. This is (gracelessly) handled by appending name=$name to the URL of the Add Folder page. $name is already populated, at this point, with our new Committee’s name.

if($_POST['fileshare']){
    header("Location: http://staff.shoujocon.com/modify.php?sess=$sess
    &action=folder_create&parent=1&expand=1&name=$name");
        }else{
        header("Location: index.php?sess=$sess");
        }
}

The Add Folder form is generated by modify.php. We want to fill in default values for the name of the new folder (should be $GET[‘name’]), and for which group is selected in the ownership drop down menu (should be $GET[‘name’]).

The former is a simple matter of adding a “value” to the input field:

INPUT TYPE=TEXT NAME=name value='$_GET['name']'

The latter requires a little bit of logic. As we cycle through the list of groups on the system in order to print the option list, we want to keep an eye out for the one with the same name as $_GET[‘name’]:

foreach($groups as $g) {
    if($g[1] == $name){
        print("<OPTION SELECTED VALUE=$g[0]>$g[1]");
    }else{
        print("<OPTION VALUE=$g[0]>$g[1]");
    }
}

And that’s it. Now, when you add a new group, you have the option of automatically creating a fileshare folder for that group. If you select to, the new folder form is displayed with the groups name set as the new folder name, and the group selected as the owner of the new folder. You can, at this point, edit the description or modify the permissions on the new folder. Then submit the form, and the new committee is set up & ready to go.

Creating a Committee List

In order for our volunteers to have a clear sense of separate committee space, and to easily navigate between committee’s, we want to have a column down the left-hand side of the screen, which lists which committee’s they are a member of, and has hotlinks to various workspaces for each committee. (This will be more relevant, once we add MLs, wikis, etc.)

Part of this is just a matter of modifying the site header, to include a left hand column which we can push custom content into.

The (marginally) more interesting part of this is to actually pull up that list for the logged in user.

lib/header.inc is the file in question for both of these steps. Since this was originally done in my pre-CSS days, I opted for wrapping the entire site inside of a table, with the Committee list on the left-hand side, and Owl’s content on the right-hand side. If I were to do this again today, I would wrap everything in CSS blocks instead, and position them at will.

In order to pull up the logged in user’s committee list, we just use:

$mycommittees = mysql_query("SELECT * FROM membergroup WHERE userid='$userid'")
    or die(mysql_error());



while( $rows = MySQL_fetch_array($mycommittees) ){ $cid = $rows['groupid'];


$mycommitteename = mysql_query("SELECT * FROM groups WHERE id='$cid'") or die(mysql_error());


while( $rows = MySQL_fetch_array($mycommitteename) ){ $cname = $rows['name']; $cwikiname = str_replace(" ","",$cname); $clist = $rows['maillist'];


$mycommittee_folder = mysql_query("SELECT * FROM folders WHERE groupid='$cid' AND parent='1'") or die(mysql_error());


while( $rows = MySQL_fetch_array($mycommittee_folder) ){ $fid = $rows['id']; echo "
$cname
[ files | ml | chat* | db* | wiki ]

"; }
        }
    }