Archive for January, 2005

Extending MediaWiki

January 28th, 2005 by daryl

MediaWiki is the software that drives Wikipedia, a huge online collaborative encyclopedia that is at times at the heart of a fair amount of controvery having to do with matters of the site’s reliability, given that it’s authored by Joe Public. When I’ve installed wikis before, I’ve usually gone with phpwiki, which is very simple and somewhat less intimidating than Mediawiki. My new company decided to use a wiki as the starting point for our intranet, and I decided to take the plunge and try out MediaWiki.

As it turns out, the software’s a breeze to install and a dream to use. Its interface is crisp and simple to navigate, and it’s got loads of formatting options. Among the things we wanted to add to the wiki to make it more extranet-like was our company del.icio.us feed, which contains links relevant to our plans. Naturally, rather than just showing the raw RSS feed, we wanted to parse the feed and display it as a list of links. Which presented a bit of a problem, as MediaWiki out of the box doesn’t allow parsing of code. So I couldn’t very well just put in a PHP block that’d parse the feed and convert it to a list of links.

I read around a little and confirmed my suspicion that you can write extensions for MediaWiki. It’s actually very simple. Because MediaWiki’s schtick is to parse tags, the extensions API assumes that you’re going to define a new tag to be parsed, and once you register the extension, any time you use the newly defined html-style tag in an entry, it passes the content between the tags to the extension and prints the return value to the screen in place of the tag and its contents. So for example, you could define a tag “<name>” and have its extension just return your name. Whenever the wiki’s parsing a page and runs across the <name> tag, it’ll substitute your name. In my case, I needed a tag that’d parse a PHP block. The extension I wrote is as follows:

//Add the hook function call to an array defined earlier in the wiki code execution.
$wgExtensionFunctions[] = “wfPhpParse”;

//This is the hook function. It adds the tag to the wiki parser and tells it what callback function to use.
function wfPhpParse() {
global $wgParser;
# register the extension with the WikiText parser
$wgParser->setHook( “phpcode”, “renderPhpParse” );
}

# The callback function for converting the input text to HTML output
function renderPhpParse( $input ) {
//Eval the code between the tags.
return eval($input);
}

Once you’ve written the extension, you add a line to LocalSettings.php in the root that includes the extension file. And that’s it. To use the extension within a wiki entry, I’d type something like the following:

<phpcode>
$txt="The date is " . date('M d, Y') . ".";
return $txt;
</phpcode>

Note that I’m building my text and returning the value. This is because a PHP eval (used in my extension) will execute the code in line unless it finds a return at the end. So if you want the eval to return its value to the extension function to be returned to the main wiki code rather than just executing in line (which will give you weird results), you need to add any output to a variable and return the variable. This extension probably wouldn’t be the best in the world to use for a public wiki because it will indiscriminately execute PHP code submitted by users, and a malicious user could, for example, add to the main page an infinite loop that’d bring your site crashing to its knees. In my case, the wiki I’m administering is for private corporate use, and all users are trusted, so I feel ok about letting them add PHP code if necessary. I provide the example merely to demonstrate how absurdly easy it is to extend an already very cool piece of software.

Setting up SpamAssassin

January 27th, 2005 by daryl

I just set up SpamAssassin for my new company. Over the last year or so, I’ve picked up a lot more about doing sysadmin than I suppose I ever figured I’d know. There’s still plenty of very basic stuff I haven’t figured out yet, but I’m slowly glomming things onto my knowledge base. For example, in September or so, I did my first install/config of postfix, qpopper, and mailman. I had managed previously not to have to do much in the way of mail configuration. With the help of Google, I got it all figured out.

This week, I’ve been working on a server that already had postfix installed, but when I set up the accounts on the box, I almost immediately began to get spam, so I figured I’d set up SpamAssassin. It’s really ridiculously easy, though I ran into one problem that even Google couldn’t help me run down a solution to. Basically, you just get SpamAssassin installed and make sure spamd’s running and that spamc is in place. Then you edit /etc/postfix/master.cf to add the following lines:

smtp      inet  n       -       n       -       -       smtpd -o content_filter=spamchk

That goes in the services section and tells smtpd to run mail through the content filter named (below) “spamchk”. The section defining spamchck is as follows:

spamchk   unix  -       n       n       -       -      pipe
    flags=Rq user=filter argv=/usr/local/bin/spamchk -f ${sender} ${recipient}

