Archive for 'geek'

Facebook’s long memory: Hotel California still in place…

As I remarked in a previous tweet, people these days seem surprised when you say you’re not on The Book. So, as I came back after seeing a friend and yet another person asked me to add them as a friend on Facebook, I thought I might reconsider my previous position.

So I signed up… typed in my name, email address etc… and what did I see?

I saw a list of “suggested friends”, which was essentially everyone I knew before I deleted my account, as well as a bunch of people I knew but hadn’t connected to.. the social graph in action I guess.

I would be interested to find out where this information was obtained if my account was truly deleted, from my former connections? But surely, I could be any Marcus Povey? True, emails are “unique”, but I’m fairly sure that at least half of the suggested connections never knew my email address (social graph again)… besides, that’s missing the point.

To be clear, at the very least Facebook is remembering my name/age or email address as unique identifiers, and who I am connected to. So while the delete account option may remove your pictures etc, it clearly doesn’t remove the connection data – which I have previously stated is actually quite a powerful and private bit of information.

Am I alone in being a little freaked out by this?

Clearly, even though they provide a way of deleting your account, much of the important connective information is retained. Your account still isn’t being deleted.

In other words; “You can check out any time you like, but you can never leave”.

Suffice it to say, I reconsidered my reconsideration. I deleted my account again (for what good it will do), my first instinct was correct.

I guess people are just going to have to email me.

Old Skool.

What you need to know about Drupal views

Every content management system needs its query builder—an application which creates customizable lists of content elements and present them in a similarly customisable way. Customization will be typically through an admin interface on the website, and the query builder can be as basic as a text box for SQL or as complex as a many-layered GUI across multiple webpages. Drupal, for its part, has Views. D5 has Views 1, D6 has Views 2, and it looks like the forthcoming Drupal 7 will have Views 3.

However, as the criteria for list-building get more and more complex, there will come a point where custom code will produce the exited result far more quickly and efficiently than Views. The problem for the developer is: while simple lists are obviously candidates for Views; and riotously tangled layouts are obviously candidates for your own modules and SQL; how do you cope with the middle ground? How can you tell from the outset that a particular problem will land you in a Views-only cul-de-sac?

Well, I contend that the individual developer needn’t worry, so long as he’s clued up about developing with, not outside, Views. I reckon that the middle ground can almost always be bridged by Views augmented with custom code; unless you’re completely convinced from the start that, say, the logic of what you want is not representable in a query builder, you can start with Views and tweak with customisations later.

