Advertisement

Customize

What Kind of Man

Apr. 30th, 2009 | 09:09 am

This entry was originally published at my site's personal web log. Additional information or comments may be available on the original posting.

Over the past month or so, several people with whom I am close—either because we were once close and reconnected, or because we are newly close—have remarked on the jewelry I wear. I have five thin chain bracelets; one around each wrist and ankle, and a fifth closely fitted at my neck. I remember the nights Sara put them there.

“You’re still wearing these,” each of these friends said to me as they slipped a finger underneath one of them.

“I know,” I reply each time. “I’m still figuring out how much of them are me, and how much of them are Sara.” Who am I today, without the life I thought I’d have?

New York City has been a difficult place to be in. Instead, I have spent much of my time North, shuffling between Boston and Providence. The “organized” Boston communities are vastly divergent from The Scene that I am used to. I like the differences—I like that they exist, and that one place is different from another—even if I don’t like all the specifics.

In Boston, I attended the second NEPups.org puppy munch. I went with a friend and met a few gay pups and a kitty girl, and I spoke about queer masculinities and how uncomfortable I feel in the gay communities I’ve tentatively explored. I have never been gay, and I still feel a twinge of discomfort “admitting” to bisexuality in such spaces.

I have a growing connection to Providence. In large part, this is due to the people I’m coming to think of as the sun girl and the metal boy. They are young (younger than I am), which for the first time in my life is a notable thing. They live in slow time and enjoy the physical world in ways that are not entirely new yet not entirely familiar to me. There is much of Sara—a goodness and comfort—in each of them.

The metal boy in particular has been a quiet revelation for me. I find myself more unsure around him than I would have thought, as though I am younger, less experienced, more hesitant. I’ve been sexual with other men before but only now, after being with him, can I wholly and without silent reservation answer “Yes” to the still often asked question, “Are you really bi?” The sun girl, for her part, is in many ways a pure blessing. She is magic and warmth and a grounding force that has helped me move forward.

My trip to San Francisco these past five days proved useful but disappointing. It’s now obvious to me that the plan I had conceived before I left Sydney and which I so steadfastly tried to make happen despite the financial and emotional burdens of losing my relationship with Sara will not actually work. I’m thankful that I met with several other friends who have each generously offered support and crash space for my planned arrival time in late June. It may have perhaps been destined for me to be alone (but not isolated) when I arrive in San Francisco; it’s been almost a decade in the making for me by now.

I’ve been to San Francisco twice before this trip, but I’ve never been so happy to leave it before. I am still determined to move there, but as I write this in my airplane seat somewhere over the landlocked middle of the continent, I find myself eagerly awaiting a return to Providence. I can’t stay on the East coast, but I can’t leave. Not yet, not when there is still so much for me to do here.

My thoughts are consistently drawn to productive pursuits; my second CSS book, my sexuality projects (KinkForAll.org and MaleSubmissionArt.com). I feel strong in ways I’ve never felt before: I bend the world. I change reality. I can.

But I’m still so, so sad, and so, so pained. I don’t cry every day anymore, but I do feel overwhelmed by it. I suspect that, in part, Sara left me because I am so driven by the things I need to change rather than the things that work. Some parts of me want to reach a point where I’m no longer fueled by things that way, but other parts of me doesn’t. As one Bostonian friend fondly reminds me, “All progress is the work of unreasonable men.”

I speak about KinkForAll so often everywhere I go that I’m uncertain whether I’ve latched onto it or if it has latched onto me. I fear for it like a father fears for a child growing too fast and yet I keep pushing it out from underneath my own auspice because I know it can’t ever be what I want it to be without experience in the world. The weekend after I was in Boston, KinkForAll Boston was set into motion by the people I spoke with there and now I am determined to be a part of it.

In the mean time, I am also thinking and becoming increasingly excited about the Sex 2.0 presentations I will give on May 9th. In particular, I’ll get to meet the likes of Sarah Dopp, one of the inspirations for the Gender and Technology presentation that was accepted (and seems to be in increasingly high demand) at the Sex 2.0 conference. I’m just learning to speak with the people I admire to that degree, and in a week and a half I’m going to stand up and present my own version of the very things they inspire me to be. I will feel like I am standing in front of the very giants whose shoulders I stood on when I was across the planet.

So again, I ask myself, who am I? What is my sexual submissiveness without the dominant presence that revived it when I had given it up those four long years ago? What is my career when I have achieved, for me, an unprecedented level of recognition after 8 long years of being in the workforce? What is my contribution to my own future, and to people like me who are still young children today?

What kind of man am I if so much of the world I live in refuses to see manliness in what I am? Because today, having considered the possibility that I was perhaps a woman at earlier stages of my life, it turns out I am a man. And I am going to make the world know it is good to be the kind of man I am.

Permanent Link | Leave a comment {1} | Add to Memories | Tell a Friend

Guest Appearance on Technocolor NYC Technology Talk Radio Show

Apr. 7th, 2009 | 03:45 am

This entry was originally published at my site's personal web log. Additional information or comments may be available on the original posting.

Last week, I was invited to make a guest appearance on a technology talk radio show called Technocolor, which airs on 90.3 FM locally in New York City. The radio station is WHCR. The invitation was rather unexpected but I had a great time and a fun conversation with the host, Lena Marvin. We had such a fun time, actually, that Lena invited me to make a second guest appearance this week and, unlike the first show, I managed to record the audio stream, so you can replay the taping of the show and download it.

Here are my late-night and very sleepy attempts at listing some of the stuff we talked about, with as many links for show notes as I can manage to find:

  • April Fools’ Day jokes: GMail Autopilot automatically writes your emails for you, Identi.ca acquires Twitter, The Guardian will publish its archives by tweeting them.
  • NetFlix will demolish traditional cable television.
  • Drop.io can replace email attachments.
  • Skype has an official iPhone client; AT&T is not happy.
  • Stanford University to offer free iPhone development courses. Why go to college anymore? MIT already offers plenty of educational material from Open Courseware, iTunes University does something similar.
  • iPod Shuffle randomly maximizes its volume when people exercise. Owch. DRM physically bad for your ears?
  • New York Public Library offers free access to language learning courses from MangoLanguages.com, a $150 value.
  • Internet not actually good for job hunts.
  • Identi.ca hopes to add OpenID support (eventually). It’s a distributed “micro-blogging” platform. Fear vendor lock-in; Laconi.ca implements the open micro-blogging standard. Community organizations are especially vulnerable to vendor-lock in.
  • Free as in beer is an open source cultural reference. But wait, there is actually a “free beer”.
  • How to create your own secure, yet memorable, password algorithm: use the name of the site you’re on combined with a secret prefix to create unique passwords for each site.
  • Financial software to help you do taxes: Mint.com versus Quicken or Microsoft Money. TaxSlayer.com helps you file taxes electronically, possibly for free! Also, online government tools exist at, for instance, the New York State Department of Taxation and Finance.
  • PDFs should be used better than they are; PDF creators can use PDFs as online, electronic forms. Lots to learn about Adobe’s products for free at CreativeSuitePodcast.com.
  • Newer Microsoft Word document formats cause pain for the uninformed. Also, will newer versions of the PDF standard stay backwards compatible with older PDF files?

Listening to myself is a bit odd, and makes me realize just how quickly I speak. I need to learn to slow down a little. Nonetheless, I think I did okay, although I suppose I should have plugged my own web dev book a bit more. Meh, whatever. I was just there to have a good time, and I did exactly that—it’s incredible how quickly an hour goes by when you’re having fun!

Still, I’d love to hear feedback from listeners, as I very much welcome constructive criticism of what I could have done better and how. I’m also hopeful that I’ll get even more opportunities to chat with Lena, Javier, and the rest of the Technocolor crew semi-regularly from now on, since she mentioned something about being able to Skype me in even after I move to San Francisco.

Permanent Link | Leave a comment | Add to Memories | Tell a Friend

Now it’s all the little things

Mar. 12th, 2009 | 04:54 pm

This entry was originally published at my site's personal web log. Additional information or comments may be available on the original posting.

Immediately after arriving in New York City, I turned myself into a tornado of work and worry in order to make sure KinkForAll was the success I desperately needed it to be. To my indescribable relief and happiness, KFANYC wasn’t just a success, it smashed through even my wildest expectations, topping at 45 presentations with well over 100 participants physically present and countless others watching the online feeds. (I was so worried about presentation shortage, I prepared 4, but only ended up needing to present 1. Likewise, I originally thought we’d top off at maybe 35–45 participants, and in the end one of our biggest problems was simply lack of physical space!)

On that front, I’m now looking at the amazing possibility of helping people in sexuality communities who have contacted me from Washington DC, Toronto, and San Francisco emulate the success of New York City’s event in their own hometowns. But not yet…. Not quite.

As the unconference ended, Sara and I were joined by a group of over 20 friends (and friendly acquaintances) for dinner at a nearby Asian restaurant. Despite my hunger (I only ate at the behest of my concerned friends during the day ’cause I was so busy), I didn’t want to finish my meal; I knew that would be the end of dinner, and the day. Nevertheless, day turned to night and as Sara and I walked around the corner for a modicum of privacy, excitement gave way to sadness and we said (temporary) goodbyes in tears.

