Author Archive

“n2″ Message Board Software: Update

This is a cross-posting with the nextBBS support board.

Some of you already know about this but keep reading…

Development of nextBBS v2 was steered in a new direction about two months ago and this is for the better.

“n2″ is the software’s new code name. And the change is more than skin-deep because it is actually the result of the merger of three different pieces of software:

+ wtcBB
+ nextBBS v2 “current”
+ My own PHP framework called “Lenses”

The result is a very fast, very user and admin-friendly board with easy install and localization across the board.

This new direction is very exciting for at least two reasons:

1. It allows me to work without being hindered by “youthful” mistakes I had made when developing nBBS v1 such as SEO being an afterthought and an Admin Control Panel that was too intimidating

2. wtcBB and nextBBS share a common philosophy on many levels and integrating both programs allows me to pick the best implementation. A few examples are BBCode editor, sub-sub forums, micro-caching, high logging granularity, editing look and feel in the admin cp…

You can follow progress through my submits and the issues tracker.

Go to my original post to see a few screenshots. I should bring a demo online soon.

If you enjoyed this post, make sure you subscribe to my RSS feed!


Zenoss jobs mailing list: Mistakes to avoid

zenoss-100x38Oh, how unfortunate: Zenoss, most likely not by malice but because they were not paying close enough attention to social netiquette, committed a big no-no: they decided that everyone whose email address they had on record was to be automatically added to their new jobs-related mailing list, no confirmation required.

Of course, now people are — some pretty aggressively — complaining and demanding to be removed from the list, and this makes matters worse because their list server is configured so that all replies go out to everybody on the list.

In the process, these unhappy responders’ signatures with work phone number, etc, are in turn published for everybody to see/collect.

And, to make matters worse, their list server does not properly weed out out-of-office messages and these, too, have become part of the email storm.

So, how could you avoid the same mistake(s)?

  1. When launching a new mailing list, it’s OK to *tell* people about it but the list itself should be opt-in (ideally double opt-in), never opt-out
  2. Even so, make sure that all emails sent from your list server contain a prominent link allowing your users to easily unsubscribe
  3. Configure your list server properly! Have a professional marketer do it for you it that’s not your thing. Do not underestimate what could go wrong: this is real-time communication, you do not have a safety net.

Update: - June 18th
Uh-oh. What was, I am sure, a misguided act, is starting to elicit more “hateful” reactions. I hope the Zenoss people address the issue before things get too ugly.

If you enjoyed this post, make sure you subscribe to my RSS feed!


Mount a recalcitrant .dmg file

pzizzI have no idea why but sometimes a .dmg file will just-not-mount.
For instance I just downloaded the latest PostBox from http://postbox-inc.com/ and the silly little image will *not* cooperate.

My amazingly quick’nt dirty workaround? Convert it to another format file (using the command-line)!

hdiutil convert postbox-1.0b12-mac.dmg -format UDTO -o postbox_iso

If you enjoyed this post, make sure you subscribe to my RSS feed!


Wordpress FLV Player Plugin v2.0

Cat  reloadedClose to two years ago, after quickly putting together my own FLV Player plugin for Wordpress (original post) I added it to Wordpress.org’s already impressive list of plugins. Who knows? Someone else might find it useful (it’s been downloaded more than 4,500 times since then so I guess that means someone did)

Yesterday a few people commented on that original post, thus reminding me of that plugin. It shamed me when I revisited its packaging to find out that it required from its users to download more pieces left and right. So, here it is, brand new v2.0, with everything included, and this means brand new SWF wrapper and brand new Flash file. Hope you forgive the fact that it took me all this time to provide a real self-contained archive.

wordpress-e280ba-flv-player-c2ab-wordpress-pluginsGo to the Plugin Page

Oh, and there is something I would like to address about this plugin. It’s actually a reply to one of the comments I received recently:

What do you mean by “a flash stream”? Does it stream an flv or use progressive download? To stream flash, you need a streaming media server. You should be clear and say what you mean - stop contributing to peoples’ ignorance.

Well, I hope it helps you feel a little less ignorant to know that the answer is “both.” This plugin can stream both types, depending on your use of a http-type or a rtmp-type URI. It can also play live streams. More information can be found here.

If you enjoyed this post, make sure you subscribe to my RSS feed!


Long-live the Triangle!

die_project_triangleAaron Oliver points out that knowing about the “Pick two” triangle is not as much the issue as what people do with that obvious bit of knowledge.

The “triangle,” if you are wondering, is a regular triangle with three named corners: Good, Cheap, Fast. Quite often, when faced with unreasonable demands, project managers/team leaders will draw this triangle on a white board/sheet of paper/paper napkin and ask their management to “pick two” because honestly it’s the best you can realistically get.

Sometimes, freelancers try that as well; often ends up with more unemployed freelancers. People do kill the messenger.

