Half-Elf on Tech

Thoughts From a Professional Lesbian

Author: Ipstenu (Mika Epstein)

  • Open Source Doesn’t Mean Public

    Open Source Doesn’t Mean Public

    Someone made a vague implication that my post about licenses were shots fired from someone who doesn’t ‘do’ but is only an ‘observer.’

    This is quite inaccurate, though I don’t blog about it here and I don’t talk about it anywhere for one simple reason. I can’t. I signed a paper, years ago, that agreed the work I did for them would be private. I would neither reuse the code (which I can’t anyway) nor would I discuss it. In fact, I had to make a phone call to ask if I could blog about it in general. I understand why someone might assume I’m not speaking from experience, but that just makes an ass of you and me.

    This isn’t about me refuting or dismissing allegations from someone who, for whatever reason, dislikes me and likes to make their hate public. No, this is about the interesting predicament about what happens when you can’t release information about your code.

    Half Open

    Here’s your scenario. The front end is an open system, a plugin say, that one installs on WordPress. It’s GPLv2 (or later) compatible because it’s distributed code I want to put on WordPress.org. That right there is a requirement. Alright, so I have one half of a product that is GPL and Open Source. The other half lives on a server somewhere in the world and does all the backend work. The plugin? It just passes API data too and fro as needed.

    I just described Akismet.

    You and I know very little about how Akismet works on the backend. And here’s the thing, that’s how it should be. We have a lot of information on how to interact with the Akismet API but none about how it actually calculates what is and isn’t spam on the back end. I repeat – this is the way it should be.

    Look at what Akismet does. It magically identifies spam. While it’s all well and good to be open source, the very first thing that would happen if they opened up all their code is we would see spammers read it and subvert it.

    But then again, we have things like SpamAssassin, an open source product I use on my email servers. Does this mean SpamAssassin is too dangerous to use? Does it mean it should be avoided? No, absolutely not! While it’s far from perfect, SpamAssassin does a phenomenal job at catching and stopping spam. But at the same time, it’s imperfect and being public, it’s more likely to be subverted by clever spammers. Thankfully the things it checks for are parts of email that a clever server admin can protect from and, all in all, it’s useful.

    Half Closed

    If we accept the fact that having a code base open or closed actually has very little impact on it’s usability, then why do we lock down our systems? That’s easy. Security and profit.

    Profit is the easy answer. If a system is closed then you can’t download it and install it for yourself. This means if you want to use it, you have to pay. Again, we can look at Akismet and VaultPress, which I would wager actually are built on open source code, as examples. They don’t have to be free, after all. There’s nothing wrong with being closed, either.

    By making a system a closed system that no one sees the backend code for, we create a product where only people who have access to the source code can easily infiltrate. This, of course, offers no assurance that it will never be hacked, only it raises the bar and makes it harder to deal with when it does get hacked. But at the same time, it is harder to hack an unknown than a known, and it does make things somewhat safer.

    Of course, if I told you all the ATM code in the world was not only open source but freely distributable and it was out there right now, how would you feel? That probably filled you with a little dread, thinking about how much trouble we already have with card skimmers and ATMs. If we have people who already know how to jack in, how much worse could it be if they knew how to encode software into the fake cards they make, and use them to backdoor your accounts?

    Have Your Cake And Eat It Too

    Just because the code you work on is open source doesn’t mean you can talk about it in public. Just because the code is closed doesn’t mean you can’t.

    I’m not talking about licenses here, though, I’m talking about contracts. I signed a paper about certain code I’ve written that prevents me from discussing it. So while I’d love to tell you everything about everything I’ve worked on, I can’t. But that’s not a bad thing. I’ve been privileged to work on the open and the closed, and it’s given me a greater appreciation and understanding of when we should and shouldn’t open our work. And this comes down to understanding the nature of the risks involved.

    Things like ATMs, financial trading, and mortgages should be secured and private. Why? Because the risk is much too high. A license? Well a worst case scenario is that someone figures out how to backdoor a free license for themselves. Another is they figure out how to use someone else’s license to gain access to their information. Those are pretty bad. So if you want to make your license API open but the code behind it not, I support that call.

    But. I do think you should have a way to manage your licenses and updates. That’s just business sense.

  • Referrer Spam In Adsense

    Referrer Spam In Adsense

    You may have heard of Semalt.com. I’ve heard them argue that they’re not spammers, they’re not evil, they’re not bad people.

    You know what? They are. They are spamming, they are doing evil, and they’re bad people.

    The other day I was checking my top-sites in Google Adsense, trying to think of how to increase revenue on my passive income, when I saw this random domain showing up on my list of sites. A site that wasn’t mine. A site that looked like a spammer:

    Adsense top sites shows one of Semalt's URLs

    Why is this happening?

    According to Google, this happens when a site loads cached content of your domain (Google does this). It can also happen when someone copies your whole webpage into an HTML email, or if someone uses a bad iframe.

    There’s also the obvious, but rare, case where someone uses your code without your knowledge.

    Do I need to block them?

    No. Except for the part where they screw up your analytics metrics and cause load on your server. Keep reading, I’ll explain.

    Will I Be Penalized by Google?

    My first thought was “Oh shit, Google’s going to yell at me!” I quickly checked that I had site authorization on, which means only domains I’ve approved and added can show my ads. Whew.

    This is a big deal by the way. While it would be nice to earn more views, if a site that isn’t mine uses my ads without knowing, I can get in trouble. More than once I’ve told off plugin developers about using Adsense in their plugins. This is for a couple reasons, first is that you can use it to track who uses your plugin (bad), but also because Google doesn’t want you to. They outright say that you cannot put ads “on any non-content-based page.” An admin dashboard is not a content page. Done and done. No ads in your plugins, thank you.

    But that’s exactly why I was worried!

    Where is Semalt showing my ads?

    What is this URL for anyway?

    The URL was http://keywords-monitoring-your-success.com/try.php?u=http%3A%2F%2Fexample.com (not my real URL). The only reason I could find it was I dug into my Google stats and found it as a referrer. If you happen to pop that into a browser, you will be redirected to http://semalt.com/ — Real nice.

    That is, by the way, how I knew it was Semalt.

    What is Semalt?

    Semalt is a professional SEO and marketing service. They literally make their money ‘crawling’ websites. When their site started, it was really the scamiest looking thing I’d seen in a long time. A year and a half later, they’ve cleaned up their act a bit but back in 2014 we all looked at them with a massive Spock eye.

    As it turned out, they were using infected computers to scan the web. My personal guess was that they are leveraging hacked computers and using them to scan for vulnerable websites. Once they find a site, they hack it and use it to push malware.

    That’s a guess. I have no proof. But based on their search patters and behavior, it’s looking pretty likely to me.

    Can I block them?

    Yes! But there’s a catch.

    You see, everyone says you can do this:

    # Block visits from semalt.com 
    RewriteEngine on 
    RewriteCond %{HTTP_REFERER} ^http://([^.]+\.)*semalt\.com [NC]
    RewriteRule .* - [F]
    

    And while that works, it’s obvious that Semalt is on to us because now they use keywords-monitoring-your-success.com and other URLs as passthroughs.

    How do I get them out of my analytics?

    Do you use WordPress.com? Or Jetpack? Great! Report the referrer as spam! WordPress.com blocked Semalt back in 2014, but obviously they’re on the rise again.

    If you’re using Google Analytics, Referrer Spam Blocker is probably your best bet.

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

  • Prettier DreamObjects Listing

    Prettier DreamObjects Listing

    A long time ago, I wrote about how to list your objects on DreamObjects. This code still works. I’m using it today, and as long as my bucket is public, it’s perfect.

    It’s also kind of ugly and a hassle to get the link. I have to right-click every time, and really I just want to grab the link, paste it somewhere else, and go.

    Thankfully it’s 2016 and there’s a library called clipboard.js that does this.

    Before I did that, I decided how I wanted the layout to be. Two buttons, one for a link copy and one for a link to open in a new window.

    The button list

    Looks pretty basic, I know, but it’s better than that list.

    Next I took my foreach loop and made it this:

    	foreach ($bucket_contents as $file){
    	
    	    $fname = $file['name'];
    	    $fname_pretty = strtolower( substr( $file['name'] , 0, strrpos( $file['name'] , ".") ) );
    	    $furl = "http://".$bucketName.".objects.dreamhost.com/".$fname;
    	
    	    echo '<div id="example-text" class="example">';
            echo '<button class="btn" data-clipboard-demo data-clipboard-action="copy" data-clipboard-text="'.$furl.'" aria-true="Copied!">Copy link to '.$fname_pretty.'</button> ';
            echo ' <a class="btn" href="'.$furl.'" target="new">Open link to '.$fname_pretty.'</a>';
            echo '</div>';
    	}
    

    This gave me the output and set me up for the script code at the bottom of the page:

        <script src="clipboard.min.js"></script>
        <script src="tooltips.js"></script>
        <script>
        var btns = document.querySelectorAll('button');
        var clipboard = new Clipboard(btns);
        clipboard.on('success', function(e) {
            console.log(e);
            showTooltip(e.trigger, 'Copied!');
        });
        clipboard.on('error', function(e) {
            console.log(e);
        });
        </script>
    

    Obviously clipboard.min.js is what you think it is, but the tooltips is so you can have that nice showTooltip popup so you know what you just did.

    When you combine that with the work I did the other day for a droplet, all I have to do is keep that page up and handy to throw links at people.

    You can see it at https://ipstenu.org/dreamobjects/.

    Before you ask, since not everything there is an image (‘Wrong’ is Dom Deluise shouting that), and since the images are all varying sizes, I went with not showing the image at all.