I retreated from the city then, headed towards Providence, Rhode Island to stay with close friends who generously offered me the opportunity to create a small sanctuary in their spare room. This has been helpful, and I can begin to feel myself recovering, but I’m still having trouble grounding myself in the here and now or focusing on the new tasks at hand. For one thing, there are so many, and for another thing, they are so vastly different from what I’ve just done that mentally changing gears so radically, so quickly, under so much pressure, is actually painful.

When I moved my self and my life half way around the globe to Sydney last year, I felt optimistic about what I would find. Sadly, I didn’t find what I wanted. Now, having moved myself and my life all the way back across the planet and then some, I’m determined to make what I want—because it doesn’t exist yet, and no one knows what it’s going to look like…except me.

My hosts, Emms and Zac, are nothing short of a godsend. They are literally a healing warmth of a magnitude I could not possibly express adequately in words. Unfortunately, shortly after arriving in their home, I fell ill. Of course, this is not at all a surprise considering my physiological history for exactly such mind-body connection.

My attempts to focus on my writing (for my second and much more advanced web development book on CSS I’m authoring; my first book was much more 101-level) have been only partially successful, but I’m encouraged by this anyway. As Emms told me last night while cooking a pasta dinner for us all, “Comfort yourself with the standards of the world,” a piece of advice she wisely preceded with, “Now’s the time to focus on only the most important parts of your chapters.” This, all while taking my hand every time my eyes unexpectedly overflow with the salt water I feel like I’ve been storing up in them.

I’m a little…not annoyed…chagrined at the admission that yesterday was the first full day in more than 4 weeks that I didn’t cry at all. Not only this, but earlier today while my hosts were at their day jobs and I mainlined enormous quantities of tea as though it were a blood transfusion, I couldn’t stop myself from crawling backwards in time towards happier memories. I cried again, embarrassingly loudly since no one was home, and resigned to let my head rest for a while instead of forcing it further into failing attempts to create reusable patterns of CSS code for styling semantic markup.

To help with the memories, I’ve been playing MGMT’s Kids on repeat for what must be an hour or more now. I first heard it on Australia Day (apparently Australia’s almost-equivalent of America’s Columbus Day), which Sara and I spent with Janek and company at his house on a tropical, warm, rainy day in Sydney. The radio was playing all day but the only song I remember was this one because, somehow, it stood out like a spotlight. I remember laying on the couch in the living room with my head in Sara’s lap, eyes closed, as she pet my head and I purred along with the kittens in the far corner of the room. The memory is emblazoned in my mind’s eye as a vivid still frame.

When Zac came home and gave me a hug to comfort my tears, he remarked on the song. “It’s always weird to hear this song,” he said.

“Why?” I asked.

“Because Emms and I went to college with them—the band.”

And now I have two memories.

Permanent Link | Leave a comment | Add to Memories | Tell a Friend

Too many tears: My first morning back in NYC

Mar. 7th, 2009 | 10:24 am

This entry was originally published at my site's personal web log. Additional information or comments may be available on the original posting.

A few minutes ago I awoke in a friend’s bed in their apartment in Harlem. I wanted to do nothing but stay there and not get up. I feel like there is too much to take care of, way too much to handle.

My flight from Sydney to New York City was less than good, better than terrible. I already knew I hated United Airlines, now I’m just more committed never to flying with them again. More than that, I’m frustrated that my flight was so dependent on choices Sara’s family made for her without consideration for me. If little else, I’m happy to be finally out of reach of their influence.

It’s been weeks, literally, since I haven’t cried at one point or another, usually multiple, in the day. I’ve been falling asleep in either tears or unmatched stress and restlessness—each has benefits over the other. Last night was no different.

Today I have errands to run for the KinkForAll New York City event I’m helping to run tomorrow. I’m extremely proud of the work Sara and I have managed to accomplish on it not only for the first time ever in our lives but also literally from the other side of the planet.

Simultaneously, I’ve been chasing and feeling continually frustrated by failing to make significant-enough progress on writing my book on CSS. My co-author Joe has been fantastic, and one particular employee, Clay, from the publisher has also been equally supportive. However, the rest of this project feels extremely precarious and that is endlessly aggravating.

It’s aggravating because it was a project I sincerely wanted to see done well, and have been working toward for a long time. I quit my day job something like 6 months ago now in order to focus on getting it accomplished successfully, but I am now further behind than I was then. Despite my best efforts, life kept throwing me curveballs to the point where I already know it’s not going to be the book I wanted it to be. I’m extremely angry at…everything…for that.

As if that weren’t enough, as many already know by now, Sara and I are no longer together, for reasons I’d rather not discuss quite yet. As painful as this would be in general, this is even more painful when seen in light of the fact that it’s one of the reasons my book has suffered. The book isn’t some great money-maker for me, but rather an opportunity for professional exposure and recognition that I’ve been working towards for 8 years—that’s how long I’ve been making money in the web development industry. To have that opportunity suffer pours salt into wounds that moving to Sydney in the first place had already re-opened and which the loss of this relationship is a 3rd degree burn.

All in all, I’m struggling to keep professional commitments afloat, organizing a first-of-its-kind unconference for the sexuality communities in New York City, ending a 4-year relationship (with the person I’m organizing the unconference with), and moving across the planet. All. At. Once.

I want to change the channel off of this ridiculous soap opera, but can’t. Instead, I keep playing everything in fast-forward in my head until I can again see a point somewhere in the hopefully not too distant future where everything I’ve worked on is successful and I’m peaceful once again. Please let that day be soon.

Permanent Link | Leave a comment {2} | Add to Memories | Tell a Friend

Buy Web Development Books from SitePoint’s 5-for-1 Sale and Donate to Bushfire Relief

Feb. 10th, 2009 | 08:06 am

This entry was originally published at my site's personal web log. Additional information or comments may be available on the original posting.

For those of you who don’t already know, I’ve been a blogger over at SitePoint for a few months now. Today, I’m even happier to be a participant in the SitePoint community because, for a limited time only, SitePoint is offering the sale of the century: buy 5 SitePoint books for the price of 1. Every last cent of the proceeds from the sale of these books will go towards relief efforts for the recent Victorian bushfires that have claimed over 300 lives and are among the worst fire disasters on record.

The books are full-color PDF downloads, and include some really awesome titles. These are precisely the kinds of books you want as PDFs, too, since you can search through them and always keep them with you while you’re coding and looking for inspiration or a reference (even when you’re without Internet access). I couldn’t help but pounce on this deal, and I’m now the proud owner of the following books, which have all received some pretty great reviews:

In just 3.5 hours, SitePoint has managed to raise over $15,000 AUD, according to employee Kevin Yank on Twitter. And that’s just on this side of the world. All my North hemisphere friends were asleep when this was announced, but not to worry. SitePoint’s sale will last until this Friday, so there’s plenty of time to take advantage of it.

Obviously, I think you should do so. Not only are you getting some really quality content and helping disaster victims at the same time, you’re also sending a loud and clear message that companies whose humanity outshines their accounting are the ones you’re going to support. I’m thrilled to see that SitePoint is one of these human companies, and ever more thrilled to be a part of it.

Permanent Link | Leave a comment | Add to Memories | Tell a Friend

Gender and Technology at IgniteSydney (with presentation slides)

Jan. 22nd, 2009 | 08:02 pm

This entry was originally published at my site's personal web log. Additional information or comments may be available on the original posting.

Last night at Ignite Sydney, I presented a 5-minute talk about how technology influences sexual awareness and how sexual awareness returns the favor, influencing the technology that we build. I had an amazing time, although I’m surprised I wasn’t literally vibrating from all my nervous energy. Thankfully, I think it all turned out okay and my presentation was received rather well.

For those of you that missed it, you can expect to find videos of all the presentations, including mine, posted on YouTube within the next few weeks and I’ll update this post when mine gets published. In the mean time, It took longer than I’d hoped and sadly the audio isn’t so great, but my talk is now published on YouTube. Along with that, here are my presentation slides in various formats for your remixing pleasure:

All materials in my presentation are by attribution Creative Commons licensed. Briefly, this means you can do whatever you want with it but please give credit where credit is due, just as I’ve done. :)

I do wonder if perhaps this presentation would have been even better received in a place like New York City or San Francisco, where I feel that there is more of an awareness of gender theory and its effects on the way we live day-to-day than there is in Sydney. Still, I’m glad that I set myself this challenge and really thrilled to have pulled it off. It’s amazingly difficult to condense gender theory 101 along with all the stuff I wanted to say about technology into a five minute presentation.

My thanks go out to all the wonderful people who cheered me on both before and after I presented, and to the organizers and volunteers at the event.

Permanent Link | Leave a comment | Add to Memories | Tell a Friend

clickjane.css: A CSS User Style Sheet to Help Detect and Avoid Clickjacking Attacks

Dec. 29th, 2008 | 05:31 am

This entry was originally published at my site's personal web log. Additional information or comments may be available on the original posting.

Clickjacking or, more formally, user interface redressing, is a class of security vulnerabilities similar to phishing scams. The technique uses web standards to trick unsuspecting victims into performing actions they were not intending to.

Clickjacking does not rely on bugs in any software. Instead, the technique is simply an abuse of the growing graphical capabilities that advanced web standards like CSS provide to web browsers. A good introduction to clickjacking is provided by Steve Gibson and Leo Laporte on their Security Now! podcast.