So smtpd goes to this section and sees that it’s supposed to execute the file /usr/local/bin/spamchk as the user “filter” (which user has to be created and given permission on the script), passing the incoming mail to the script via pipe. You can put any number of things in your spamchk script. For example, I wrote some code for our system here at my soon-to-be-ex-job that scans subject lines of emails for a certain pattern and saves a copy of relevant emails to the file system (looking in the mails for attachments and saving them out elsewhere) and puts some info about the email in a database, tying it to a customer record so that we automatically have a searchable collection of email stored note in personal mail folders but in a spot accessible by all our internal users. For my new install of SpamAssassin, my filter’s pretty simple:

#!/bin/sh

# -----------------------------------------------------------------
# File:        spamchk
#
# Purpose:     SPAMASSASIN shell-based filter
#
# Location:    /usr/local/bin
#
# Usage:       Call this script from master.cf (Postfix)
#
# -----------------------------------------------------------------

# Variables
SENDMAIL="/usr/sbin/sendmail.postfix -i"
EGREP=/bin/egrep

# Exit codes from 
EX_UNAVAILABLE=69

# Number of *’s in X-Spam-level header needed to sideline message:
# (Eg. Score of 5.5 = “*****” )
SPAMLIMIT=5

# Clean up when done or when aborting.
trap “rm -f /var/tmp/out.$$” 0 1 2 3 15

# Pipe message to spamc
cat | /usr/bin/spamc -u filter > /var/tmp/out.$$

# Are there more than $SPAMLIMIT stars in X-Spam-Level header? :
if $EGREP -q “^X-Spam-Level: \*{$SPAMLIMIT,}” < /var/tmp/out.$$
then
  # Option 1: Move high scoring messages to sideline dir so
  # a human can look at them later:
  # mv out.$$ $SIDELINE_DIR/`date +%Y-%m-%d_%R`-$$

  # Option 2: Divert to an alternate e-mail address:
  $SENDMAIL daryl@emailaddress.com < /var/tmp/out.$$

  # Option 3: Delete the message
  # rm -f /var/tmp/out.$$
else
  $SENDMAIL "$@" < /var/tmp/out.$$
fi

# Postfix returns the exit status of the Postfix sendmail command.
exit $?

Initially, when I set this (or even any much simpler filter) up, I’d get a loop error sent to my root account telling me that the message had “Too many hops.” I finally figured out that basically, postfix was routing the mail back through sendmail, which was routing it back through postfix, back through sendmail, and so on, until there were too many iterations and the message failed. The fix turned out to be to change the line ‘SENDMAIL=”/usr/sbin/sendmail -i”‘ to ‘SENDMAIL=”/usr/sbin/sendmail.postfix -i”‘. That done, the filter seems to work like a charm.

I probably need to tweak it because right now, it delivers all spam mail to me rather than saving it out or just marking the subject line with a spam marker and delivering it to the intended recipients. That’s the default in the script I found, and I’m not sure it’s going to cut it for my purposes. Now that I’ve gotten over the looping hump, the rest is simple, though.

Humanopard

January 27th, 2005 by daryl

Giraffes are sometimes called cameleopards because they sort of resemble what might be produced from a union between a camel and a leopard. In Greek mythology, there’s a creature called a chimera that has the body of a lion, a serpent for a tail, and the head of a goat. Apparently, scientists are coming closer and closer to producing species of animals that are a cross between human beings and other species.

This raises all sorts of interesting questions, such as what rights such a creature would or should be afforded. Does its human genetic material grant it the same rights as the rest of us or do its animal genes cause it to be lumped with pets and farm animals?

New Job

January 24th, 2005 by daryl

So I’m changing jobs. I’ve worked for almost two years at The InSite Group, where I produced intranet and extranet applications that facilitated the management of image and sign projects. If you see a new bright green Radisson sign going up somewhere, my code helped bid the project out, make sure deadlines were met, make sure all vendors (including my company) got paid, etc. The same goes for any number of other pretty major brands regionally and nationally. It was a good job, and I really enjoyed it a lot.

A few months ago, I started doing some volunteer work for the Mozilla Foundation and wound up becoming one of the fearless admins of the Spread Firefox initiative. One of my main contacts for that was Bart Decrem, who later left MoFo to start his own company. He asked me to do some contract work for him, and ultimately he offered me a job with his company. After some haggling, it turned out to be an offer I couldn’t refuse.

