Theme choice (Twenty Fifteen, for now) and my threat model for the blog

I’m trying to stick with Twenty Fifteen for now. I would guess using the default theme would serve the “trying not to stand out” ethos best, but don’t take my word for it. Indeed, don’t take my word for anything, because this is a log of learning as I go.

Also, I’m not sure how well “not standing out” on the publishing end fits within the threat model. Certainly my threat model for this blog does not account for its hosting service. My baseline assumption here is a benevolent, not critically anonymity-savvy host (myself). I should also take into account the provider of my underlying infrastructure, whose benevolence I trust slightly less than my own.

But as I said, this is a learning log, not an attempt to simulate anonymous publishing. Additionally I’m using this blog to get a feel for the difficulties in blogging when using an anonymizing service and a browser tuned for it. Like how I keep forgetting to save these drafts now that auto-save doesn’t work.

Search Everything and no search results in Posts > Edit

I had this weird problem with WordPress searches: in one of my blogs I couldn’t get any search results in the Edit Posts listing. Not even a simple search for the letter ‘a’ would yield anything. I tracked the cause down to the Search Everything plugin, and then began comparing what was different between the problematic blog and one that didn’t have this problem. Here’s where it got weird: there were no differences. The other blog is for testing only, so I could set it identical to the one with the problem, and still the searches worked consistently in the testing blog while in the other one they didn’t.

I tried unsetting Search Everything’s options and the searches began to work in the problematic blog too. So I tried setting them back on one by one… until I had them all as they had initially been, and the searches still worked!

There must have been some kind of a screw-up with the plugin’s settings, perhaps brought on by an upgrade.

How to separate every other comment within a wp_list_comments callback function

Just upgraded one of my themes (the only one I’m still using that I can truly say I’ve created myself) to finally utilize WordPress 2.7’s new comment listing function. This made separating actual comments from pings a breeze compared to what it used to be.

The only slight problem was with porting the old separation of every other comment with a different class; since I needed to use a custom callback to retain the old look, I couldn’t utilize the automated classification done by wp_list_comments(). In the end all it took was these three lines added to my callback function:

global $comment_alt;
$oddcomment = $comment_alt % 2 ? 'alt' : '';
$comment_alt++;

With these in place I could now bring in the <li> tag from the old template without any further tweaking:

<li id="comment-<?php comment_ID() ?>"
class="<?php echo $oddcomment?>">

Victims of Akismet's false positives shouldn't be left in the cold

Every now and then Akismet falsely identifies an innocent comment as spam. From the commenter’s perspective this results in their comment vanishing into thin air. In reality that’s not the case, as the comment can be recovered from Akismet’s queue, but there’s no way for the commenter to know this. I’m a little uneasy with the idea of my commenters left thinking their contribution has gone to waste, so I’d like to give them a hint of what has happened. Additionally, I could provide them with an email link, prompting them to contact me about the misidentification so I can fix it.

The trouble is, once a comment is marked spam by Akismet, there’s apparently no way to react to it in the comments template, as there is to comments ending up in the traditional moderation system. The code fetching the comments for the comments template is in the comments_template() function at comment-template.php. There’s a comment marked ‘@todo’ to use API instead of SELECTs, followed by three queries. I suspect the todo refers to the fact that as it is, there’s no way to tap into those queries short from editing them directly by hacking the file. Some people, myself included, would rather not do that because of the way it inconveniences upgrades.

Until a clean way to tap into the way comments are fetched, or better yet, the functionality I’m after being integrated directly into Akismet, I guess I’ll have to do with a big sign saying if your comment seems to have vanished, read this. Then I’ll link it to a page explaining how to contact me about the misidentification, and show it to every commenter beside the comment form. It’s ugly, but still better than giving them the impression my comment box is just a big black hole.

The Pain of WordPress: "You do not have sufficient permissions to access this page" when trying to upgrade

I searched far and wide for a working solution for this, and in the end had to cook one up myself. For a short description of the issue, every time I tried to use the new (and otherwise higly cool) one-click upgrade feature in one of my blogs, I was greeted with the blunt response of “You do not have sufficient permissions to access this page.” This was made all the more curious by the fact that simultaneously upgrades of plugins did work in very the same blog.

