LnBlog 0.7.0 beta 1

Well, it's finally here: the first beta release of LnBlog 0.7.0. You can download it here if you're feeling adventurous. Note that this version requires that you run an upgrade on each of your blogs in order for it to work correctly, so I strongly recommend that you make backup copies of all your blog directories as well as you LnBlog directory.  Also note that you'll need to register your blogs before you can do this.  It's not hard - just type the path in the box and hit the button, just like running an upgrade.  This is just so that the system knows about them. New blogs are registered when they are created.

This release includes massive code cleanup and a number of new features. On the cleanup side, if you look in the LnBlog/pages directory, you'll notice that the article handling pages are gone. That's because they've been folded into the blog entry pages. This is also the reason that you need to upgrade your blog wrappers: if you don't, articles simply won't work. I've also moved a lot of the logic out of the back-end classes and into the page files, where it belongs. The classes were simply getting too smart. While this was fine for normal operation, and made for really small pages, it got me into serious trouble when I started adding support for the Blogger API, because the classes all assumed they were interacting with a client browser.

But enough of that. You probably want to know about the new features. Well, here's an incomplete list for you, in no particular order:

  • Blog tracking. The system now tracks what blogs you create and keeps a list of them. So now, instead of typing in the blog path on the administration page, you can just select it from a drop-down list. Note that if you are upgrading from an old installation, you will have to type the same old path in the "register blog" box on the admin page to get it in the list. Or you can just add the blogs to the BlogList line (comma-separated, no spaces) in your LnBlog/userdata/system.ini file.
  • Partial support for group-based security. Basically, it is now possible to have more than one administrator. More meaningful group security will come later. There is no graphical interface for this yet, but you can set users in groups by adding their name to the appropriate comma-delimited list in your LnBlog/userdata/group.ini file.
  • Another path for plugins and themes. You can now create LnBlog/userdata/themes and LnBlog/userdata/plugins directories for your non-standard themes and plugins. This just makes it a little easier to upgrade, as you don't have to individually sort out and copy any extra stuff you've installed.
  • Support for the Blogger 1.0 API. Use your LnBlog/blogger.php file as the URL for the requests. One thing to note abou the API is that the blogger.getTemplate and blogger.setTemplate methods are not implemented. This is because they don't really apply to the way LnBlog works.
  • Support for post editor plugins. That's right, now that the pre-releases of Opera 9 have support for edit mode, I've finally added the ability to use a JavaScript rich text editor. There is no such editor included in the standard release (as the editor would take up more space than the rest of LnBlog), but you can download plugins for TinyMCE and FCKEditor from the new plugins page. Of course, you can only enable one such plugin at a time, but that shouldn't be surprising.

That's about it for now. If you have any problems or find any bugs, please report them to me by e-mail or by leaving a comment. I'm thinking that I'll finish off the Blogger API support, fix any more bugs I find, and call that the final release. There are a number of other things to add, but I'd like to stick a little more to the "release early and often" philosophy.

Theming, Part 2: Sidebar Templates and Plugins

It's time for part 2 of the LnBlog themes tutorial series. In this episode, we'll cover modifying your sidebar. This will include a brief discussion of how theme templates work as well as an introduction to the plugin system. In the process, we will also create a very simple and extremely unimpressive plugin. Note that in this tutorial, unlike the last one, I will assume that you have a basic knowledge of HTML and CSS. This tutorial will also include some PHP code, although I will nto assume a working knowledge of PHP (although if you have one, it will help).

As you may recall from last time, LnBlog's theme system has a concept of paths. This applies not only to images and style sheets, as we saw before, but also to template. In other words, LnBlog will look for a given template first in your blog's templates directory, second in the templates directory of your current theme, and lastly in the templates for the default theme. This means that you can easily modify the templates for each of your blogs individually or for all of them at a time.

Modifying the template

Let's start by making a copy of your LnBlog/themes/default/templates/include_sidebar.php file and saving it on your local hard drive so we can play with it. If you open up the file in a text editor, you'll notice that there's almost nothing in it. It should just look like this: activateEventFull($tmp=false, "sidebar", "OnOutput"); $EVENT_REGISTER->activateEventFull($tmp=false, "sidebar", "OutputComplete"); ?> Of course, if you don't know PHP, that's probably doesn't mean anything to you. In fact, it probably doesn't mean much even if you do know PHP. That's because this code is part of LnBlog's event system