As far as I’m aware, only Firefox when combined with the NoScript add-on and Internet Explorer when combined with the GuardedID product provide any measure of protection against clickjacking attacks. To date no other browser can detect, alert, or otherwise help you to avoid or mitigate the risks of clickjacking attacks.

That said, there’s gotta be something users of other browsers can do. Well, it may not be as much as what NoScript can do, but there is something: use a user style sheet to help expose common clickjacking attack attempts.

clickjane.css helps detect clickjacking attacks for all browsers

Until browser manufacturers provide built-in protections against clickjacking attacks in their software (which is arguably the best place for such logic in the first place), I’ve started putting together a user style sheet I’m calling clickjane.css that attempts to instantly reveal common clickjacking attempts. Since it’s a CSS user style sheet, this approach should be cross-browser compatible so that users of any browser including Safari, Opera, and other browsers that don’t have other means of protecting against clickjacking attacks can use it.

I’ve only recently learned about this class of exploits and so I’m not supremely well-informed on the topic. As a result, the clickjane.css file is relatively sparse and currently only reveals what I’m sure is a small set of clickjacking attmpts. However, as I research the topic further and learn more about the actual underlying HTML and CSS that clickjacking uses, I’ll be updating the clickjane.css code to reveal those attempts as well.

Naturally, contributions and assistance in any form are most welcome! Learn more about clickjane.css as well as how to use it at the Clickjane CSS Github wiki.

Before and after clickjane.css

Here are two example screenshots of a benign clickjacking demo.

  1. Before:
    Screenshot of Safari before clickjane.css is used to expose clickjacking attempts.

    Screenshot of Safari before clickjane.css is used to expose clickjacking attempts.

  2. After:
    Screenshot of Safari after clickjane.css is used to expose clickjacking attempts.

    Screenshot of Safari after clickjane.css is used to expose clickjacking attempts.

Good habits you should get into to mitigate clickjacking risks

Here is a list of behaviors that you should make habitual while you browse the web. Engaging in these behaviors can dramatically reduce the likelihood that you will be victimized by a clickjacking attack.

More resources to learn about clickjacking

Permanent Link | Leave a comment | Add to Memories | Tell a Friend

Introducing KinkForAll: A no-limits gender and sexuality unconference

Dec. 18th, 2008 | 03:05 pm

This is crossposted from one of my other blogs. Read the full post for more context.


As if I didn’t have enough projects going right now, while here in Sydney, Eileen and I had an idea for a social and educational event that will promote positive ideals of sexuality from and to many communities and organizations. The idea is called KinkForAll, and I need your help to make the first KinkForAll event a reality this March. Below is the 411 on KinkForAll as well as links for where to learn more.


Most of all, I need your help to spread the word that KinkForAll event exists. To that end, please copy the flyer text below and post it on your blog(s), send it to any mailing lists you belong to, talk about it to your friends, and generally help get the word out. For this hugely beneficial movement to succeed, it needs enthusiastic participants on the ground—and that’s you!


Here’s the flyer text to copy:



PLEASE COPY AND CROSSPOST THIS MESSAGE FREELY.


If you have already heard about KinkForAll through the grapevine, then please consider this email a reminder. If you haven’t, then please take a minute to scan this message. You’re receiving this message because someone trusts you to read it with an open mind. Smile! :)


Vitals

======


What: A no-limits sex-positive gender and sexuality unconference.

Why: To inspire a creative, interactive and open environment where everyone feels comfortable talking, learning, and being inspired by all kinds of sexuality.

When: March, 2009 (exact date yet to be determined)

Where: NYC (We’re still looking for a venue! Can you help? See ‘Get Involved,’ below!)

Who: Everyone

How much: Free (as in beer as well as freedom)


Details

=======


KinkForAll is an ad-hoc gathering born from the desire for people of the kink, queer, sex-positive and related communities to share and learn in an open environment. It is an intense event with discussions, presentations, and interaction from all participants. (It is inspired by the BarCamp community.)


ANYONE WITH SOMETHING TO CONTRIBUTE OR WITH THE DESIRE TO LEARN IS WELCOME AND INVITED TO JOIN. When you attend, be prepared to share with others. When you leave, be prepared to share it with the world.


A KinkForAll is a special kind of gathering because there are no spectators, only participants. Attendees must give a talk or a presentation, help with one, or otherwise volunteer/contribute in some way to support the event. This is called sharing and we like it. All presentations are scheduled the day they happen—there are no pre-scheduled presentations or keynote addresses. The people present at the event will select the presentations they want to see.


Anyone can present, on any topic related to sexuality. You do not necessarily have to teach a new skill or idea. You might share an experience, review a product, or read a poem. The goal is to start a discussion, make connections, and exchange knowledge. Presentations promoting specific commercial products or companies are discouraged.


Learn more about what to expect at

http://kinkforall.pbwiki.com/WhatToExpect


Learn more about the event guidelines at

http://kinkforall.pbwiki.com/TheRulesOfKinkForAll


Get Involved

============


We need your help in spreading the word. Please help by participating. Here’s how:


1. Get excited by reading the ideas on http://kinkforall.pbwiki.com/KinkForAllNewYorkCity

2. Add your name or handle to the list of participants

3. Join the mailing list and introduce yourself by emailing kinkforall@googlegroups.com


If you have access to a venue, or know someone who has access to a venue, please email the kinkforall@googlegroups.com mailing list with that information.


Still have questions? Read the Frequently Asked Questions at

http://kinkforall.pbwiki.com/FrequentlyAskedQuestions


or email kinkforall@googlegroups.com for more details.


KinkForAll Online

=================


Participate online before the event at your favorite social networking web site.


Homepage: http://KinkForAll.org

Google: http://groups.google.com/group/kinkforall

Twitter: http://twitter.com/KinkForAll

Identica: http://identi.ca/kinkforall

Facebook: http://www.facebook.com/pages/KinkForAll/40066342762


All primary organizational efforts are being coordinated via the mailing list. Join for free and help turn ideas into realities!

http://groups.google.com/group/kinkforall

Permanent Link | Leave a comment {4} | Add to Memories | Tell a Friend

Why CSS needs delegation capabilities and not “variables”

Dec. 14th, 2008 | 02:55 am

This entry was originally published at my site's personal web log. Additional information or comments may be available on the original posting.

It’s been too long since I joined the fun, if amazingly heated, debates over the direction that Web standards are moving in. Recently, given the “free” time to do so, I decided to dive head first into what is (sadly) an almost 14 year old debate. The result is this blog post, which is mostly a response to Bert Bos’s essay Why “variables” in CSS are harmful and Matt Wilcox’s opposing response to that essay, Why CSS needs to borrow from programming languages. Their articles are each worthy of a read, possibly before this one.

Here’s the summary of my argument.

Adding many “programmatic” features to the CSS language such as variables, macros, or flow control is a mistake. However, CSS’s failure to simply encode visual relationships (instead of merely typographic properties)—a severe deficiency in the core language itself—requires the addition of delegation features. With the additional capability to reference an arbitrary element’s computed value regardless of its hierarchical context, CSS will be more accessible to both amateur and professional web designers, more capable, and will more forcefully promote the semantic Web and its ideals.

In this corner: CSS variables are harmful

Bert does a great job of summarizing the conclusion of his argument himself. In his essay, Bert says:

Adding any form of macros or additional scopes and indirections, including symbolic constants, is not just redundant, but changes CSS in ways that make it unsuitable for its intended audience. Given that there is currently no alternative to CSS, these things must not be added.

As we all know, one of the wonderful things about CSS is that the core language itself is remarkably simple. (What’s not simple is the spectacular way browser manufacturers have destroyed everyone’s hope that implementing CSS-based designs in the real world will ever be easy, but that’s a whole different can of worms.) Fundamentally, CSS’s syntax can be explained with a mere three major components: property/value pairs, declaration blocks, and rule sets.

What this means is that CSS as a language is stupidly easy to learn. I think everyone would agree that it’s certainly easier to learn than, say, JavaScript or XSL. Now, that’s important because, without putting too fine a point on it, Bert mentions multiple times that CSS’s “intended audience” are the diverse and likely relatively technically ignorant content authors that are responsible for the overwhelming majority of web pages on the public Internet today.

He makes the very good point that The value of the semantic Web isn’t defined by how well structured the best documents are, but by how well structured the vast majority of documents are. In other words, CSS needs to remain instantly useable and reusable to these untrained, amateur web content publishers for the benefits of self-describing documents (i.e., the semantic Web) to see mass adoption.

To wit:

reusing other people’s style sheets is more difficult if those style sheets contain user-defined names. Class names are an example. Their names may suggest why the author created them (assuming they are in a language you understand), but typically you will have to look at the document to see where they occur and why. Symbolic constants make that problem worse.

And, later:

For many people, style sheets with constants will thus simply not be usable. It is too difficult to look in two places at once, the place where a value is used and the place where it is defined, if you don’t know why the rule is split in this way. Many people are confused by indirection anyway and adding an extra one, in addition to the element and class names, has the same effect as obfuscating the style sheet.