So effective Feb. 2, I’ll be working as a Web Services Architect for the new company, operating out of my home office and embarking on what we think will be new territory for the Web at large. It should be fun, educational (as was the sfx experience), and perhaps a bit hair-raising. Wish me luck.

Latin Booty Party

January 15th, 2005 by daryl

Latin Booty Party JamWe went to a clothing store last night to look for some stuff for Mleeka. As I got out of the car, I noticed a CD on the ground. A woman on her hands and knees with her butt up in the air and in a generally prevocative position whom, because of the lighting, I initially thought might be naked or very nearly naked was pictured on the CD. The title? Latin Booty Party Jams. I can only assume its songs are largely about some sort of Latin pirate fruit-preserves-making party, a cross between a treasure/scavenger hunt and a tupperware party and a canning get-together. Why the nearly naked lady I couldn’t say.

Are Atheists a Bunch of Whiners?

January 15th, 2005 by daryl

American Atheists sent out a press release yesterday that read in part as follows:

Statements made earlier this week by President George W. Bush, including the claim that he does not “see how you can be president without a relationship with Lord,” are divisive and insult millions of Americans who do not believe in religious creeds or a deity charged an Atheist civil rights group.

Ellen Johnson, President of American Atheists, added that Mr. Bush’s interview with the Washington Times newspaper “demonstrates clearly that he does not respect the diversity of the country, and the fact that nonbelievers and so-called ’seculars’ are one of the fastest growing segments of American society.”

“He just doesn’t get it,” said Johnson, “and he seems to ignore the fact that in our Constitution we do not have a religious test for those seeking public office.”

I think Johnson may be overreacting. There’s a difference between what Bush has said here and what his father said a few years ago (”No, I don’t know that atheists should be considered as citizens, nor should they be considered patriots. This is one nation under God.”). Junior seems to me merely to be saying that with all the stress and hardship that goes along with being president, he doesn’t see how anybody could manage it without a belief in God. His dad was actually questioning the rights of those with no belief in any god. It’s as if G.H.W. Bush would have stripped atheists of their rights, while G.W. Bush simply can’t imagine that someone could fill such a difficult role without faith as a ballast, much as some might suggest that taking on such a role would be made less stressful by a few good stiff drinks in the evening. I may disagree with G.W. Bush’s statement, but I wouldn’t vilify him for it, and I worry that the AA statement makes atheists look like reactionaries and whiners, as if there wasn’t already enough negative sentiment toward them.

AA sent another press release yesterday pertaining to a decision by a U.S. District Judge to toss out a case brought by Michael Newdow (the infamous California pledge in schools guy) to remove prayer from the presidential inauguration. I’m more in line with AA on this issue. It’s not appropriate, in an official ceremony, to worship a particular sect’s god. This comes much closer to establishment of a religion than does a pretty harmless (ie, a non-citizenship-threatening) statement of opinion by the president. If the government would tolerate the drinking of ram’s blood at the inauguration by a pagan president or compelling the audience to bow to Mecca at the inauguration of an Islamic president, then perhaps Christian prayer at the inauguration would be acceptable. But as it is, this practice comes very very close to the establishment of a particular religion, and it should be carefully evaluated and possibly stopped. The president may pray privately with his family and friends all he wishes at no detriment to the political or governmental process.

Finally, there’s been some todo lately over evolution stickers in textbooks. Our old friend Gervase Markham is at it again with his question about the hubbub surrounding evolution stickers. The reason these stickers can be considered unconstitutional is that their use is based solely on the beliefs of a sect of Christianity. That sect disagrees with the theory of evolution and on that basis wishes to challenge it by having the government question the theory. This amounts to the government’s acknowledging that that sect’s viewpoint is valid in spite of the fact that it is at total opposition to science. If fundamentalists were insisting that stickers warning about credulity with regard to the theory of relativity and other theories, they might have a leg to stand on. In fact, good scientists, ever pushing for an emphasis on critical thinking, would probably favor not stickers, but whole chapters devoted to questioning established ideas in the name of increasing our knowledge. But it’s a one-issue deal, which relegates it to the realm of dogma. And for the government to endorse a particular dogma comes perilously close to its establishing the religion that purveys that dogma as the state religion.