Now, I know how to google and this issue seems alarmingly widespread. Luckily there are also quite a few solutions, but unfortunately, as I said, none of them worked for me. Anyway, here’s a list of the solutions othes have found useful, just in case:

In addition, I tried changing the permissions of wp-content and subfolders, clearing my cookies and cache, logging in and out, reloading and so on — all to no avail. When all of these failed, I began to compare the database tables between my other blogs, in which the upgrade worked smoothly, and the one in which it didn’t.

I first discovered that prefix_options had two options called fileupload_realpath and fileupload_url. In my other, working blog they referred to the correct upload path on my webserver. In the broken one they were at default, example values which of course were flawed. So I fixed the paths thinking I’d found the culprit, but not so: the issue remained. However, this fix probably didn’t hurt either, as the upgrades probably use the ‘upgrade’ subdirectory inside the upload path.

The solution

Then I found that the values of prefix_user_roles in prefix_options differed between the working blogs and the one that didn’t, but didn’t differ among the working ones. So, without any idea of the values’ syntax I simply copied the value from one of the working blogs’ tables and pasted it onto the broken one’s. And that did it: the upgrade now works as intended. Yay!

Just in case someone with only a single blog has this issue, I’ll paste the actual contents of my working prefix_user_roles below. It shouldn’t have anything too unportable, as the value is probably a default set by the installation of one of my more recent blogs.

Note that the newlines in weird-looking places are apparently either part of the syntax, or ignored completely, so copying and pasting the value below should work. Unless WordPress — the installation I’m publishing this post in — somehow screws it up. The browser will break the lines when viewed on this page, but it shouldn’t affect selecting and copying, as it’s only part of the visible rendering.

a:5:{s:13:"administrator";a:2:{s:4:"name";s:13:"Administrator";s:12:"capabilities";a:53:{s:13:"switch_themes";b:1;s:11:"edit_themes";b:1;s:16:"activate_plugins";b:1;s:12:"edit_plugins";b:1;s:10:"edit_users";b:1;s:10:"edit_files";b:1;s:14:"manage_options";b:1;s:17:"moderate_comments";b:1;s:17:"manage_categories";b:1;s:12:"manage_links";b:1;s:12:"upload_files";b:1;s:6:"import";b:1;s:15:"unfiltered_html";b:1;s:10:"edit_posts";b:1;s:17:"edit_others_posts";b:1;s:20:"edit_published_posts";b:1;s:13:"publish_posts";b:1;s:10:"edit_pages";b:1;s:4:"read";b:1;s:8:"level_10";b:1;s:7:"level_9";b:1;s:7:"level_8";b:1;s:7:"level_7";b:1;s:7:"level_6";b:1;s:7:"level_5";b:1;s:7:"level_4";b:1;s:7:"level_3";b:1;s:7:"level_2";b:1;s:7:"level_1";b:1;s:7:"level_0";b:1;s:17:"edit_others_pages";b:1;s:20:"edit_published_pages";b:1;s:13:"publish_pages";b:1;s:12:"delete_pages";b:1;s:19:"delete_others_pages";b:1;s:22:"delete_published_pages";b:1;s:12:"delete_posts";b:1;s:19:"delete_others_posts";b:1;s:22:"delete_published_posts";b:1;s:20:"delete_private_posts";b:1;s:18:"edit_private_posts";b:1;s:18:"read_private_posts";b:1;s:20:"delete_private_pages";b:1;s:18:"edit_private_pages";b:1;s:18:"read_private_pages";b:1;s:12:"delete_users";b:1;s:12:"create_users";b:1;s:17:"unfiltered_upload";b:1;s:14:"edit_dashboard";b:1;s:14:"update_plugins";b:1;s:14:"delete_plugins";b:1;s:15:"install_plugins";b:1;s:13:"update_themes";b:1;}}s:6:"editor";a:2:{s:4:"name";s:6:"Editor";s:12:"capabilities";a:34:{s:17:"moderate_comments";b:1;s:17:"manage_categories";b:1;s:12:"manage_links";b:1;s:12:"upload_files";b:1;s:15:"unfiltered_html";b:1;s:10:"edit_posts";b:1;s:17:"edit_others_posts";b:1;s:20:"edit_published_posts";b:1;s:13:"publish_posts";b:1;s:10:"edit_pages";b:1;s:4:"read";b:1;s:7:"level_7";b:1;s:7:"level_6";b:1;s:7:"level_5";b:1;s:7:"level_4";b:1;s:7:"level_3";b:1;s:7:"level_2";b:1;s:7:"level_1";b:1;s:7:"level_0";b:1;s:17:"edit_others_pages";b:1;s:20:"edit_published_pages";b:1;s:13:"publish_pages";b:1;s:12:"delete_pages";b:1;s:19:"delete_others_pages";b:1;s:22:"delete_published_pages";b:1;s:12:"delete_posts";b:1;s:19:"delete_others_posts";b:1;s:22:"delete_published_posts";b:1;s:20:"delete_private_posts";b:1;s:18:"edit_private_posts";b:1;s:18:"read_private_posts";b:1;s:20:"delete_private_pages";b:1;s:18:"edit_private_pages";b:1;s:18:"read_private_pages";b:1;}}s:6:"author";a:2:{s:4:"name";s:6:"Author";s:12:"capabilities";a:10:{s:12:"upload_files";b:1;s:10:"edit_posts";b:1;s:20:"edit_published_posts";b:1;s:13:"publish_posts";b:1;s:4:"read";b:1;s:7:"level_2";b:1;s:7:"level_1";b:1;s:7:"level_0";b:1;s:12:"delete_posts";b:1;s:22:"delete_published_posts";b:1;}}s:11:"contributor";a:2:{s:4:"name";s:11:"Contributor";s:12:"capabilities";a:5:{s:10:"edit_posts";b:1;s:4:"read";b:1;s:7:"level_1";b:1;s:7:"level_0";b:1;s:12:"delete_posts";b:1;}}s:10:"subscriber";a:2:{s:4:"name";s:10:"Subscriber";s:12:"capabilities";a:2:{s:4:"read";b:1;s:7:"level_0";b:1;}}}