But to be sure you can extricate yourself from any small to medium tiger traps that “Views+your spec” might drop you in, it’s wise to know in advance the full range of tools at your disposal. Here are five of what I consider the most important tricks for building a complex Drupal view.

  1. Views themeing  Views has a very modular set of Drupal theme files. The markup and presentation of individual fields, rows of fields, and whole views of many rows can all be modified on a per-view, per-view-format or even cross-site basis. In a particular view’s admin GUI, you can see an entry marked “Theme: Information.” If you click on this, it will tell you what template files the view will try to use, and what files it’s currently using (in bold.) You can copy these files across from the module directory to your theme and rescan to use them; you can even rename them to be specific to the current view or formatting options, and when you rescan the directories, Views should spot the new files.
  2. Addon modules  There are a number of extension modules for views which will very quickly improve view presentation or data flexibility. At the one end is Semantic Views, which allows you to present certain fields in your views with more semantic markup: titles can be h2 elements; contact details can be in address elements, etc. At the other end of the workflow, close to the database, is the Views Or plugin, which lets you swap the normal views filter AND logic (“all items must be published AND have type=blogpost”) for a more inclusive OR logic (“all items must have type=blogpost OR be less than three weeks old”). If you’re not sure whether there’s an addon module for you, ask on the #drupaluk IRC channel.
  3. Views as a backend  Several third-party modules use views as an adjunct: that means that while the module itself is doing something apparently clever with your content, it’s secretly using a view to manage most of the hard work. If you want to maintain arbitrary admin-sortable lists of content, Nodequeue provides a nice interface for doing so. But behind each nodequeue sits… a Drupal view, and a plugin which ties the nodequeue database table to your nodes to produce the required results. Tagadelic, a module which produces tag clouds for e.g. your recent blogposts, has over the years moved from a standalone module (which still exists), to a Views style plugin, so you can build the initial tags view yourself and activate Tagadelic styling and popular-tags filtering once you’re done.
  4. Views hooks  The workflow for views is like the workflow of Drupal itself in miniature: as such, it has its own set of views-specific hooks, including hook_views_pre_render and hook_views_pre_build. All the Views hooks are documented on drupalcontrib.org. So, learn the basic page-view flow, from a blogpost by Mr Views himself, Earl Miles. Pick it apart. See what each bit does in the code. You should eventually be able to find the views hook you want in the code, and be able to modify the view object, its compiled SQL, the results returned, and even the eventual output, all in your own modules.
  5. Writing your own plugins  A Views plugin is less complicated than you might fear. There’s not a great deal of easy-to-find, easy-to-read documentation out there about Views plugins, but try not to let that put you off. A plugin consists basically of a module, a hook function (or two) and a PHP object: the rest is just detail and theming! While that sounds a bit glib, it has some merit: look at the plugins for such modules above as Semantic Views and Nodequeue, and see how they all relate back to an object in a .inc file and a template in a .tpl.php file. You can extend an existing plugin using standard PHP class syntax, and develop it piece by piece by overriding methods one at a time. Views plugins are incredibly powerful, more so than using configurable third-party modules or just interrupting the current view using a Views hook. They get your code right into the heart of a given view’s workflow and let you do (almost) whatever you want. Remember to clear caches if you get stuck: you might even need to resort to a “TRUNCATE cache” at your MySQL command line if your changes don’t seem to be having an effect.

If you’ve started building your listing page with Views, but the spec has ended up getting more complicated, try each of the five solutions above in turn. When the problem at hand suddenly gets a whole lot more complicated, escalate your solution’s complexity by moving another step down the list!

There’s obviously a lot more to developing with Views than a single blogpost could ever really summarize without turning into an extended essay. But there’s a lot more documentation out there—although of a pretty sprawling and hard-to-navigate sort—and the tips above should hopefully give you pointers both for where to start your extending of Views, and also what to google for when you get stuck. Have fun and good luck!

OGN18 in under two weeks’ time

The next Oxford Geek Night is on Wednesday 21 July, in less than two weeks’ time. I for one am really looking forward to it.

We managed out of sheer luck and cheek to bagsy a fantastic speaker for OGN18, the ever-Interesting Russell Davies. Russell was the organizer of the 2007 and 2008 Interesting conferences, and is involved in lots of fantastic projects, including Speechification and Newspaper Club. He’s also a writer for Wired, a speaker at many conferences including Lift 2010, and what one might frivolously call a futorologist or pundit. He’s going to talk about his experiences turning internets into print, and what he’s learned from doing it as part of projects like the Newspaper Club.

Along with our keynote speaker we’ve got half a dozen of the absolute best of local microslot volunteers. There’s talks on topics as far ranging as “designing backwards”, linked data, graphing 19th-century social networks, genomics, CSS and Rotacoo’s Spotify #fridaymix tape. A few new faces and a few established (and deservedly so) local faces. As always we’ll be putting video up on the site afterwards, so there’ll be a permanent record of our high-quality speakers.

Finally, we hope to have space for the Pitches – our sixty-second open mic slots that anyone can volunteer for, even on the night – and a book raffle. All told it should be a great excuse to saunter over to the Jericho Tavern in the July sun / sudden downpour (delete as applicable.) Hope to see all the other Oxford geeks there.

Blowing up markets

The Red VicBanning sublets

Last week, the State of New York passed a bill that bans short-term rentals: specifically, no homeowner or renter may sublet their home for less than a month. The target is sites like AirBNB, an up and coming website that allows travelers to eschew pricey hotels – and their accompanying hotel room occupancy tax – in favor of private homes.