Gervase suggests that the U.S. government overreaches its obligation to make no law respecting the establishment of religion and thus stands to violate its second constitutional obligation to make no law prohibiting the free practice thereof. What he doesn’t seem to understand is that nobody’s trying to keep people from having their kooky beliefs. Believe whatever you want; practice whatever you want. Just don’t try to force it on my kids or on me by having the government adopt your religion as the one true faith. Prohibiting the use of these stupid stickers doesn’t in any way prohibit the individual practice of a given religion.

Sick on Three Counts

January 9th, 2005 by daryl

Lennie’s sick, Mleeka’s sick, I’m sick. Lennie’s gotten the worst of it, with what appears to be a urinary tract infection. It all started a few weeks ago, when I gave her my cold (I also gave it to my sister and her family and I think to my dad). She developed an ear infection toward the end of getting over that cold, and she was on antibiotics for that. The antibiotics gave her diarrhea (on top of a yeast rash that makes her butt look angry and scarred even still, in spite of some medecine we’ve gotten for it), which we’re hoping is what has given her the urinary tract infection. (We’re hoping that’s what it is because one of the alternatives is that the valves in her ureters are screwed up and she’s got reflux that basically lets waste get back up to her kidneys and infect the whole tract; the treatments for this can be as mild as a daily antibiotic and as severe as surgery to repair the valves. So we’re hoping it’s the diarrhea and are going in next week for testing.) For the third day in a row now, we’re going in to the doctor this morning to have them administer a very painful antibiotic to Lennie. Very painful as in our baby, whom we coddle so thoroughly that the first peep of a cry is reduced to a whimper within minutes if not seconds, has bawled open-mouthed and at the top of her lungs for 15 minutes each time. And on top of it, we keep pumping Motrin into her for the fever (which got up to 104.something) and bulb suctioning her nose and generally allowing her to poked and prodded at. This really stinks.

In other, more pleasant, news, she’s got a second tooth coming in (we were at Target when Mleeka discovered it; we were browsing separate sections of the store, and she started cooing and talking to Lennie about the tooth and apparently kind of freaked out a little girl nearby who thought she was being addressed). It’s a bottom near-front one. And she’s sitting up well enough now that we’re not constantly worried that she’s going to go tumbling backward (though last night, as she and Ella were sitting facing one another on the floor sort of petting at one another’s hands, Ella reached up casually and put her hand gingerly on Lennie’s forehead to push her over backward; we got it on video, and I’m a little ashamed to say that I can be heard saying “thunk” in time with the impact of Lennie’s head bumping the floor).

Tucker Carlson Axed

January 6th, 2005 by daryl

A couple of months ago, The Daily Show’s Jon Stewart lambasted nut-job pundit Tucker Carlson on Crossfire, using that forum to blast its own genre. Now, although they’re being very courteous about the whole thing, CNN has figured out what a panty waste Carlson is and has ditched him. Crossfire is probably going away as well. CNN CEO Jonathan Klein has expressed a desire to maintain relationships with other Crossfire pundits Bob Novak, Paul Begala, and James Carville.

Umnounting a Stubborn Share

January 5th, 2005 by daryl

In order to make sure one of my current projects gets backed up regularly, I keep the files on a server that I mount using samba so that I can access the files as if they’re on my system. This is easier than finding a way to back up my system because I can force the system to mount the share at boot and never have to think about saving the files out (well, except that I’m paranoid and am also keeping versions in CVS [no, not the drug store — it’s a computer dork thing]). Occasionally, samba mounts go haywire, though, and when this happens, you can often un- and remount them to solve the problem.

When I tried this today, I got a “device is busy” error and couldn’t unmount the share even when I tried to force it. I googled for a minute and found this site, which pointed me in the right direction. Although I had checked all my terminals to verify that my cwd wasn’t on the share in question, I thought it’d be good to check and see if there was somehow somebody (me or someone else) using the share. And it turns out that the fuser command allows you to see this sort of info:

[houston]# fuser -vmu /home/files
                     USER          PID ACCESS COMMAND
/home/files          root          1553 ..c..  su
                     houston       9046 ..c..  bash

The “c” beside these entries means that the file system is in question is the cwd for that process. So in these cases, I was in /home/files when I opened a new session (in one case an su and in another a whole other terminal session) from which I then changed directories (meaning that it wasn’t obvious to me that I was actually using the file system because pwd showed me being elsewhere). Once I killed the processes, I was able to unmount the share, and when I remounted, the flakiness was gone. Nifty.