Extending the Zimbra Canvas

Posted by Quinn Madson | Posted in | Posted on 11:17 AM

1

The Zimbra Canvas is pretty cool but, somewhat limited from the Zimlet XML definition file. For example, you cannot modify the buttons of the container if it's called from the XML. You can get around it by using the Zimbra JavaScript implementation.

It's pretty easy to get a canvas going from the JS side but, I was having issues getting the iframe style <actionUrl> functionality from the XML side. I had to reverse engineer this based on the source of ZmZimletBase();.

Here is the XML:

<zimlet name="edu_myschool_myzimlet" version="1.0" description="Some Zimlet">

<include>http://www.myschool.edu/LOCATION/TO/ZIMLET/zimlet.js</include>
<includeCSS>http://www.myschool.edu/LOCATION/TO/ZIMLET/zimlet.css</includeCSS>
<handlerObject>Edu_myschool_myzimlet</handlerObject>

<zimletPanelItem label="Some Zimlet" icon="My-panelIcon">
<toolTipText>This is a super awesome zimlet that does something.</toolTipText>
<contextMenu>
<menuItem label="Do something" id="doSomething" icon="My-panelIcon">
<canvas type="dialog" width="700" height="500" />
<actionUrl target="http://www.myschool.edu/LOCATION/TO/MASHUP/AWESOMENESS/" />
</menuItem>
</contextMenu>
</zimletPanelItem>
</zimlet>
This sets a right-click menu using the <zimletPanelItem> directive. More importantly, (for us, right now) is that it calls out to our JavaScript. Here is what the JavaScript should look like:
function Edu_myschool_myzimlet() {
}

Edu_myschool_myzimlet.prototype = new ZmZimletBase();
Edu_myschool_myzimlet.prototype.constructor = Edu_myschool_myzimlet;

Edu_myschool_myzimlet.prototype.init =
function() {
};

// Called by the Zimbra framework when the panel item was double clicked
Edu_myschool_myzimlet.prototype.doubleClicked = function() {
this.singleClicked();
};

// Called by the Zimbra framework when the panel item was clicked
Edu_myschool_myzimlet.prototype.singleClicked = function() {

var view = new DwtComposite(this.getShell());
view.setSize("500px", "500px");
var el = view.getHtmlElement();
var myBox = document.createElement("div");
el.appendChild(myBox);

var html = new Array();
var i = 0;
html[i++] = "First line of HTML <br/>";
html[i++] = "More lines of HTML";

// package up html and display it
myBox.innerHTML = html.join('');
this._dialog = this._createDialog({title:"My Dialog Title", view:view});
this._dialog.setButtonListener(DwtDialog.OK_BUTTON, new AjxListener(this, this.myHandler));
this._dialog.setButtonTitle(DwtDialog.OK_BUTTON, "Go go gadget Zimlet!");
this._dialog.popup();
};

Edu_myschool_myzimlet.prototype.myHandler =
function(ev) {
//do come more stuff: web services, api calls, etc
this._dialog.popdown();
}
This will show some HTML within the Zimbra Canvas. You can create a form and allow it to call web services, the Zimbra API, etc based on what the user did. This is pretty handy. Also, if you look at the code, you can add handler functions to the buttons, change the button text, etc.

In some cases, you may just want to call out to some other code: PHP, JSP, ASP, (or in my case) ColdFusion, etc. To do an iframe the exact same way that <actionUrl> does, change the click action functions:
Edu_myschool_myzimlet.prototype.singleClicked =
function() {
var view = new DwtComposite(this.getShell());
view.setSize("700px", "500px");
var el = document.createElement("iframe");
el.src = "http://www.myschool.edu/PATH/TO/MY/CODE/mashup.cfm";
var sz = view.getSize();
if (!AjxEnv.isIE) {
// substract default frame borders
sz.x -= 4;
sz.y -= 4;
}
el.style.width = sz.x + "px";
el.style.height = sz.y + "px";
view.getHtmlElement().appendChild(el);

//TITLE OF THE DIALOG BOX
var dialog_args = {
title : "Example",
view : view
};
var dlg = this._createDialog(dialog_args);
dlg.popup();
};
From here you could add code to modify the buttons, pass a query string from JavaScript via the URL, etc.

Dual Network Booting (Mythbuntu, MediaMVP, and random crappy laptops)

Posted by Quinn Madson | Posted in | Posted on 7:27 PM

0

Background
I built a Mythbuntu machine out of a Dell PowerEdge 1600SC dual Xeon box with a Hauppauge PVR-500 dual TV tuner. Because I'm cheap *and* wanted to run a gigabit network, this machine also serves as the router for a gigabit switch (which was 1/3 the cost of a gigabit router).

