Half-Elf on Tech

Thoughts From a Professional Lesbian

Tag: coding

  • Debugging Unexpected Output

    Debugging Unexpected Output

    It’s going to happen one day. You’re going to get that weird error when you activate your plugin to test it and you will have no idea what it means.

    What error?

    The plugin generated 306 characters of unexpected output during activation...

    Unexpected output.

    The problem is WordPress doesn’t tell you what did it, where, or why, not even if you have debug turned on. You do have debug turned on, right? Well I was stumped on this one. I checked all my PHP calls to make sure I didn’t have whitespace, I looked for any files that were accidentally saved UTF-8, and I checked and double checked my diffs between the good and bad versions.

    What I ended up doing was writing a function that saved the error and output it.

    /* For debugging only */
    if (defined('WP_DEBUG') && true === WP_DEBUG) { 
        function myplugin_activated_plugin_error() {
            update_option( 'myplugin_error',  ob_get_contents() );
        }
        function myplugin_deactivated_plugin_error() {
            delete_option( 'myplugin_error' );
        }
        add_action( 'activated_plugin', 'myplugin_activated_plugin_error' );
        add_action( 'deactivated_plugin', 'myplugin_deactivated_plugin_error' );
        
    	function myplugin_message_plugin_error() {
    	    ?>
    	    <div class="notice notice-error">
    	        <p><?php echo get_option( 'myplugin_error' ); ?></p>
    	    </div>
    	    <?php
    		}
    	if( get_option( 'myplugin_error' ) ) {
    		add_action( 'admin_notices', 'myplugin_message_plugin_error' );	
    	}
    }
    

    That results in a pretty kind of output:

    A pretty version of my errors!

    I like to use the pretty display so I can easily read what, exactly I messed up and how.

  • Encrypting Source Code Doesn’t Make It Safer

    Encrypting Source Code Doesn’t Make It Safer

    I’d love to think that’s all I have to say on the matter, that you all will read the subject, go “Yup!” and we’re done.

    The reality is that I have to argue this, regularly, with people.

    Here’s the code from a plugin out there:

    <?php ${"\x47L\x4fB\x41\x4c\x53"}["w\x73\x78\x6e\x69\x66\x69\x6f\x71\x6c"]="\x73l_s\x65arch\x61bl\x65\x5fc\x6f\x6cu\x6d\x6e\x73";${"\x47L\x4fBAL\x53"}["\x66\x6b\x78xg\x63\x6ap\x68\x6d\x6ft"]="\x73\x6c\x5fdb";${"\x47\x4c\x4f\x42AL\x53"}["\x65\x62\x67\x79\x6b\x66\x64"]="\x69\x73\x5f\x73\x6c\x5fca\x74e\x67\x6f\x72\x69\x7a\x61\x74\x69\x6fn_\x63\x6f\x6c\x75\x6dn";${"\x47\x4c\x4fBA\x4c\x53"}
    

    The whole file is like that. The developer explained it was done that way for ‘security’ — it would make things harder to hack. I pointed out that’s simply not true.

    Here’s what having encrypted, hashed, packed code does:

    1. It makes your build process take longer.
    2. It adds another failure point into your code.
    3. It makes it harder for the end users, other developers (who write plugins), web hosts to debug, and you to debug.
    4. It makes you look like a developer with evil intents.
    5. It sets an expectation with users that this kind of code is ‘normal’ in WordPress.

    Recently Sucuri posted about a redirect hack that works by putting junk code in your header.php file which looks rather similar:

    Malicious injection in your header.php

    The issue here is that an end user, your normal WordPress user, cannot tell the difference between the somewhat safe code I quoted before and this code. They see ‘gibberish’ where as I know they can use a hex decoder to translate ["w\x73\x78\x6e\x69\x66\x69\x6f\x71\x6c"] into ["wsxnifioql"] … which is still pretty terrible.

    Well written code, well named functions, are self-explanatory. You see a function called redirect_404_pages() and you have a pretty good idea of what it’s for. You see a function named wsxnifioql() and good luck knowing what the heck that’s for. This goes back to the claim that the code is more secure. It’s not. It’s needlessly complicated, and as I shoed with the hex decoder tool, it can trivially be decrypted and read.

    So what is the real point of hiding your code? Who are you trying to protect? What’s ‘safer’ about any of this?

    The answer is that it’s about about you, you, you. You don’t want someone to take your great idea.

    That’s it. And that’s foolish.

    WordPress is GPLv2 (or later). Furthermore, to be hosted on WordPress.org, your code cannot be encrypted or hidden or otherwise non-human-readable. The basic reason is that WordPress’ success is due to it’s understandability and extendability. Anyone can read WordPress’ core code, parse it, learn from it, and enhance it. When you take that away from users, you isolate your code and prevent people from extending it.

    This person, this developer, charges upwards of $1000 for the add ons to their code. Yes, a plugin that costs over a grand. It sounds economically sound to try and lock things down so people don’t steal their intellectual property. We can all understand that impetus. I support it. I also feel that part of being in an open source community is being aware of how your actions impact the world at large.

    Because WordPress is open and because there is a standard expectation of non-encrypted code (except by evil-doers), the burden moves to developers to not hide their code that is installed on users’ servers. The code that is deployed to an end-user is expected to be human readable. This comes at a risk. I have a copy of a theme I bought, and I could give it away to anyone I wanted. They may not get updates, which means I have to be aware of the risk I’m introducing to my friends when I give them something like a premium theme or plugin.

    Similarly, what are the risks of telling people it’s okay to install plugin code in uploads instead of the plugins folder? What are the risks of allowing people to think that encrypted code is generally okay? In and of themselves, neither action seems particularly dangerous. PHP code is PHP code, right? If it runs, you’re good. But the reality is not so. By installing code in uploads I’ve made it so it’s no longer fully protected by WordPress and ‘standard’ security practices. I’ve also made it riskier that my code would even run, since many hosts prevent executable code from running out of that folder for security.

    So how do I meet the (assumed) criteria of not having someone rip off my code?

    You don’t. Your machinations aren’t preventing it now, and they won’t prevent it tomorrow. Hexcode is easily parsed. Even the Zend framework has to be able to be reversed to be run, so a dedicated person will always find a way around it. And the majority of your users aren’t going to be the problem. It’s those extremes. So what you’ve done is wasted time, effort, and money to annoy the majority to stop the minority. Let people inspect your code. If someone steals it, there are laws to help you handle them. Use them. Theft is theft. The GPL may allow them to take your code, copy and expand on it, but it doesn’t let them violate your copyright.

    All the work you’re doing to hiding your code is about as useful as preventing right-click on images. It doesn’t protect the end users, and it doesn’t protect your intellectual property.

  • A Blog Thought On Documentation

    A Blog Thought On Documentation

    Everyone, everyone, hates doing it. We all do.

    But there’s something that blogging regularly has brought me that is specifically related to documentation. And it’s this.

    I am more likely to write down exactly how I solved a problem if I think about it as a new blog post.

    I know, that sounds so simply it’s stupid, but I’ve realized that the whole reason I’ve figured all these things out is that I want to have something to blog about, and I want the blog posts to be interesting, so I started writing down how I solved problems.

    Of course, the joy of a problem is in the solving, so most of the time I’m talking about happy things. I do also blog about my failures, my missteps, and my totally-wrongs. Nothing wrong with being wrong. You learn a lot more from it, I feel.

    Start Without Code

    When I start ‘figuring out’ a thing, I write it down without any code. I write down “I want to do X.” And then I start brain storming.

    Take Monday’s post about term icons. “I want to assign an icon to a term.”

    That’s how it started. Then I talked through my vague concepts:

    • Show the icon on the back end
    • No uploading icons
    • Show the icon on the term edit and terms list page
    • Make sure it can show on the front end

    It’s really just the broad ideas. I’m not digging in deep.

    Pick Something Easy

    When I start coding, I pick the thing I already know how to do the most of. In this case, it was showing the icon on the front end. That let me start in comfort. I uploaded the images to the development server (VVV in this case) and started messing around with showing the images on the front end.

    I hardcoded in everything at first, using a default icon of ‘bacon’, and went about figuring out how I wanted it to display. I didn’t document this as much since it really was just about the look first. I knew when I got down to brass tacks, I’d be doing this:

    	<ul class="myterms-list"><?php
    		$terms = get_the_terms( $show_id, 'my_terms' );
    		if ( $terms && ! is_wp_error( $terms ) ) {
    			// loop over each returned cliche
    			foreach( $terms as $term ) { ?>
    				<li class="show myterm myterm-<?php echo $term->slug; ?>">
    					<a href="<?php echo get_term_link( $term->slug, 'my_terms'); ?>" rel="show cliche"><?php
    						$icon = get_term_meta( $term->term_id, 'my_termsmeta_icon', true );
    						$iconpath = get_stylesheet_directory().'/images/symbolicons/'.$icon.'.svg';
    						if ( empty( $icon ) || !file_exists( $iconpath ) ) {
    							$iconpath = get_stylesheet_directory().'/images/symbolicons/bacon.svg';
    						}
    						echo file_get_contents( $iconpath );
    						echo ' '.$term->name;
    					?></a>
    				</li><?php
    			}
    		} ?>
    	</ul>
    

    All of that code, except the icon part, was already written. That’s why it was easy.

    Pick Something Obvious

    Once I’ve done something easy and boosted my confidence, I start with the actual work. How do I set a term meta for a custom taxonomy?

    I knew how to make custom meta boxes, but taxonomies were different. I quickly remembered all the work Boone did for WordPress 4.4 and read his post on the Taxonomy Roundup. That way I learned that, as I had assumed, get_term_meta was a thing.

    Then I check to see if CMB2 knew how to use term meta, and happily found that it will work with term meta out of the box. No extra work. Thus the obvious became simple and I made a custom meta box for my term to put in a plain text field which was (originally) the path to my media file.

    I used that process to start the blog post. That was the new thing, so I wrote up the answer, not the process, and explained how to do the thing.

    Write About the Tweaks

    At that point, all that was left was busy work. I added in how to show the images on the back end, but then… then I did something extra. As I wrote the end of the post, I asked myself what the next logical step was? Well that would be not letting someone typo or put in names of images that didn’t exist. Instead of having to document all the images, I could just show a list.

    And that’s what I did.

    Share It

    This is actually universal.

    If you just documented something, you either did it so you can repeat the process over and over, or so you could have someone else do your dirty work for a change.

    If it’s personal, change ‘share it’ to ‘store it in an accessible place.’ Something in the cloud will do in a pinch. I often have my little things in a DropBox folder called “How Do I…” That’s because I usually ask “How do I edit all the images for …”

    But if it’s not personal, if I know a group will have to do it again later, I document it and share it. It may go in the company internal knowledge base or maybe it’ll be on a GoogleDoc shared with the people who need to know. Maybe I’ve put it on this blog.

    Either way, I documented. I released it.

    Now it’s your turn.

  • Making More With Less Work

    Making More With Less Work

    The other day, I added meta data of an icon to a custom taxonomy. When you need to add one or two filters to one or two items, it’s simple.

    add_filter( 'manage_edit-{my_taxonomy}_columns',  'my_terms_column_header' );
    add_action( 'manage_{my_taxonomy}_custom_column', 'my_terms_column_rows', 10, 3  );
    

    Replace {my_taxonomy} with your taxonomies, call it a day. But when you add in two, or three, or four, you don’t want to make four, or six, or eight lines of code. And when you’re calling the same array over and over, it’s time to get smart.

    Make An Array

    I originally only want to do this custom work in one taxonomy, so it was no sweat to repeat a little code. But then I realized I wanted to see it in four. Maybe more. So I picked out my array:

    $icon_taxonomies = array( 'tax_cliches', 'tax_chartags', 'tax_gender', 'tax_sexuality' );
    

    I made this outside the two functions, because I knew I was going to need it in multiple places. It would necessitate me tossing global $icon_taxonomies; into every function that needed it, but that was okay. Better that then trying to make sure every time I updated an array, I did it in all the places. Once is better.

    Make Your Loop

    The easiest thing was to trigger this on admit_init. Grabbing my global, I ran a simple for-loop from that array and added a filter based on the taxonomy named stored in the array:

    add_action( 'admin_init', 'my_add_taxonomy_icon_options' );
    function my_add_taxonomy_icon_options() {
        global $icon_taxonomies;
        foreach ( $icon_taxonomies as $tax_name ) {
    	add_filter( 'manage_edit-'.$tax_name. '_columns',  'my_terms_column_header' );
    	add_action( 'manage_'.$tax_name. '_custom_column', 'my_terms_column_rows', 10, 3 );
        }
    }
    

    Is It Really Less?

    A clever person will count the lines in this code (10 when you add in the variable) and think “Mika, you wrote two extra lines!”

    A more clever person will count the lines and think “At 5 taxonomies begins the break even point.”

    I know. From the outset it looks like I’m taking more time to over-engineer the solution to a very simple problem. And while I am, I’m also making it easier not to make typos and not to forget a step. I can make one change, one word, and update multiple places becuase that array is also used back in the my_register_taxonomy_metabox() function.

    'taxonomies'       => array( 'my_cliches', 'my_chartags' ),
    

    I removed the array and tossed in the new code.

    Yes, that’s adding two lines, but it removes my need to think “Where does this all go?” down to one place. And yes, I documented this in-line. The code header has a nice docblock explaining the whole section, what each variable is, and what each function does.

  • Custom Terms and CMB2

    Custom Terms and CMB2

    Let’s say you have some custom taxonomies in WordPress. And let’s say you want to add a special field to them for an icon. How would you do it?

    There’s a cool plugin by someone I know that can do this, called WP SVG Icons and it works great. But it wasn’t quite what I needed.

    You see, I had 832 really awesome SVG icons I wanted to use. In order to use Evan’s plugin I’d have to convert them into a font using Icomoon. I already had about 300 in a font, which is cool, but I was in the thought to move these from fonts to pure SVG anyway since they’ll show up in better detail if you don’t have retina screens. Also they’re smaller and loaded on demand and … well it is what it is.

    I decided the simplest solution was as follows:

    1. Upload all the SVG to the server
    2. Add a custom term meta field to the taxonomies for ‘icon’
    3. Show the icon on the Terms List Page
    4. Show the icon on the Term Edit page

    And yes, it works.

    Where Do The Icons Go?

    I put them in my theme. They’re pretty specific to the theme itself, but usually things that are related to custom data ends up in mu-plugins since I want them to exist outside of the theme. For the record, I also have CMB2 outside the theme, so the code is all there, but the images are in the theme. You can decide how you want.

    Adding Custom Term Meta

    There are a lot of ways of doing this, but as I’m using CMB2, well, I’m using CMB2 so it looks like this:

    add_action( 'cmb2_admin_init', 'my_register_taxonomy_metabox' );
    function my_register_taxonomy_metabox() {
    	$prefix = 'my_termsmeta_';
    
    	$cmb_term = new_cmb2_box( array(
    		'id'               => $prefix . 'edit',
    		'title'            => 'Category Metabox',
    		'object_types'     => array( 'term' ),
    		'taxonomies'       => array( 'my_cliches', 'my_chartags' ),
    		'new_term_section' => true, 
    	) );
    
    	$cmb_term->add_field( array(
    		'name'		=> 'Icon',
    		'desc'		=> 'Name of the image you want to use, without filetype (i.e. carrot)',
    		'id'		=> $prefix . 'icon',
    		'type'		=> 'text_medium',
    		'before_field'	=> 'cmb2_before_field_icon',
    	) );
    }
    

    You’ll notice before_field there. That’s what will let me do the 4th item on my list. The description tells you how to use the field. Don’t worry, I do sanity checks later on.

    Show The Icon On The Terms List

    I wanted the icon to show after save so that people would be able to know what they’d added and change it if needed.

    add_filter( "manage_edit-{my_taxonomy}_columns", "my_terms_column_header" );
    add_action( "manage_{my_taxonomy}_custom_column",  "my_terms_column_rows", 10, 3  );
    
    function my_terms_column_header($columns){
        $columns['icon'] = 'Icon';
        return $columns;
    }
    
    function my_terms_column_rows($value, $content, $term_id){
    	$icon = get_term_meta( $term_id, 'lez_termsmeta_icon', true );
    	$iconpath = get_stylesheet_directory().'/images/symbolicons/'.$icon.'.svg';
    	if ( empty($icon) || !file_exists( $iconpath ) ) {
    		$content = 'N/A';
    	} else {
    		$content = '<span role="img" class="cmb2-icon">'.file_get_contents($iconpath).'</span>';
    	}
        return $content;
    }
    

    You can see where I’m checking if the icon has been set and if the file exists. What this does is first generate a column for the icon and then populate the content based on the term information.

    Icons shown on the list of terms

    There you can see the icon, looking rather nice.

    See The Icon When You Edit

    This is a little different. I had to check the output the of the field value, which is set by CMB2, and then base the rest of the code off that.

    function cmb2_before_field_icon( $field_args, $field ) {
    	$icon = $field->value;
    	$iconpath = get_stylesheet_directory().'/images/symbolicons/'.$icon.'.svg';
    	if ( !empty($icon) || file_exists( $iconpath ) ) {
    		echo '<span role="img" class="cmb2-icon">'.file_get_contents(get_stylesheet_directory_uri().'/images/symbolicons/'.$icon.'.svg').'</span>';
    	}
    }
    

    Again I double check the file actually exists, just in case you typo.

    The edit term page

    I put it before the field because that looked better to me, but there are other places this could go.

    Results?

    I started this because, originally, it was all done with CSS. That meant if people added in new terms, someone with admin ability had to go in and edit things. This way, people can not only see what they’ve added, but you can get a quick view of what doesn’t have icons set. It’s instructive and has visual feedback.

    The ‘next level up’ would be to only allow selection from a dropdown.

    For the least amount of hustle, add this to your my_register_taxonomy_metabox function:

    	$icon_array = array();
    	foreach (glob( get_stylesheet_directory().'/images/symbolicons/*.svg' ) as $file) {
    		$icon_array[ basename($file, '.svg') ] = basename($file, '.svg');
    	}
    

    And then replace 'type' => 'text_medium', with this:

    	    'type'             => 'select',
    	    'show_option_none' => true,
    	    'default'          => 'custom',
    	    'options'          => $icon_array,
    

    And voila. Done. Now you’re even harder to get wrong.

    names as dropdowns

    It even looks good.