If the governor chooses to pass the legislation (as opposed to veto it), AirBNB will effectively be outlawed, and with it, a grassroots marketplace economy for short-term accommodation. New York State will have cemented hotels and bed & breakfasts as gatekeepers to the city for travelers who can’t stay with friends or relatives.

To me, this is an interesting reaction: it shows, once again, that established gatekeepers are terrified of the Internet. We’re used to that by now in the context of media content – we already know that newspapers, publishers, record companies and movie distributors aren’t as important as they were – but this is a scarcity-driven marketplace. It used to be that finding a safe, clean room in a strange city was a hard problem, so we turned to hotels as a trusted source. Running a hotel is in itself an expensive, tough business, and as a result there were a limited number in any given city, and the price went up according to demand. Although the hotel business is a ruthless game, it’s always been hotels competing with other hotels.

Now, though, we can visit websites like AirBNB and Couchsurfing, where private citizens can offer their homes to travelers, and the site will let us know who we can trust based on other peoples’ experiences. The marketplace has been blown wide open, and it turns out that a lot of us would rather go for a cheaper, friendlier option. I wouldn’t put money on New York blotting out short sublets for long.

Power to the people

We’re going to be seeing a lot more of this, in all kinds of market sectors. We’re already seeing ridesharing sites become popular, for example, blowing up the market previously owned by taxicabs and making it available to anyone who happens to be driving somewhere. Effectively this formalizes hitchhiking, making it both safer and more efficient.

It all comes down to one simple rule: People want to be free.

The Internet is opinionated: as a medium, it inherently works to empower people and eliminate hierarchies in society. It shouldn’t be a surprise that the most popular Internet companies hail from California; their philosophies are direct descendents of the civil rights activism that took place there in the sixties and seventies. In many cases, it’s even the same people. (Or – and here I put up my hand as the son of Berkeley “radicals” – their children.)

Gatekeepers – companies, structures or processes that act as exclusive barriers or filters – are not long for this world. Where gatekeepers exist, they do so because the alternative was inconvenient at the time when the gatekeeper became established – not because they’re inherently better than an empowered population. Those organizations, companies, and even governments, need to look at themselves very carefully and figure out what needs to be changed, before those things are changed for them.

Most Commented Posts

Comments

The product management cycle

Monday: “The plan is A! We’ll market it at A!”

Tuesday: “Actually, I was thinking B. A is stupid. Who would want to do that?”

Wednesday: “Goddamnit, we need to be working towards C. Why does no-one see that?”

Thursday: “Maybe A was right …”

Friday: “This team sucks.”

Hint: pick a direction and run. And make sure – just as your tech team does – that your management team has measurable metrics for success.

Most Commented Posts

Comments

Barcamp Oxford 2010

This weekend was Barcamp Oxford, and suffice it to say it was utterly fantastic. While a delicious ham cooks, I just thought I’d jot down some notes.

The day for me started early on Saturday with a walk into town (Oxford’s buses being resoundingly useless), still it was a lovely sunny day and I had some good tunes on my mp3 player so I didn’t mind working on my tan for a while.

Anywho, got to the Oxford Club in time for registration and for the slots to be put up… a dizzying array of very interesting possible discussions were soon put up.

Obviously I couldn’t go to all the sessions, but those I did go to were fantastically useful.

Highlights were a thought provoking, passionate and mature discussion of women in technology, and education in general. Additionally, met a bunch of very cool people who I hope to keep in touch with!

The beeper has just gone on my oven so I must tend to my food. Suffice it to say, I found the event both highly enjoyable, stimulating and very very useful.

Props to all the people who worked so hard to make this happen, you are all awesome!

Same time next year?

Image by Sylwia Presley

Write real-time web applications with XMPP, PHP, and JavaScript

I’ve written a tutorial for writing XMPP-based web applications over at IBM DeveloperWorks:

Real-time web applications are networked applications, with web-based user interfaces, that display Internet information as soon as it’s published. Examples include social news aggregators and monitoring tools that continually update themselves with data from an external source. In this tutorial, you will create Pingstream, a small notification tool that uses PHP and JavaScript to communicate over the Extensible Messaging and Presence Protocol (XMPP), a set of XML technologies designed to support presence and real-time-communications functionality.

You can read the whole tutorial here. IBM have made it a featured article, commenting, “bet you have it up and running before lunch.” I hope you find it useful. (And don’t forget to check out my introduction to Activity Streams, also written for IBM.)

Photo: IBM by antonfortunato, released under a Creative Commons license.

Related entries

Comments

An introduction to Activity Streams

I’ve written an introduction to the Activity Streams standard for IBM DeveloperWorks:

Enter Activity Streams, an evolving standard that extends Atom for expressing social objects. Although it is a young standard, Activity Streams is fast becoming the de facto method for syndicating activity between web applications. For example, MySpace, Facebook, and TypePad all now produce Activity Streams XML feeds. But this technology isn’t just for the consumer web environment. As corporate intranets and internal software become more social, solid business reasons support implementing Activity Streams as a feature. This article describes Activity Streams in detail, considers its potential uses in enterprise environments, and provides some examples for interpreting Activity Streams feeds using PHP.

The full article is over here.

Related entries

Comments

How to set up ProFTP, MySQL and Virtual Users

ProFTP is a configurable FTP server available on most *nix platforms.

I recently had the need to get this working and authenticating off a PHP maintained MySQL backend, and this post is primarily to aid my own memory should I ever have to do it again.

Installing ProFTP

In order to use MySQL as a back end you need to install some packages. If you’re using a Debian based distro like Ubuntu, this is easy:

apt-get install mysql-server proftpd proftpd-mod-mysql

The database schema

Next, you need to install the database schema to store your users and passwords.

CREATE TABLE IF NOT EXISTS users (
userid varchar(30) NOT NULL default '',
passwd varchar(128) NOT NULL default '',
uid int(11) default NULL,
gid int(11) default NULL,
homedir varchar(255) default NULL,
shell varchar(255) default NULL,
UNIQUE KEY uid (uid),
UNIQUE KEY userid (userid)
) TYPE=MyISAM;

CREATE TABLE IF NOT EXISTS groups (
groupname varchar(30) NOT NULL default '',
gid int(11) NOT NULL default '0',
members varchar(255) default NULL
) TYPE=MyISAM;

One important thing to note here – that caused me a fair amount of hair pulling when I tried to use encrypted passwords – is that the password field shown in many howtos on the internet is much too short. This causes the hashed password to be quietly truncated by MySQL when saved.

This results in a somewhat misleading “No such user found” error to appear in the logs when using encrypted passwords.

To end all argument I’ve allowed passwords up to 128 chars, but this field could probably be a good deal shorter.

The user table looks much like /etc/passwd and is largely self explanatory. The uid & gid fields correspond to a system user in most cases, but since we’re using virtual users they can largely be ignored. Homedir points to a location which will serve as the user’s default directory. Shell is largely unused and can be set to /bin/false or similar.

Configuring ProFTP

Next, you need to make some changes to the ProFTP configuration files stored in /etc/proftpd. While doing this it is handy to run proftp in debug mode from the console:

proftpd -nd6

proftpd.conf

  1. Make sure the AuthOrder line looks like:

    AuthOrder mod_sql.c

  2. Ensure that the following line is uncommented:

    Include /etc/proftpd/sql.conf

  3. For belts and braces I’ve included the following at the end, although I’m not entirely sure it’s strictly required:

    <IfModule mod_auth_pam.c>
    AuthPAM off
    </IfModule>

  4. Our users don’t need a valid shell, so:

    RequireValidShell off

modules.conf

  1. Make sure the following lines are uncommented:

    LoadModule mod_sql.c
    LoadModule mod_sql_mysql.c

