Blosxom -- one of the oldest minimalistic static blog engines
Blosxom is one of the oldest minimalistic static blog engines in the history of the world
wide web.
Blosxom was written by Rael Dornfest, a programmer at O'Reilly and Associates. This is example of
"mini_blog" engine and as such it proved to be extremely useful for variety of purposes including creating
various journal for private purposes.
Blosxom's power is in its simplicity. The key idea is similar to the automatic generators of content
of a directory, but with several interesting twists. Or to the way mail client display emails.
As the while script is around 500 lines of Perl code (with comments) this is example of "small is
beautiful" type of software design. So it probably be a mistake to "enhance" its capabilities. It is
the most valuable in its current "primitive" form. Again that idea of "small is beautiful"
means that it is this blog engine simplicity that represents its advantage and due to it it can provide
the ability to perform non-trivial tasks.
There are multiple more complex and more capable blog engines that are more suitable if you need
more functionality.
Another strong point of blosxom is that it uses plain vanilla HTML. As powerful
HTML editors are now widespread and cheap/free (see for example
Microsoft FrontPage and Microsoft Expression Web) such
an editor can carry large part of complexity of blog engine leaving to blog engine only essential function
to generate common elements (timestamp, title, etc) and display blog entries. So in a way
combination of Frontpage and blosxom multiply power of both.
Blosxom sports a plugin architecture, allowing the core of Blosxom to remain small while providing room
for extension and integration into different environments and uses.
Browse the Blosxom Plugin Registry for the
full list of availble plugins. There is a large number of plugins developed for Blosxom. There are display
plugins, reformatting blog posts on the fly and providing additional template elements. Image plugins
provide everything from convenient image references to resizing and creating an image gallery. Input
plugins provide writebacks (comments and trackbacks), karma tracking, and email-to-blog gateways.
Blosxom consists of a single short (less then 500 lines of code) CGI program written in Perl.
All I had to do is copy the file, blosxom.cgi, to your apache cgi-bin directory.
To configure Blosxom for my system, for example, I changed the following variables:
- $blog_title: the title of the Weblog as it appears to users and in the RSS syndication
feed.
- $blog_description: blog description that appears on the front page and in the RSS feed.
- $datadir: each entry in a Blosxom Weblog actually is a text file on disk somewhere;
$datadir defines where those files should reside.
With those three elements defined, the blog is instantly up and running. There more more variable
available at the beginning of the script and as you learn the ropes you can customize blosxom
more:
# --- Configurable variables -----
# What's this blog's title?
$blog_title = "My Weblog";
# What's this blog's description (for outgoing RSS feed)?
$blog_description = "Yet another Blosxom weblog.";
# What's this blog's primary language (for outgoing RSS feed)?
$blog_language = "en";
# Where are this blog's entries kept?
$datadir = "/Library/WebServer/Documents/blosxom";
# What's my preferred base URL for this blog (leave blank for automatic)?
$url = "";
# Should I stick only to the datadir for items or travel down the
# directory hierarchy looking for items? If so, to what depth?
# 0 = infinite depth (aka grab everything), 1 = datadir only, n = n levels down
$depth = 0;
# How many entries should I show on the home page?
$num_entries = 40;
# What file extension signifies a blosxom entry?
$file_extension = "txt";
# What is the default flavour?
$default_flavour = "html";
# Should I show entries from the future (i.e. dated after now)?
$show_future_entries = 0;
# --- Plugins (Optional) -----
# Where are my plugins kept?
$plugin_dir = "";
# Where should my modules keep their state information?
$plugin_state_dir = "$plugin_dir/state";
# --- Static Rendering -----
# Where are this blog's static files to be created?
$static_dir = "/Library/WebServer/Documents/blog";
# What's my administrative password (you must set this for static rendering)?
$static_password = "";
# What flavours should I generate statically?
@static_flavours = qw/html rss/;
# Should I statically generate individual entries?
# 0 = no, 1 = yes
$static_entries = 0;
# --------------------------------
To test Blosxom you need to create a simple text file in $datadir, for example
introduction.txt:
This is a test entry.
<p>This is a test of Blosxom</p>
If you installed Blosxom in the the cgi-bin directory of your Linux server (or Cygwin),
you should be able to view this entry as a part of Blosxom blog at the URL http://localhost/cgi-bin/blosxom.cgi.
Each entry appears in the blog, preceded by a date, followed by a timestamp and a permanent link
and with the first line boldfaced, as if it were a headline or title.
In other words, you can add entries to a Blosxom Weblog simply by creating new text files in
the data directory.
Any file ending with the value of $file_extension, which is txt by default, is
considered to be a Weblog entry. Any other files, such as backup files, which end with ~, are never
are considered entries. If you save the entry while writing in the directory, you might be surprised
to discover that your Weblog is being updated as you write it, live and for the whole world to see.
If you want to work in the background, simply leave the .txt extension off the filename until you're
ready to publish it or use other directory and copy the entry into your blog directory.
Blosxom assigns a date and time to an entry based on the timestamp of the file that was created
If you created the file on February 11, at 4PM, the Weblog entry was timestamped with that time.
This means you can change the timestamp of a file retroactively with the touch command, for example:
touch -t 200401011500 testing.txt
The above command modifies the date of the file testing.txt to 3PM on January 1, 2004. (If
testing.txt does not exist already, it is created.) moving the file back in time. Although
this might go against the etiquette of the Weblog universe, this provides additional flexibility as
allow you to rearrange entries at will by manipulation with their timestamps. Actually you can
provide "creation date" within the blog entry and make the timestamp to serve as "publication date",
which of course can be different.
More interestingly, you can modify the time of a Weblog entry to be in the future, using the same
touch command on the command line. Such entry can contain some instructions and it will be always first
if the $show_future_entries configuration variable is set to 1
But in the default configuration, entries are displayed only when their date matches the current
date. This means you can calendar your entries to be displayed on a particular time and date.
Adapted from blosxom
plugins.txt
Blosxom sports a plugin architecture, allowing the core of Blosxom to remain small, sleek, and simpler-than-pie
while providing room for extension and integration into different environments and uses. Please browse
the Blosxom Plugin Registry for all your plugin
needs.Take a gander at the
users' plugin documentation
for information on activating Blosxom plugin support, installing plugins, ordering plugins, removing
plugins, and so forth.
Ideally, a plugin is a single file to be dropped in to the plugins directory and, optionally,
configured.
Should you need to add other bits and require other modules, attempt to bundle all this up as a plugin
file and associated subdirectory to be dropped as a group into the plugins folder. Don't require
a plethora of prerequisites forcing your users to become experts and compiling and installing Perl modules.
The best way to understand Blosxom's plugin architecture is to step through each bit in turn.
Available to each plugin are key Blosxom variables for their reference (read: customarily read-only).
The vast majority appear in Blosxom's # --- Configurable variables -----
section and documented
in the configuration documentation.
Here's the complete list:
- $blog_title
- $blog_description
- $blog_language
- $datadir
- $url
- $depth
- $num_entries
- $file_extension
- $default_flavour
- $plugin_dir
- @plugins
- $static_dir
- $static_password
- @static_flavours
- $static_entries
- $path_info
- $flavour
- $static_or_dynamic
- $output
- $version
All of these variables live in the main blosxom
namespace, so reference them as
$blosxom::datadir
, @blosxom::plugins
, and the like.
Also passed to each subroutine as appropriate are context-specific variables for reference and alteration
(e.g. a reference to a story's body is passed to the story()
subroutine).
Every plugin should start off by identifying itself; a few friendly lines of commentary will do nicely...
# Blosxom Plugin: sample
# Author(s): Rael Dornfest
# Version: 0+1i
# Blosxom Home/Docs/Licensing: http://www.raelity.org/apps/blosxom/
Your plugin should live in its own namespace so that all its variables and subroutines won't conflict
with those of other plugins. In Perl, this is accomplished using a package
, like so:
package sample;
For this example, I've named the package sample
.
Each plugin lives not only in its own package, but in its own file. Files are kept in the plugins
directory and MUST be named precisely the same name as their package name. So, for this example, the
plugin would live in plugins/sample.
If you'd like to control the order in which plugins load, prepend the filenames with numbers like:
00loadfirst, 50loadsometime, 99loadlast, and so forth. Plugins are loaded in alphanumeric
order, so this will force the ordering nicely for you. Blosxom will strip the numeric bits from the
plugin name for you, so refer to the plugin by its package name (e.g. loadfirst
).
As in Blosxom itself, user-configurable variables should be kept together. I suggest that everything
from the beginning of the file down through the configurable variables section be considered for the
user's information and alteration. Something like:
# --- Configurable variables -----
$email_address = 'me@example';
# --------------------------------
Configuration variables should be anything you need the user to define in order to use the plugin
properly.
Now's a good time to define variables useful to the plugin. I'll define a couple here to be used
in just a moment:
$title_and_path = '';
$story_number = 1;
All of these variables you define (unless my'd) are available to your flavour templates, prefixed
with the package name; so, $title_and_path
would be referenced in your template in classic
Perl style as $sample::title_and_path
.
Indeed, one possible use of the plugin architecture is simply to define a set of custom variables
you'll be using on a regular basis but which do not come in the Blosxom box.
This is also a good place to require any Perl modules you might need for your plugin. Perhaps you'd
like access to the wonderful set of functions in the CGI module:
use CGI qw/:standard/;
The Blosxom plugin architecture defines a set of hooks, points in Blosxom's execution that it'll
give each plugin the chance to act. These hooks -- they're just subroutines -- are, on order of execution:
start
, entries
, filter
, head
, sort
,
date
, story
, foot
, end
. The only required subroutine
is start
.
-
The start
subroutine is required. Its purpose is to Blosxom know that it has indeed
loaded a plugin and should consider it active. Inform Blosxom so by returning a 1 (true), as shown
in this simplest of possible examples:
sub start {
1;
}
This lets Blosxom know that it should consider the plugin alive and well and should offer it
the ability to act at each upcoming callback point.
The start routine is a perfect point to restrict a plugin's operation to dynamic or static rendering,
like so:
sub start {
return $blosxom::static_or_dynamic eq 'dynamic' ? 1 : 0;
}
The above example declares the plugin active only if Blosxom is currently running dynamically.
Otherwise it effectively shuts the plugin down.
- The
template
subroutine offers the plugin the chance to swap in a replacement for
the default template subroutine (the one that brings in your flavour templates).
The template
hook should return a reference to an anonymous subroutine to be used
in place of the default, as defined and assigned to $template
in blosxom.cgi itself.
Given a path, template chunk (e.g. "head" or "foot") and a flavour, The subroutine should return
the contents of the template component at hand.
The following example reads template from an alternate "flavour" directory rather than the main
data directory, separating flavours from weblog postings:
sub template {
return sub {
my ($path, $chunk, $flavour) = @_;
$path =~ s!^/*!!; $path = "/$path";
my $p = $path;
do {
return join '', <$fh> if
$fh->open("< $flavour_dir/$p/$chunk.$flavour");
} while ($p =~ s/(\/*[^\/]*)$// and $1);
return join '', ($blosxom::template{$flavour}{$chunk}
|| $blosxom::template{error}{$chunk}
|| '');
};
}
If your plugin decides not to override the default after all, simply return an undefined value,
like so:
sub template {
# for some reason determine that you don't want to override the default...
return undef;
}
Subsequent plugins will then be given the chance to override the default template subroutine.
-
The entries
subroutine offers the plugin the chance to swap in a replacement for
the default entry find subroutine (the one that finds all those weblog postings of yours).
The entries
hook should return a reference to an anonymous subroutine to be used
in place of the default, as defined and assigned to $entries in blosxom.cgi itself.
The subroutine should return references to a hash of files and another of indexes to be built
(in the case of static rendering).
The following simplistic (read: silly) example populates the %files hash with just one story,
$datadir/just/one/story.txt:
sub entries {
# The entries() sub returns a reference an anonymous subroutine
return sub {
my(%files, %indexes);
# Populate the files list with just one file and its modification time
$files{"$blosxom::datadir/just/one/story.txt"} =
stat("$blosxom::datadir/just/one/story.txt")->mtime;
# When run, the subroutine returns references to the files it found and
# indexes to be constructed when building statically
return (\%files, \%indexes);
};
}
A more comprehensive and realistic example may be found in
entries_index
plugin.
If your plugin decides not to override the default after all, simply return an undefined value,
like so:
sub entries {
# for some reason determine that you don't want to override the default...
return undef;
}
Subsequent plugins will then be given the chance to override the default entries subroutine.
-
The filter
subroutine offers the plugin the chance to alter the full list of entries
Blosxom has found in its
data directory.
The subroutine is passed a reference ($files_ref
) to the hash of files. The hash
consists of key/value pairs, the keys being the full-path of an entry and the value being its Unix-style
modification time (mtime).
sub filter {
my($pkg, $files_ref) = @_;
1;
}
One example of filtering is re-building the list based on the results of a local search -- the
Lucene plugin used on my site does this. Here's a silly example, removing all files that don't contain
the word "spiffy":
sub filter {
my($pkg, $files_ref) = @_;
foreach ( keys %$files_ref ) {
$_ =~ /spiffy/ or delete $files_ref->{$_};
}
1;
}
Notice that I end my subroutine with a 1;
. Returning a true (1) value when all
goes as expected is good form; return a false (0) when problems occur. While Blosxom doesn't halt
execution on a 0 or anything that severe, it does report on what happens with each plugin when run
statically.
- The
skip
subroutine is called just as Blosxom starts actually generating output.
Any plugin can cut short story generation by returning a value of 1
. Of course, the
first plugin to return a 1
is the last one called.
The skip
routine is useful, for example, if your plugin is to return a redirect
for some reason or send a binary stream (e.g. an image) to the browser, and hasn't any reason to
bother generating any blog entries.
- The
interpolate
subroutine offers the plugin the chance to swap in a replacement
for the default interpolation subroutine (the one that replaces variables like $title
and $someplugin::somevariable
with their associated values).
The first plugin whose interpolate
hook returns a reference to an anonymous subroutine
to be used in place of the default has that code assigned to $interpolate
in blosxom.cgi
itself.
The subroutine assigned to $interpolate
is called for template components (e.g.
head, story, foot), being passed the contents thereof for appropriate interpolation.
The interpolate_conditional
plugin, for example, provides all manner of conditional interpolation including: defined, not defined,
not equal to, equal to, greater than, less than, and a recursive default (allowing you to use template
variables in your stories themselves).
If your plugin decides not to override the default after all, simply return an undefined value,
like so:
sub interpolate {
# for some reason determine that you don't want to override the default...
return undef;
}
Subsequent plugins will then be given the chance to override the default interpolate subroutine.
-
Bloxsom calls the head
subroutine after reading in the appropriate head.flavour
and before swapping in values for
template components.
The subroutine is passed the current working directory (as defined by the path) and a reference
to the raw head.flavour source.
sub head {
my($pkg, $currentdir, $head_ref) = @_;
1;
}
The head
subroutine offers the plugin the opportunity to alter the raw header source
and define or alter any variables before the header is added to the output stream.
This is also a good point to alter those custom non-story-specific template variables. Here,
for example, I append the path passed on the URL-line to the title, sandwiched with a stylish "
:: "
sub head {
my($pkg, $currentdir, $head_ref) = @_;
$title_and_path = $blosxom::blog_title;
$blosxom::path_info and $title_and_path .= " :: /$blosxom::path_info";
1;
}
I couldn't have accomplished this by simply having my head.flavour contain:
$blog_title :: $path_info
since the " :: " bit would have shown up even if there was
no path specified on the URL-line, making for a silly "raelity bytes ::".
A more non-trivial example is that used in creating the readme plugin used
on my site. A readme or readme.flavour
file encountered in the current working directory ($currentdir
) is read in and appended
to the raw header source ($head_ref
).
-
The sort
subroutine offers the plugin the chance to swap in a replacement for the
default sorting subroutine that determines in what order all those weblog postings of yours are
displayed, the default being reverse-chronological order (read: newest first).
The entries hook should return a reference to an anonymous subroutine to be used in place of
the default, as defined and assigned to $entries in blosxom.cgi itself.
The subroutine should return a list of fully-qualified filenames in whatever order you prefer.
The following example sorts entries in chronological (oldest first) order, the polar opposite
of the default:
sub sort {
return sub {
my($files_ref) = @_;
return sort { $files_ref->{$a} <=> $files_ref->{$b} } keys
%$files_ref;
};
}
If your plugin decides not to override the default after all, simply return an undefined value,
like so:
sub sort {
# for some reason determine that you don't want to override the default...
return undef;
}
Subsequent plugins will then be given the chance to override the default sort subroutine.
-
Bloxsom calls date
for each new day, after reading in the appropriate date.flavour
and before swapping in values for
template components.
The subroutine is passed the current directory, a reference to the raw date.flavour
source, Unix-style modification time of the latest entry for the day, and some useful date bits
derived from the modification time.
sub date
{
my ($pkg, $currentdir, $date_ref, $mtime, @date_bits) = @_;
my($dw,$mo,$mo_num,$da,$ti,$yr) = @date_bits;
1;
}
date
has the opportunity to alter the raw date template or build an entirely new
date. The following bit of code, for instance, translates the english month names into French or
Japanese or ...
sub date {
my ($pkg, $date_ref, $mtime, $dw,$mo,$mo_num,$da,$ti,$yr) = @_;
# %months defined in the header of the date_translate plugin
$$date_ref =~ s/\$mo(?!_num)/$months[$mo_num]/mg;
1;
}
-
Bloxsom calls story
for each and every story, after reading in the appropriate
story.flavour and before swapping in values for
template components.
The subroutine is passed the story's path, filename, reference to the raw story.flavour
source, reference to the story title, and reference to the body of the post.
sub story {
my ($pkg, $path, $filename, $story_ref, $title_ref, $body_ref)
1;
}
You can alter the raw story.flavour source, alter the title or body of the post
before its pasted into the template, and so forth.
As a simplistic example, let's use the $story_number
variable defined above to number
weblog entries...
sub story {
my ($pkg, $path, $filename, $story_ref, $title_ref, $body_ref)
$$title_ref = "#" . $story_number++ . ". " . $$title_ref;
1;
}
Or, as a better example, here's a simplified (but not by much) version of the TrackBack plugin
used on my weblog. It retrieves the number of trackbacks from the standalone TrackBack implementation,
storing the results in a $trackback variable. The value is swapped in for $trackbacks::trackback
in my story.flavour.
$trackback = '';
sub story {
my ($pkg, $path, $filename, $story_ref, $title_ref, $body_ref)
# code to glean trackback filename based
# upon story path and filename goes here
$trackback =
qq{<a href="$tb_url?__mode=list&tb_id=$tb_id">trackbacks ($tb_count)</a>};
1;
}
-
The flip-side of the
head
subroutine, Bloxsom calls the foot
subroutine after reading in
the appropriate foot.flavour and before swapping in values for
template components.
The subroutine is passed the current working directory (as defined by the path) and a reference
to the raw foot.flavour source.
sub foot {
my($pkg, $currentdir, $foot_ref) = @_;
1;
}
The foot
subroutine offers the plugin the opportunity to alter the raw footer source
and define or alter any variables before the footer is added to the output stream.
The end
subroutine is called at the last minute, after all output has been processed
and sent to the browser and before Blosxom finishes executing.
sub end {
1;
}
The subroutine is not passed anything by Blosxom.
Here's where you can perform any cleanup or last-minute operations you might find useful. A couple
of uses I've found thus far are: pinging weblogs.com if anything's
changed since the modification time of a "touch file", and sending mail to a mailing list with all
new weblog posts since so-many hours ago.
- The
last
subroutine hook is called just before the header is prepended to the output
and the whole kit-and-kaboodle returned by the generate routine, either for display by the browser
or saving to file (if statically rendering)
The subroutine is not passed anything by Blosxom.
5 Minimalist Static Blog Generators to Check Out SiliconANGLE
5 Minimalist Static Blog Generators to Check Out
Klint Finley
| March 20th
READ MORE
inShare0
One of the reasons that the
Slashdot
effect (which perhaps we should now call the "Hacker News
effect") is such a problem is that
WordPress and many other
blogging engines dynamically generate content. Caching plugins
can help this, but there's nothing quite as fast, or as secure,
as serving a site in plain static HTML. This used to be the
norm, even for blogs.
Radio
UserLand, the first dedicated blogging engine, was a desktop
application that generated static html output and uploaded it to
a server.
Until 2010, Blogger had the ability to generate HTML and
publish it to a remote site. And some of the earliest self-hostable
blog engines like
Blosxom and
MovableType had static
HTML output (see below).
Now there's a
growing trend among developers who blog to use static HTML
generators. Most provide no Web based interface – users write a
post in their favorite text editor and the engine takes a text
file and reformats it using predefined templates. Many coders
write their own generators, but there are dozens, probably
hundreds, of open source site generators available. The most
popular use the Markdown markup language and support special formatting for
presenting code samples.
Git is a popular way to manage a static HTML site, but using
Dropbox is a viable alternative as well.
These instructions for
setting up Dropbox with Pelican should be useful for using
Dropbox with other blogging engines as well.
A Word of Warning
One
criticism of static generators is that they encourage the
use of proprietary systems such as Disqus. However, there are some plugins out there that
enable the use of local comments and those willing to do some
hacking can add their own commenting systems. But those wanting
a pure open source, self-hostable system should consider what
they need.
Another potential problem, as
described by Alex Knight, is switching from a static system
to a more complex system. There are ways of migrating a Blosxom
blog to WordPress or MovableType, but I'm not sure how difficult
it would be to migrate a pile of Markdown files to another
blogging engine. On the other hand, this format makes it trivial
to move between static engines.
Migrating from Another Blog Engine
There are a number of ways to get your existing blog out of
its existing CMS and into a pile of static Markdown-formatted
files.
Jekyll has a number of built in importers, and once you have
your files in Markdown you can use them with almost any other
blogging engine listed here (you'll just need a plugin to use
them with Blosxom). You can also use
exitwp, a stand
alone tool for converting WordPress sites into Markdown.
1. Jekyll/Octopress
Jekyll is a
Ruby based "blog aware" static content manager and is one of the
most popular and well-known applications in this category. It
was originally created by Github co-founder
Tom Preston-Werner and is used for Github Pages. It features tight integration with
Github. Those wanting a local commenting system, instead of
Disqus, can check out the static comments plugin.
OctoPress is based on
Jekyll and makes it easier to get started by adding default
templates and various other tweaks.
There are several other Ruby based static site generators as
well, including Webby,
StaticMatic and
toto.
2. Pelican
Pelican
is a Python based static HTML blogging engine that's gathered a
lot of steam. It supports both reStructuredText and Markdown,
and has most of the features you'd expect: syntax highlighting,
Disqus support, etc.
Calepin is a hosted service
based on Pelican that uses Dropbox as its uploading system.
Other Python based engines include
Hyde,
Blogofile and
Igor.
3. Blosxom
Blosxom is the original
open source static site generator. It was created in 2002 by
Rael
Dornfest, who went on to work for Twitter and is now part of
The Obvious Corporation. It
was written in Perl, which means you can run it almost anywhere
with very little configuration. There's also an extensive
plugin registry
that adds features such as comments, pingbacks and even a
graphical Web-based interface. One downside is that Blosxam
hasn't had a stable release since 2008, but the project is quite
mature. If you want to use Markdown, you'll need
John
Gruber's plugin.
There are also several ports of Blosxam to other languages.
PyBlosxam is
actively developed and also has a nice
plugin
registry, including a plugin that adds support for Markdown.
4. Second Crack
Second
Crack is a PHP based static blog engine developed by
Instapaper creator
Marco Arment. Arment designed it
specifically to be used with Dropbox and actively develops it.
Like most of the engines mentions, it works with Markdown.
5. Blacksmith
For those looking for a more cutting edge stack,
Blacksmith is a static blogging written in Node.js. As I
mentioned in my
round-up of Node.js blog engines and content management systems,
Blogsmith was created by the Nodejitsu team and runs the company's blog.
Bonus
If you need a more advanced content management system, but
want to use static HTML, you have a couple of options. The
venerable MovableType
still allows users to generate static HTML, and it's been open
source since 2007. And if you just can't let go of WordPress,
the plugin
ReallySatic makes it possible to generate static HTML from
WP.
If you want even more static site engines you can check out
Timo Reitnauer's list of 32 generators.
Static websites are safer, use fewer resources, and avoid vendor and platform lock-in. You can read
more about this in the
Nikola Handbook
It has many features, but here are some of the nicer ones:
- Blogs, with tags, feeds,
archives, comments, etc.
- Themable
- Fast builds, thanks to doit
- Flexible, extensible via plugins
- Small codebase (programmers can understand all of Nikola core in a day)
- reStructuredText
or Markdown as input language (also Wiki, BBCode, Textile, and HTML)
- Easy image galleries
(just drop files in a folder!)
- Syntax highlighting for almost any programming language or markup
- Multilingual sites,
translated
to 18 languages.
- Doesn't reinvent wheels, leverages existing tools.
- Python 2.6, 2.7, 3.3 and 3.4 compatible.
Already a while ago, Kevin Scaldeferri,
head of the
current
Blosxom developer group, managed to get
all the content from Rael's well known but neglected
Blosxom prime site at blosxom.com online at
the SourceForge hosted website of the current Blosxom
developer group at blosxom.sourceforge.net,
where the developers have access to and can start updating the content.
To really be up-to-date, it will take a while, but at least the content is there, since blosxom.com
seems no more reachable, as
someone noticed today on the
Blosxom user's
mailing list.
FlavoursIf this were all that Blosxom provides, I would not be too impressed. But after
examining it a bit more closely, I see that it contains a great deal of power. That power is there
thanks to the combination of display templates (known as flavours, using the British spelling) and
the ability to accept any number of plugin programs. The combination of these two features makes
Blosxom quite extensible.
Blosxom comes with two flavours built-in, the default HTML flavour and the optional RSS flavour
for the RSS syndication feed. You can view the RSS feed yourself by tacking ?flav=rss
onto the end of your blog's URL. So, if you normally view your Weblog at http://localhost/cgi-bin/blosxom.cgi,
you can view the RSS feed for the site at http://localhost/cgi-bin/blosxom.cgi?flav=rss.
Alternatively, you can specify your preferred flavour by changing the suffix of the page you retrieve.
Thus, we can see RSS with http://localhost/cgi-bin/blosxom.cgi/index.rss.
A complete flavour registry is available on the Blosxom Web site. But the basic idea is easy
to grasp: in your data directory, alongside your Weblog entries, you create an HTML file whose name
reflects the part of Blosxom's output you want to change.
The filename's suffix is the same as the flavour you want to modify. Thus, the file header.html
changes the way the Weblog's header is displayed in the HTML flavour, and date.blah changes
Blosxom's display of dates in the blah flavour. Users can set the flavour in the URL by adding the
flav name-value pair (as we saw before), and the default is set in blosxom.cgi itself, with the
variable $default_flavour. Because blog entries have a .txt suffix, you cannot
have a txt flavour.
Each flavour file consists of an HTML snippet, along with Perl variable names that might be instantiated
into the particular file. For example, story flavour files receive the variables $title
and $body, among others. (A full list is available on the Blosxom Web site.) I thus
can change my blog's output such that headlines are huge and right-aligned, followed by the body:
<p>
<H1 align="right">$title</h1>
<br />
$body
</p>
The above flavour inserts the $body variable, the contents of our blog story, verbatim
into the HTML. This is fine if the blog author knows HTML and is willing to enter paragraph tags
manually. But if we want to let people separate paragraphs with blank lines, we need to run a program
on our story. Luckily, Blosxom makes it easy to write such programs with an extensible plugin
architecture.
PluginsEach plugin is a Perl program loaded with the require function, which reads and
evaluates code in a particular file. So require foo.pl opens foo.pl and
evaluates the code it contains. Because require executes at runtime, whereas use executes during
the compilation phase, it is far easier to work with it here.
Blosxom assumes that any file in the plugin directory, defined by the optional $plugin_dir
variable, is a plugin. Plugins are both loaded and applied in alphabetical order, which means if
you want to make sure a particular plugin is applied first or last, you might need to rename it.
Each plugin is nothing more than a simple Perl program that defines one or more subroutines.
Every plugin must define the start subroutine, which simply returns 1. This allows Blosxom to determine
that the plugin is alive, ready and willing to be invoked. A number of other plugin subroutines
are available that each plugin optionally may define, ranging from entries (which returns a list
of entries) to story (which allows you to modify the contents of a story). By breaking things down
in this way, Blosxom allows for a tremendous amount of customization and sophistication, while keeping
the core code small and compact.
So, what sorts of features can plugins provide? There seems to be only a few restrictions. You
can change the source from which Weblog entries are retrieved, the way in which this list of entries
is filtered, the templates used to display the entries and the contents of the entries themselves.
A large number of plugins are available from the Blosxom Web site. Some of them depend on other
plugins, while others, such as the calendar, appear only if you are using a flavour that supports
the plugin. Other plugins work immediately and merely need to be dropped into your plugin directory.
A simple example of a plugin that works out of the box is atomfeed, which provides an Atom syndication
feed. Atom is a competitor to RSS that has been promoted by a number of heavy-hitting bloggers and
programmers, in no small part because of the competing standards now evident in the RSS world. To
get an Atom feed, simply copy the atomfeed plugin to your plugins directory. You then can retrieve
your Atom feed with http://localhost/cgi-bin/blosxom.cgi?flav=atom
or http://localhost/cgi-bin/blosxom.cgi/index.atom
.
Writing PluginsListing 1 contains a simple filter, called egotrip, to make my name appear
in boldface whenever it appears in a Weblog entry. Notice how the plugin must define its own package;
this ensures that each plugin's subroutines are kept in a separate namespace and makes it possible
for Blosxom to determine whether a package contains a particular method name.
Listing 1. egotrip.pl
#!/usr/bin/perl
use strict;
use warnings;
use diagnostics;
package egotrip;
# Returns 1 to indicate the plugin is active
sub start
{
return 1;
}
# Boldfaces my name
sub story {
my ($pkg, $path, $filename, $story_ref,
$title_ref, $body_ref) = @_;
$$body_ref =~ s|Reuven|<b>Reuven</b>|g;
1;
}
1;
The actual work is done in the story subroutine, which is passed six arguments when invoked by
Blosxom, corresponding to a number of items having to do with the entry. In our case, we care about
changing only the body of the entry, which is in the final variable, known as $body_ref. As its
name implies, this is a scalar reference, which means we can access or modify its contents by dereferencing
it, using two $$ signs. With that in mind, it should not come as a surprise that we can boldface
every instance of my name with:
$$body_ref =~ s|Reuven|<b>Reuven</b>|g;
Of course, we could make this step even more sophisticated and insert automatic hyperlinks to
a number of different items:
$$body_ref =~ s|(Reuven Lerner)| ↪<a href="http://www.lerner.co.il/">$1</a>|g; $$body_ref =~ s|(Linux Journal)| ↪<a href="/">$1</a>|g;
Indeed, a plugin of this sort already exists; it automatically creates links to the community-driven
Wikipedia. Any text placed within [[brackets]] automatically is turned into a link to that on-line
reference book.
Notice how flavours are HTML templates into which we can instantiate Perl variable values, whereas
plugins are Perl programs. This division between display and actions takes a little bit of time
to grasp, but it shouldn't be too difficult.
As for our paragraph-separating problem from before, there's no need to reinvent the wheel. You
simply can download a plugin, Blox, that allows you to separate paragraphs with blank lines when
writing your blog entry. The plugin then separates paragraphs with the HTML of your choice. Blox
is listed on Blosxom's plugin registry (see the on-line Resources section).
The fact that Blosxom keeps all entries and flavours in a single directory is a bit disturbing
to me and makes me wonder about the program's scalability. Even if my filesystem and Perl can handle
that many files without too much trouble, do I really want to wade through them all? If and when
this becomes a problem, an entries plugin probably can provide the right solution, scooping up files
from multiple directories and returning an appropriate hash to Blosxom.
ConclusionBlosxom is a powerful tool for creating a Weblog; it's more than it might appear
at first glance. Blosxom consists of an easy-to-install, easy-to-configure CGI program written in
Perl, but its true power lies in the fact that it lets you change every part of the display through
a combination of flavours (display templates) and plugin routines. By mixing and matching existing
flavours and templates with something of your own, it can be easy to create your own Weblog.
Resources for this article:
www.linuxjournal.com/article/7454.
Reuven M. Lerner, a longtime consultant in Web/database programming, now is a graduate student
in Learning Sciences at Northwestern University in Evanston, Illinois. You can reach him at
[email protected].
If you spend any amount of time
on the Web, it's a pretty safe guess that you've heard of blogs. Basically, a blog is
an online journal, but there's more to them than just posting your daily thoughts.
Blogs are used
used by corporations to keep their customers updated on current products and trends, business
leaders use them to share their views on a variety of topics (Jupitermedia Chairman and Chief Executive
Officer Alan M. Meckler has
his own blog), they are
used by individuals to address topics related to specific subject areas (JupiterReasearch has several
analysts who write their
own blogs) and
individuals use blogs to address subjects which are more personal to them. There are political
blogs, religious blogs, news blogs, personal blogs, industry-specific blogs and many more. Together,
I suspect they cover the entire human experience.
From a
Web designer point-of-view, blogs may need to be established for several reasons: to
provide current information about your services; to comment on the topics of the day as they relate
to
Web design or to set one up for a client. Anybody can start a blog and there are several
ways to go about setting one up. The three most basic methods are:
- Create a page on your Web site and post your comments to it.
- Join one of the many existing blog communities (i.e.
Weblogs, Inc. or
Blogger).
- Create your own blog on your own Web site, using one of the
many existing blogging packages (i.e.
Blosxom,
Movable Type,
or WordPress)
|
Each of these methods has its share of positive and negative aspects, although the first method
is rarely used. Within the blogging community, the second two methods seem to be the most popular.
For our purposes we'll take a look at one of the existing blogging scripts,
Blosxom.
During my recent vacation, I decided it was time to set up a blog about my
personal Web sites. I've read the horror stories that many people have experienced with
some of these programs - and many of those people are really tech-savvy. It seems that blogging
software can be a bit frustrating at times. Many of the packages also require a database (which
I didn't want) as that could complicate things a bit. I was just looking for something simple, something
I could quickly set up and start posting. I don't even recall how I stumbled upon Blosxom but it
seems to be a popular program (judging from the
search results on Google).
Blosxom (pronounced "blossom") is a compact, easy-to-use blogging script created by
Rael Dornfest, Chief Technology
Officer at O'Reilly Media. It's
Open Source so it's free. The entire package consists of one file written in 444 lines
of Perl code. Very simple. There are 10 variables to configure, 12 if you use plugins, which I'm
sure you will. (There are four additional variables to configure if you set up
static
rendering.)
This script has all the bells and whistles, just like the others. It automatically creates RSS
feeds, you can set up
trackback links, ping other servers and allow visitors comments.
Configuration and Installation
As I said, the program is just one script, so configuring the variables is quite simple.
Instructions
are given right on the Web site. Basically, it's just a matter of adding the title of your blog,
a description and some path information. That's all there is to it. If you're interested in the
coding, Frank Hecker created an
annotation version of
the script.
Installing the script is a snap. Once again,
instructions
are on the Web site, but if you've ever installed a CGI script, you could do it blindfolded. You
just drop the script into your CGI bin and change the file permission to make it executable.
Plugins and Flavours
These are used to change the display and makeup of the blog itself. By mixing and matching these,
you can personalize the blog to match your own site or preferences.
Plugins
are used to add customized features to each blog. They're easy to use; most just need to be uploaded
to the site. To activate plugin support, just create a plugin directory on your Web site. While
you don't need them to use Blosxom, they add another dimension to the blog. There are plugins available
for all kinds of different things: setting up archives or a calendar, listing different categories
for your postings, changing the date display, setting up the display, letting visitors make comments,
customizing RSS feeds, setting up cookies, creating polls and many other options. On the Blosxom
Web site there are 239 plugins,
divided into 35 categories. In addition, there are other plugins on other Web sites. You can even
write
your own plugins.
Flavours
are nothing more than templates that tell the script how to format the pages displayed. (The spelling
within the program is "flavours.") If you like the default output, you don't even need to create
one. You will need to do it, however, if you want to blend the blog into an existing site. It took
me about five minutes to create a set to match my site. A "set" is made up of four small files which,
together, comprise a whole page. Just take an existing page from the site and cut it up into four
parts:
- head (the top section).
- date (displays in the blog's date section but you can choose
to display another stuff).
- story (the individual blog posting itself).
- foot (the footer at the bottom).
|
Posting to the Blog
Well, this is what we were working for, the ability to post our comments and thoughts for all
the world to see. The actual blog postings are plain text files loaded into a designated directory
on your Web server with a ".txt" extension. You can add HTML coding, if you like. You can even post
to it via e-mail.
Conclusion
For the most part, that's all there is to setting up the Blosxom blog. As I said, it's easy to
create and use a blog with this script. There's no need to set up any databases either. One of the
nice things is that it doesn't have to look like all the other blogs.
If you're looking to create your own blog, or set one up for a customer, be sure and check out
Blosxom. It could save you a lot of headaches.
Additional Links
[1-Feb-2003]
Network Computing/Perl-ing
your BlogsDr Seamus Phan,
Weblogs, or blogs, have become the underground movement for online journalism. With blogs, it
is very easy for users who have no experience in writing HTML code, or using visual HTML editing
tools such as Macromedia DreamWeaver MX, to upload Web content.
It is done by using nothing more than glorified text editors with FTP (file transfer protocol),
or even through the new breed of GUI-based blog writing and upload tools with a Web browser.
If you examine some of the blog editing tools closely, you will see that they are nothing more than
repackaged text editors with a simple FTP client included. If you are familiar with C++, Java or
Cocoa programming, you are likely to be able to write such a tool in under one day flat. The code
may not be pretty and there may be specific GUI quirks depending on your operating environment,
but I suspect that the tool will work.
Rael Dornfest, a researcher at O'Reilly & Associates, has a simple and elegant Perl blog script,
which I have used in this example. It remains one of the simplest blog scripts I have seen, although
in the future we may even have simpler PHP versions. If you need to integrate the blog uploads to
a calendar, you may have to patch the script to accept Javascript or Perl calendar scripts.
Parameters for editing
Dornfest's Perl blog script provides a few simple parameters to edit and you are ready to go. Bear
in mind that if you intend to have a Website look-and-feel that resembles your own content, you
have to tweak the head.html and foot.html files accordingly. Since this blog script, as with many
server-based CGI scripts these days, rely on discrete HTML files to be joined during runtime execution,
some server-based testing is necessary-quite a departure from static HTML editing.
First off, check that the line #!/usr/bin/perl –w is pointing to the right Perl directory on your
server. Next, change those variables under "configurable variables", especially the $datadir directory.
Dornfest's script works by having you deposit simple text files into the right directory, and the
script will automatically merge the textual content into the format determined by the style templates
of the HTML code.
I have given an example of how the text file can look like. You can label the text file in any way
you choose, although I would recommend that you name them in ways you can reference later, such
as full date with single word description of the content (e.g. 20030115_higheredu.txt). Remember
that as with any server systems, you should NOT have spaces in file names, and should respect Unix
file naming conventions to avoid problems during deployment.
You can determine how many articles will display in a single Web page, under the $num_entries parameter.
If you tend to upload short news clips, with embedded links to full text, you can have a higher
number (e.g. 30). But if you tend to feature the entire article in full, you may want to limit the
$num_entries to five or under.
Style's a lot of work
As with many blog scripts out there, Dornfest's Perl script allows the use of "flavours", or templates.
You name the templates xxx.html, and it can be addressed through the use of the URL convention.
For example, you may want to call an alternative "flavour" other than the default, and your URL
should be: http://www.ABC.com/pathto/blosxom.cgi/?flav=yourflavour.
If you think your job is done, think again. You need to prepare flavour template HTML files for
each of the components, including the likes of head.yourflavour, foot.yourflavour, story.yourflavour,
and content_type.yourflavour.
The content_type.yourflavour file is to state that the default content for all these discrete HTML
components are indeed HTML, and not any other type of encoding.
HTML is a subset of XML, as is RSS, which is something that is used for news aggregation. Because
RSS is recognised innately as well, it is therefore possible to tweak the script to recognise XML
formatting, assuming that you have edited a new set of HTML or XML templates, including the head,
foot and story files.
The script uses the join command to join the discrete HTML or XML components together to form the
entire Web page, before using the print command to print to screen for representation in Web browsers.
Further, if you intend to stray away from the standard and understandably boring stylesheet, you
have to know a bit about Cascading Style Sheets (CSS). With CSS, you can easily modify the entire
look-and-feel of all Web pages and still be able to tweak individual textual elements on specific
pages.
Dornfest's script works mostly as advertised. However, showing full URL links exhibited some errors
in certain freeBSD installations, although they can be tweaked to work. Most other Unix or similar
operating systems should work without much hassle.
Worth the effort?
If you need a platform that can be an efficient and affordable news generation and collaborative
tool, that is accessible to just about anyone who can use a Web browser, blogging is the way.
But if you need something more powerful, find a full-fledged content management system (CMS).
Seamus Phan is a research director at KnowledgeLabs News Center (www.knowledgelabs.net), an independent
technology news bureau. He can be reached at [email protected].
by Simon Cozens
December 18, 2003
Recently we heard from Kake Pugh about the
OpenGuides project,
a wiki-based collaborative city guide system; previously, we heard from Brian Ingerson about his
Kwiki wiki implementation. Guides, wikis, blogs ... the new fashion in software engineering at the
moment is the use of software to help organize, document, and facilitate collaboration -- the social
software movement is gaining momentum, and Perl is one of the best languages for it.
In this article we'll look not just at some of the existing social software tools in Perl (focusing,
naturally, on my own Bryar blog toolkit), but we'll look at some ways to break, bend, and embed
them in other tasks.
Basic Blogging with Blosxom
When I finally decided that the world would benefit from hearing my internal monologue, I naturally
looked around for nice, simple blogging programs. Blogs are, essentially, simple things, and so
I didn't want all-singing, all-dancing web-based database-backed content management systems. I knew
that if I were going to blog, it would have to be easy for me to do so, and there's nothing easier
than firing up a text editor in the next available terminal window and doodling my thoughts into
it.
Thankfully, Rael Dornfest has the same
sort of laziness as I, and created Blosxom,
a very simple blogging tool, which simply reads a bunch of files from the file system, finds the
most recent and relevant, packages them up together, and sends them at a browser. That was how I
saw blogging.
Getting Blosxom up and running is, in keeping with the whole theme of Blosxom, quite simple.
You need to download the
blosxom zip file, unpack it, drop the blosxom.cgi
file in your web server's cgi-bin
directory, and then edit the first few lines of it to tell it the name of your blog and where the
entries will live, and you're done.
Posting into the blog is just a matter of creating a file called something.txt
in
the blog directory. It doesn't even matter what the something
is. All that matters
is the first line of the file, which becomes the title, and the rest, which becomes the story in
raw HTML:
First post!
<p> Today I set up a blosxom blog. It was really easy! </p>
You can then, if you like,
style your blog
with custom header and footer files, CSS, custom HTML for each blog post, and so on.
Enter Bryar
Of course, back when I started using Blosxom, things were not quite so easy, and templating required
hacking the Blosxom CGI file itself, and things just didn't seem as neat as I wanted them to be.
I liked Blosxom's simplicity, but didn't want to pay the price for it in terms of flexibility.
At the same time, I was learning the wonders of the
Template Toolkit, and thought
that a well-designed blog should merely collect Post objects and send them to a user-defined template
to do what it wants with them.
So I started writing Bryar, which is designed to be a modular, extensible replacement for Blosxom.
To make this happen, I needed to provide a default set of components that simply Does The Right
Thing. Let's take a look at that default set before we go any further.
When we install Bryar from CPAN, we're encouraged to run a command to set up a new blog:
You probably want to run bryar-newblog in a likely home for
your blog once we've finished installing.
The bryar-newblog
command simply sets up a decent default set of templates, creates
a first blog post, and drops in a bryar.cgi
driver, similar to blosxom
.
At this point, we're ready to go.
Bryar's default collection of modules consists of a Bryar::DataSource::FlatFile
,
which emulates Blosxom's use of text files in the file system as a database of blog posts; there
are Bryar::Frontend::CGI
and Bryar::Frontend::mod_perl
, which describe
how URL parameters are retrieved from the server translated into a request for documents,
Bryar::Document
which represents each post, and Bryar::Collector
which ties
it all together. With the benefit of hindsight, that should have been called a Bryar::Controller
,
since the whole thing can be described as a Model-View-Controller application. But more on that
later!
Since all of these things can be overridden, we need something to keep track of which classes
we're using, and the Bryar::Config
class does that, reading an optional configuration
file but otherwise providing mostly sensible defaults.
In the rest of this article we're going to look at some interesting ways to override those classes,
and build some more funky tools out of this social software framework.
Recommended Links
Society
Groupthink :
Two Party System
as Polyarchy :
Corruption of Regulators :
Bureaucracies :
Understanding Micromanagers
and Control Freaks : Toxic Managers :
Harvard Mafia :
Diplomatic Communication
: Surviving a Bad Performance
Review : Insufficient Retirement Funds as
Immanent Problem of Neoliberal Regime : PseudoScience :
Who Rules America :
Neoliberalism
: The Iron
Law of Oligarchy :
Libertarian Philosophy
Quotes
War and Peace
: Skeptical
Finance : John
Kenneth Galbraith :Talleyrand :
Oscar Wilde :
Otto Von Bismarck :
Keynes :
George Carlin :
Skeptics :
Propaganda : SE
quotes : Language Design and Programming Quotes :
Random IT-related quotes :
Somerset Maugham :
Marcus Aurelius :
Kurt Vonnegut :
Eric Hoffer :
Winston Churchill :
Napoleon Bonaparte :
Ambrose Bierce :
Bernard Shaw :
Mark Twain Quotes
Bulletin:
Vol 25, No.12 (December, 2013) Rational Fools vs. Efficient Crooks The efficient
markets hypothesis :
Political Skeptic Bulletin, 2013 :
Unemployment Bulletin, 2010 :
Vol 23, No.10
(October, 2011) An observation about corporate security departments :
Slightly Skeptical Euromaydan Chronicles, June 2014 :
Greenspan legacy bulletin, 2008 :
Vol 25, No.10 (October, 2013) Cryptolocker Trojan
(Win32/Crilock.A) :
Vol 25, No.08 (August, 2013) Cloud providers
as intelligence collection hubs :
Financial Humor Bulletin, 2010 :
Inequality Bulletin, 2009 :
Financial Humor Bulletin, 2008 :
Copyleft Problems
Bulletin, 2004 :
Financial Humor Bulletin, 2011 :
Energy Bulletin, 2010 :
Malware Protection Bulletin, 2010 : Vol 26,
No.1 (January, 2013) Object-Oriented Cult :
Political Skeptic Bulletin, 2011 :
Vol 23, No.11 (November, 2011) Softpanorama classification
of sysadmin horror stories : Vol 25, No.05
(May, 2013) Corporate bullshit as a communication method :
Vol 25, No.06 (June, 2013) A Note on the Relationship of Brooks Law and Conway Law
History:
Fifty glorious years (1950-2000):
the triumph of the US computer engineering :
Donald Knuth : TAoCP
and its Influence of Computer Science : Richard Stallman
: Linus Torvalds :
Larry Wall :
John K. Ousterhout :
CTSS : Multix OS Unix
History : Unix shell history :
VI editor :
History of pipes concept :
Solaris : MS DOS
: Programming Languages History :
PL/1 : Simula 67 :
C :
History of GCC development :
Scripting Languages :
Perl history :
OS History : Mail :
DNS : SSH
: CPU Instruction Sets :
SPARC systems 1987-2006 :
Norton Commander :
Norton Utilities :
Norton Ghost :
Frontpage history :
Malware Defense History :
GNU Screen :
OSS early history
Classic books:
The Peter
Principle : Parkinson
Law : 1984 :
The Mythical Man-Month :
How to Solve It by George Polya :
The Art of Computer Programming :
The Elements of Programming Style :
The Unix Hater’s Handbook :
The Jargon file :
The True Believer :
Programming Pearls :
The Good Soldier Svejk :
The Power Elite
Most popular humor pages:
Manifest of the Softpanorama IT Slacker Society :
Ten Commandments
of the IT Slackers Society : Computer Humor Collection
: BSD Logo Story :
The Cuckoo's Egg :
IT Slang : C++ Humor
: ARE YOU A BBS ADDICT? :
The Perl Purity Test :
Object oriented programmers of all nations
: Financial Humor :
Financial Humor Bulletin,
2008 : Financial
Humor Bulletin, 2010 : The Most Comprehensive Collection of Editor-related
Humor : Programming Language Humor :
Goldman Sachs related humor :
Greenspan humor : C Humor :
Scripting Humor :
Real Programmers Humor :
Web Humor : GPL-related Humor
: OFM Humor :
Politically Incorrect Humor :
IDS Humor :
"Linux Sucks" Humor : Russian
Musical Humor : Best Russian Programmer
Humor : Microsoft plans to buy Catholic Church
: Richard Stallman Related Humor :
Admin Humor : Perl-related
Humor : Linus Torvalds Related
humor : PseudoScience Related Humor :
Networking Humor :
Shell Humor :
Financial Humor Bulletin,
2011 : Financial
Humor Bulletin, 2012 :
Financial Humor Bulletin,
2013 : Java Humor : Software
Engineering Humor : Sun Solaris Related Humor :
Education Humor : IBM
Humor : Assembler-related Humor :
VIM Humor : Computer
Viruses Humor : Bright tomorrow is rescheduled
to a day after tomorrow : Classic Computer
Humor
The Last but not Least Technology is dominated by
two types of people: those who understand what they do not manage and those who manage what they do not understand ~Archibald Putt.
Ph.D
Copyright © 1996-2021 by Softpanorama Society. www.softpanorama.org
was initially created as a service to the (now defunct) UN Sustainable Development Networking Programme (SDNP)
without any remuneration. This document is an industrial compilation designed and created exclusively
for educational use and is distributed under the Softpanorama Content License.
Original materials copyright belong
to respective owners. Quotes are made for educational purposes only
in compliance with the fair use doctrine.
FAIR USE NOTICE This site contains
copyrighted material the use of which has not always been specifically
authorized by the copyright owner. We are making such material available
to advance understanding of computer science, IT technology, economic, scientific, and social
issues. We believe this constitutes a 'fair use' of any such
copyrighted material as provided by section 107 of the US Copyright Law according to which
such material can be distributed without profit exclusively for research and educational purposes.
This is a Spartan WHYFF (We Help You For Free)
site written by people for whom English is not a native language. Grammar and spelling errors should
be expected. The site contain some broken links as it develops like a living tree...
Disclaimer:
The statements, views and opinions presented on this web page are those of the author (or
referenced source) and are
not endorsed by, nor do they necessarily reflect, the opinions of the Softpanorama society. We do not warrant the correctness
of the information provided or its fitness for any purpose. The site uses AdSense so you need to be aware of Google privacy policy. You you do not want to be
tracked by Google please disable Javascript for this site. This site is perfectly usable without
Javascript.
Last modified: March 29, 2020