I ended up getting 2 Hauppauge MediaMVPs. It's basically a small (1.5 x 6.5 x 5.5-inches), cheap 300MHz PowerPC that boots off the network and plays music, video, and pictures off your network. A group of developers released their own software available at: http://mvpmc.org that runs a small linux distro and can connect to: MythTV, ReplayTV, Hauppauge, VLC, SqueezeCenter (aka SlimServer) with various other bells and/or whistles.

I also have a few busted up laptops with no hard drives. I wanted to be able to netboot the MediaMVPs and use Mythbuntu's diskless server for the laptops. (I let the kids use one for flash based games and I use one in our home theater.)

There wasn't great documentation on how to do this so, hopefully this helps people out somewhat in the future. There are some decent guides to get MVPMC working with Mythbuntu but, they use the aTFTP server which conflicts with Mythbuntu's diskless server.

HOW-TO:
DHCP:
On the Mythbuntu media server, go to:

  • Applications >> System >> Mythbuntu Control Centre >> System Roles.
  • Check "Diskless Server" and "Add DHCP server"
  • Click "Apply"

A progress bar will whir away and eventually the "Mythbuntu Control Centre" dialog will come back. The "Diskless Server" option on the left side menu should now be available. When you go to it, there is a drop-down menu for "CPU architecture of your clients". Select "i386". Click "Build Image" and "Apply". This process can take a long time and sometimes fails.

To check, go to: Applications >> Accessories >> Terminal.

At the prompt type:
ls /opt/ltsp
If you see:

i386 images
... you should be all set. If the "images" directory is missing, the build failed. If the build failed, at the command prompt type:
sudo rm -rf i386
sudo ltsp-build-client --mythbuntu --mythbuntu-copy-user-credentials
If the first command fails, you can try going back to the Myth Control Centre. Diskless Server >> CPU architecture of your clients: >> i386 >> Delete Image >> Apply. DO NOT run the second command from a root shell (only run it through sudo) or it will take a long time and eventually fail.