As you may already know, the default page banner, menubar, and sidebar in LnBlog are all implemented as plugins. If you open up your include_banner.php or include_menubar.php, they'll contain similar code. Basically, this code raises an event, i.e. it tells LnBlog's event manager that something interesting is happening and any plugin that's interested in this event better get it's act together. The event manager them checks a list of plugins that signed up to be notified when this event happens and tells them to do their thing.

Now, since this is a template, we can actually ad HTML code right into it. For illustrative purposes, I'll add some of my favorite links to the sidebar. Here's what the resulting code looks like: <?php global $EVENT_REGISTER; $EVENT_REGISTER->activateEventFull($tmp=false, "sidebar", "OnOutput"); ?> <h3>Recommended Links</h3> <ul> <li><a href="http://blogs.msdn.com/oldnewthing/">The Old New Thing</a></li> <li><a href="http://www.securityfocus.com/">Security Focus</a></li> <li><a href="http://www.larkware.com/">The Daily Grind</a></li> </ul> <?php $EVENT_REGISTER->activateEventFull($tmp=false, "sidebar", "OutputComplete"); ?> Notice that I broke the PHP code into two blocks and put the HTML in between them. Since tempaltes are actually PHP files, anything inside the <?php ?> tags is treated as PHP code, and anything outside them is treated as HTML. If you're sharp, you probably noticed that I did this because of the event code: I put my markup between the OnOutput and OutputComplete events.

If you save this file and upload it to your blog's templates directory, you'll see your list of links in the sidebar. However, you'll notice that the links are at the bottom of the sidebar. That's because all the plugins are loaded by the OnOutput event. If you move the HTML code above that event, then all your links will end up at the top of the sidebar. But what if you want your links in the middle somewhere? Maybe you want your links between your articles and your RSS feeds. Well, that's why this isn't the recommended way to add to the sidebar.

A simple sidebar plugin

However, there is good news. Writing a simple plugin to display some links in the sidebar is easy. Really easy. In fact, it's about a dozen lines of boiler-plate PHP code with your HTML inserted in the middle. And once you have the plugin written, it will be detected by the plugin manager and you will be able to change where it appears in the sidebar by changing its load order in the plugin loading configuration page.

Here's a plugin version of the links in the example above: <?php class MyLinks extends Plugin { function MyLinks() { $this->plugin_desc = "Shows my favorite links in the sidebar"; $this->plugin_version = "0.1.0"; } function show_links() { ?> <h3>Recommended Links</h3> <ul> <li><a href="http://blogs.msdn.com/oldnewthing/">The Old New Thing</a></li> <li><a href="http://www.securityfocus.com/">Security Focus</a></li> <li><a href="http://www.larkware.com/">The Daily Grind</a></li> </ul> <?php } } $plug = new MyLinks(); $plug->registerEventHandler("sidebar", "OnOutput", "show_links"); ?> This is about the simplest plugin you can have. It is a simple PHP class with a constructor that defines the version number and a short description, and a single method that dumps some HTML output to the screen. Note at the bottom that you have to create an instance of the class and register the method with the event manager.

Now is probably a good time to mention that plugins use a path mechanism too. In other words, you can have plugins that apply only to a single blog, just like you can with theme template and style sheet. Just make a "plugins" directory in the blog's directory and put the plugins there. They will be treated just like a regular plugin, but no other blog will be able to see them.

So, now let's install your new plugin. Copy the above code and paste it into a new file named sidebar_mylinks.php. Note that it is very important that you not have any blank lines or spaces outside the PHP <?php >> tags, as this will cause error messages due to the way PHP handles output. Now, create that plugins directory in you blog's directory on the server and upload the sidebar_mylinks.php file into it. If you open up your blog in a web browser, you should see the new links. If you change the load order of your sidebar_mylinks plugin from the plugin loading page, then the link section will move in the sidebar.

