Clone or download

  • Download the latest version as a ZIP or tarball
  • Clone with: git clone https://elmord.org/code/blognir


A very simple blog system in PHP

Version 1.3, May 2016.

What is this?

Blognir is a very simple, no-frills, databaseless blog system written in PHP. It supports roughly the minimum you can expect from a blog system, and not much more. I wrote Blognir so that I could host a blog at my university home page, and so that I could compose posts with a plain text editor and post them by just dropping the file in a folder. I maintain it primarily for my personal use, but you might find it useful. (The code is simple enough that you can easily adapt it to your own needs if you wish.)

Blognir is free software under the GNU General Public License, version 2 or later. See COPYING for details.

What can it do?

Features include:

  • comments;
  • tags;
  • RSS feeds for posts and comments;
  • an access log (in case you don't have access to the webserver's log);
  • a very crude anti-spam mechanism (which has been catching spambots every day for a long time, but it only works because my blog is too uninteresting and the method too uncommon to write a spambot specifically to target it; it has been inspired by http://yosefk.com/human.html);
  • the ability to control whether comments are allowed for individual posts;
  • comment counts in the "Comments" links;
  • posts-with-a-tag counts in the "tag cloud";
  • a "duplicate comment" checker;
  • password-protected posts;


Blognir is composed of four main files:

blognir.php     The blog engine
template.php    Most of the HTML generation
index.php       Configuration and starting point of the system
messages.*.php  Messages in various languages

Currently, the "configuration" is pretty "low-level": it consists of including a message file, instantiating a new Blog object, initializing its properties to the appropriate values, and calling $blog->main() to handle an HTTP request. You should be able to change all the "configurations" from index.php.

One of the first lines of index.php is something like

$blog = new Blog(".data");

Here, ".data" is the data directory of the blog: it's where Blognir will look for post and comment files and keep its index. You should make sure that the content of this directory is not reachable through links in your site (e.g., through directory listing); otherwise, search engines will index your plain post files together with the actual blog entries. One way to avoid this is to put an index.html file in the data directory.

Inside the data directory, Blognir expects to find the following files and subdirectories:

entries/          The files with posts

comments/         Where comment files will be put

recent-comments/  Where a copy of the most recent comments will be kept
                  (for RSS generation) [these should really be symlinks to
                  the comment files, but Suhosin disables the symlink()
                  function in PHP]

.htpass           A file containing the MD5 sum of the "magnific password",
                  i.e., the password used to post comments as author of the

.htlog            The access log; Blognir will create this file if it does
                 not exist (assuming it has permission to do so)

entryidx.*       The index. Blognir will create these files if they don't

The exact pathnames can be changed in the configuration file, e.g.,

$blog->entries_dir = ".data/posts";
$blog->log_file = NULL;  // Disable logging

Make sure Blognir has write permission to comments/, recent-comments/, .htlog and entryidx.*.

How do I post an entry?

To post something to the blog:

  1. Write a file with the following format

    Title: <the title of your post>
    Created: <the date of creation, in a format strtotime() recognizes
              (e.g., 2013-04-23 07:33 -0300; you can omit time if you wish)>
    Tags: <list of tags separated by ", " (i.e., one comma and one space)>
    <blank line>
    <the content of your post, as HTML>

    For example:

    Title: My first post
    Created: 2013-04-23 07:33 -0300
    Tags: about, life
    <P>This is my first post with Blognir!
    <P>I'm full of it already.

An optional header in the post file is "Allow-comments: no", to disable comments for this post, and "Allow-comments: no-more", to disable further comments but still show comments that have already been posted.

  1. Save it in the entries directory. Note that posts are ordered by their file name (in reverse order), so you should add some prefix indicating order (e.g., 20130423-my-first-post). This name will become the entry's id (i.e., the entry URL will be http://your_blog/?entry=20130423-my-first-post).

  2. Rebuild the index by accessing http://your_blog/?build_index=t. [In the future, this might be changed to require the .htpass password, so as to impede an attacker to keep rebuilding the index.] Alternatively, you can simply delete the entryidx.* files, so that the blog will rebuild them the next time it is accessed.

    You might configure your text editor to do this automatically when you save something under the entries folder. For example, if your blog entries are under /home/user/html/blog/.data/entries (perhaps as a sshfs mount point), you could add this to your ~/.vimrc:

    autocmd BufWrite /home/user/html/blog/.data/entries/*
    \   call UpdateIndex("/home/user/html/blog/local_html/blog/.data")
    function UpdateIndex(path)
        call delete(a:path . "/entryidx.entries")
        call delete(a:path . "/entryidx.tagcount")

How do I manage comments?

Comments live in the comments/<entry_id>/ directories. The comment files have a format very similar to the blog entry files.

To post an "author comment", access the post page in "magnific mode", by adding &magnific=t to the end of the URL. In the comment form, a new field will be present, where you can type the "magnific password" required to post a comment as author. The comment will show up with a star beside the comment author.

To check for new comments, subscribe to your comment feed. Alternatively, write a script to check the recent-comments/ directory for new files.

How do I set up the magnific password?

Compute your password's MD5 sum and write it to the .htpass file. For example:

echo -n "most_secret_password" | md5sum - | cut -d' ' -f 1 >.data/.htpass

When you use the password (e.g., to post author comments), you should access the blog via HTTPS if possible. In any case, it is best NOT to use the same password you use for more serious things, in case it is seen by someone.

How do I create a password-protected post?

Add to your post a header Password: some-password. You can also optionally add a header Password-message: some-html, which specifies some text to be presented to the reader before the password form. Note that the message should go all in a single line (but it can be arbitrary HTML, so you are free to use multiple <P>s and <BR>s in a single line).

What are the plans for the future?

At some unknown point in the future, I may or may not add the following features:

  • An "Undo comment" feature in the "comment saved" page (as people often spot errors in their comments just after they post them);
  • Basic HTML tags in comments;
  • A "recent comments" feature in the sidebar;
  • ~~Internationalization (i.e., messages in their own file rather than scattered through the blog);~~ [done in 1.1]
  • Better isolation between the template and the rest of the blog;
  • Separation of the comments module into its own thing, usable without the rest of the blog;
  • Perhaps a way to submit new posts via HTTP(S)?
  • Who knows?

That's it

For more information, consult your pineal gland.