sql.conf

  1. Set your SQL backend and ensure that authentication is turned on:

    SQLBackend mysql
    SQLEngine on
    SQLAuthenticate on

  2. Tell proftp how passwords are stored. You have a number of options here, but since I was using mysql’s PASSWORD function, I’ll defer to the backend.

    SQLAuthTypes backend

  3. Tell proftp how to connect to your database by providing the required connection details, ensure that the user has full access to these tables.

    SQLConnectInfo database@host user password

  4. Define your table structure in the format tablename fields….

    SQLUserInfo users userid passwd uid gid homedir shell
    SQLGroupInfo groups groupname gid members

Adding users

I manage users from within a PHP web application that I’m developing, but in a nutshell adding FTP users from this point is a simple insert statement looking something like:

mysql_query("REPLACE INTO users
(userid, passwd, uid, gid, homedir, shell)
VALUES
('$userid', PASSWORD('$password'), $uid, $gid, '$homedir', '$shell')");

Have fun!

Feeds objects within feeds objects

We’ve been doing a lot of work with the Drupal Feeds module recently. The frontend is nice enough, although the sub-navigation was rendered almost illegible by our theme’s CSS. The online tutorials need work, and the admin navigation needs to be made a bit more robust to layout changes; but then it will be the de facto way for people to consume feeds on their Drupal sites.

The most recent work we’ve been doing involved custom integration with RSS feeds arriving effectively as PHP string variables containing all the XML. This is different from either a file on disk or a remote URL: in fact, we had a Python program creating the RSS file from us via a shell (which in turn, horribly, was hitting a remote Oracle database using cx_Oracle). Feeds was definitely up to the job in terms of power. In fact, it was quite a toolkit of useful functionality, which is Drupal code for “incredibly powerful but almost incomprehensible.

It’s not that the developer documentation for Feeds isn’t decent: it’s pretty good. But it’s limited in scope: it tells you roughly how to expose your own Feeds-like objects to the admin interface, but not really how all those objects interact. Most importantly, we wanted to know what happened on a cron run: this is the bedrock of how Feeds works on your site, after all.

I poked around a bit and this is what I discovered:

 

Workflow of a Feeds cron run

Here’s a summary of the above diagram to give you some idea of what’s going on.

 

  1. Drupal’s cron creates a FeedsScheduler object and passes it a “job”, which is all the configuration for a feed call, including any configuration that was attached originally to the particular node which defines the Feed. The scheduler creates a FeedsImporter and passes it the job; the importer then creates a FeedsSource and embeds itself in it as a parent. In each case, the method ::work() is called to create the child/helper object.
  2. The Source object is what now runs the three phases of feed consumption, via its parent Importer. The Source asks the Importer for the relevant Fetcher, Parser and Processor objects: for example, the HTTP Fetcher, the RSS Parser and the Node Processor objects are strung together to turn an RSS feed at a HTTP URL into a set of nodes, one per entry. Each of these have a relevant, verb-like named method: so ::fetch() for the Fetcher etc. The common currency is a FeedsBatch object, which gets passed around and needs to have methods that make it feel like a batch of feed objects.
  3. After the three phases have run, the Source calls hook_feeds_after_import() to do any tidying, then quits to the Importer, which quits to the Scheduler, which then runs its ::finished() method on the job, and the cron run for this particular feed is done.

 

When you build a new plugin, you need to implement hook_feeds_plugins() in a module and reference a class file: this class will be selectable in the admin interface for one of the three consumption phases, depending on what class it’s ultimately based on. You should therefore extend existing classes rather than start from scratch: there are abstract PHP classes in the feeds module directories, which give you skeleton “interfaces” which you can then flesh out with relevant functions. But what’s better is to extend e.g. the HTTP fetcher to fetch from a command on disk (which is what we did) or, say, extend the CSV parser to interrogate JSON.

Class hierarchies mean you don’t have to spend a lot of time reinventing the wheel or hacking existing modules until they become unupgradeable; instead you can take existing classes and tweak them through inheritance, experimenting as you develop.