If you want to have several independant sidebar sections, you can make copies of this plugin to achieve that. Just change the HTML code, the plugin_desc on the fourth line, and change all three instances of the name MyLinks to MyOtherLinks, or something like that (the exact name doesn't matter, so long as no two plugins have the same name). If you're feeling adventurous, you can also adapt this to add markup to the banner or menubar by changing the "sidebar" parameter in the registerEventHandler line to "banner" or "menubar".

You can download files for this tutorial here. In the next installment, we'll go into theming the content areas of a page, including templates for blog entries. We'll also cover modifying the associated style sheets and possibly adding some images.

Theming, Part 1: Custom Banner

It's been a long time since I posted anything, so I figured I'd put up a little informal documentation on the theme system. After all, who wants to be stuck with just the default themes? The answer is: me, because I'm the one who designed them. But I'm sure other people would like to personalize the look of their site a bit.

Today, let's talk about setting a custom page banner. That seems to be one of the first things most people change on their blog. Plus it's fairly easy to do in LnBlog and doesn't require a great deal of HTML or CSS knowledge. So let's get started!

For this exercise, you'll need two things. The first is a banner image. It can be anything you want, so long as a web browser can display it and it's a suitable size. Since I'll be assuming you use the default LnBlog theme, which is not fixed-width, I'd recommend a JPEG image that's at least 1024 pixels wide and around 160 pixels high. For illustrative purposes, I'll use this picture of the hills. If you have a moderately high resolution digital camera, you can probably take a decent picture yourself and use the GIMP or some other image editor to cut out an appropriately sized image.

The second thing you'll need is a copy of your banner style sheet to work on. This one is easy: just go into your LnBlog/themes folder, find the directory for your theme, and copy the styles/banner.css file to someplace on your local hard drive so that you can edit it.

Now that we've got a stylesheet and an image, setting the banner background is easy. Just open up your copy of the banner.css file, find the #banner section, and change it so it looks like this: #banner { width: 100%; border: 1px solid black; background-image: url(../images/horizon.jpg); background-repeat: no-repeat; max-width: 1281px; max-height: 160px; } This gives us a banner box with a thin border and our horizon image as the background. Note that the max-width and max-height are set to the width and height of the image. This keeps the box from expanding to larger than the size of the picture and looking funny.

As long as we're in the style sheet, we might as well consider the text. Let's say, for the sake of argument, that you wanted to change the alignment of the default banner text. Let's say you want to put the blog name on the left side of the banner and the description on the right. Well, in that case, you would look for the #banner h1 style for the name and the #banner h3 style for the description. If you look just below the section we just modified, you'll see something like this: #banner h1, #banner h2, #banner h3 { text-align: center; vertical-align: middle; color: white; } This sets the default style for the first three levels of heading. We can override the alignment by simply creating additional styles below that section, because in CSS, styles later in the file take precedence over earlier ones. So, let's add the following: #banner h1 { text-align: left; margin-left: 10%; } #banner h3 { text-align: right; font-style: italic; margin-right: 10%; } This gives us a left-aligned heading, and a right-aligned, italicized description. (If you don't see a blog description, you can turn it on in the plugin configuration page, under the "pageheader" plugin option.) Note the margins are set so that the text doesn't bump up against the edge of the banner.

So at this point, we have our image and our stylesheet. Now what? Well, we install them on the server, of course! But where to put them?

This is where the flexibility of LnBlog's theme system come in. You see, we actually have several options. First, we can always put them in our theme directory, overwriting the old style sheet. The second possibility is creating a new theme. The third is applying this only to a single blog. Changing the files for the default themes isn't really recommended, so we'll stick to the second and third options.

Creating a new theme, especially one this simple, is quite easy. Just go into your LnBlog/themes directory and create a new folder with whatever name you want the theme to have. Then, inside that folder, create four more folders with the following names: images, styles, scripts, and templates. Now copy your banner image into the images directory you just made and put the banner.css file in the styles directory. Now, if you edit your blog setting and change the theme to the one you just created, you should see your new banner.

The process for applying your custom banner to a single weblog is very similar. You would simply open up the directory for that weblog and create an images directory and a styles directory. Copy your image and style sheet to the corresponding directories and the changes will automatically take effect for that blog.

By now, you've probalby noticed the pattern here. When constructing a page to send to the client web browser, LnBlog uses a search path mechanism to find files. There are four kinds of files: images, styles, scripts, and templates. LnBlog looks for each type of file in a directory of the same name, located in the current blog's folder, the current theme's folder, or the default theme's folder. The search takes place in that order, so if you don't have a particular file in your blog or in your theme, the default will always be there. The idea is to make it easy to create small variations on existing themes. The down side, of course, is that it's somewhat more difficult to create custom themes from scratch. But, then again, given that you have to get all the template variable right in order for things to work, it's usually easier to just start from an existing theme anyway.

Next time, we'll talk about templates and how the enevt-driven plugin system interacts with them.

LnBlog 0.6.5 "No need for config.php"

Well, I've finally done my lst-minute cleanup and my highly irresponsible testing, resulting in LnBlog 0.6.5 now being available for download. You can grab the ZIP archive here, or get the documentation, checksums, and all that good stuff from the download page.

Before I list the changes, I'd like to thank MoonMind for providing lots of feedback and bug reports.. Thanks also to Ben Schorr for the bug reports. Improving software is always easier when you get helpful feedback.

There are a number of noteworthy changes in this release. First, it is important to note that the config.php file format has changed. This means that you must upgrade your blogs immediately after uploading the new version. To do this, login to your LnBlog administration page, enter the path of the blog (the same one you gave when you created it) in the "upgrade to current version" box, and click the upgrade button. You must do this for each blog you have.

The reason for this change is to facilitate changing the LnBlog installation path/URL and the blog URL. In older versions, these paths and URLs were stored in the config.php file in each directory. However, since these paths were computed automatically, there was no easy way to change them. Now, the config.php files simply include a pathconfig.php file which is located in the blog root. The blog root is calculated at run-time based on the type of directory, i.e. how far it is from the blog root. This allows you to more easily adjust these paths and URLs. Of course, most users won't need to do this, but for those who do, it is now easy. There's even a graphical interface for it. You can find the link on the weblog settings page.

The other noticable changes have to do with plugins. The new version of DisableComments is standard in this release. This version includes a feature to automatically disable comments and trackbacks on posts more than a certain number of days old.

I've also added two new plugins. The first, which is disabled by default, is the PrivateBlog plugin. When loaded, this allows you to set a list of users who are allowed to read the blog. Any user who is not on this list (and can't post to the blog) will simply be redirected to the blog login page. Not an idea solution, but it's more of a proof of concept than anything else.

