Half-Elf on Tech

Thoughts From a Professional Lesbian

Author: Ipstenu (Mika Epstein)

  • Subdomains and Subfolders, One Network

    Subdomains and Subfolders, One Network

    For the longest time, if someone wanted to have example.com, foo.example.com and example.com/bar for their Network on Multisite, I’d tell them to use a Multinetwork Plugin like Networks+ (which you can buy from e-Books by Ron and Andrea) or WP Multi Network (free from JJJ).

    But sometimes you don’t need multiple networks and the multiple admin sections. Sometimes you just want to have options. Thanks to the work that started with the roadmap you can have your cake and eat it too.

    If you’ll recall, I detailed how you can map a domain without a plugin on Multisite these days. Guess what? You can also do this with subfolders and subdomains.

    I did this with a subdomain install, since it made more sense to go that way.

    WordPress is installed at multisite.dev and I have subsites of foo.multisite.dev and bar.multisite.dev

    I then made a new site called baz.multisite.dev:

    Creating baz.multisite.dev

    Then I edited that from this:

    Editing baz.multsite.dev

    To this:

    Now it's multisite.dev/baz

    Be careful here! If you don’t put the trailing slash on the folder name, this will not work. And does this work? Yes it does. Of course there is the small issue of how this looks on my list of domains:

    Domain List is Ugly

    I have two sites as ‘multisite.dev’ and I have two ‘foo’ sites (because you can also make foo.multisite.dev/zot if you want to). The problem is that the Sites page in the Network Admin has a check:

    $blogname_columns = ( is_subdomain_install() ) ? __( 'Domain' ) : __( 'Path' );

    This means the ‘domain’ of foo.multisite.dev/zot and foo.multisite.dev are (correctly) foo. I couldn’t see how to filter, so I made a quick MU Plugin:

    class Add_Blog_Blogname {
    	
    	public function __construct() {
            add_filter( 'wpmu_blogs_columns', array( $this, 'blogname' ) );
            add_action('manage_sites_custom_column',  array( $this, 'blogname_columns' ) , 10, 3);
            add_action('manage_blogs_custom_column', array( $this, 'blogname_columns' ) , 10, 3);
        }
    
    	function blogname_columns($column, $blog_id) {
    	        global $wpdb;
    	        
    	        $blog_details = get_blog_details($blog_id);
    	        
    	        if ( $column == 'my_blogname' ) {
    	                echo $blog_details->blogname;
    	        }
    	        return $value;
    	}
    	
    	// Add in a column header
    	function blogname($columns) {
    	    $columns['my_blogname'] = __('True BlogName');
    	    return $columns;
    	}
    }
    
    new Add_Blog_Blogname();
    

    This tosses the True Blog Name to the end of the sites list. It’s not perfect, but it gets the job done.

  • GeoIP Options

    GeoIP Options

    Thanks to crazy thinks like the EU VAT laws, sometimes we really have to know where people are coming from when they visit our sites. The problem with this is … how?

    There’s a cool extension for PHP called GeoIP, which I’ve finally installed on this server (along with my upgrade to PHP 5.5 and some other things, yes, still on Apache, shut up Otto). The extension comes from MaxMind, who also have a pure PHP version you can use. I’m not because the GeoLite2 databases are distributed under the Creative Commons Attribution-ShareAlike 3.0 Unported License and that means I can’t include it in a WordPress plugin.

    But that really made me wonder why it was okay not to attribute Maxmind when I used it via Pecl. I mean, technically I should, right? But where and how? I ended up putting a note in my site footer, to say that the site used the Maxmind DBs, but I haven’t included any note about that in my plugin since the DBs are included in the plugin, just called if the functions are found. It’s on you to install and attribute as needed.

    Installing mod_geoip

    Installing this is simple, from a server admin perspective.

    Since you can’t use the yum install on Apache 2.4, I got to use a cPanel Custom Module, which meant running this:

    wget http://easyapache.cpanel.net/optmods/custom_opt_mod-mod_geoip.tar.gz
    tar -C /var/cpanel/easy/apache/custom_opt_mods -xzf custom_opt_mod-mod_geoip.tar.gz
    

    And then I ran an EasyApache build. That was fine, I needed to do that anyway. Once that was done, I installed the pecl for GeoIP:

    pecl install geoip
    

    Done. Optionally you can add it to apache in either your .htaccess or (better) a conf file for your whole server:

    <IfModule mod_geoip.c>
      GeoIPEnable On
      GeoIPDBFile /usr/local/share/GeoIP/GeoIP.dat
    </IfModule> 
    

    What about upgrades?

    Every month you don’t upgrade your geoIP DB, the more your site sucks. Someone quoted a statistic that every month you don’t upgrade the DB, the accuracy drops by 1.5%. I can’t validate that, but I’d believe it.

    Upgrades are fairly painless, thanks to geoipupdate, though it doesn’t include the IPv6 files for some reason. Still, being able to toss this into crontab makes my life easier:

    38 15 * * 5 /usr/local/bin/geoipupdate
    

    Of course… I did notice that there’s a new MaxMind DB Apache Module.

    If you’re on nginx, you can grab the nginx geoip module too.

    What if I can’t install PHP modules?

    By request, I’d already added in the GeoIP2 PHP API to my wee little plugin. Not everyone can use mod_geoip or mod_maxminddb, after all, so it’s good to have options. And with this option, you have the question of how to update since geoipupdate won’t work anymore.

    If you want to go hardcore, you can Auto-update your GeoIP databases with Cron via that very robust script. Or if you’re simple like me, it’s a geoip.sh script in your ~/scripts/ folder:

    #!/bin/sh
    cd /home/username/public_html/wp-content/edd-pec-geoip
    wget -q http://geolite.maxmind.com/download/geoip/database/GeoLite2-Country.mmdb.gz
    gzip -d -f GeoLite2-Country.mmdb.gz
    

    And then I have this in my crontab:

    30 22 2 * * /home/username/scripts/geoip.sh
    

    Which is a lot easier for a lot of people.

  • Mailbag: Multiple Download Buttons

    Mailbag: Multiple Download Buttons

    Less a mailbag and more a forum question that grew from a logical question.

    How do you link ‘external’ stores from your product pages?

    Well, for me I do it by having a custom page I designed for my products, and listing three shortcodes. One for EDD (the default [purchase_link]) and then two for my own links. In non-shortcode, its like this:

    [Buy from Me][Buy from Amazon][Buy from Apple]

    The actual code is below. I try to keep things as simple as I can when I do this, and I did nick a bit of code from EDD core (you’re supposed to) to make it match. All this does is the most basic of links and it all fits in a nice little box like this:

    The sales box sits on the upper rght of the page and lists image, price,  and links.

    I like that layout. Reminds you a bit of Amazon, and there’s a reason. If you keep the space open and clear, it’s easy for a visitor to grasp their options. Also I can put below a link to my EU/VAT page and say this “Purchase disabled? Here’s why…” I don’t right now, though I probably should. I couldn’t think of how to elegantly handle making the button a link like that.

    The code

    	// EDD Buy Externally [edd_external store="iTunes" link="http://apple.com/foo" text="Add to Cart" ]
    	function edd_external_shortcode_func( $atts ) {
    		global $edd_options;
    
    	    $atts = shortcode_atts( array(
    	        'store' => '',
    	        'link'  => '',
    	        'text'	=> 'Buy Via',
    			'style' => isset( $edd_options[ 'button_style' ] ) ? $edd_options[ 'button_style' ] : 'button',
    			'color' => isset( $edd_options[ 'checkout_color' ] ) ? $edd_options[ 'checkout_color' ] : 'blue',
    			'class' => 'edd-submit'
    	    ),
    	    $atts, 'edd_external' );
    
    		// Override color if color == inherit
    		if( isset( $atts['color'] )	) {
    			$atts['color'] = ( $atts['color'] == 'inherit' ) ? '' : $atts['color'];
    		}
    
    		$content = '<a href="'.$atts&#91;'link'&#93;.'" class="edd-external edd-'.$atts&#91;'store'&#93;.'
    		 '.$atts&#91;'style'&#93;.' '.$atts&#91;'color'&#93;.' '.$atts&#91;'class'&#93;.'
    		"><span class="edd-add-to-cart-label">'.$atts['text'].' '.$atts['store'].'</a></span>';
    
    		return '<div class="edd_purchase_submit_wrapper">'.$content.'</div>';
    	}
    
    	add_shortcode( 'edd_external', 'edd_external_shortcode_func' );
    

    Like I said. Pretty basic.

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

  • MailBag: Why Do You Do It?

    MailBag: Why Do You Do It?

    Zaman dropped me a year end note. He’s been asking people, interviewing them, for a site, and had three questions about why I do what I do (and a little bit of how). It deserved a public reply.

    1.You have been actively volunteering at WordPress support forum and with your solutions individuals and companies save big chunk of money. Your family and Job at DreamHost are your top priorities. Then your priority becomes the website you run (halfelf.org). You still manage to take out couple of hours to hit WordPress forum. You mention in one of your blog that some people volunteer because they enjoy it and some do it to master skills. What drives you to volunteer at WordPress?

    What drives me to volunteer at WordPress is little more than a bit of technical socialism. I give back because I get back, and it seems only logical and fair and just to make the time to do these things. Admittedly, having my job actually be know WordPress’ ecosystem and keep a good relationship between WP and DreamHost makes this far easier for me than most. But at the same time, I was doing this before it was my job. And I did it because I could.

    I have a hard time explaining the need to give back to people, because it’s something you either understand in your heart or you don’t. Call it a random act of kindness to the universe, I help with WordPress because I can, because I enjoy it, and because it makes me feel good to do it. I won’t deny I get awesome emotional props from doing it, a feeling of absolute satisfaction and pleasure knowing I can help people, but it’s really just that. I like doing it. I make the time for it.

    2.Your insights on halfelf.org are remarkable and the blog “whose responsibility is it” in particular draws my attention. You convey it is the business owner responsibility and not the WordPress core or Webhosting Company to perform due diligence before they install plugin’s. You also call out there is a need for more security experts. Is there a shortage of wordpress security experts in general or in wordpress public support forum?

    Do I think there’s a shortage of WP security experts? No, I think there’s a shortage of security experts in general. I think the masses of people would rather do awesome and create awesome than study security and delve into things. The fact that I can think of a hundred ways to socially engineer going to see a movie for free without breaking a sweat, the fact that someone like Frank Abagnale was able to pull off what he did underscores the issue.

    At our heart, humans want to trust. We want to believe people won’t screw with us. And when you factor in just how complex computers and code can be, of course we have faith that the people who write code are writing the best code to their ability and know what they’re doing. And we have faith that, when a bug or a security flaw is reported, people will fix it as fast as they can.

    WordPress complicates this, since there are so many plugins and themes out there that there isn’t a centralized place to reply a problem. Even if there was, there’s no way to enforce the bug is fixed, and there’s no way to be certain everyone will upgrade. Just look at the nightmare from the RevSlider situation. Once you add in the world of non wordpress.org hosted code, it’s impossible to maintain any control.

    If more developers were security conscious this might be less of the case, but it’s a problem in Open Source. The Heartbleed vulnerability is a prime example of that. One change, missed by many. It’s not just WordPress, it’s how we develop in Open Source. The speed of our work makes issues like this sadly more common and possible. So we need more people who love hacking into things and breaking them and then responsibly passing on fixes to make things more secure. I do feel that Github and sites like it are actually a great step forward. I can file a pull request with a fix and pass on the help in that way.

    This does require hobbyists to step up and be a bit more of a true developer, but they have the most to gain from it in the end.

    3. Examining and reviewing the plugin software may not be possible for small businesses. Do you have a list of plugins that should be avoided or a checklist that should be considered before installing the plugins? I am not asking if you to list here. May be an article in halfelf.org will be very useful for WordPress community.

    I don’t have a list. I can’t have a list. It’s impossible, given the rapidity with which plugins are updated, fixed, released, and closed. It’s just not feasible. I tried, at DreamHost, to keep tabs on plugins like that for about a week. Then I gave up. It would be a full time job.

    And I disagree it may not be possible for a small business to have an audit done on their plugins and themes. They can hire someone. It would be expensive, certainly, but frankly I find the alternative untenable. If you had a physical store, you’d pay to have a security audit once in a while, if only by your security company. This too is a part of running a business. Period. You just can’t dismiss it as ‘not possible’ when it’s your career on the line. Complicated, expensive, and annoying I will grant you. But you have to do it. Even if it’s just once a year, you’re a step or ten ahead from where you were before.

    I’ll say this, however. I would expect someone like Pippin over on Easy Digital Downloads to be reviewing all add-ons he lists on his site. Anything he sells, certainly, but also this big list of free add-ons should be checked for basic security before being listed. In this way, a small company can know they’re reasonably secure with that suite of plugins.

    Are there plugins that should be avoided? Sure. I suggest you avoid anyone you can’t figure out how to contact in case of a security issue, anyone who encrypts their code so you can’t read it, and anyone whom, when you do contact them, blow you off.