WordPress and wrong $numposts?

After a fresh WordPress installation, I was dumbfounded for a while when a simple “global $numposts; echo $numposts;” would always print N+1 despite the total number of posts actually being N. Turns out I had forgot to delete the initial “About” page, which obviously isn’t listed among the posts, but among pages, yet gets included when $numposts is calculated.

Old news, but news to me: WordPress security key definitions in wp-config.php

While investigating an entirely separate issue with one of my WordPress installations, I came across this:

“Beginning with WordPress Version 2.6, three (3) security keys, AUTH_KEY, SECURE_AUTH_KEY, and LOGGED_IN_KEY, are used to insure better encryption of information stored in the user’s cookies. Beginning with Version 2.7 a fourth key, NONCE_KEY, was added to this group.

If you don’t find the keys in your wp-config.php file, add the keys definitions with reference to Editing wp-config.php – Security Keys, and upload to your server.”

Step 13: Add security key definitions to the wp-config.php file
WP Codex

Since most of my WordPress installations are pretty ancient, and upgrading them has long since become a routine job, this was the first time I heard about this feature. So my blogs have been lacking in this security feature, until now (I set up the aforementioned keys in each of my wp-config.php files).

Some notes about podcasting in WordPress

  • Theoretically, publishing a podcast feed in WordPress should take nothing more than a link to the episode file, using an absolute URL. This should prompt WordPress to generate the appropriate enclosure tag in the feed.
  • However, WordPress generates the enclosure only upon initial generation of a post, not on subsequent edits. So if the podcast URL is added after the entry is created, during an edit, the enclosure isn’t generated.
  • For some reason, WordPress doesn’t generate the enclosure for me even when I post the link straight up. It doesn’t do so either, when I use the ‘Add media’ function, although I’m not sure if it’s even supposed to.
  • Luckily, it’s possible to hand-craft the enclosure for a post for which no enclosure has been created. Though laborious, it works. The “enclosure” field’s value should consist of three lines:
    • Full URL to the file
    • Length of the file in bytes
    • Content-Type of the file (like “audio/x-vorbis+ogg”)