Half-Elf on Tech

Thoughts From a Professional Lesbian

Tag: coding

  • Better Headers

    Better Headers

    I review a lot of code and by extension read a lot of source code files. One of the things that drives me to distraction is trying to sort out what a specific bit of code is licensed. Now, I don’t care about GPL the way a lot of people do. When I’m reviewing plugins for WordPress.org, I only care in that a repository requirement is that all code in your plugin is GPLv2 (or later) compatible. If you’re not hosting on WordPress.org, I only care if I want to use your code and I need to see what the possible restrictions are.

    While I’m mostly talking about JS files here, I wish people would remember to put in the right header information for all their code.

    Headers I Hate

    It absolutely kills me to see this as the header of a JS file:

    /*! My Awesome JS - v1.0.0 - 2015-01-14
    * http://example.com/myawesomejs/
    * Copyright (c) 2015 John Doe */
    

    Actually, what’s worse is this:

    /*! My Awesome JS - v1.0.0 - 2015-01-14 */
    

    This means I know nothing about your code license. If I have the URL, maybe I can be really lucky and go there, see a link to your full source code, download, open the zip, and maybe you put a license file in there. Most often, however, the answer to that is not. With a lot of newer projects, they link to Github, which is great since I can go and look for that LICENSE file. Github even prompts you about making one when you create a project. Love ’em

    Realistically, if you’re releasing code for the world to use then you’ve got to license it. Even if you don’t care about licenses, putting a public-domain clause on your code means it’s free for all nations to use is so easy a caveman could do it.

    Headers I Love

    Okay, so if you’re making your own JS, what do I think your header should look like?

    /**!
     * My Awesome JS v1.0.0
     *
     * @copyright Copyright 2015 John Doe
     * @author    John Doe
     * @link      http://example.com/myawesomejs/
     *            http://github.com/johndoe/myawesomejs/
     *
     * @license   Use permitted under terms of CC0 1.0 Universal (CC0 1.0) Public Domain Dedication
     *            https://creativecommons.org/publicdomain/zero/1.0/
     *            http://example.com/myawesomejs#license
     */
    

    That’s it. Obviously that’s the non-minified version. If I wanted a minified version it would be this:

    /*! My Awesome JS v1.0.0 | (c) 2015 John Doe | example.com/myawesomejs#license */
    

    There’s an argument to be made about minification and how I shouldn’t have any headers in order to compress the code to the extreme, but let me show you the jQuery minified file’s header:

    /*! jQuery v2.1.3 | (c) 2005, 2014 jQuery Foundation, Inc. | jquery.org/license */
    

    It covers your license and your copyright information there in one go. It protects your interests and makes it plain for everyone to see what’s going on, how to get in touch with you for changes, and all sorts of awesome open-source things.

    Picking a license…

    In the above example, I picked CC0 for a reason.

    That’s the ‘unlicense’ I think you should be using if you’re releasing code to the world and don’t want to be bothered by the hassles of any informal sort of license. Sadly, not declaring a real license can cause problems outside the United States. Here, we would interpret the license based on what the author intends, which is already a bit of a dangerous idea, and presume a license means exactly what it says, which makes them non-copyleft free software licenses and compatible with most other free software licenses. It may make it outright incompatible with commercial software. And worse, other countries have stringent views on the copyright aspects of these licenses.

    Now that said, my other favorite ‘For god’s sake, just take my code’ license is the WTFPL license.

    For me, if I want to release code that really is free and can and will be used by anyone, I pick the CC0 or WTFPL. It covers this for everyone, as far as I’ve been able to tell, even commercial.

    The GNU have their own license recommendations of course, and Jeff Atwood has a good post about picking a license that explains how most of us feel about the headache. Of course, if you’re forking someone else’s code or building on their work, check the license they used to make sure you don’t violate it with your new license. Not all licenses are ‘backwards compatible.’

  • Listing Everything on DreamObjects

    Listing Everything on DreamObjects

    I was asked about listing everything in a DreamObjects bucket, which is practically the same thing as listing everything in an Amazon S3 bucket, just on a different server.

    This isn’t as easy as we’d like, because while there is a nice Amazon S3 PHP class we can use (and I forked it and flipped it to be a DreamObjects PHP Class), telling people they have to download the S3.php file and then make this separate PHP file is a little annoying.

    //include the S3 class
    if (!class_exists('S3'))require_once('S3.php');
    
    //AWS access info
    if (!defined('awsAccessKey')) define('awsAccessKey', 'MYACCESSKEY');
    if (!defined('awsSecretKey')) define('awsSecretKey', 'MYSECRETKEY');
    
    //Bucket Info
    $bucketName = 'MYBUCKETNAME';
    
    /* STOP EDITING HERE */
    
    //instantiate the class
    $s3 = new S3(awsAccessKey, awsSecretKey);
    
    
    // Get the contents of our bucket
    $bucket_contents = $s3->getBucket($bucketName);
    
    foreach ($bucket_contents as $file){
    
        $fname = $file['name'];
        $furl = 'http://'.$bucketName.'.objects.dreamhost.com/'.$fname;
    
        //output a link to the file
        echo '<a href=\'$furl\'>$fname</a><br />';
    }
    

    I know, it’s not too terribly complicated, but it is annoying to make two files for that, and my DreamObjects listing page is very barebones. You could style it with CSS, make it show the image, make it show in a grid, or even show the file size and have it pop up in a new window.

    It does highlight one of my issues with CEPH (AWS whatever) storage, and that it’s still not quite friendly enough. It dumps us back to the old days where we FTP’d our images up to a server and then manually crafted our links. Certainly there are plugins for WordPress that can help us with that, but in general it requires knowing code (or where to get the code) in order to display content.

  • Hide Your Site on Multisite

    Hide Your Site on Multisite

    Sometimes when you’re building a network, you don’t want all your sites to be available just yet. While you can install a ‘Coming Soon’ plugin, there are also built in ways to handle this.

    First you’ll want to take advantage of two of the Network’s least loved features: Deactivate and Archive. When you go to the Sites page on the Network Admin and hover over the items, you have new options appear:

    The edit options for your sites

    Should you click on Deactivate, you’ll be asked to confirm and then you get this:

    A deactivated site - it says 'Deleted'

    Don’t panic!!

    I know it says Deleted. It’s not. A deleted site is 100% deleted, the DB tables dropped and the images nuked. So while it ‘says’ deleted, it’s not. If you press Archive it’s a little more realistic:

    A site that has been archived is in light pink and says 'archived'

    What’s the difference? In both cases, this is what a non-logged in user sees:

    What a visitor sees on a deactivated site is 'This site is no longer available.'
    This site is no longer available.

    And in both cases, you can’t log in, because this is what you see for wp-admin and wp-login.php.

    Archived site WP Admin says the site is suspended

    Deleted site WP Admin says the site isn't available

    It’s weird, but it pretty much ‘archived’ the sites. You can, as a Super Admin, see it, but you can’t even change user roles from the network dashboard. (I spent about an hour trying to debug why I, as a Super Admin, couldn’t get to the dashboard at all, and it turned out I needed to flush my cache, so remember folks, caching is wonderful until you shoot your foot.) Still this presents a predicament.

    Frankly, I don’t want people to know a site doesn’t exist. That can be easily done with a filter and a redirect:

    // Archived sites only I can see
    function helf_redirect_hidden_sites() {
    
    	// Super Admins always get in
    	if ( is_super_admin() || current_user_can( 'manage_options' ) ) {
    		return true;
    	} else {
    		// Defines
    		if ( defined( 'NOBLOGREDIRECT' ) ) {
    			$goto = NOBLOGREDIRECT;
    		} else {
    			$goto = network_site_url();
    		}
    
    		$blog = get_blog_details();
    
    		if( '1' == $blog-&gt;deleted || '2' == $blog-&gt;deleted || '1' == $blog-&gt;archived || '1' == $blog-&gt;spam ) {
    			wp_redirect( $goto );
    	        die();
    		}
    	}
    }
    add_filter('ms_site_check','helf_redirect_hidden_sites');
    

    I wanted to allow my site admins and my super admin to view it, but if you don’t, edit if ( is_super_admin() || current_user_can( 'manage_options' ) ) to only allow what you want. And because I’m using a subdomain site, this makes it look like an archived/deleted site is just another non-existent site, by redirecting to NOBLOGREDIRECT.

    But this doesn’t work around the problem that my whole wp-admin is blocked off to non logged in users. I mean, how can I log in? The only workaround is that if the site is a subdomain (test.halfelf.org) or a subfolder (halfelf.org/test), then I can log in at halfelf.org/wp-admin and then visit over. If this was a mapped domain, I’d be in trouble. So it’s clearly not a perfect solution for everyone.

    By the way, you can customize the various messages for suspended or deleted sites by creating the following files in wp-content:

    blog-suspended.php
    blog-deleted.php
    blog-inactive.php

    So if you just want it to be pretty, that’s easy.

  • Don’t Be Afraid To Learn In Adversity

    Don’t Be Afraid To Learn In Adversity

    also i’d like you to either never submit pull requests again or at least try to not put harmful code in them

    That was what a developer said when I made a derp pull request, adding in a check for 0 that should have been better as a check for not -1.

    Regardless of the fact that he and I fundamentally disagree on the usefulness of the code (and frankly, that’s why I assumed he’d be punting my pull request), his reply is something I’m very glad I got now and not 10 years ago.

    Like pretty much everyone on the planet, I have moments where I wonder if you’re all going to figure out that I don’t know a damn thing and I’ve been faking it all these years. It’s Imposter Syndrome, and we all suffer from it to a degree. And it’s comments like that developer made that reinforce it.

    Now, I know this guy’s history. And I know at first glance his reply may seem terse but not all that bad. Sadly, this is probably the nicest I’ve ever seem him tell someone they sucked. He’s not nice. At all. His support forums are filled with him calling people demeaning names, or saying they’re stupid for not understanding his code, and frankly on the list of humans I would willingly interact with for fun, he’s not there. He’s not even on the reserves. But I still respect his code (though not his documentation, inline or otherwise) and I use it every day. I won’t be contributing to it anymore because I don’t have any need to be in an abusive relationship.

    Toy dinosaurs attacking an action figure
    “Curse your sudden, but inevitable, betrayal!”

    And that’s what this is! He’s abusive and behavior I don’t care for and wether he means it or not, he’s being mean. It feels silly and petty to put it that way, but that’s what it is. He’s a mean person. I don’t care that he’s mean, and it didn’t actually hurt my feelings though it did make me momentarily angry at him, but I do care that meanness like that will convince someone to stop and never get better at things. Did it hurt my feelings? Yes, it did. It sucks to be told your code sucks, but it sucks more to be told in a way that makes you feel like you’ll never be good enough in any way, which is precisely what many people will read from that comment.

    When you ask me “Where does Imposter Syndrome come from?” I say “People like that.” People who reinforce the belief that you’re not good enough, that you’re crap and don’t deserve their time to learn better, and you can go eff yourself.

    Is he required to be nice and handhold me through the code and explain why? Hell no! But he made an open source product which he opened to the public, put on GitHub, and allowed for pull requests. He’s naive to think everyone will come to his product knowing everything, and I suspect part of his attitude issue is because he doesn’t want to help people. Which again, is fine. Obviously I don’t feel the same way, but I also don’t think everyone can be good at support. I do think that if you’ve got all this in the open, you’re going to get people who are far less experienced than you are. How you treat them will set the standard for what kind of help you get from your community in the future.

    Let’s contrast this. I was talking to people about a change in some laws recently and fiddling with an add on to code I use because of it. When I reached a point at which the code worked, I put it on Github and said “Pull requests and fixes welcome!” I knew the code wasn’t good enough. I knew I wasn’t sanitizing everything yet, some of it was terribly inefficient, and some of it was bad code. I knew this. I knew it wasn’t perfect at all, but I put it up and then pinged a developer for the product I was using. His reply?

    mind if I fork that and we distribute it either on [our] site or in (pending yet another round of core team discussion) in core?

    Boom. He knew it wasn’t perfect. He saw the value in the attempt and proof of concept, and he ran with it. Naturally I told him to use and enjoy, because I’d licensed it GPL. He also said he’d try and do a pull request to make it so when you used the code, it stopped you from picking the wrong thing. That was something I’ve yet to sort out, even though I’ve been playing with the code some more. I’m learning something new. I’ve never written for that code project before (except a typo fix). This is all new for me.

    The difference is pretty bold. One guy pretty much insulted me, one encouraged. The insult, justified or not, discouraged me from wanting to pitch other suggestions or improvements. The encouragement is making me think about an offer they made a while ago more seriously. It also inspired me to sit and study the code, read what it did and why (seriously awesome inline documentation there), and be able to go from zero to add-on in 4 hours while prepping for a holiday dinner.

    How you represent yourself, as a developer, creates your community. How you treat others can help or hinder their entire lives. You may not think about your words as having that much power because you’re just someone who helps in a support forum, or you wrote a simple two line plugin, or you translated a file, but they do. Your words matter a lot.

    As for the people reading this who don’t code well either, don’t be afraid to code badly. You can’t know it all from the beginning and don’t let people get you down about that. Tell them you’re learning, that you’re trying to be bold and step out, and you won’t get any better in a vacuum. Some of us have to learn by doing, after all. We can’t all read the code and know the answers, and that’s okay.

    By the way, yes I’m still using the code from the other guy. I’ve forked it (and now I get to learn about syncing your fork back with master changes) and I’m keeping my one change in there. I’m sure there’s another fix, with a filter perhaps, but given the lack of documentation and assistance, I’ll be stuck with this for a while yet. But you know what? That’s actually okay.

    I honestly have no hard feelings on a personal level. I’m not obligated to like him or agree with his choices. He’s not obligated to agree with mine. That’s why open source is great. I can fork it and go. But what won’t happen is that I won’t be afraid to make changes, to get things wrong, and to keep learning.

    I’m not an imposter. I’m just still learning.

  • 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.