2005/03/28
CommitMessage and HTML emails
| /metameta/English.lproj/TextFilterInspector.nib/ info.nib, keyedobjects.nib |
=================================================================== --- mm/English.lproj/Test.nib/info.nib 2004-05-28 20:49:23 UTC (rev 81) +++ mm/English.lproj//Test.nib/info.nib 2004-05-28 20:49:37 UTC (rev 82) @@ -11,6 +11,6 @@14 IBSystem Version -7F44 +7H63
=================================================================== (Binary files differ)
- Get and install commitmessage.
- From the root of the commitmessage installation, create a new directory for the HTML extension
$ mkdir commitmessage/views/extensions/
- Download my html-extension.tar.gz and extract it in the commitmessage installation. It should create a commitmessage/views/extensions directory.
- In the commitmessage.conf, in the [views] section, you probably have a something like:
email = commitmessage.views.email.TigrisStyleEmailViewReplace it with:email = commitmessage.views.extensions.htmlmail.HTMLStyleEmailView
- You can test it right away in the root of the commitmessage installation with:
$ python main.py /path/to/your/svn/repository any-revision-number
Some problems with Python when writing this extension. I'm an absolute beginner in Python, so I'm probably missing something. My first implementation used mimetools and MimeWrite, but I learned that the email module was probably better, I rewrote it. The issue was that I included my HTMLStyleEmailView inside the commitmessage-provided email.py (thus commitmessage.views.email module), and doing an import email from within this module was ambiguous. I moved everything to a separate commitmessage.views.extensions module and everything was fine. Please let me know if there is a clean way to reference a top-level module from a module with a similar name.
I was not able to just inherit from BaseEmailView as the execute method finishes the mail headers before calling generateBody, and I needed header customization to define the MIME multipart info.
2005/03/09
Obj-C runtime fun
So of course, I had this irrepressible urge to hack something similar for Objective-C.
Let's take the following Obj-C code:
@interface Bi : NSObject {
NSString* xxa;
}
@end
@interface Bo : Bi {
NSString* d;
id e;
}
@end
@implementation Bo
-(id)init
{
[super init];
e = [[NSScanner scannerWithString:@"asdfasdf asdf"] retain];
return self;
}
@end
@interface Ga : NSObject {
NSString* grunt;
NSMutableArray* a;
Bo* x;
}
@end
@implementation Ga
-(id)init
{
[super init];
grunt = @"pok";
a = [[NSArray alloc] initWithObjects:@"ag",
[NSString stringWithString:@"b"],
nil];
x = [[Bo alloc] init];
return self;
}
@end
(yes, I know, I did not code release methods, I'm leaking). Just use some magical NSObject category:
[g dumpObjectGraph];
And shazam !

- Objective-C is not Java, and introspection API is simpler, but /usr/include/objc/objc-class.h and friends are enough for this.
- This works reasonably well, even for some large programs, with one caveat: if you have garbage in one of your ivar, you're dead. It's not a problem most of the time but when I tried this on some AppKit code, it crashed. This could be fixed by maintaining a list of classes that should not be introspected.
- I need to cleanup the source code and put this on the web somewhere.
update: I wrote a new post with additional explanations and the source code on
2005/03/01
Airport Extreme-Express and SNMP
Installation went (almost) smoothly: my previous airport setup was just MAC based, and this not the best idea for WDS setup. Apparently doable, but it was simpler to switch to WPA.
Then ? Then I have this little obsession these days about data representation. How to express and manipulate complex data structure, provide high-level representation, graph running data, etc. Thus my current interests in Software Visualization, end-user 'big data', alternative representations for common tasks, etc. And in that context, I'm playing with automated graphing tools, for instance for network usage patterns, and so on, and trying things like Cacti, RRDTool. Somewhat too much sysadmin-oriented to my taste, but that's just a piece in the puzzle.
Back to the Airport: what about graphing the bandwidth usage, number of clients and see when my laptop is connected, etc. The Airport base station does have SNMP support, but a simple
Actually, Apple did release a MIB for Airport Express/Extreme base stations a while ago, but I did not find any useful information about how to exploit these, among with some comments 'great, but how do I access these paramters'. Motivation for further digging, so here is my findings. I must confess I was a SNMP absolute beginner, so most of this is probably very common.
- Download the MIB file for Airport Express/Extreme base stastions on http://docs.info.apple.com/article.html?artnum=120227
- Copy it in a directory where snmpwalk / snmpget will find it. For instance /usr/share/snmp/mibs on OS X
- The trick is that apparently a simple snmpwalk will not return airport-specific stuff, but if you specify you want these OIDs, it will work. For example:
$ snmpget -v 2c -c yourBasePassword 10.0.1.1 AIRPORT-BASESTATION-3-MIB::sysConfFirmwareVersion.0AIRPORT-BASESTATION-3-MIB::sysConfFirmwareVersion.0 = STRING: 5.5
- Give a look into the MIB file itself, there's some interesting stuff about the access point (name, location, firmware version, DHCP status and clients, physical interfaces) and connected clients (number of connected clients, noise, rates). Interesting enough, client information is actually provided by the client itself, the base station requesting the latest info for a client when needed. From the comments in the MIB, the level of support for non-apple drivers is unclear.
- You can actually do a snmpwalk and get all airport-specific information, if you provide a starting point:
$ snmpwalk -m AIRPORT-BASESTATION-3-MIB -Os -v 2c -c yourBasePassword 10.0.1.1 SNMPv2-SMI::enterprises.apple.airportsysConfName.0 = STRING: AirGeek BaseHere is a full dump
sysConfContact.0 = STRING: Olivier Gutknecht
sysConfUptime.0 = INTEGER: 512881
sysConfFirmwareVersion.0 = STRING: 5.5
wirelessNumber.0 = INTEGER: 3
wirelessPhysAddress."".17.36.12.8.97 = Hex-STRING: xx xx xx xx xx xx
[...]
wirelessType."".17.36.12.8.97 = INTEGER: wds(2)
wirelessType."".17.36.35.233.195 = INTEGER: sta(1)
wirelessDataRates."".3.147.236.96.87 = STRING: [ 1 2 5.5 11 18 24 36 48 54 ]
[...]
wirelessLastRefreshTime."".17.36.35.233.195 = INTEGER: 0
wirelessNoise."".3.147.236.96.87 = INTEGER: -45
wirelessRate."".3.147.236.96.87 = INTEGER: 54
wirelessNumRX."".3.147.236.96.87 = INTEGER: 193498
[...]
wirelessNumTXErrors."".17.36.35.233.195 = INTEGER: 1
dhcpNumber.0 = INTEGER: 0
physicalInterfaceCount.0 = INTEGER: 3
[...]
physicalInterfaceName.1 = STRING: "wl"
physicalInterfaceName.2 = STRING: "au"
[...]
physicalInterfaceState.1 = INTEGER: linkUp(1)
physicalInterfaceState.2 = INTEGER: linkDown(0)
physicalInterfaceState.3 = INTEGER: linkUp(1)
physicalInterfaceDuplex.1 = INTEGER: half(0)
physicalInterfaceDuplex.3 = INTEGER: full(1)
physicalInterfaceNumTX.1 = INTEGER: 2144683
[...]