Whether or not you believe Bert Bos is underestimating the average web designer, it’s pretty clear that these are really good points. Nobody wants CSS to be obfuscated, hard to learn, or hard to reuse. That’d just be crazy talk.

In the other corner: CSS variables are a real-world requirement

The more features you add to an application, a programming language, or indeed any software, the more difficult it becomes to grok it. As the Python people would say, the larger a language gets the more difficult it is to hold all of it in your head. Nevertheless, adding “features” is sometimes the only way to add capabilities, and I don’t think anyone in their right mind would argue that, once written, software should never change. (That’d just be crazy talk, too.)

In his opposing arguments, Matt Wilcox recognizes this when he says, Yes, the syntax should be simple, but the capabilities of CSS should not. What he’s alluding to without verbalizing it is the balance between adding necessary capabilities without unnecessarily growing the “size of the language.”

However, Matt says that modern web design methodologies (e.g., separation of concerns between structure, presentation, and behavior) dictate that CSS needs more capabilities than it currently has:

CSS lacks capabilities to allow truly flexible design, requiring layer upon layer of ‘tricks’ to accomplish certain objectives, requiring content to be structured ‘just so’ to achieve a display objective, or in the case of some designs proving instead to be completely incapable.

[…]

CSS’s positioning is a cludge. It’s a cludge because you can only position relative to the last positioned parent container. Well, that limitation in itself dictates that all positioning relies upon how the content is structured. And that means the presentation and the content are not truly separable.

To align CSS’s capabilities with the requirements of real-world web design objectives, he says, CSS needs to be capable of describing relationships between semantically and structurally arbitrary but visually related elements.

Visual design is fundamentally about relationships between elements. For all of the artistic flourishes and creativity, it’s about relationships. ‘That yellow’ only grabs your attention because of its contrasting relationship with ‘that blue’. ‘This heading’ only works as a heading because of it’s exaggerated relationship to the size of the body text. […] CSS has no clue about relationships, period. And that’s why CSS as it stands right now, is not good enough. That’s why CSS without variables (true variables), without basic logic, without maths, can never be as flexible as we need it to be.

This is what web designers have been complaining about for (what feels like hundreds of) years. The fact that CSS has no capability to describe presentational relationships between elements in addition to directly describing an individual element’s presentational properties is a gaping hole that sorely degrades its ability to be a media-agnostic styling language. Every single web designer I’ve worked with has gasped at this omission, and though at first I didn’t understand why, the more I understood the principles behind graphic design the more I came to realize how fundamentally problematic this omission really is.

Adding delegation makes CSS easier for designers

As Matt eloquently stated, design is all about relationships. Good web designers create designs by constructing visual elements that have strong, often exacting relationships with other visual elements. There are many names and examples for this: visual language, visual hierarchy, the golden ratio, the grid, visual balance, the typographer’s scale, and so on.

What happens when the designer tries to define a relationship between elements? “How do I say that the whitespace between element A and element B should always be the same? How do I define element A’s height as half of element B’s?” These definitions, which are natural and necessary to the way designers work in both their mind and their mediums, are impossible to encode in CSS.

The closest you can get is declaring the same values to each element’s properties, not describing the relationship itself. This suffices only so long as these values are known ahead of time and are the same as one another, which severely limits the design possibilities we are capable of (without resorting to what Matt calls “tricks”). That’s why achieving simple visual effects are actually very complex and so, sadly, that’s where you’ll find the majority of indirection and obfuscation in CSS today. (I’m looking at you, faux columns.)

So who wins?

Both Bert Bos and Matt Wilcox have made some great points. Bert rightfully wishes to keep CSS lean and simple, even at the expense of some arguably beneficial styling power. Matt, on the other hand, argues that our needs as web designers have evolved faster than the technology to the point where CSS is too limited, fundamentally so.

The truth is, they’re both right. And they’re both wrong. Or rather, they are each taking a position that is too extreme. Bert’s absolutely correct when says that many of these proposed extensions are redundant and harmful, and yet Matt’s also correct that CSS lacks some fundamental capabilities that designers expect to be present.

Bert says that the CSS capabilities everyone’s asking for can be implemented using techniques that don’t rely on CSS whatsoever. These techniques, he says, make things like true CSS variables “redundant.”

There are examples of CSS with constants to satisfy all styles of programming, e.g.: David Walsh (in PHP), Tedd Sperling (in PHP), Digital Web Magazine (in PHP), Eco Consulting (in SSI), and Christian Heilmann (SSI and PHP).

Quite simply, he’s correct in stating that programmatic features need not be added to CSS proper to achieve desired results, but he’s incorrect in his apparent thinking that designers will be able to use these other tools to leverage CSS. Take, for instance, the probably more familiar (though not linked above) notion of using JavaScript to manipulate CSS values.

var x = document.getElementById('SideBar'); // get #SideBar element
var y = document.getElementById('MainColumn'); // get #MainColumn
var z = document.defaultView.getComputedStyle(y, '').getPropertyValue('height'); // get computed height of #MainColumn
x.style.height = ( parseInt(z) / 2 ) + 'px'; // set #SideBar's height 1/2 of #MainColumn's

This is an example of programmatic code that uses variables and expressions. It sets the element with the ID of SideBar to half the pixel height of the element with the ID of MainColumn. It does this by obtaining the MainColumn’s height (at the time this code runs) and saving it in a variable, then performs some trivial math to half the value and use the result as the pixel height of the SideBar.

Doing this is currently impossible with CSS alone, yet it’s something that clearly belongs with whatever other “presentational” code exists and not in “programmatic” scripts that would otherwise be charged with defining “functionality.” As Matt states, using JavaScript to “script” solutions to CSS’s shortcomings like this is not an acceptable answer.

CSS doesn’t have [basic logic or maths]. Nor is it the job of JavaScript to make up for this lack of abilities. JavaScript is about interaction behaviour, and what we are talking about here is pure display logic. Not interaction logic.

Moreover, the place designers expect to put code like this is, of course, into a CSS style sheet. The way designers expect to put code like this into CSS is by adding delegation features. Requiring designers to learn JavaScript (or any other programming language) to encode such design relationships is nothing short of ridiculous. In what world is that easier for untrained laymen to understand than CSS?

Adding delegation to CSS is worth the effort

One of Bert’s arguments against such additions to CSS is that implementations would become harder to create, and that we’ll (almost certainly) see more bugs.

extending CSS makes implementing more difficult and programs bigger, which leads to fewer implementations and more bugs. That has to be balanced against the usefulness of the extension.

Although I do agree with his statement that an extension’s usefulness has to be balanced against its potential costs, I think something so fundamental to design methodology as delegation greatly overcompensates for the cost of such implementation efforts. Moreover, if I understand Bert correctly and as he also discusses, the majority of implementations that would need to implement such delegation already have relatively complex internal structures to make the implementation effort somewhat easier:

There is no scoping [in proposals that only define global constants]. That means that an implementation needs a symbol table, but no stack. A stack would require a little bit more memory, but mostly it would make implementations more complex. (Although every programmer has, one hopes, learnt to program a symbol table with lexical scope during his training.) Constants in CSS are thus easier than, e.g., XML Namespaces, which are lexically scoped.

It is different for those CSS implementations that provide a CSS Object Model (an API for manipulating a style sheet in memory). Those implementations do need to keep track of scope in some way, because adding or removing a line of the style sheet can make a previously redundant definition become meaningful.

In order to use JavaScript to solve many of the shortcomings of CSS, as huge numbers of professional web developers do routinely, we use the very CSS Object Model whose prior implementation already exists for us to build upon.

CSS delegation doesn’t grow the size of the language

For the sake of argument, let’s simplify our requirement somewhat so that our somewhat contrived example of design intent is to create a relationship between the MainColumn and the SideBar elements such that they are of equal height. This is more informally known as “making columns.”

Here’s what a natural, hypothetical snippet of CSS would look like if the language supported delegation features such that it could encode visual relationships.

#SideBar { height: #MainColumn; }

This code theoretically says almost the exact same thing as the JavaScript shown earlier (save for the division, of course); it takes the computed value of the MainColumn element’s height property and applies that value to the SideBar element’s height property. In other words, “The SideBar’s (element B’s) height is always the same as the MainColumn’s (element A’s).” (Of course, this is a parse error in reality today.)

This extremely trivial example has some remarkably far-reaching implications, and yet there is really nothing radical about its syntax. Making this a reality significantly expands the capabilities of CSS without dramatically increasing the size of the language. This capability would not only beat the pants offCSS tables,” it also potentially obsoletes the arguably misguided efforts of the CSS3 Advanced Layout and Grid Positioning modules, too.

We’ve long since abandoned table layouts because they force us to use presentational markup. That’s still what “CSS tables” force us to do, too. In other words, with display: table, the SideBar needs to be a child of the MainColumn element or, maybe worse and more likely, a child of a semantically meaningless wrapper element.

CSS positioning was introduced with the promise of freeing us from source-order-dependent styling, without which there is no hope of efficiently abstracting presentation away from structure. Moreover, abstracting presentation away from structure is the single most important prerequisite needed to improve document reusability and strengthen the semantic Web. Absolute positioning works, but limitations elsewhere in CSS mean its use is problematic for many designs, so in practice it doesn’t gain widespread adoption.