Moving along, commandline:
sudo -s
vim /etc/dhcp3/dhcpd.conf
[or if you don't like the vi editor (wha?) use something else]
make the file look like this:

authoritative;

log-facility local7;

option domain-name "madsonclan.net";
option subnet-mask 255.255.255.0;
option domain-name-servers 65.24.7.10, 65.24.7.11;

allow bootp;
allow booting;

#option ip-forwarding false; # No IP forwarding
#option mask-supplier false; # Don't respond to ICMP Mask req

subnet 192.168.0.0 netmask 255.255.255.0 {
option routers 192.168.0.1;
range 192.168.0.100 192.168.0.250;
option broadcast-address 192.168.0.255;
option subnet-mask 255.255.255.0;
option root-path "/opt/ltsp/i386";
if substring( option vendor-class-identifier, 0, 9 ) = "PXEClient" {
filename "/ltsp/i386/pxelinux.0";
} else {
filename "/ltsp/i386/nbi.img";
}

}

group {
next-server 192.168.0.1; # IP address of your TFTP server

host mvp { # NOTE: Change the hardware ethernet to the MAC address of your actual MVP
hardware ethernet 00:0d:fe:39:21:04;
fixed-address 192.168.0.50;
filename "dongle.bin.mvpmc";
option root-path "/home/mvp,rsize=4096,wsize=4096,nolock";
}
host mvp2 {
hardware ethernet 00:0d:fe:39:21:06;
fixed-address 192.168.0.51;
filename "dongle.bin.mvpmc";
option root-path "/home/mvp,rsize=4096,wsize=4096,nolock";
}
}
[substitutions]
madsonclan.net = yourdomain.com or make something up
65.24.7.10, 65.24.7.11 = your ISP dns servers
192.168.0.XXX = your internal IP addresses
00:0d:fe:39:21:04/06 = the MAC address of you MediaMVP (sticker on the bottom)

MVPMC:
Go get the latest dongle.bin from: mvpmc.org
and then:
mkdir /tftpboot
cp [DOWNLOADED_FILE] /tftpboot/dongle.bin
dd if=/tftpboot/dongle.bin of=/tftpboot/dongle.bin.ver bs=1 count=40 skip=52
vim /tftpboot/dongle.bin.config
file should like:
# set up host environment variable
HNAME='mvp_uno'
export HNAME

# time stuff
TZ='US, Central: CST+6CDT,M3.2.0/2,M11.1.0/2'
export TZ
echo "TZ='US, Central: CST+6CDT,M3.2.0/2,M11.1.0/2'" >; /etc/shell.config
echo "export TZ" >> /etc/shell.config
NTP=time-a.nist.gov

# create an /etc/hosts file
echo "127.0.0.1 localhost localhost" >> /etc/hosts
echo "192.168.0.1 media-server media-server" >> /etc/hosts
echo "192.168.0.1 eteo eteo" >> /etc/hosts #important! or mythtv won't play. replace eteo w/ myth server hostname

# load settings
. /etc/udhcpc.config
SETTINGSDIR=/tmp/settings
mkdir -p ${SETTINGSDIR}
SETTINGS=${SETTINGSDIR}/settings
RSETTINGS=settings.${HNAME:-$IP}
LASTSAVED=${SETTINGSDIR}/.lastsaved
touch $LASTSAVED
tftp -g -r $RSETTINGS -l $SETTINGS $SERVER;

# mounts (change for your network)
# i use nfs for linux and cifs for xp
mkdir /media
mkdir /media/sde1
mkdir /media/sda1
mkdir /media/sdb1
mkdir /media/quinn
mount -t nfs -o nolock,rsize=4096,wsize=4096,nfsvers=3 192.168.0.1:/media/sde1 /media/sde1
mount -t nfs -o nolock,rsize=4096,wsize=4096,nfsvers=3 192.168.0.1:/media/sda1 /media/sda1
mount -t nfs -o nolock,rsize=4096,wsize=4096,nfsvers=3 192.168.0.1:/media/sdb1 /media/sdb1
#mount -t nfs -o nolock,rsize=4096,wsize=4096,nfsvers=3 192.168.0.1:/media/quinn /media/quinn
mount.cifs //192.168.0.23/quinn /media/quinn/ -o user=someuser,pass=somepass,rsize=34000

# save settings
(
while true; do
if [ $SETTINGS -nt $LASTSAVED ] ; then
tftp -p -l $SETTINGS -r $RSETTINGS $SERVER;
touch $LASTSAVED;
fi;
sleep 300;
done
)&

# mvpmc settings

#known working
#mvpmc -f /etc/helvB14.pcf -o composite -S 0 -D 192.168.0.1:0 -R 192.168.0.1 -s 192.168.0.1 --vlc 192.168.0.1 --vlc-vopts svcd -y 192.168.0.1 -T mythconverg -u mythtv -p 8DelSgNw -b /eteo/livetv --weather-location USWI0164 &

#real-world
mvpmc -f /etc/helvB14.pcf -o svideo -a 16:9 -S 0 -R 192.168.0.1 -s 192.168.0.1 -y 192.168.0.1 -T mythconverg -u mythtv -p myMythTvPassowrd-b /eteo/livetv --weather-location USWI0164 --vlc 192.168.0.1 --vlc-vopts svcd &
Change IPs, hostnames, drive mappings, weather code, etc for your needs.

TFTP/NBD:
vim /etc/inetd.conf
tftp  dgram  udp  wait  root  /usr/sbin/in.tftpd /usr/sbin/in.tftpd -s /tftpboot
9571 stream tcp nowait nobody /usr/sbin/tcpd /usr/sbin/ldminfod
9572 stream tcp nowait nobody /usr/sbin/tcpd /usr/sbin/nbdswapd
2000 stream tcp nowait nobody /usr/sbin/tcpd /usr/sbin/nbdrootd /opt/ltsp/images/i386.img

vim /etc/nbd-server/config
[generic]
# If you want to run everything as root rather than the nbd user, you
# may either say "root" in the two following lines, or remove them
# altogether. Do not remove the [generic] section, however.
user = nbd
group = nbd

# What follows are export definitions. You may create as much of them as
# you want, but the section header has to be unique.
[export]
exportname = /opt/ltsp/images/i386.img
port = 2000

If you are running a firewall, poke holes in it for tftp(:69), nbd(:2000), mythtv, etc. I recommend you make all ports open for the internal network.
/etc/init.d/dhcdbd restart
/etc/init.d/dhcp3-server restart
/etc/init.d/nbd-server restart
/etc/init.d/xinetd restart
If you are running a firewall, you need to disable when the MediaMVP first boots. I can't explain why but, I'm pretty sure it's an issue at the hardware level. When you power off the system via the remote and turn it back on, you don't need to mess with the firewall. However, if you lose power and you see the big blue MediaMVP initial boot screen, you need to disable the firewall until you see "Application Loading". If you don't the MediaMVP will not be able to get an IP address or find the Mythbuntu server.

Oh yea:
I may be missing a few things in this HOW-TO. If you are running the H3 wireless or have some other goofy setups, you may want to refer to this HOW-TO: https://help.ubuntu.com/community/MythTV/MediaMVP_Frontend

Otherwise, you should be pretty much good to go at this point. Any laptop or other i386 arch machine you plug-in and netboot off of should get Mythbuntu via squashfs read-only. The cool thing is that the server assigns a AUFS share via NFS based on the MAC address of the machine. If you save anything to the desktop, make settings changes, install software, etc and reboot, those changes will remain intact. If any methyl-ethel-bad-stuff happens, take a look in: /var/cache/mythbuntu-diskless/overlay and nuke the directory that corresponds to MAC address and it will rebuild itself on the next boot.

Still have problems:
This forum thread is pretty invaluable and if all else fails, ask them: http://ubuntuforums.org/showthread.php?t=711079

HOW-TO: HTC 6800/Mogul/Titan as USB Modem in Ubuntu

Posted by Quinn Madson | Posted in | Posted on 9:36 AM

1

sudo -s
apt-get install subversion
svn co http://synce.svn.sourceforge.net/svnroo … rndis-lite
cd usb-rndis-lite/
make
./clean.sh
make install
vim /etc/network/interfaces
add:
auto rndis0
iface rndis0 inet dhcp
reboot

Plug in the phone via USB. On the phone go to programs/applications and select "Internet Sharing"

PC Connection:USB
Network Connection: Phone as Modem

Click "Connect"

Fire up a web browser, should be all set.

PHP4 & XML Generation

Posted by Quinn Madson | Posted in | Posted on 8:31 AM

0

<?php
// generate xml mime type
header ("content-type: text/xml");

// create xml document
$doc = domxml_new_doc('1.0');

// create xml root
$root = $doc->create_element("xml_root");
$root = $doc->append_child($root);

// create xml node
$item = $doc->create_element("xml_item");
$item = $root->append_child($item);

// add some text to the node
$item_text = $doc->create_text_node("yo yo");
$item = $item->append_child($item_text);

// generate xml output
$xml_string = $doc->dump_mem(true);
echo $xml_string;
?>
would generate:

<?xml version="1.0"?>
<xml_root>
<xml_item>yo yo</xml_item>
</xml_root>

PHP & LDAP

Posted by Quinn Madson | Posted in | Posted on 8:24 AM

0

// get username and password via form scope
$user = $_POST["username"];
$pass = $_POST["password"];

// format username for uwm ldap auth
$basedn = "ou=people,o=somewhere.edu";
$ldap_user = "uid=" . $user . "," . $basedn;

// connect to uwm ldap server
$ds=ldap_connect("ldap://ldap.uwm.edu");

if ($ds) {
// bind to uwm ldap server
$r=ldap_bind($ds, $ldap_user, $pass);
}

// close out ldap connection
ldap_close($ds);
Your basedn may vary. Also, the protocol, ldaps://. supposedly works but so far, I have had no luck. I have a sneaking suspicion that it has something to do with self-signed certificates.

HOW TO: Install Flex Builder 3 Alpha on Hardy Heron 64-bit

Posted by Quinn Madson | Posted in | Posted on 12:56 PM

0

32-bit Java Runtime Environment needs to be installed (which can be done through synpatic/apt-get).

Run the following at the command line:

export PATH=/usr/lib/jvm/ia32-java-6-sun/bin/:$PATH
Install the firefox-2 package from synaptic/apt-get.

Start the Flex installer:
chmod a+x flexbuilder_linux_install_a3_033108.bin
./flexbuilder_linux_install_a3_033108.bin
At the end of the install process, it may explain that you need to manually copy a file to the Firefox 2 plugins directory:
sudo cp Adobe_Flex_Builder_Linux/Player/linux/install_flash_player_9_linux/libflashplayer.so /usr/lib/firefox/plugins/
Start Eclipse and the Flex Builder 3 Plugin should be available.

HOW TO: Run 32-bit Eclipse on a 64-bit Hardy Heron platform

Posted by Quinn Madson | Posted in , , , | Posted on 12:28 PM

0

At a command prompt run:

sudo apt-get install ia32-sun-java6-bin
... or get it from Synaptic.

Download a 32-bit version of Eclipse from: eclipse.org. Extract the package to your home directory.

Right click on the Gnome panel and select "Add to Panel..."

Select "Custom Application Launcher" and click "Add"
Name: Eclipse IDE
Command: /home/qk/eclipse/eclipse -vm /usr/lib/jvm/ia32-java-6-sun/bin/java
Comment:qk is the coolest :)
(You can also set the icon by clicking on the default icon and navigating to your eclipse install directory. Replace qk with your username and/or eclipse with where you put eclipse.)
Click "OK"

Click the Eclipse launcher and you should be all set.