The second new plugin is ContentBan. This plugin allows you to create files which contain lists of regular expressions to ban. You simply specify the regular expressions, one per line and complete with delimiters and options (using PHP's PCRE syntax), and any comment or trackback that matches one of those expressions in any of its fields will be refused. Of course, you should use this with care, as it is easy to be overzealous in your banning. Also, an ill-formed regular expression can cause errors that prevent anyone from posting.

Lastly, there's also a small interface change. I thought the administration sidebar panel was getting crowded, so I created a new event for sidebar plugins to capture. There is now a separate sidebar panel for plugin configuration and configuration links generated by plugins. Hopefully, that will make things slightly cleaner.

That's pretty much it for the interesting changes. The rest are mostly small bug fixes and expanded documentation. See the change log for full details. As usual, if you find any problems, please e-mail me or leave a comment.

Small fix to 0.6.4

Looks like I neglected to remove a line of debugging code from the newblog.php page in version 0.6.4. This causes the redirect after creating the blog to fail, so you never get sent to your new blog. The fix is just to remove the echo statement on line 107 of newblog.php. Or you can just download the fixed file here and extract it to the root of your LnBlog folder, overwriting the old version.

Figuring out my comment spam

So I come home after a rotten day, feeling really down, and what do I find in my inbox? Twenty-four (yes, that's 24) e-mail notifications for comments on my blogs: all of them spam. Damned degenerate scumbags. I guess it's time to get serious about implementing a content filter, because these sub-human wastes of perfectly good carbon atoms just won't leave me alone. And I'm getting tired of deleting comments and trackbacks by these walking piles of monkey excrement, so my only choice is to get pro-active.

The thing that really pisses me off about today's hit and run is that it isn't even commercial spam. Oh, I hate the assholes who leave that too, but at least I can understand it. Deleting links to online gambling and loan refinancing sites is unpleasant, but at least the act of posting such links on blogs makes sense: more links = better Google ranking = more money. They're still slightly below flesh-eating bacteria on the scale of human worth, but at least their actions aren't completely incomprehensible.

Today's round of comment spam, however, is different. This isn't the first time I've suffered this type of attack, but it is the first time I ever stopped to analyze it. You see, there were two distinct types of comment. The first makes absolutely no sense to me. It is simple something@skepticats.com posted as the name, subject, and body of the comment. That's it. No links or anything. Just an invalid e-mail address at my domain. Does anybody have any clue what the purpose of such a comment could be? Does it have something to do with gaming e-mail harvesters? That's pretty much all I could think of.

The second type of message is significantly more complicated. Like the previous message type, it contains a random e-mail address at my domain in the subject and body of the comment. However, for the name field, it contains some variation on the following text:
to
Content-Type: multipart/alternative; boundary=912124b723a23f3d33ad518075fc69e8
MIME-Version: 1.0
Subject: carelessly. s no one in the hut, no
bcc: real_address_removed@aol.com

This is a multi-part message in MIME format.

--912124b723a23f3d33ad518075fc69e8
Content-Type: text/plain; charset="us-ascii"
MIME-Version: 1.0
Content-Transfer-Encoding: 7bit

strove to compete with the steam packet, the dark smoke from which, like some demon, partly rested upon the vessel, partly
--912124b723a23f3d33ad518075fc69e8--

.
I actually had to look at the raw data files on my server to figure out that this was going in the name field. On the comments page, most of it actually showed up in the body. This seems to be because the comment class expects every field except the body to be one line, because that's the only way to enter it on the form.

I could be wrong, but this appears to be an attempt to piggyback on the comment notification system. Apparently the idea is that by injecting mail headers directly into the name field, they can fool the mailer into thinking they're real headers and sending a copy of the message to the address in the BCC line. Fortunately, it doesn't appear to work. However, I'm still concerned that there's no actual commercial content in the messages. They appear to be just text snippets taken at random from a story of some type. Why would anyone want to send that? Is somebody just using this as a test? What on earth is going on with these messages?

DisableComments 0.2.0

Just as a change of pace, I'm releasing a new version of a standard plugin. Actually, I'm doing it because the comment and trackback spam is starting to bug me (it's been picking up again lately), so I figured I'd adjust one of the plugins to get rid of it. And since I'm not planning a new release any time soon (unless I get some bug reports), I figured I'd just release it separately.

You can download the DisableComments plugin version 0.2.0 here. To install, just extract the PHP file from the ZIP archive and copy it into your LnBlog/plugins folder, overwriting the old version. This version adds an option to automatically disable comments and trackbacks on entries older than a certain number of days. To enable the new feature, just go the the plugin's configuration page and enter a number in the text box. That'll stop the trackback spam on entries that are a year old!

LnBlog 0.6.4 released

Time for yet another maintenance release. LnBlog 0.6.4 is now available. This release includes a critical security fix for users who have AUTH_USE_SESSION set to false. If that's you, consider this a required upgrade. Users who are using the default authentication configuration are not affected by this bug.

In other news, this release also fixes several minor bugs and annoyances. For starters, the broken "back to plugin list" links in the plugin configuration now works. I've also removed the broken default code when the pageheader plugin is disabled and fixed the trailing newline bug in LBCode that's been annoying me for some time.

By way of small "features," I added a warning when trying to create a blog in your LnBlog installation directory, because that just won't work. I also added a little feature to the LBCode URL auto-translation to allow absolutizing to the blog root. Previously, any URL given in a url or img tag that didn't contain slashes had the URL of the entry it was stored in prepended to it, so that it would display correctly on the front page or in RSS feeds. Now, however, you give links relative to the blog root by including a slash in them and links relative to the root of your site by starting them with a slash. So, for example, when I post a link to the LnBlog download page in this blog, I can give content/download/, whereas if I want to link to my computing blog, I can give /linlog/. Just a little extra convenience.

As usual, you can grab the new archive here or go to the download page itself and grab the signature, checksums, and documentation. If you find any problems or have any questions, you can e-mail me or post a comment.

LnBlog 0.6.3 is up

Well, I finally got around to uploading the next maintenance release. You can grab the archive here or get all the associated goodies from the download page.

This release fixes the previously mentioned sitemap problem, sorts blacklisted IP addresses for easier management, and adds out of the box support for running from /home/user/public_html (which it could do before, but required setting a configuration regex). The one big "feature" is a redesign of the ever-so-crappy plugin loading configuration page. Now, instead of three crappy text areas, it uses a table with text boxes to enter the load order and check boxes to disable loading a file.

As usual, please e-mail me or leave a comment if you have any problems or questions.

Sitemap error

It turns out there's a bug in the script used to set the custom sitemap. The file name was not being set correctly, so changes never showed up on the page. I'll fix this in the next release, but here's a quick fix to use in the mean time. Just save this in the LnBlog root directory as "sitemap.php", overwriting the old file.