Here’s a theoretical solution to a two-column and a footer layout using CSS delegation with this semantic HTML:

<body>
    <div id="MainColumn">I'm the main column.</div>
    <div id="SideBar">I'm the right-hand sidebar.</div>
    <div id="Legalese">No one will read me.</div>
</body>

The CSS would look extremely familiar, possibly like this:

#MainColumn { margin: 0 25% 1em 0; float: left; }
#SideBar { width: 25%; min-height: #MainColumn; }

Using the same HTML, the same solution using the CSS3 Advanced Layout module would look something more like this, although to be frank I’m not certain I fully understand this syntax even after staring at it for months:

body {
    display: "a  b"
             ".  ." /1em
             "c  c"
             75% 25%
}
#MainColumn { position: a; }
#SideBar { position: b; }
#Legalese { position: c; }

Not only does there seem to me to be far more indirection in this method than there would be using CSS delegation, there is also an enormous increase to the size of the CSS language: a new (ASCII-art?!) value to the display property whose syntax is clunky at best. A similar story can be said of the CSS3 Grid Positioning module, which does lots more than just add a new (already complex) gr CSS unit.

The upshot is that the Advanced Layout and the Grid Positioning modules are doing some of the right things in many of the wrong ways. Both those modules add unnecessary complexity to CSS without giving designers a natural way to say what they mean. They do more to introduce obfuscation and indirection than simple delegation would, and they aren’t as broadly capable. Both of them try to solve a specific problem instead of dealing with fundamental deficiencies in the toolset designer’s have to work with.

Designers want relationships via delegation, not variables

Adding delegation such as that I’ve just shown is a natural, necessary addition to CSS because it is how designers create visual components—such as grids—in their designs. Variables (and constants, and macros, etc.), which simply reuse and modify pre-defined statements aren’t what designers care about. Adding them will bloat CSS without adding useful functionality.

“Okay,” you may be saying to yourself, “but delegation is itself a kind of variable, isn’t it?” Technically yes, however adding delegation resolves the core deficiency in the CSS language that designers need to use every day. Yes, it’s technically a form of variable, but that’s not how designers think of it. To say that one element’s visual properties is like another makes a variable only by creating a logical and visually appropriate mapping from the first element’s property to the second independent of markup, thereby avoiding indirection in the form of a variable name or other unfamiliar symbol.

Delegation like this doesn’t require the addition of anything other than what already exists in CSS. Class names and ID values are identifiers whose indirection people already have to deal with. Using them for delegation (to reference another element’s style) doesn’t increase the cognitive load any more than using them to reference HTML elements does. Though untested, the cognitive load might actually be even less since the CSS delegation’s references could be in the same (style sheet) file.

Moreover, delegation will increase the likelihood of document reusability by enabling style sheets to be more self-describing, more self-referential, in a similar way as good markup is. It satisfies a very fundamental need that designers have to define graphical relationships between elements. At the same time, it does so in a way that is natural to both their way of thinking and beneficial to the separation of concerns principle on which the “web stack” (the trifecta of HTML, CSS, and JavaScript) is based.

Permanent Link | Leave a comment | Add to Memories | Tell a Friend

WP-Oomph: Add the Oomph Microformat Overlay to your WordPress blog

Nov. 11th, 2008 | 07:44 am

This entry was originally published at my site's personal web log. Additional information or comments may be available on the original posting.

I’ve just developed a completely idiotic (by which I mean brain-dead simple) plugin for WordPress that will add the Oomph Microformat Toolkit to all WordPress-generated pages. If you use a WordPress template that encodes your data with valid microformats anywhere on your page, this means when you install the plugin your users will see the Oomph microformat overlay and will be able to instantly export this encoded data.

This page is a live example, so if you’re using a JavaScript-enabled browser you should see a microformat icon on the top-left of the viewport that is pulling data from (at least) my “The bio” section in my sidebar. Go ahead, click it. I’ll wait.

Pretty nifty, isn’t it? Naturally, all of the credit for this functionality belongs to the Oomph team, not me. If you want to learn how to add microformats to your blog, I’d recommend Emily Lewis’s latest series of blog posts, Getting Semantic with Microformats. If you want to learn how to easily add the Oomph microformat overlay to your WordPress blog, read on.

The backstory

After Ask.com’s announcement that they are adding semantic search capabilities to their search engine, there’s little doubt in anyone’s mind that the semantic web is the future’s web. As far as I know, Google has yet to reveal similar initiatives but they are clearly in the know as well. Mark Birbeck, one of the smart folks who devised RDFa, recently gave a Google Tech Talk that made the point that semantics are the next big thing in the Internet search engine game.

However, for semantic web stuff to really take hold, two things need to happen first. I think these things need to look like this:

  1. Developers must create tools, plugins, and other software that makes it possible for the wider community to create compelling, interoperable applications that support semantic encoding. Thankfully, we are already at this point, with toolkits like the Oomph Microformat toolkit coming out of MixLabs.
  2. Armed with these software tools, CMS and other publishing platforms need to adopt semantics as first-class features of their platforms, and build interfaces that end-users can make immediate use of. This is where we still need to go, though some platforms like Drupal have begun to pave the way for this.

Drupal 7 will be fantastic, I’m sure, but we live in the here and now. I saw the Oomph microformat overlay on Emily Lewis’s blog and was more convinced than ever that if everyone—programmers and laymen alike—had easy access to these tools, they’d simply be pounding down the doors to use them. So that’s why I sat down and wrote a completely idiotic plugin for WordPress that makes it completely, utterly, brain-dead simple for anyone with a microformats-enabled WordPress theme to add the overlay to their site.

WP-Oomph: Download the plugin

My request to add the plugin to the WordPress.org Plugin Directory has not yet been completed, so in the mean time I’m hosting the plugin right here. (When/if it’s accepted it’ll end up being The plugin is hosted on that site permanently.)

The latest version is: 0.1.1.

Download the latest version of the WP-Oomph plugin.

Thanks to the Oomph team’s work, the plugin is a ridiculous 1-liner (for now) that uses WordPress’s wp_enqueue_script() function to call both its included jQuery library and the Oomph library itself. And, well, that’s it. I told you it was idiotic, but at least now the whole process of microformat-enabling a WordPress blog is 100% point-and-click.

WP-Oomph: Frequently Asked Questions

I installed and activated the plugin, but nothing is different. How come?

First, view the source of your WordPres-generated page and make sure you see a line similar to the following near the top:

<script type='text/javascript' src='http://visitmix.com/labs/oomph/1.0/Client/oomph.min.js?ver=1.0'></script>

If you see that but there’s still nothing different about your page, then you probably don’t have any (valid) microformats. You might consider switching to a WordPress theme with built-in microformat support, or modifying your theme’s code to add some of your own. You can learn more about the support WordPress offers for microformats in the Microformat wiki.

The plugin does let me do X thing that I want to do! Why not?

Most likely because I haven’t taken X thing into account. Sorry, I’m not a psychic (as much as I wish I were). However, you’re encouraged to leave a comment on this post or to contact me elsewhere to request that I add capabilities to the plugin. Better yet, if you’re comfortable doing so, send me a patch.

Permanent Link | Leave a comment {1} | Add to Memories | Tell a Friend

Are you missing the point of using a version control tool?

Nov. 8th, 2008 | 12:49 am

This entry was originally published at my site's personal web log. Additional information or comments may be available on the original posting.

The other day I gave a brief (and overly-hyper) talk about git, the (very) dumb, (very) fast version control system. It was part of SyPy’s Git vs. Hg vs. Bzr night. Rather than be flamingly competitive, however, I had a lot of fun that night learning about the differences between the DSCM tools, which was especially interesting since I’ve only ever used Git in real life scenarios.

Since I’m a Subversion refugee, my only experience with different version control systems is mostly with the distinctions between the centralized versus the distributed models, not between the various tools you can use in either paradigm. What struck me when I first began using git was how conceptually similar it felt to using Subversion when I was using it by myself (as a lone developer) but how radically different it suddenly felt the moment I was sharing my code with someone else.

Now, I’m a die-hard individualist. I want things to happen my way as much as possible, and I don’t really care what happens for anyone else as long as when I interact with other people those interactions are as mutually beneficial as they can possibly be. That’s why I love DSCM tools so much.

Distributed source code management systems feel much more like translator tools between the ways in which people work as opposed to feeling like a dogma of workflow management processes, like centralized systems do. This paradigm appeals both to my preferred way to work and, as it turns out, helps more people stay more productive all at the same time.

This is also why I’m a firm believer that most of the people I’ve worked with in the past completely missed the point of using version control systems. It seems to me that most developers I’ve worked with have thought of SCM tools as “the ‘Save As…’ button on steroids.” While these developers are technically correct, their narrow view of what a VCS does means they aren’t taking advantage of the full potential of the concept.

The power of a version control system isn’t just in that it gives you the ability to easily hit the proverbial “Save As…” button as much as you want, but rather in that you get to retrieve those other versions when you’re ready for them, regardless of what your fellow developers are doing to the code on their machines. This means that a version control system’s real purpose is to insulate you from changes of any sort until you’re ready to deal with them. A good tool also does this reciprocally; it will insulate your fellow developers from the changes you’re making until they’re ready for them.