I find only one flaw with Aaron’s post: granted, grade-school students understand this thing. And so do your management/customers. Unfortunately this is irrelevant: their own management applies enough pressure on them that all they can do is look at your drawing and nod in agreement and ask in the very next sentence what can be done do “get all three.”

It’s like when using CMMI: one of the first things you need to do is to decide whether, for your project, schedule is the most important criteria, or whether features scope is.
It’s almost 100% certain that you will find, months in the project, that the most important criteria is the one that’s behind:

So, yes, the triangle is a bit obnoxious. And no, if you’re an engineer, it’s very likely that your management does not need to see it once again. But the problem lies mostly with the stakeholders: management’s management, marketing, other groups/units. These are the ones who need to be regularly reminded that “it’s not so simple.”

Because the more stakeholders the project has, the more likely they are to behave irrationally. That’s how we are wired to cope with external pressure.

If you enjoyed this post, make sure you subscribe to my RSS feed!


Sunday Hacking: Cue:Cat, Delicious Library

Blue LED.jpgSunday Hacking is going to be this new and irregular feature, where I blather about how I made my week-end a bit geekier by doing such or such hardware hack. I do not guarantee originality, nor much software-related content. If you’re not into that kind of thing, I promise that it shouldn’t feel much worse than a flu shot.

 

I like hacking on Sundays; that’s how I ended up with a stack of Wiimotes even though I did not own a Wii.
Anyway, I was in the process of sorting my various cables when I found her. And by “her” I mean my USB Cue:Cat.
This gave me an idea: my friend Tom and I both swear by Delicious Library. Now, there are two things you really need to know about Tom:

  1. He does not hesitate to spend money when he needs a good quality product
  2. He is insanely competitive

Regarding #1: he bought a nice barcode reader because it works better than an iSight.
Regarding #2: if I can come up with a cheaper barcode reader, it will totally feel like victory!

So, I googled “cuecat” and “delicious” and, of course, it’s easy to use the feline with Delicious Library.

Step #1: If you do not already have a Cue:Cat, you need to get one. It’s very easy: more than 2 million Raminagrobis were distributed before Digital Designs’ predictable demise (it’s one of those times when it’s not just hindsight, that should have been 20/20) — Make sure you get a USB model.

Step #2: Now, to “fix” it! By default, the device was dedicated to Digital Designs applications and this was achieved through the use of a very simple protocol (originally described by Steven Satchell)
cuecat before
Obviously, this is going to be confusing for programs that expect standard barcode information.


Hmmm...bad kitty!

Hmmm...bad kitty!


cuecat surgery
All you need if a wife who’s a med or a vet student and — voila! — you have a very convenient scalpel that you can use to remove pin #5 of the 8-bit chip labeled ‘HMS91C7316′

cuecat surgery detail
The circle shows where you need to remove pin #5. The arrow shows which way to go when counting pins (counter-clockwise)

And that’s it! Your malkin will now deliver compatible messages:
cuecat after

Amusingly, it is seen by your Mac as some kind of keyboard (not doubt through USB-HID); therefore, each scan operation will be an opportunity for your computer to play the bongos.
You can check what’s happening by scanning a barcode while in TextEdit rather than Delicious Library.

If you enjoyed this post, make sure you subscribe to my RSS feed!


Twitterified Client now fully Open-Source

Twitterified Client - Open Sourced!Well, this title says it all!

Find the announcement here.

And, of course, find the source code at GitHub: here.

If you enjoyed this post, make sure you subscribe to my RSS feed!


Determining if an IP is within a specific range: redux

Submarine NetI was reading Paul Gregg’s very clear explanation of “classless” ranges comparison when I realized that his code was not as “bare metal” as could be.

So, here is the code I’ve been using in nextBBS.
It only accepts ranges in the form “x.x.x.x/b” but it’s short and all I needed, really.

function isSubnet($subnet, $ip)
{
    // Classless (in more than one way) comparison
    $cursubnet = explode('/', $subnet);
    $longsubnet = ip2long($cursubnet[0]);
    $longip = ip2long($ip);
 
    if(count($cursubnet)<2)
    {
        // Compare IP itself
        return ($longip==$longsubnet);
    }
 
    // IPv4 only!
    $subnetmask = 0xffffffff << (32-$cursubnet[1]);
    return (($longip & $subnetmask) == ($longsubnet & $subnetmask));
}

If you enjoyed this post, make sure you subscribe to my RSS feed!


One-line variables swap in PHP, Ruby, Perl, Python and C

Joy in BlueToday’s fun and games: let’s swap a few variables without using more variables than necessary.

Let me know if you disagree with any of this…

