Half-Elf on Tech

Thoughts From a Professional Lesbian

Author: Ipstenu (Mika Epstein)

  • Whose Responsibility Is It?

    Whose Responsibility Is It?

    When WordPress 4.0.1 came out, a small number of sites broke.

    For a while, we’ve been touting that minor releases to WordPress core, the ones we auto-upgrade for you, are very safe, very tested, and very important. While all this is true, it has brought a few people complaining to me that obviously I was wrong.

    It’s true that the 4.0.1 release broke people. It was an object lesson in why I tell people not to reinvent the wheel. But this upgrade situation does not mean the upgrades aren’t safe, secure or smart. It does bring thoughts to mind, like what my friend David talks about when he considers WordPress at the enterprise level. I know people who are using this failed upgrade scenario as a reason to tout that WordPress isn’t ready for big business, but I think they’re looking at it from the wrong perspective.

    Caution Minefield sign

    Let’s step back.

    I used to work for The Man. I’m well aware of the machinations you go through to upgrade anything at a massive enterprise. One of the things they do is a code review. Every single upgrade is checked and tested and a dry-run of the upgrade is run to ensure everything works the way they think it should. By allowing WordPress auto-upgrades, you remove that ability. For a massive corporation? I would turn off the auto-update.

    But at the same time, this mythical major company running WordPress would have at least one person who knew WordPress. They would have someone who’s job it was to review every single bit of code that went into their WordPress site. Each plugin would be checked, tested, evaluated for security, and only installed if that WordPress Checker said it was good. Because that’s exactly what you must do in any and all enterprise situations.

    David’s viewpoint is that the vetting of a site should be delegated.

    My gut reaction to say that they should know better has to be tempered with the fact that no, they should not have to. It’s the job of every site owner to vet their system, but to make a platform that is truly global, that vetting should be delegated. Web hosts and security analysts should vet code for collisions and bugs. Theme and plugin shops should ensure that their products adhere to best practices. Putting accountability for the full stack on each site owner is not only inefficient, but impractical. Inherent trust should exist that code in the official repository maintains a baseline level of code, trust that is eroded when the problems that occurred with a subset of sites on this update occur.

    And here, he and I disagree somewhat.

    It’s the job of everyone who uses software to be aware of what they’re doing. Vetting the software before it goes in to your system has to be someone’s job. WordPress core does an amazing job of this for you. WordPress core is safe. The 45k plugins and themes in the world don’t always meet the same level of robust checking. Which means when you introduce WordPress to your environment, you absolutely have to seriously review those third party odds and sods you want to use because they’re so shiny and cool.

    Web hosts vet code for collisions, sure. We do at DreamHost. That’s part of my and Mike’s jobs! We know what’s going into WordPress and if it’s going to blow things up at DreamHost for our customers. But like the site owner who found her site down one morning because we’d upgraded her from PHP 5.2 to 5.4 and it broke her WordPress 2.5 site, we cannot account for everything.

    I think there’s a need for security specialists to review plugins, in a public forum, and point out who’s not doing things in the best way. I also think that there’s a need for developers to remember there’s a reason why we do things a certain way, and while it’s fine not to, you have to keep in mind that it’s now your responsibility to keep a close eye on anything that changes in core that might cause your code not to work as well.

    For example. If I wrote a plugin that worked around the shortcode API for whatever reason, I would have a custom query on trac for any ticket related to Shortcodes and have it as an RSS feed to monitor. Or I might even subscribe to the trac firehose and use a filter to pull out anything that so much as mentioned the word. Because I’ve now made a change that I know might be a problem someday.

    Every business owner should know the risks of all the software they use, be it website or desktop. This responsibility is the cost of doing business. The size of the business and the importance of the software will change what resources you can afford to allocate to that part of your business, but you absolutely cannot ignore it.

    While I really want to say that because WordPress core does due diligence you don’t have to, I would be a lying liar who lies. Even if we do as David suggests and have everyone in the world making sure things are vetted and checked and stamped, it still requires the owners of a site listen to that information and not use the code that’s less optimal. Enforcing that would be impossible unless you wanted to suggest that WordPress outright deactivate code that doesn’t use the proper APIs. That would put a lot of weight on WordPress and slow it down and be pretty annoying for people who are legitimately using non-standard methods of development and implementation.

    No matter what, at the end of the day, the person who is responsible for the code quality is the person who wrote and maintains it. But the person responsible for their site is the person using the code. You have to know what code you’re putting into the site and be aware of the risks you’re introducing to your environment by doing so. If your website is your entire business, you cannot afford to be cavalier about these things.

    Disasters happen. Understanding the risks will prepare you for dealing with them when they do.

  • Switching The Main Blog on Multisite

    Switching The Main Blog on Multisite

    Previously I’d only ever posted this in my ebook, WordPress Multisite 110.

    What people mean by this is the site they originally set to be seen at domain.com is no longer the one they want to use, but the one at (say) domain.com/temp or temp.domain.com. If this is what you’re wanting to due, it’s not impossible, but it is annoying and a little tricky. If you’re using the trick to give WP it’s own directory, these are not the directions you’re looking for. I haven’t written those out yet.

    First you have to go to Network Dashboard > Sites and edit the site you want to be the main site.

    Example.com using two

    This you want to to look like this:

    Changing the subset two to no folder name

    Make certain you leave ‘Update siteurl and home as well’ checked! If you forget that, you’ll be sad. You no longer need to check the box (it’s gone in newer versions of WP), but if you DO have it, check it.

    Now you’d think you go to edit the main site and change it, but you can’t.

    Default main site is not editable

    By default, the main site is not editable. This makes sense when you think about how messy this might be, so in order to edit it you have to go to your wp-config.php file and look for this line:

    define('BLOG_ID_CURRENT_SITE', 1);

    Change it to the site ID you want to use as your main site. In this example, I want site , aka, two, to become my main site.

    define('BLOG_ID_CURRENT_SITE', 2);

    Save the file and then you have to go back to your Sites and edit the old main site.

    Main site can now be edited

    Give its path a new name and press save, making sure you keep that checkbox checked if it’s there.

    Change the original main site to new

    In this example, I’ve picked a new URL for my formerly main site becuase I don’t want any conflicts, but there’s nothing stopping me from picking ‘two’ again and just totally swapping things.

    The last step is to change your post content. Using a plugin like Velvet Blues Update URLs, you will need to search each site separately and replace the URLs. If you have wp-cli, you can do that too like this:

    wp search-replace 'example.com' 'example.com/new' wp_posts wp_postmeta --dry-run
    wp search-replace 'example.com/two' 'example.com' wp_2_posts wp_2_postmeta --dry-run
    

    If those look good, rerun without dry run and call it a day!

    An interesting quirk is that you may need to edit the Fileupload URL if you’re using blogs.dir for your images. I noticed that on one site it was set to http://example/two/files which clearly is wrong. To fix that, go to Network Admin, click on Sites, and click on edit for the site. From there, click on the dangerous “Settings” tab and look for “Fileupload URL” and edit as needed to match things.

    Cool tricks like this can be found in WordPress Multisite 110.

  • Being Smart Cures Headaches

    Being Smart Cures Headaches

    While reviewing WordPress plugins, I often kick a plugin for calling file locations poorly. This usually happens when they’ve hardcoded their plugin name or (worse) wp-content into paths.

    When you hardcode in paths, or assume that everyone has WordPress in the root of their domain, you cause anyone using ‘Giving WordPress it’s own directory’ (a VERY common setup) to break. In addition, WordPress allows users to change the name of wp-content, so you would break anyone who choses to do so. And when this happens, I always link them to how to figure out the constants, which leads them to the function plugins_url().

    In many ways, plugins_url() is a panacea, a silver bullet, because it can take this:

    <?php
    echo '<img src="' . plugins_url( 'images/wordpress.png', __FILE__ ) . '" > ';
    

    And magically turn it into this:

    <img src="http://www.example.com/wp-content/plugins/my-plugin/images/wordpress.png">
    

    Even better, if you put the plugin in the mu-plugins folder, it would know to be this:

    <img src="http://www.example.com/wp-content/mu-plugins/images/wordpress.png">
    

    That makes it insanely flexible and wonderful.

    This allows me to happily rename a plugin folder to my-plugins_off to force disable it and will reward me with this error:

    The plugin my-plugin/myplugin.php has been deactivated due to an error: Plugin file does not exist.

    I like that error. I like that it happens no matter what, once I’ve renamed that plugin folder and I refresh a page that uses the plugin, it’s gone. Of course, sometimes it’s not enough, but most of the time, if you know what plugin’s being a doofus, you can fix it with that.

  • Don’t Reinvent the Wheel

    Don’t Reinvent the Wheel

    In WordPress, I punt plugins now and then for doing weird things that can best be described as reinventing the wheel.

    Any time a plugin replicates functionality found in WordPress (i.e. the uploader, jquery), it is frowned upon. It presents a possible security risk since the features in WordPress have been tested by many more people than use most plugins. Simply put, the built in tools are less likely to have issues.

    This was always something a little theoretical. I hadn’t yet run into someone who had broken their code with an upgrade of WordPress just because we updated the core wheel. Until November 20th.

    The shortcode API in WordPress was updated. It was decided that in order to stop breaking on PHP 5.4.8 and under, we needed to apply wptexturize() to shortcodes. This had a fun side effect when people didn’t properly register shortcodes, which of course brought up the logical question … why wouldn’t you register your shortcode?

    What I generally see in plugins is someone’s using a filter to look for their shortcode instead of registering it, so the post content is, in it’s entirety, parsed. That always struck me as foolish, since posts can get pretty long if Chris Lema or I are writing. And the reason people would do it was also odd. Either they were being lazy, they didn’t know about shortcodes (which I can understand, you can’t know everything), or they were trying to get around an ‘issue’ with nested shortcodes.

    For what it’s worth, the shortcode parser correctly deals with nested shortcode macros.

    [tag-a]
       [tag-b]
          [tag-c]
       [/tag-b]
    [/tag-a]
    

    That works fine. This won’t:

    [tag-a]
       [tag-a]
       [/tag-a]
    [/tag-a]
    

    Now I want to note, I’m using a php shortcode around those tags. So yes, it works great. But the problem would be if I wanted to show you the php code in a php shortcode… Doesn’t work that way, and it’s a limitation of the context-free regexp parser used by do_shortcode(). We went for speed over levels, and it can’t match each opening tag with its correct closing tag.

    Obviously the ‘right’ answer is ‘don’t nest same-named shortcodes’ but instead, some plugin authors have chosen the strategy of not registering shortcode names. That way the parser doesn’t try to mess with it. Sounds great, right?

    Not with wptexturize() running.

    [tag-a unit="north"]
       [tag-b size="24"]
          [tag-c color="red"]
       [/tag-b]
    [/tag-a]
    

    That turns into this:

    [tag-a unit="north"]
       [tag-b size=&#8221;24&#8221;]
          [tag-c color=&#8221;red&#8221;]
       [/tag-b]
    [/tag-a]
    

    Basically the code is understood to be code and not a quote. That means it would simply output the tags as code and not the tag content.

    And you see why this is a problem.

    There are two answers to fix this. One is to turn off wptexturize for your pseudo-shortcodes (via the no_texturize_shortcodes filters which are not complete, sadly, if you need to unfilter shortcode variables) and the other is to use the Shortcode API as it was intended. I would, personally, suggest you use the API since that prevents your code from breaking like this if another security update happens.

    Which brings us back to why reinventing the wheel is generally foolhardy in robust, well maintained systems. WordPress is constantly being improved, fixed, patched, and secured. The more you work around it by making your own way, the harder it is to fix things when WordPress makes a change. You’d think that people who make their own wheel would be attentive to anything that might break it, but they rarely are. They make their way, forget about it, and get annoyed when their code breaks and blame WordPress for not warning them. That’s a dirty secret about Open Source. No one’s going to tell you that a change will break your code. They expect you to be paying attention.

    The absolutely worst part about all this is that your users will have to decide to either stop using your code (which isn’t always an option) or not to apply an upgrade. In the case of 4.0.1, this is dangerous. This is why I will keep telling you not to reinvent the wheel, unless the wheel really needs it. And if the wheel needs a reinvention, you should consider submitting a patch to WordPress core, because if it’s that bad, everyone should know.

  • No Notice For Upgrades?

    No Notice For Upgrades?

    About a week ago I realized I’d not see an email with the subject “[Ipstenu.Org] Background updates have finished” in a long time. A really long time. Like so long that when I looked in my email trash, there wasn’t one.

    This was bad, because on Ipstenu.org I’m running trunk WordPress, which means I should get two emails a day about this. I ran to my server and scanned logs for 30 days. Nothing. And that was really bad.

    I’ve been using Advanced Automatic Updates for a long time, and I love it, it works well, but it wasn’t working ‘right’ for some reason, because it wasn’t emailing me on that one site, so I uninstalled it. The problem there is that without it, how would I upgrade plugins and themes? Since I know I can control the upgrades with filters, I decided to make an mu-plugin to handle just that.

    And that was when I saw I already had an mu-plugin called upgrades.php with this:

    WordPress site: https://ipstenu.org/
    The following plugins were successfully updated:
    * SUCCESS: Akismet

    Perfect!

    I don’t know how fun that story was, Benny, but that’s what happened.

  • Multisite Favicons

    Multisite Favicons

    One of the challenges with WordPress Multisite is that everything is on the same install. This means something that is rather trivial, like a favicon, becomes exceptionally complex and tiresome.

    On a normal site, when I want to make a favicon, I just toss the file into my main HTML folder, next to that .htaccess file, and I’m done. Now, for me it’s a bit of an extra step because I use StudioPress’ Genesis theme, and it applies its own favicon. It’s probably the only thing about Genesis that makes me annoyed, though it’s right next to when my host does that for me. Still, there’s a trick with Genesis.

    Because of Genesis

    Genesis is my parent theme, and it defines my favicon. So I have to delete its and put in mine:

    // No, you may not have your favicon
    remove_action('genesis_meta', 'genesis_load_favicon');
    
    add_filter( 'genesis_pre_load_favicon', 'halfelf_favicon_filter' );
    function halfelf_favicon_filter( $favicon_url ) {
    	return 'https://halfelf.org/code/images/favicons/halfelf.ico';
    }
    

    And it’s that simple.

    But I’m talking about Multisite, and I want to have a different favicon per site, I end up facing a new challenge.

    Because of Genesis and Multisite

    I still need to tell Genesis to shove it, but then I need to check what site I’m on and call the right favicon per site and this works very well. I’m using it today (you can see the code on that other link). But what if there was another option? What if I didn’t have to code it? Because the real problem with that code is I have to do it! If someone wants a new site to have their own favicon, I have to go in and add it to my mu-plugin, save it, commit it, and push it. Ew.

    Jetpack Site Icons

    Jetpack has a newish feature called Site Icon. With that module activated, I can allow each site to upload their own site icon and it will make a mobile icon too where I won’t have to.

    Uploading my Space Invader

    For a Multisite running Jetpack auto-activated on all sites, this is perfect. And yes, I do that because it saves me a headache of having to set it up later. I allow all sites to connect on their own, but I can also control all that from the network admin.

    So what does that old code look like now?

    With Genesis and Jetpack

    Now my code is simple. For everyone, I kill the default favicon, and then I set my own:

    // No, you may not have your favicon
    remove_action('genesis_meta', 'genesis_load_favicon');
    
    global $blog_id;
    
    add_filter( 'genesis_pre_load_favicon', 'example_favicon_filter' );
    function ipstenu_favicon_filter( $favicon_url ) {
    	return 'http://example.com/images/favicons/example.ico';
    }
    

    And the best part is if I set a site icon in Jetpack, it uses that instead.

    Best of both worlds.