Admittedly, that’s not a very concrete “feature.” It’s more like a fundamental philosophical principle, which is probably why it’s so hard to encode into the physical manifestation of a tool. Then on top of all of that complicatedness you have to add things like usability and interoperability and resource efficiency. That’s where I learned about the majority of the distinctions between the various DSCM tools discussed in SyPy’s presentation.

However, for me, all of those things ultimately get evaluated against the following question: Does Feature X help insulate me from change (does it help in persisting my view of the state of the world until I’m ready for it to change), or not?

For example, Bazaar’s interesting notion of “nested commits” with dotted revision numbers is really intriguing because it’s much (much) more user-friendly than git’s notion of exposing SHA-1 hashes to (mere mortal) end user’s eyes. Yet, while it’s certainly less painful than copying-and-pasting hashes all over the place, there’s little fundamental difference in the way these mechanisms actually portray the state of the world to me. Any given SHA-1 will always be the exact same commit object. Any given dotted revision number will also always be the same commit (within one’s own unchanged repository).

In contrast, I learned from Martin Pool that Bazaar has a “push over SFTP” feature to let you “export” or “archive” a version of code by transmitting it over an SFTP connection. Now that really caught my attention because it’s an example of the version control tool acting like that translator I was mentioning earlier; the interoperability helps people not need to change until they want to. In this case, it means you never have to install Bazaar on a remote server to get your content there via the tool. That’s very cool—much cooler than the mundane technical fact that bzr supports the SFTP protocol out of the box.

Of course, it’s technically pretty trivial to write an expect or shell script wrapper to enable git (or whatever other tool you want to use) mimic this behavior. And that’s exactly the point: technology is always the easy part. It’s doing it right at a fundamental level that’s actually really difficult to do correctly.

Permanent Link | Leave a comment | Add to Memories | Tell a Friend

SECURITY FAIL: Workamajig.com encourages users to email cleartext passwords

Oct. 22nd, 2008 | 03:29 am

This entry was originally published at my site's personal web log. Additional information or comments may be available on the original posting.

Creative agency management tool company Workamajig.com is a sizable operation with an international client base. Their product used to be called “Creative Manager Pro” which I can only assume they changed because it wasn’t actually creative enough. Anyway, it turns out that Workamajig has what is without doubt the absolute worst error message I can possibly think of from a security standpoint.

The error, which is triggered on login regardless of whether or not the username and password you enter are correct (presumably because the issue occurs while trying to authenticate), displays the username and the password the user has entered in cleartext and then (as if that wasn’t bad enough) encourages the user to email this information to their support department!

Yes, we have made the company aware of the problem. No, they have not fixed it yet. Proof in the form of a screen capture from literally 10 minutes ago:

Workamajig.com login error echoes the entered password in cleartext and encourages the user to send this to their support via email.

Workamajig.com login error echoes the entered password in cleartext and encourages the user to send this to their support via email.

No, these are not real credentials, but an uninformed user may very well enter access credentials that are valid. Since this issue is not triggered by invalid credentials, that means valid login information for god knows how many Workamajig user accounts is very likely sitting in the SMTP logs of countless mail servers. Since in many countries these logs are federally mandated to be saved for at least two years, if I were a user of Workamajig I would seriously consider changing my account password ASAP, as well as changing any other account that I used the same password for!

I can’t be sure from this screen shot, but I sincerely hope that user’s passwords are passed around in the application as well as stored on disk as salted cryptographic hashes. Of course, after seeing this, I wouldn’t be shocked if that wasn’t the case. The good news is that the login screen to their application is only accessible with an SSL/TLS connection, which does prevent someone from snooping on the wire. Nevertheless, there are still many attack vectors that SSL/TLS doesn’t protect against if the rest of the application is not secure or, say, if you’re encouraged to bypass those protections by sending emails with sensitive data in order to request technical support.

Anyway, hopefully this gets fixed sooner rather than later. At the very least, don’t encourage users to email cleartext passwords. That is pretty much always a Very Bad Thing.

Update: It took only a couple of days for Workamajig to notice this blog post, which is great because it means I woke up to a forwarded email in my inbox in which a Workamajig representative said:

On the issue of showing the user id and password in an error message, [we] will be changing the way that error message is displayed. […] Just to clarify the user id and password is just on the screen of the user that is logged in, and that message to copy and paste is a standard messages and it is just intended for you to copy and paste the error message; you are not required to send the user id and password.

I haven’t encountered the same issue again (but then again I only tried to login to my account twice in between then and now), so I can’t verify that the error message really has changed but I’d give Workamajig the benefit of the doubt. If you’re using Workamajig and notice a change in the way this login error is handled before I do, leave a comment to let me know it’s really been changed.

Permanent Link | Leave a comment | Add to Memories | Tell a Friend

One Minute Mac Tip: Create an encrypted disk image to store confidential files

Oct. 13th, 2008 | 01:33 am

This entry was originally published at my site's personal web log. Additional information or comments may be available on the original posting.

Nary a day goes by when I don’t use my computer for some extremely personal stuff. I would consider it a Very Bad Thing if some of this information (my bank account details or private SSH keys, for instance) fell out of my control.

Everyone has sensitive files that they keep on their computer and, fortunately for Mac OS X Users, Apple has made it ridiculously easy to create a cryptographically secure containers for such files. You can think of a container like this, which is just a standard Mac OS X disk image (.dmg) file, like a vault that you open, put stuff you want to keep safe inside, and then close again.

Here’s how you go about making and using one.

Create the container, an encrypted disk image

  1. First, open up your copy of Disk Utility.app, which is located in your computer’s /Applications/Utilities folder. (As an aside, this program is a bit like a swiss army knife for handling disk operations in Mac OS X. You should definitely find out what else it can do).
  2. Next, select the File → New → Blank Disk Image… option. This will cause the New Blank Image window to appear.
  3. Fill in the typical details such as the disk image file’s name and where you want to save it to. In addition, you’ll be presented with a number of options such as Volume Name, Volume Size, and Image Format. The defaults are usually adequate except for Volume Name, which you should customize so that when you mount the disk image the disk label is meaningful for you, and the Image Format, which I recommend you switch to “sparse disk image.”

    Sparse disk images can start small and grow automatically as you write more files into them. If what you want to keep secure in this manner are very large files, say gigantic high resolution PhotoShop documents, then you might consider the sparse bundle disk image format instead.

    Also, obviously, set the Encryption to a value other than “None.”

    Here’s an example screenshot from my Mac:

    Screenshot of the New Blank Image window showing meaningful values entered, Encryption field set to 128-bit, and Image Format field set to sparse disk image.

    Screenshot of the New Blank Image window showing meaningful values entered, Encryption field set to 128-bit, and Image Format field set to sparse disk image.

  4. Press the “Create” button and you’ll be presented with a standard password selection dialogue. This is the password you’ll use to mount the disk image and is analogous to the idea of setting the combination on your vault’s lock. It’s critical that the password you choose is a good one. Ideally, your password is a totally random string that may include any printable character. Since that’s hard to remember, you can have the Mac OS X keychain manage your passwords for you.

Encrypt some files by writing them to the disk image

Now that you have an encrypted disk image, a secure container for your sensitive data, you can make use of it just as you might any other disk image on Mac OS X. For instance, say I have a top secret file called “My Killer Business Plan.pages” and I don’t want anyone to get at it. All I need to do is copy the file into my encrypted disk image, as the following screenshot shows:

Copying "My Killer Business Plan.pages" to the encrypted disk image encrypts the file, too.

It should go without saying that you want to delete the original, unencrypted copy of the file you’re copying into the encrypted disk image, but I’ll say that anyway. Don’t leave unprotected copies of your files lying around. Also, be certain to unmount (eject) the disk image when you’re done using it because the only thing the password protects is opening the disk image, not the files contained within it.

External references

Here are some additional places where this technique is discussed. Check out these additional articles about this topic elsewhere for more information and other perspectives:

Permanent Link | Leave a comment {1} | Add to Memories | Tell a Friend

Extract list of all Apple WikiServer wiki titles into CSV format

Sep. 22nd, 2008 | 12:35 am

This entry was originally published at my site's personal web log. Additional information or comments may be available on the original posting.

An interesting request came in today from a coworker. She wanted to create a spreadsheet that contained all of our intranet’s wiki pages (which uses the Apple WikiServer), presumably because Apple doesn’t provide an easy way to “list all pages” in the wiki itself. Along with the page title, she also wanted to extract its internal ID, its URL, and the time the page was created as well as the time it was last modified.

I spent about an hour looking into this this afternoon and it turns out that much of this information is readily available on the filesystem in the Apple WikiServer’s data store. I whipped up the following shell script to extract this information in CSV format, exactly as requested.

I’m posting this script here in case someone else wants similar “export a list of WikiServer pages to a comma-separated values (CSV) file” functionality but isn’t sure how to go about getting it. To use this, just edit the line that reads http://my-server.example.com/groups/wiki/ so that it refers to the wiki base URI of your own server.

Update: The latest version of this script is now available at its Github-hosted repository. You should probably use that instead of the script below.

