We're making progress

I just wanted to post a quick update here because I'm actually very pleased with how LnBlog has been evolving lately.  As you may have noticed from the changes in the last few releases, this "my first PHP project" is actually turning into a real application.  In addition to having a bunch of features, I've squashed a bunch bugs, added some security, and implemented some more manageability features.

One of the things that I'm most pleased about, however, is that I've finally gotten around to some UI improvements.  Nothing radical, but just some stuff that makes my life easier.  One of the more recent ones is revamping the file upload interface.  Here's what it looks like at the moment.

The current LnBlog file upload and management interface

There are several new things here.  Starting at the bottom is the upload box, which uses Dropzone.  This isn't actually new, but I did add a handy feature to it: paste to upload.  So if you just click someplace outsize the edit box and paste some image data, the file will start to upload and appear in the Dropzone area.  Not a huge thing, but a handy feature that  cuts out a few steps when you just want to upload a screenshot or something.

Above that, you see the revamped file management interface.  For a long time, LnBlog didn't have any file management interface.  You just had to know what files you'd uploaded.  (No, I'm not kidding about that.)  Then I added the bare minimum: a list of files and a "delete" link.  It stayed like that for a long time.  Now, the name is actually a link you can click to open the file (you know, something actually useful) and there are up to four controls next to it. 

  1. First, the little "x" is the delete link.  That's pretty self-explanatory.
  2. Then there's the "add link" icon, which inserts a hyperlink to the file at the current cursor location in the editor.  Crazy, right? 
  3. After that is the "insert image" link, which does the same thing, but it only shows up for images and inserts an IMG tag instead of a hyperlink.  An interesting feature of this is that if an image has a "full sized" version and a "scaled down" version, then clicking this for the scaled down version will insert that image and make it a link to the full version.  So just that's a handy way to speed up a common workflow. 
  4. And last is a control that generates "scaled down" versions of images.  It's very simple and just supports four pre-defined sizes.  And, of course, this only shows up for images.

Clearly this is not revolutionary stuff.  However, I find that it actually makes a big difference.  Consider the amount of friction involved in the workflow for adding the above screenshot to this post:

  1. I grab a screenshot of the area using Greenshot and copy it to the clipboard.  (4 clicks)
  2. I click on the post editor page and press ctrl+V to paste the image.  (1 click, 2 keystrokes)
  3. After the image uploads, I click the "scale down image" link and select "medium" to get the 800x600 (max) version.  (2 clicks)
  4. When the scaled down version is created, I click the "insert image" link to insert the image with a link to the full-sized version.  (1 click)

Compare that to the old workflow.  Keep in mind that this is what I actually had to do, which is part of the reason I didn't post a lot of pictures in the past:

  1. Grab the screenshot, but save it to a file. (5 clicks, plus as many keystrokes as the filename takes)
  2. Use the "Convert Images" tool in Directory Opus to scale down the image to the desired size.  (Before I started using Directory Opus, I actually opened the image up in The GIMP and rescaled it that way.  Ugh!)  (3+ clicks, depending on your defaults in Directory Opus)
  3. Upload both the original and scaled versions of the image to the entry.  (2 clicks in the Dropzone era, more in the bad old days)
  4. Manually add the image tag for the scaled version, either typing or copy-pasting the file name.  (2 clicks, plus keystrokes or clicks for the filename, more if not using TInyMCE)
  5. Manually add a link tag around that image, either typing or copy-pasting the file name of the full version.  (2 clicks, plus keystrokes or clicks for the filename, more if not using TinyMCE)

Granted, that's only one extra step, but the new workflow is two keystrokes and 8 mouse clicks - and half of those clicks are just acquiring the screenshot.  In the old workflow, we're looking at a minimum of 14 mouse clicks, plus potentially a dozen or more keystrokes, plus switching windows multiple times between scaling and file selection dialogs.  I mean, it's not that bad if you really want to put a picture in your post, but if you're just casually posting something and aren't really committed to having a picture, it can be enough to make you think, "Eh, I don't feel like bothering with that."

I've also done a lot of other UI cleanup recently.  I still have some work to do (for instance, the layout of the post editor could stand improving), but it's getting to the point where I'm actually fairly happy with the UI.  And to think, it only took 16 years.

LnBlog 2.2.0 - No Need to Start Over

It's here!  We have a new LnBlog release, not quite a year after the last one.  By current standards, that's fast and furious.

Anyway, this release actually has some new and interesting (at least to me) features.   You can grab a copy from the download page or the GitHub release page.    Note that this release will require an upgrade of any existing blogs.  Also note that this release changes the way URLs are calculated, so you'll need to visit the admin page to go through the initial setup again.  If your blogs don't show up after that, you may need to re-register them from the admin page.

Now, on to the changes in this version.  And there's actually quite a few of them - and some pretty substantial ones, too.  Not bad for one guy developing it on an extremely-part-time basis.  In fact, the app is starting to look and work fairly well, if I do say so myself.  But anyway, here's what you need to know:

  • First, I finally fixed the stupid, ugly layout of the various forms.  They now use a standard vertical layout rather than the old, uneven, "I'm too lazy to style this" one.  I know this doesn't sound like a big deal, and it really isn't (I mean, I did it in like an hour), but it's been a long-standing issue and it made the entire app look crappy.
  • Another small but noteworthy change, the "DisableComments" plugin is now configured to disable TrackBacks on all entries by default.  Related to this, disabling TrackBacks on an entry will now disable all TrackBack-related UI elements.  Of course, you can still change that setting in the plugin configuration, but I don't even remember the last time I saw mention of TrackBacks on a blog, so I figured it was time to turn that stuff off.
  • Now the big one - import from WordPress!  This feature allows you to take a WordPress extended RSS export file and import it into LnBlog.  You can either import the data into an existing blog, or create a new one based on the export file.  This is the first iteration, and it has some limitations, but it works.  The biggest limitations are that the import process will not import media items and it will not touch the contents of the posts - everything is treated as raw HTML, so you're on your own as far as any WordPress markup magic.  (Note that if you keep the media files for your WordPress installation at the old URL, they should still work.  Alternatively, you can set up a mapping on your web server or just edit the URLs in the export file before you do the import.)  However, the process will import pages as LnBlog articles, published posts, draft posts, comments, and pingbacks.  You also have the option to import user accounts for any username in the export that doesn't already exist in LnBlog.  The import will attempt to map the WordPress usernames to LnBlog usernames and default to the blog owner if the username can't be found.
  • Here's one you'll definitely notice - the addition of the Tag-It widget.  This is now used in a couple of places, but the most obvious is the entry editor.  So instead of the text-box with the ghetto JS drop-down for selecting tags, we have an actual decent-looking widget.
  • Another noticeable feature is an auto-scaler for uploaded images.  In the collapsible file list for the upload box, we now have a little icon next to images that you can click to auto-generate a scaled version.  There are only a few pre-set choices for size, but it's a convenient way to create thumbnails or scale down high-def pictures.
  • Now the under-the-hood changes.  First, blog data upgrades can now be done from the command line.  Just run php cli.php --upgrade to upgrade all your blogs in one shot, or supply a blog ID to do just one.
  • Second, third-party JavaScript libraries have moved from whatever random CDN I could find to local files.  These are collected and put in the "third-party" directory by the build process.  Part of the blog upgrade process now includes making sure each blog has a references to these files.  (By this, I just mean that the upgrade gets around cross-domain JS issues by copying or symlinking this directory into any blog that's on a different domain than the LnBlog directory.)
  • Lastly, and most importantly, I completely changed the way LnBlog tries to deal with path and URL mapping.  The old version used some hair-brained and convoluted rules to try to auto-detect what path mapped to what URL.  This was fine...when it worked.  The problem was that it didn't work often enough, and when it failed, the failures were opaque and hard to diagnose.  So instead of that, LnBlog now requires you to explicitly tell it what path and URL each blog will have.  It also requires you to explicitly tell it the path and URL of the LnBlog installation and your userdata folder.  Of course, the UI will present you with reasonable defaults that you can edit if desired.  For blogs, it will even update these when you change the blog ID you enter (note: the "blog ID" is just a string identifying the blog - usually, it's just the name of the blog's folder).  I know this is a little bit of a pain, in that it adds some extra boxes to think about, but it shouldn't be too bad.  And it makes the URL resolution much more reliable.
  • One last note: Because of the above change to the URL and directory mapping, LnBlog will now generate a pathconfig.php file inside the LnBlog install directory.  So when upgrading, you may have to copy this file to the new version.  (Yes, I know this violates the whole "put everything in userdata" rule I had, but since it now stores the path to userdata, that obviously wasn't going to work.)  This file now stores the paths and URLs to your LnBlog install, your userdata folder, and each of your blogs.  However, that's all it stores.  So this file is critical to LnBlog working, but if anything happens to this file, there's nothing in it that can't be recreated through the admin page UI.  Just delete the broken file, go to the admin page to regenerate the basics, and then re-register each of your blogs.

Here's the list of GitHub issues closed in this release:

  • Cannot edit URL of current blog (#14)
  • Better subdomain resolution (#15)
  • Auto sitemap broken for subdomains (#17)
  • RSS links shown when plugin disabled (#18)
  • Add tag widget (#19)
  • Include files for third-party JavaScript (#20)
  • Import from WordPress (#25)
  • Comment delete link broken (#26)
  • Auto-scale feature (#27)
  • Upgrade from command-line (#29)

Aren't I Web 2.0-y

I've been reworking the sidebar calendar plugin lately. It was kind of buggy and just didn't work as well as I would have hoped. In particular, using query strings to browse through the months just really sucked.

My solution to the bugginess was to rewrite a large chunk of it. It's much cleaner and more managable now.

My solution to query strings sucking was to get with this whole Web 2.0 thing and do it with AJAX. So now, rather than the whole page refreshing when you click the previous month link on the calendar, a JavaScript requests an update from the server and then updates the page in place. The down side of this is that the next and previous links don't work if you don't have JavaScript or are using an archaic browser. Of course, you can still use the archive links, so it's not like you can't get to the previous month's links.

I've installed the new calendar plugin on this site. I haven't made it available for download yet because it's still in progress and requires a couple of support files. However, it will be standard in the next version.

LnBlog 0.8.0, "No Need for TrackBack"

Well, it's finally here: LnBlog 0.8.0 is now available. You can grab it here or go to the download page.

Several files have been removed in this release, so to upgrade, you should upload the new directory to your server and then copy/move your old userdata folder into it. Before that, though, you might want to take a look at the new system.ini file, just to see what the new options are. That part is optional, though.

Lots of changes and lots of bug fixes in this release. I won't bore you with all (or even most) of the specifics. That's what the changelog is for. However, for this version, I did do some extra testing and even documented the outstanding problems in this release. Fortunately, most of them are relatively small.

There are bunches of new features. First, LnBlog now has support for Pingbacks. You can turn on and off both the sending and receiving of Pingbacks on a per-entry basis. Note that there is an AllowLocalPingback setting in the entryconfig section of the system.ini file. If you set this to 0, then LnBlog will not send Pingback pings to enrties on your

Second, there's a new standard plugin: the TrackbackValidator. Basically, this checks the URLs of incoming TrackBack pings to see if they link to your blog. This works on the principle that legitimate TrackBacks almost always link to you, but TrackBack spam almost never does. So far, it seems to have completely eliminated my TrackBack spam problem.

Third, there's now a standard profile.ini file. This adds a custom "contact me" link field for your profile. This field takes an HTML link as its input. If this is given, then your e-mail address will not be displayed in your profile. You can use this with the ContactForm plugin.

Fourth, LnBlog now has simple Podcast support. Basically, this means you can add an enclosure URL to your entries and it will be included as an RSS enclosure in the RSS 2.0 feed (if you have one). You can either enter the RSS attributes directly, specifying url="http://somehost/file" length="12345" type="audio/mpeg", or, if the file in on the same server as LnBlog, you can give the URL and let LnBlog compute the file size and MIME type. Note that you can also use LBCode-style relative URIs, giving only the name for files in the entry directory, or a path relative to the blog root.

Last, I've reworked the post editor, including a lot more JavaScript. I've condensed the LBCode editor buttons, added a drop-down menu to add topics, and hidden the extra settings in an expandable box. I think it's much easier to use now. Also note that there's an EditorOnBottom setting to the entryconfig section of the system.ini file. Although it's not acutally in the default file, the default value is 0, which puts the editor buttons above the text area. Add this setting with the value of 1 to put them below.

I think that pretty much sums up the big things for this release. As usual, all forms of feedback are welcome. If you have any comments, find any bugs, or whatever, feel free to leave a comment, e-mail me, or whatever.

New post editor

Here's a little sneak preview of the New post editorchanges I've made to the post editor for the next release. I've cleaned it up a little and added a fair amount of "unobtrusive JavaScript" for enhancements. Here's a screenshot of the basic view.

The default view is simpler than in previous releases. Notice the drop-down topic list so you no longer have to type in existing topics. The LBCode editor controls are also closer to the content area, so you can actually get to them. They also disappear when the markup type is something other than LBCode, so they're not in the way.

The rest of the post settings are available by expanding the lower panel. Here's the shapshot. Post settings panel Of course, the default configuration only has one upload box, but that can be changed in your system.ini. The new features to note here are, of course, the box to allow Pingbacks and the enclosure URL. If you're not familiar with RSS enclosures, they're basically the mechanism by which "Podcasting" is made possible. As with other URLs in LnBlog, you can specify a relative URL in this box.

So far, I think the new setup is pretty good. More functionality, fewer distractions, and just generally better. This interface will be available in the next 0.8.0 prerelease, which I'll be putting up some time this week.

Release preview

It's time for a preview release. We'll call this one LnBlog 0.8.0-pre1. I don't really want to call it a beta release, because that would imply that the feature set is at least close to finalized. I'm actually still not sure if I want to release after a little more testing or add a few more features and call it version 1.0.0.

Since this is a testing release, I of course recommend keeping a backup copy of the previous version around. No blog upgrades are required, so just upload the new version and rename it after your old installation. Note a few old plugins are now redundant and have been removed and a file has been added in the userdata folder, so I the recommended starting with the fresh installation directory and copying over your old userdata folder rather than trying to upload the new files into your existing directory.

This is going to be a major feature addition release. The big one in this release is support for sending and receiving Pingbacks. If you're not already aware, Pingbacks are very similar to TrackBacks, in that they are used to send a notification to another blog that you've linked to them. The main differences are that 1) Pingbacks are significantly more complicated to implement and 2) Pingbacks don't suffer from the same spam problems as TrackBacks, due to the fact that the server, rather than the client, determines what data goes into them.

The second bigish feature is support for enclosures. Basically, this means podcasting support. An enclosure is just a hint to an RSS reader that a post is related to a particular file so that it can be downloaded in the background. All you need to do is enter the URL of the file in the box and, provided it's on the same server, LnBlog will calculate the MIME type and file size to insert into the RSS feed. I also added a default profile.ini file that allows you to enter a "contact me" URL. Basically, you enter the HTML for the link you want and this will be displayed in your profile instead of your e-mail address. You can use that in ContactForm plugin.

There's a bunch of smaller stuff in this release too. Check the change log for the details. For starters, I did some cleanup to various plugins. For example, I added a "ban and delete" option to the IPBan plugin, added the "new standard" RSS icons to the sidebar, made the calendar look slightly less crappy, added a stylesheet to the RSS 2 feeds (so they look like something in a browser), and created RSS feeds for comments even when there are no comments yet.

There are also a number of small bug fixes. For example, TrackBacks finally work regardless of whether or not you have CURL. I also found a bug with receiving the response code when sending TrackBacks. I also fixed a few small display issues that were weird or didn't make sense.

Last, there's a bit of code cleanup and consolidation. For instance, the TrackbackNotifier and CommentNotifier plugins are now gone, replaced by a generic ReplyNotifier plugin that handles comments, TrackBacks, and Pingbacks. I also consolidated some functions in the utility library and a few things in the entry subclasses.

I'm debating whether to hold off on the next release, add some features, and go straight to version 1.0. Before that, I want to at least add a simple theme editor. My plan is to do something very simple and hacky: a stylesheet editor. Basically, just a GUI to automatically generate a stylesheet based on settings entered by the user. The idea is that this stylesheet will just be inserted into the page last, thus overriding the default settings for the theme.

Other possibile features include more granular security, support for draft entries, and Atom feeds, among other cleanup. If I'm going to go straight to version 1.0, then I'll probably try to do some of these first. Anyone have any thoughts on other features for 1.0 or opinions on the release schedule?

Notice the new search feature

Alert LnBlog uses who look at the sidebar may notice that the search section has changed. I've finally gotten around to writing a native search plugin. Yes, I finally got sick of waiting for Google to spider my site. It's pretty simple right now; it just searches for entries matching all search terms. It will also accept a regular expression if you enclose it in forward slashes. This will replace the Google search plugin as the standard search feature in the next release. The Google search plugin will still be included for anyone who wants it, but will be disabled in teh default configuration.

There is one interesting thing about the new plugin: it's the first plugin I've done that displays an entire page on its own. By that I mean that the sidebar panel and the search results page are both displayed by the plugin file, rather than using a separate page file for the search results. I still have a few bugs to work out of it, but if and when I get it sorted out, this plugin will provide a nice template for future self-contained plugins.

One problem down

Well, it looks like the new IP blacklisting plugin has solved my trackback spam problem. All the spam was coming from two or three subnets, so I just banned the entire subnet and I haven't had anything since.

In other news, I implemented a couple of fixes and features today. First, I fixed a problem with links to uploaded files being broken by the new pretty link feature. Second, I fixed that annoying problem where tags weren't preserved in the edit box when previewing an entry.

On the feature front, I added the ability to turn off trackbacks. For now, there's no seperate setting for it - it just follows the setting for comments. I also added a plugin that allows you to turn off trackbacks or comments for an entire blog. That should be nice for people like me who never actually get any legitimate trackbacks.

Anyway, I want to do some testing, but I think I'm pretty much done with this version in terms of features. Look for a new release before the end of the week.

Gack! More trackback spam!

Well, it looks like testing out the IP banning plugin for a few days was a good idea, because it didn't work quite as well as I'd have hoped. In other words, I'm still getting trackback spam.

I took an hour or so to rework the plugin. This time I decided to keep it nice and simple. I made sure to remove all extraneous whitespace, separate the per-blog and global IP lists, and did the check with a simple preg_match() call. This has the added benefit that I can now use the same code to ban an entire subnet just by including a star in the IP.

I think I should also include a setting to turn off trackbacks and/or comments altogether. I'll bet there are a lot of people who just don't feel like trying to keep up with the spammers. And at this point, I really can't say I blame them. My site isn't even that popular, and I've gotten nearly 50 trackback spams just since I implemented e-mail notification the other day.

Yay! Spam handling!

Well, now my spam problem is (partially) taken care of. Today I added trackbacks to the IP blacklisting plugin, added a plugin to send e-mail notifications for new trackback pings, and added an interface to delete trackback pings. After I burn them in for a few days, I'll put up a new release.

I would have liked to just release the plugins, but it turns out that isn't possible. You see, I haven't actually touched the trackback code since I first added it. As a result, the trackback class wasn't raising any events for plugins to hook into. In fact, the class didn't even have a delete method. So I had to add all of that. The good news is that now it's taken care of, so hopefully in the future I can just release plugins.

And here I was worried about comment spam

Sigh.... And here I had just finished an IP banning plugin for comment spam and I discover that I'm now getting trackback spam. Pornographic trackback spam, no less. And I didn't even bother to implement an interface for deleting trackbacks, much less blocking them. I guess I'll be doing that tomorrow. My apologies for the oversight.

So it looks like I've got another couple of plugins to implement before the next release. For one, I'll want e-mail notifications of trackbacks, so that I'll actually know when I get trackback spam. Second, I'll have to extend the comment banning to trackbacks. Third, I guess I'll have to start working on that keyword banning idea I was thinking of for comment spam.

Pretty URLs

LnBlog grew a new feature this week: pretty URLs. And it's about time, too. I never really worried too much about the URLs being largely numeric, but after a year of looking at my logs and my own links, trying to figure out what an entry was about, I've now changed my tune.

I think the solution I came up with is fairly simple. When an entry is created or edited, a PHP wrapper script will be created in the same directory as the entry. All the script will do is change to the entry directory and call the index.php file there. It will be named using the entry subject with all non-word characters (everything but numbers and letters) converted into underscores and a PHP suffix tacked onto the end. If this file exists, it will be used as the permalink for the entry. So, for example, the permalink for this entry will be http://www.skepticats.com/lnblog/entries/2006/01/Pretty_URLs.php. I'll probably make this configurable so that people can still use the old-style URLs (in part because I'm not sure how I should handle non-Latin subject text), but the new ones will be the default.

There are a two main benefits to doing it this way:

  1. There is no need for conversion. All the old URLs will continue to work.
  2. Permalinks will not break if you edit an entry's subject. A new script will be created using the correct subject text, and will be used as the permalink in the future, but the old one will continue to point to the same location.

I suppose I'll probably release the next version soon. I want to add a few other changes, including some more hooks into the way entries are displayed to make plugins easier to write. One thing I'd like to include in the next few releases is a comment spam plugin, although I haven't really needed one so far. I just need to lay the groundwork first.

Coming features

If you're exceptionally alert, you might have noticed that LnBlog has acquired a new feature: tags. Yes, you can now categorize your posts by topic. I've even added a sidebar plugin to allow readers to pull up all posts with a given tag. You can also view them as a single page, kind of like a sub-blog.

For anyone not familiar with the term "tag," tags are one of the hot things in "social software." They're basically just free-form categories. Rather than have some pre-defined list or hierarchy of categories, you just pick your category on the fly. If it's never been used before and is never used again, that's not a problem. If several categories seem appropriate, that's no problem either - just tag your item with all of them. It's a great way to communicate associations that might not fit any strict organizational model, but which could still be interesting to others.

However, that's not the reason I chose to add tags to LnBlog. The reason is that it was simply easy to implement. I figured it would be nice to have some sort of categorization system, but I didn't feel like writing an interface to add new categories. So I decided to just implement tags instead and do everything on the fly.

Working with tags in LnBlog is quite simple. When you create or edit an entry, there will be a text box to enter tags. You can enter anything you like in this box. If you want to tag the entry with multiple terms, just separate them with a comma. (Note: This can be changed with the TAG_SEPARATOR configuration constant.) So, for example, putting in "Linux,KDE,FreeDesktop.org" would tag an entry as being related to Linux, to KDE, and to FreeDesktop.org. When you search for any one of those tags, that post will show up. In addition, the blog itself will keep track of any tags you use and expose that list of tags for use by plugins. That's how the sidebar topics plugin works.

I'll probably have the next version with this feature up some time before Christmas. But first, I want to add another feature: a plugin loading configuration page. Basically, this will allow you to configure which plugins are loaded and set certain plugins to load first without having to mess around with moving or renaming the files. Currently, the interface for it isn't too pretty, but it's better than nothing. I'll polish it up in a future release.