$a = 1;
$b = 2;
list($a, $b) = array($b, $a);
print "a=$a, b=$b\n";
a = 1
b = 2
a, b = b, a
puts "a=#{a}, b=#{b}\n"
my $a = 1;
my $b = 2;
($a, $b) = ($b, $a);
print "a=$a, b=$b\n";
?View Code PYTHON
a=1
b=2
a, b = b, a
print 'a=%i, b=%i' % (a, b)

And now, good old C. Let’s use the only method that does not generate an overflow…first, for integer types:

int a=0, b=27;
a=(a^(b=(a=a^b)^b));
printf("a=%d, b=%d\n", a, b);

“Well,” you may say, “but what about pointers arithmetic? Any solution?”
Why, yes. That’s what I came up with after 15 minutes of fiddling:

char *a = "one", *b = "two";
a=(void *)(((long)a)^(long)(b=(void *)(((long)(a=(void *)((long)a^(long)b)))^(long)b)));
printf("a=%s, b=%s\n", a, b);

Note the use of void *, which allows me to ignore the pointer type. And, yes, I know, a C++ compiler may not really like this syntax. This may be doable using templates but I haven’t looked into that.
Sorry, I haven’t looked into Erlang or Haskell yet…

If you enjoyed this post, make sure you subscribe to my RSS feed!


Bespin in Titanium: From The Jaws Of Victory…

bespin is really an intriguing project. Since I’ve grown frustrated with the inconsistencies between the various code editors that I have been using — I work on Leopard at home and Ubuntu at work — I thought that creating my own editor would be the answer to that. Nothing fancy, mind you. Just something consistent.

My first impulse was to use Flex. And it almost worked! Using mx:html I was able to wrap a nice web page in an otherwise very ActionScript-y application.
And then, catastrophe! Flex Webkit’s canvas implementation is subpar and I could only get a very mamed version of bespin. Nothing usable, anyway.

Thus, I turned to Titanium.
After some light trial and error, I got it to work!

Unfortunately, the result is less than awesome: Titanium’s Webkit gets easily overwhelmed and, worse, crashes reliably ( :g: ) as soon as I ask it to do some medium lifting.

This video shows the original victory followed by the vexing defeat:

Note that, to get it to work, I replaced embed.js with my own version that works around any dojo.request()/eval issue:

?View Code JAVASCRIPT
(function() {
    // -- Load Script
    var loadme = new Array();
    var loadScript = function(src, onload) {
        var embedscript = document.createElement("script");
        embedscript.type = "text/javascript";
        embedscript.src = src;
        embedscript.onload = onload;
        document.getElementsByTagName("head")[0].appendChild(embedscript);
    }
    var onScriptLoaded = function() {
        var src = loadme.shift();
        if(src)
            loadScript(src, onScriptLoaded);
    }
 
    var componentRequires = function() {
        dojo.require("bespin.bespin");
 
        dojo.require("bespin.util.canvas");
        dojo.require("bespin.util.keys");
        dojo.require("bespin.util.navigate");
        dojo.require("bespin.util.path");
        dojo.require("bespin.util.tokenobject");
        dojo.require("bespin.util.util");
        dojo.require("bespin.util.mousewheelevent");
        dojo.require("bespin.util.urlbar");
 
        dojo.require("bespin.client.filesystem");
        dojo.require("bespin.client.settings");
        dojo.require("bespin.client.status");
        dojo.require("bespin.client.server");
        dojo.require("bespin.client.session");
 
        dojo.require("bespin.editor.actions");
        dojo.require("bespin.editor.clipboard");
        dojo.require("bespin.editor.cursor");
        dojo.require("bespin.editor.editor");
        dojo.require("bespin.editor.events");
        dojo.require("bespin.editor.model");
        dojo.require("bespin.editor.toolbar");
        dojo.require("bespin.editor.themes");
        dojo.require("bespin.editor.undo");
 
        dojo.require("bespin.syntax.base"); 
        dojo.require("bespin.syntax.simple._base");
 
        dojo.require("bespin.cmd.commandline");
        dojo.require("bespin.cmd.commands");
        dojo.require("bespin.cmd.editorcommands");
 
        dojo.require("th.helpers"); // -- Thunderhead... hooooo
        dojo.require("th.css");
        dojo.require("th.th");
        dojo.require("th.models");
        dojo.require("th.borders");
        dojo.require("th.components");      
    }
 
    loadScript("js/dojo/dojo.js.uncompressed.js", function() {
        dojo.require = function(src) {          
            loadme.push('js/' + src.replace(/\./g, '/') + '.js');
        }
        componentRequires();
        dojo.require("bespin.editor.component");
        loadScript(loadme.shift(), onScriptLoaded);
    });
})();

As you can see, I override dojo.request() with my own, stack up all the component names, then load them one by one, waiting for each to be fully loaded before moving on.

If you enjoyed this post, make sure you subscribe to my RSS feed!