#!/bin/sh -
#
# Script to extract data from an Apple WikiServer's data store by querying the
# filesystem itself. Creates a 'wikipages.csv' file that's readable by any
# spreadsheeting application, such as Numbers.app or Microsoft Excel.app.
#
# USAGE:   To use this script, change to the WikiServer's pages directory, then
#          just run this script. A file named wikipages.csv will be created in
#          your current directory. For instance:
#
#              cd /Library/Collaboration/Groups/mygroup/wiki  # dir to work in
#              wikipages2csv.sh                               # run the script
#              cp wikipages.csv ~/Desktop                     # save output
#
# WARNING: Since the WikiServer's files are only accessible as root, this script
#          must be run as root to function. Additionally, this is not extremely
#          well tested, so use at your own risk.
#
# Author:  Meitar Moscovitz
# Date:    Mon Sep 22 15:03:54 EST 2008

##### CONFIGURE HERE ########

# The prefix to append to generated links. NO SPACES!
WS_URI_PREFIX=http://my-server.example.com/groups/wiki/

##### END CONFIGURATION #####
# DO NOT EDIT PAST THIS LINE
#############################

WS_CSV_OUTFILE=wikipages.csv
WS_PAGE_IDS_FILE=`mktemp ws-ids.tmp.XXXXXX`

function extractPlistValueByKey () {
    head -n \
      $(expr 1 + `grep -n "<key>$1</key>" page.plist | cut -d ':' -f 1`) page.plist | \
        tail -n 1 | cut -d '>' -f 2 | cut -d '<' -f 1
}

function linkifyWikiServerTitle () {
    echo $1 | sed -e 's/ /_/g' -e 's/&amp;/_/g' -e 's/&gt;/_/g' -e 's/&lt;/_/g' -e 's/\?//g'
}

function formatISO8601date () {
    echo $1 | sed -e 's/T/ /' -e 's/Z$//'
}

function csvQuote () {
    echo $1 | grep -q ',' >/dev/null
    if [ $? -eq 0 ]; then
        echo '"'$1'"'
    else
        echo $1
    fi
}

ls -d [^w]*.page | \
  sed -e 's/^\([a-f0-9][a-f0-9][a-f0-9][a-f0-9][a-f0-9]\)\.page$/\1/' > $WS_PAGE_IDS_FILE

echo "Title,ID,Date Created,Last Modified,URI" > $WS_CSV_OUTFILE
while read id; do
    cd $id.page
    title=$(extractPlistValueByKey title)
    created_date="$(formatISO8601date $(extractPlistValueByKey createdDate))"
    modified_date="$(formatISO8601date $(extractPlistValueByKey modifiedDate))"
    link=$WS_URI_PREFIX"$id"/`linkifyWikiServerTitle "$title"`.html
    cd ..
    echo `csvQuote "$title"`,$id,$created_date,$modified_date,`csvQuote "$link"` >> $WS_CSV_OUTFILE
done < $WS_PAGE_IDS_FILE
rm $WS_PAGE_IDS_FILE

For those new to the Wiki Server, this introduction to the Apple WikiServer for web developers may be of interest.

Permanent Link | Leave a comment | Add to Memories | Tell a Friend

Add a post limit and output format to the WordPress Category Posts plugin v2.0

Sep. 19th, 2008 | 10:24 am

This entry was originally published at my site's personal web log. Additional information or comments may be available on the original posting.

Tonight I wrote a quick (and idiotic) patch to the very simple WordPress Category Post plugin v2.0. This backwards-compatible patch features:

  • parameter-based post limit to define how many posts the plugin function will print
  • parameter-based format option to output the posts in real <li> elements

The wp-category-posts.php patch file is available for download here. To apply the patch, run the following commands at your shell promp:

cd path/to/wordpress/installation/wp-content/plugins/wordpress-category-posts
patch -p0 < path/to/downloaded/wp-category-posts.patch

I’m hoping this will get integrated as the next version of the plugin, perhaps version 2.1.

Permanent Link | Leave a comment | Add to Memories | Tell a Friend

Scrum-style Burn Down Chart in iWork ‘08 Numbers.app

Sep. 6th, 2008 | 06:46 am

This entry was originally published at my site's personal web log. Additional information or comments may be available on the original posting.

Ever since I was introduced to the Scrum methodology of software development, I’ve enjoyed my work so much more than before. Most of that enjoyment is due to a sense of visibility, of knowing what’s going on.

I find working without an accurate awareness of the situation at large very disorienting, and software and web development are notorious for being circumstances that change rapidly. That’s why one of my favorite things about Scrum is the burn down chart. This is nothing more complex than a simple graph that depicts how much work you bit off and how far along trying to chew it you actually are. The benefit, of course, is that it’s pretty obvious pretty quickly if you’ve bit off more than you can chew. ;)

So up ’til now, my team and I have been doing this all on paper. There’s a certain tactile appreciation I have for doing this sort of thing on paper, but of course there are disadvantages, too. For instance, you can’t easily archive the information. You can’t easily share it with remote contractors. You can’t automatically mine this valuable data with software tools. You get the picture.

There are a few cool plugins to some tools like Trac that do all this, but at first blush most of these tools seem to require that you move all of your Scrum’s planning into the digital world. That is, you can’t just do the burn down chart, you have to do all your estimation (MoSCoW desirability, sizing, estimating ideal hours) through some tool. That’s a big step, and I wanted something simpler.

So naturally, I came up with a spreadsheet in Numbers.app as my solution. I mean, how much simpler can you get? Sure, it’s not exactly “well integrated” with other tools, but your non-tech-savvy boss will probably love it, and AppleScript can be used to automate data extraction. Here’s what it looks like:

An example Scrum-style burn down chart in Apple's iWork '08 Numbers spreadsheeting application, complete with an actual chart.

An example Scrum-style burn down chart in Apple's iWork '08 Numbers spreadsheeting application, complete with an actual chart.

(Click the screenshot to get a full-size view.)

As you can see, the Numbers sheet is a simple table and a line chart. I’ve embedded instructions for how to use the chart into the example itself, which I’ll quote here:

This is a sample Scrum-style iteration burn down chart for software development created by Meitar Moscovitz. It can be used to plot a team’s progress throughout a development cycle (aka. “iteration” or “sprint”). This sample chart depicts a 3-week iteration (15 working days) with a 150-point target goal.

The X-axis represents time, and is thus labelled Time in Days, while the Y-axis represents the work to be completed, and is labelled Points.

The green line shows the team’s ideal velocity based upon the total number of points—termed the Remaining Initial Value—scheduled for completion in the graphed iteration.

The blue line shows the team’s actual velocity (or “completed work”), which is entered by the team leader (aka. Scrum Master) after each day in the Done column.

To use this chart: duplicate this sheet, enter your iteration’s total points in the Initial Value row of the Remaining column, and delete the values in the Done column except its initial value of 0. To add more days, copy and paste more rows into the table. Optionally, give the sheet and its contents new titles. ;)

Feel free to download the Example Burn Down Chart.numbers file and use it yourself. If you do use it, please leave a comment and let me know how you’re going. Thanks, and enjoy!

(Mike Cohn of Mountain Goat Software has got a similar spreadsheet for Excel you can download.)

Permanent Link | Leave a comment | Add to Memories | Tell a Friend

YubiKey and OpenID: Two great tastes that taste better together

Sep. 1st, 2008 | 12:08 pm

This entry was originally published at my site's personal web log. Additional information or comments may be available on the original posting.

In some communities, this is sort of old news, however I’ve recently become aware of an exciting and affordable security product called the YubiKey, manufactured by Yubico. The YubiKey is a $35 USD one-time password second-factor authentication token that uses 128-bit AES encryption to provide identity verification. That’s a mouthful, but what it really means is this: using a YubiKey to log in to stuff makes your logins about as secure as a military installation. Here’s how.

When you log in to just about any Web site or Internet-enabled service, say Basecamp for example, you traditionally simply type in a user name and matching password. This is known as one-factor authentication because all you need to do to log in successfully is use a matching pair of user names and their passwords. Since the user name is not hidden, the only piece of the puzzle that’s providing any security is your password.

Now, a password is something you have to remember, so this factor is called "something you know." Of course, if someone else also knows your password, this means that person can log in pretending to be you. Thus enters the need for a second factor for authentication.

The YubiKey is a physical USB fob device with a unique ID. That is, each YubiKey in the world has its own ID, meaning that no two are identical. This implies that if you have a YubiKey with you, no one else can have that same YubiKey anywhere else in the universe. Thus, this gives you a second factor with which to authenticate yourself, specifically it’s "something you have."

When you combine something you know (for instance, a password) with something you have (such as a YubiKey), you have two-factor authentication. Authenticating yourself with both of these factors is obviously more secure than relying solely on one factor because in order to compromise it an attacker needs to compromise both factors; the attacker would need to know what you know (figure out your password) and steal something you have (physically obtain your YubiKey).

If you’re familiar with one-time credit cards such as those that PayPal offers, you can think of the YubiKey like one of these cards, but instead of being used to make online purchases, it’s used for logging into stuff (and, of course, you don’t need more than one physical YubiKey). Of course, for authentication to work with the YubiKey the application or service you are logging into has to be able to understand that you’re using one of these authentication devices.

The good news here is that the entire process of using a YubiKey is a well-documented, open-source, and open-spec scheme so it’s easy for service providers to implement. And, because Yubico is also an OpenID identity provider, you can use your YubiKey to log into any site that supports the OpenID protocol right now, such as (you guessed it) Basecamp! There’s even a WordPress YubiKey plugin so you could theoretically use your YubiKey to secure your authentication to any of your WordPress blogs.

The YubiKey spec is, itself, completely independant of the OpenID spec and vice versa, which is what makes the combination so formidable. What’s so cool about this process is that the site you’re authenticating to, such as Basecamp or your WordPress blog, doesn’t have to know anything about how you’re authenticating because the OpenID provider (Yubico in this example) simply returns the answer—a perfect example of a well-constructed API at work. Either you have successfully authenticated to your OpenID provider or you haven’t, and the site can respond accordingly.

And if that’s not cool enough, want to know the coolest thing about the YubiKey? It’s environmentally friendly! The YubiKey web site states that the robust, ultra-thin and battery-free design increases lifetime and reduces environmental impact.

I’m more than seriously considering getting one of these myself, and even beyond that, getting one for all of my fellow site editors on some of the community web sites I help maintain. This is especially important for sites dealing in confidential or otherwise sensitive information, such as those which hold financial records or have other privacy concerns. Securing the authentication of privileged users such as the site administrators seems a natural step.

Even better yet, because the only cost to implementing this system is developer resources and the cost of the physical YubiKey device, I’m also seriously considering baking this right into any new sites I develop. At $35, a YubiKey is actually cheaper than an SSL certificate, and even though they don’t protect against all the same attack vectors, I think a device like the YubiKey is clearly a vastly superior solution in the majority of use cases.

I never really had a compelling reason to begin to propagate an OpenID identity before but now, at last, I do.

Permanent Link | Leave a comment | Add to Memories | Tell a Friend

How to use mod_rewrite rules to easily enable web site “maintenance” modes

Aug. 10th, 2008 | 04:24 am

This entry was originally published at my site's personal web log. Additional information or comments may be available on the original posting.

When you’re administering a web site, sometimes you need to make changes that for whatever reasons require that the web site be temporarily unavailable for normal visitors. One obvious example is database maintenance. Unless you have the resources to do full-blown load balancing across a server cluster, you probably have to accept that your site is going to be down for a short period of time.

When this happens, it’s generally a good idea to show your visitors a web page that briefly explains the situation. This is typically a page that politely explains that the “site is temporarily down for maintenance” and so on. I’ve taken to calling such a page a “curtain” because it’s a little like putting a curtain up in front of construction work.

You put the curtain up, do whatever you need to do to fix or upgrade or maintain your web site in the background, then take the curtain down. For delicate servers, this has the added benefit of dramatically reducing server load while you do your maintenance tasks. You can even allow access to specific visitors, such as QA testers or remote admins while this curtain is up, while still redirecting normal users to the “down for maintenance” page.

Obviously, the first thing you need is the page that explains your site is down for maintenance reasons. This can be anything you like, but it’s simplest to make it a static HTML page and place any and all resources you need for this page (like images) into the same folder. I often use a directory named down-for-maintenance and I place an index.html file in that folder to use as my “curtain” page. Images go straight into the down-for-maintenance directory, too.

Once you have that, you can then use the following Apache configurations to create an “on/off switch” for putting your curtain up and taking it down.

# To take the web site into a maintenance mode, create a file named
# maintenance-mode-on at the document (website) root, such as this:
#
#     touch maintenance-mode-on
#
# To bring the web site back, remove or rename the file, such as this:
#
#    mv maintenance-mode-on maintenance-mode-off
#
# To enable the site for your IP address only but nobody else's
# uncomment the second RewriteCond directive.
<IfModule mod_rewrite.c>
    RewriteEngine On
    RewriteCond %{DOCUMENT_ROOT}/maintenance-mode-on -f
    #RewriteCond %{REMOTE_ADDR} !^your.IP.address.here$
    RewriteRule !^down-for-maintenance/.*$ /down-for-maintenance/ [R,L]
</IfModule>

What this does, step by step, is:

  1. Determines whether or not you have mod_rewrite enabled. If you don’t, then nothing happens.
  2. Enables the mod_rewrite rewriting engine.
  3. Checks for the existence of a file called maintenance-mode-on at your site’s root. If such a file does not exist, nothing happens.
  4. With the second RewriteCond directive uncommented, it also checks the visitor’s IP address and if it does match the one listed nothing special happens. If it does not match the one listed, the next line, which is the redirect, is executed.
  5. Checks the requested URI and if it does not begin with down-for-maintenance, a temporary redirect (HTTP status code 302) is issued that points browsers to the down-for-maintenance directory you created earlier. Obviously, if you named this directory something else, you should change this RewriteRule.

This isn’t perfect. For example, if a visitor is filling out a multi-page form then they might get interrupted half way through when you enable the curtain since the curtain takes effect starting at the next HTTP request after you enable it. That said, the only way to do truly graceful maintenance with zero downtime is load balancing, and that is beyond the capability of most simple sites, but this curtain is extremely simple and extremely effective.

Permanent Link | Leave a comment | Add to Memories | Tell a Friend

How to use HTTP Basic Authentication with git

Aug. 8th, 2008 | 12:56 am

This entry was originally published at my site's personal web log. Additional information or comments may be available on the original posting.

Coming right on the heels of my need to set up a git repository on shared hosts, I next wanted to see if I could use HTTP authentication for such a repository. Of course, HTTP authentication is an extremely insecure protocol, but it typically is enough to dissuade the casual user (such as Googlebot) from peeking at things you don’t want available on the public Internet, so it has its uses.

Note that with the set up described in the above-linked previous post, you can only pull over HTTP. This is usually what you want. If you want to be able to push over HTTP as well, git must be compiled with the USE_CURL_MULTI flag.

This is, as it turns out, because git seems to use curl for its HTTP operations, which also obviously means you must have curl installed on your workstation if you don’t already and it also implies that it’s curl, not git which you need to configure. In other words, accessing a git repository that is behind HTTP authentication is exactly the same as accessing one without it, and so is publishing a git repository to an HTTP server. The rest of this short tutorial assumes you have published your repository at http://example.com/git/public-repo.git and are using the Apache web server.

Step 1: Create an HTTP Basic Authentication username and password file

First, you’ll need to create a file that lists the usernames who are permitted to access your repository over HTTP Basic authentication. This is easily accomplished with the htpasswd utility (or your host’s custom web UI, if one is provided). Let’s create a file called .git-htpasswd to store these usernames and passwords.

From your shell, run the following command:

htpasswd -c /path/to/DOCUMENT_ROOT/.git-htpasswd username

where /path/to/DOCUMENT_ROOT is the full path to the root directory of your web site and username is the username you want to add. If you want to add subsequent users to this file, run the same command again without the -c, like this:

htpasswd /path/to/DOCUMENT_ROOT/.git-htpasswd another_username

You’ll then be prompted to enter a password, and then prompted again to verify that you’ve typed it correctly.

Step 2: Configure HTTP Basic Authentication on Apache

Next, configure standard HTTP Basic Authentication on Apache. In most shared hosting environments, you’ll be allowed to configure per-directory passwords using .htaccess files. Some hosts provide web UI interfaces for creating “protected folders,” which is basically the same thing. Make certain that the kind of protection you select is “Basic,” because curl will require that.

To do that, create a new file named .htaccess in your DOCUMENT_ROOT/git directory if one does not already exist with the following contents:

AuthType Basic
AuthName "Git"
AuthUserFile /path/to/DOCUMENT_ROOT/.git-htpasswd
Require valid-user

This tells Apache to look for usernames and passwords in the file named .git-htpasswd we created in step 1.

If everything is set up correctly, you should now be able to access http://example.com/git/public-repo.git in your Web browser and you should be presented with a login dialogue box.

Step 3: Configure curl on your (client) workstation computer

Next, configure your local curl client. git-pull will call curl with its --netrc-optional switch for HTTP operations. This means curl will look for a file named .netrc in your home directory and will read authentication configurations from that file. The format of this file is incredibly simple:

machine yourserver.example.com
username your_username
password your_password

To check if this is working correctly, run curl yourself to access the current HEAD of the public repository and see if you get the expected result:

curl --netrc --location -v http://example.com/git/public-repo.git/HEAD | grep 'ref: refs/heads'

If you see a line of output then you know this is working, otherwise you should double check your work.

Step 4: There is no step four

You’re done. With this configuration, you can git-pull as you normally would, and git will automatically use your .netrc file to enable curl’s HTTP authentication schemes.

Permanent Link | Leave a comment | Add to Memories | Tell a Friend

Productivity: It’s not what you do, it’s how you do it, and twentysomethings do it bette

Aug. 4th, 2008 | 10:20 am

This entry was originally published at my site's personal web log. Additional information or comments may be available on the original posting.

I don’t believe I have ever before posted an entry that, for all intents and purposes, is just a link to another blog post. However, this blog post is simply so brilliant and yet so short and easily-digestable, that I have nothing more to say. Thus: Twentysomething: 7 Reasons Why My Generation Is More Productive Than Yours.

By those definitions, I’ve been a productive twentysomething-year-old since I was a pre-teen, which just goes to show you that age has nothing to do with it. Damn straight.

Permanent Link | Leave a comment | Add to Memories | Tell a Friend