Half-Elf on Tech

Thoughts From a Professional Lesbian

Author: Ipstenu (Mika Epstein)

  • Mailbag! .htaccess questions

    Mailbag! .htaccess questions

    New thing! So many people email me for tech support, which I’m pretty clear on how you’re not going to get it. But Ken (the web mechanic) asked some pretty basic questions, and I’ve decided to answer some of them.

    A loopIn public. Lucky you, Ken. Don’t worry! These were good questions. See, one of the (many) reasons I love WordPress and the support forums is that the answers are public so everyone can see what the question was and how it was answered! This is hugely important to foster a community, so that’s why I’m going to answer this in public, with your personal information removed, of course.

    Ken’s basic concern is that .htaccess is confusing, and is there a preferred order? The answer is yes. The basic idea is that .htaccess rules are a top-down process. The server reads the file from the top on down, in order, 1-2-3. For this reason alone, it’s obvious why you don’t want a super long .htaccess file: more to read takes longer!

    The WP permalink area… Should that always be dead last?

    Yes! WordPress rules always go last. Remember what I said about top-down? If you were to put WordPress at the top, you would load WordPress, process it, and then do the rest of the rules. Which once you say that, it’s pretty obvious eh?

    Deny IP addresses/ referrers. To me it would make sense for them to be at the beginning… Would that be true?

    True! The access controls (including IP blocks) first. Redirects go next, starting from most specific (about-me to about) first to general last. Then your Rewrite rules.

    Compression/Caching/mod_expires… I haven’t a clue where they most appropriately go. Securing wp-config, htaccess itself, other files, etc. … Before? After? the WP permalink block.

    I put them before my re-writes. Since I use a deny to secure .svn type files, it’s an access control so it goes first.

    So how does this work? Here’s a practical example. You want to do the following: remove www from your domains, protect your wp-config file, protect your comments and login from direct attacks, redirect some old pages from before you were WordPress, redirect your old permalink formats, and gzip/compress things. Oh and run WordPress!

    The order would go like this:

    1. Access Control: This is the part where we’re protecting specific files, but also blocking IPs. Basically it’s ‘Security First.’
    2. Remove WWW: We want to make sure everyone’s redirected to the non-www page. If you’re redirecting specific domains (like I send tech.ipstenu.org to halfelf.org), you do it here as well.
    3. GZIP: I do my compression here, though it woudl work just as well swapped out with the next one.
    4. Redirect: Here we’re talking one-off redirects like sending ‘about-me’ to ‘about’.
    5. Rewrite: The ReWrite rules are the ones where you say “Send http://example.com/2014/01/10/postname/ to http://example.com/postname/” with those rules with regex.
    6. WordPress Rules: Last. Always always last.

    And that is .htaccess!

    If you want a look at how my .htaccess is structured, see My super-secret .htaccess file, which hasn’t changed much since 2013. I do a couple things out of order, but they’re minor enough. As long as I can limit any recursive loops with the .htaccess checks, I’m doing good.

  • New Smilies?

    New Smilies?

    While the arguments for and against are pretty hot and heavy (see the trac ticket for more), it’s no secret I’m pro-new smilies. The old ones are too small, too pixelated, and too (pardon the phrase) web 1.0. They look old and out of date on my site.

    Here they are at normal size:

    Old Smilies, normal sized

    And here’s double:

    The smilies at twice size

    These are both gifs, to illustrate the size issue. Notice how they’re fuzzy?

    I want to make one thing clear, pun intended. None of my issues have to do with Retina. I don’t like ‘small’ anything. The smilies are too small, much like the font on many people’s websites, the pixelization is hard for me to identify. In fact, while I’m using the new smilies here, you’ll notice they’re bigger. Sure, cause I tossed this in my CSS:

    #wp_grins img, img.wp-smiley {
        height: 25px;
    }
    

    And that’s all it took to make them something I felt was readable. But the beauty, and why I like the new SVG images, is that I can make them larger like that, without losing readability.

    Thankfully, due to the curmudgeony efforts of the new smilies’ biggest naysayer, Otto, we have a filter! I’ve talked about this before, in how I handled both SVG and PNG as smilies for IE. I have a couple options here. I could write some code myself, or I could use New WordPress.com Smileys (which is on GitHub for reasons, the code is fine!).

    I like the plugin a lot. I like it so much, I refactored my SSL Grins plugin to use them with the fancy pants new span code (instead of images). But… Well, I already had this done by the time his plugin came out, and I like how I accounted for things differently. The only real difference though is he uses spans, and I just swap out the images:

    <?php
    /*
    Plugin Name: Custom Smilies
    Plugin URI:  https://ipstenu.org
    Description: I like the new smilies, shut up Otto.
    Version: 1.0
    Author: Mika Epstein
    Author URI: https://ipstenu.org/
    */
    
    // Move Smilies
    add_filter('smilies_src','helf_smilies_src', 1, 10);
    function helf_smilies_src($img_src, $img, $siteurl) {
        if ( strpos( $_SERVER&#91;'HTTP_USER_AGENT'&#93;, 'MSIE 8' ) || strpos( $_SERVER&#91;'HTTP_USER_AGENT'&#93;, 'MSIE 7' ) || strpos( $_SERVER&#91;'HTTP_USER_AGENT'&#93;, 'Android' ) ) {
            $img = 'ie/'.$img;
        }
        else {
             $img = str_replace("png", "svg", $img); // Remove PNG
        }
        return $siteurl.'/code/images/smilies/'.$img;
    }
    
    // This is in a paren for my sanity....
    {
        global $wpsmiliestrans;
    
        if ( !get_option( 'use_smilies' ) )
            return;
        
        if ( !isset( $wpsmiliestrans ) ) {
            $wpsmiliestrans = array(
            ':mrgreen:' => 'icon_mrgreen.png',
            ':neutral:' => 'icon_neutral.png',
         // removing b/c new versions
            ':twisted:' => 'icon_evil.png',
              ':arrow:' => 'icon_arrow.png',
              ':shock:' => 'icon_eek.png',
              ':smile:' => 'icon_smile.png',
                ':???:' => 'icon_confused.png',
               ':cool:' => 'icon_cool.png',
               ':evil:' => 'icon_evil.png',
               ':grin:' => 'icon_biggrin.png',
               ':idea:' => 'icon_idea.png',
               ':oops:' => 'icon_redface.png',
               ':razz:' => 'icon_razz.png',
               ':roll:' => 'icon_rolleyes.png',
               ':wink:' => 'icon_wink.png',
                ':cry:' => 'icon_cry.png',
                ':eek:' => 'icon_surprised.png',
                ':lol:' => 'icon_lol.png',
                ':mad:' => 'icon_mad.png',
                ':sad:' => 'icon_sad.png',
                  '8-)' => 'icon_cool.png',
                  '8-O' => 'icon_eek.png',
                  ':-(' => 'icon_sad.png',
                  ':-)' => 'icon_smile.png',
                  ':-?' => 'icon_confused.png',
                  ':-D' => 'icon_biggrin.png',
                  ':-P' => 'icon_razz.png',
                  ':-o' => 'icon_surprised.png',
                  ':-x' => 'icon_mad.png',
                  ':-|' => 'icon_neutral.png',
                  ';-)' => 'icon_wink.png',
            // This one transformation breaks regular text with frequency.
            //     '8)' => 'icon_cool.png',
                   '8O' => 'icon_eek.png',
                   ':(' => 'icon_sad.png',
                   ':)' => 'icon_smile.png',
                   ':?' => 'icon_confused.png',
                   ':D' => 'icon_biggrin.png',
                   ':P' => 'icon_razz.png',
                   ':o' => 'icon_surprised.png',
                   ':x' => 'icon_mad.png',
                   ':|' => 'icon_neutral.png',
                   ';)' => 'icon_wink.png',
                  ':!:' => 'icon_exclaim.png',
                  ':?:' => 'icon_question.png',
            // New for me
                  '>:(' => 'icon_mad.png',
                  'o_O' => 'icon_surprised.png',
                  'O_o' => 'icon_eek.png',
                  '^^‘' => 'icon_redface.png',
                  ':‘(' => 'icon_cry.png',
                  ':’(' => 'icon_cry.png',
       ':whiterussian:' => 'icon_whiterussian.png',
                  '|_|' => 'icon_whiterussian.png',
                   ':/' => 'icon_uneasy.png',
                  ':-/' => 'icon_uneasy.png',
          ':developer:' => 'icon_developer.png',
            ':burrito:' => 'icon_burrito.png',
            ':martini:' => 'icon_martini.png',
                  '>-I' => 'icon_martini.png',
              ':blush:' => 'icon_redface.png',
              ':heart:' => 'icon_heart.png',
                //'&amp;lt;3' => 'icon_heart.png',
               ':bear:' => 'icon_bear.png',
               ':star:' => 'icon_star.png',
                  '(w)' => 'icon_wordpress.png',
                  '(W)' => 'icon_wordpress.png',        
            );
        }
        
        if (count($wpsmiliestrans) == 0) {
            return;
        }
    }
    

    But why don’t they all show up in my comments section? Where’s the martini!? I also upgraded my plugin SSL Grins with an ‘easter egg’ of code that hides anything in this array of smiled_hide. This works on both my version of the smilies plugin and Avryl’s. and looks like this:

    $smiled_hide = array("bear", "wordpress", "martini", "developer", "whiterussian", "burrito","icon_bear.gif", "icon_wordpress.gif", "icon_martini.gif", "icon_developer.gif", "icon_whiterussian.gif", "icon_burrito.gif", "icon_bear.png", "icon_wordpress.png", "icon_martini.png", "icon_developer.png", "icon_whiterussian.png", "icon_burrito.png", "icon_bear.svg", "icon_wordpress.svg", "icon_martini.svg", "icon_developer.svg", "icon_whiterussian.svg", "icon_burrito.svg");
    

    Now this is possibly the jankiest, stupidest, code I’ve written in a while. I’d rather just have the words be there, and filter “If any of the values in this array is a partial match to the name of the smilie we’re looking at right now, don’t show it.” But I’m not clever enough with arrays and preg matching at this point, so I did that ugly list, and used this:

    if (!in_array($grin, $smiled) && !in_array($grin, $smiled_hide) ) {...}
    

    So at this point, pull requests are welcome because I’d love to clean that up!

  • Bad Browser Complacency

    Bad Browser Complacency

    Back in the day, you may have seen notices on browsers like “This site best viewed in Internet Explorer v4.” Since then, we’ve moved into the belief that a website should work on as many browsers as possible, and degrade nicely when it can’t. So imagine my surprise when I’m looking at photos online and I get a message saying I’m using an unsupported browser.

    I happened to be using Chrome on my iPad, so I clicked the link which took me to http://www.corbisimages.com/BadBrowser and I saw this:

    Bad Browser

    I was taken aback. Not that they say ‘IE 7 and up’ as it’s something I try to support as well. Frankly making sites look awesome on IE is about as easy and fun as a dental student doing your root canal. You’ll get there in the end, but it may hurt like hell.

    Now, Corbis has certainly one of the more out of date designs for a photo sites I regularly visit (there are 10), but it’s not the most egregious. Yes, there are worse ones. Still for a site to have an alert like this in 2014 and to omit Chrome is rather shocking. Someone remarked it looked like that site was designed circa 2003 and Chrome, if you didn’t know, only came out in 2008. So while I remember this new design for Corbis being rather recent (2012 or 2013, but that may have just been some tweaks), it’s clear they’ve not visited that page in at least six years.

    I talked to my family about web design at a recent brunch, stressing that I do not do website design per se, but I am happy to help them find people and upload their content. At that time, I pointed out that the trick to a website was to frequently update it and make it more modern. “It’s like the runway shows,” I replied. “What’s in this season was weird last season and may be out by next season. So making a site and never changing it is as smart as never updating your wardrobe.”

    Older fashion, not that good looking todayPeople judge by how things look. If someone only wears a black turtleneck and jeans (Steve Jobs), we create a specific mindview of them and it rarely changes. Someone who always wears avant-garde clothes that are nearly unwearable (Katy Perry), we create another. If that person always wears a suit jacket (Tim Gunn), we have yet another view. Neither is right or wrong, of course, and they all have their places.

    We update our wardrobes when we gain and lose weight, when we decide we want a change, when we feel different, when we have to change, when we want to. While I tease that Brian Gardner is never satisfied with a web design and is always changing, I’m often just as guilty of this as I don’t feel things fit forever. If I’m not afraid of changing my wardrobe, why would I be afraid of changing my website?

    And yet. We worry a lot more about the change of design, to the point that sites like Corbis haven’t significantly changed or adapted since 2002, when the site was born. Since then, 12 years have gone by, browsers have changed, security changed, and the viewing experience is wildly different. Corbis on a phone? Yeah not a great experience.

    When your site never changes with the times, never grows to adapt to it’s new audience, you lose respect in the world of the Internet. We have to keep up with the times, test and retest on as many browsers as humanly possible, and make sure that it all works. We can’t just say “Yes, this one design is good” and more so, we can’t say “This site works best on…” anymore.

    Unless you’re the sort to say “This jeans only work with turtlenecks.” Then, by all means, never change.

  • You Are The Weakest Link

    You Are The Weakest Link

    I sit by people who are on the phone with customers about their accounts all day. Each and every day I hear them talk to customers who are past due or need to activate a new credit card or had an account closed by not paying. In general, I marvel at how consistently nice these coworkers of mine are, considering the number of times I hear people screaming at them. But I also get to hear some fairly impressive conversations.

    Locked safeMost of the time, the conversations are mild, a reminder that you actually have to pay, here’s how you pay, off you go. But once in a while you get to hear the tale of someone who wants to cancel an account. This is only interesting because we don’t cancel your account for you. You have to log in and cancel the charges and billing. About once a day, someone asks why we can’t just accept they are who they say they are and close the account, and I hear my coworker explain over and over that it’s not secure. We can’t verify you over the phone, we called you, and… well there’s a reason you have to call your bank and not the other way around.

    Recently I had a credit card jacked, causing me to miss a payment I didn’t know I owed. I was called by a bill collector after 60 days and they asked for my account information. I balked and asked what card he was calling about, what was the amount, when was it charged, and so on. Then I hung up (I tried to tell him thank you, he kept talking) and called the card company directly. They confirmed the situation, I explained it wasn’t me, we got the bill reversed, everyone was happy… except me. I pointed out having some random number call me and claim to represent them was not safe or secure. They agreed, and also remarked that I shouldn’t have had a collection agency after me at only 60 days, so clearly they had a billing problem.

    I’m a little thoughtful about my security, if you can’t tell. So when I read my friend Gary’s story about Paypal’s lack of security, it surprised me. There’s no true Two Factor authentication on something that has access to my bank account, just a dongle I’d have to pay for (and keep handy) or SMS. And when you read more into why Gary turned on SMS (see the story about how @N lost his user name and $50k), it gets more disturbing.

    Social engineering to figure out passwords and pose as other people is easy. I do it all the time when I need to set up something for myself and my wife, and the company says she has to call too. I happen to have all of her information, down to access to her email (after all, I’m her sysadmin), and we actually made a specific joint email address for things like our bank account. If you have the information, it’s not hard to do.

    Chains around a railingWe can blame GoDaddy and Paypal all we want for this. Should they accept the last four digits of my credit card as identification? Should they accept my social security number? What about my password (which means they can read it, by the way), or what about a special password used only for verification? Now I have to remember more, carry more, and know more all the time. It’s information overload. And because of that, because we’ve complained, they do less.

    People see our credit cards all the time. You handed your debit card to someone to pay your eye-doctor’s co-pay, or for that latte. We tweet about our first pets and mother’s maiden names, and we Facebook everything. It’s pretty obvious that the weakest link in security, and the reason social engineering can easily exploit them with companies, is us.

    There isn’t a perfect way to protect ourselves, though. Last year my phone got wiped and I lost my Google Authenicator settings. I had secondary login codes for Google itself, but not WordPress.com (I’d never set them up) so I was unable to log in. After skyping and emailing two of my good friends who work there, I was able to get back in, but had they not been able to know it was me, what could have happened?

    Every time someone asks me what I do to be safer online, I tell them this “I am working to eradicate my ability to be stupid.”

  • Save Bacon With ModSecurity

    Save Bacon With ModSecurity

    Earlier this month, my company DreamHost had a small snafu with ModSecurity. The tl;dr is that we had a typo and it stopped some people from being able to access or properly use Jetpack. Thankfully, the WordPress community (including everyone at Jetpack, whom I owe drinks and/or dinner) is filled with amazeballs awesome people who helped us figure out everything and sort out customers who, upon getting what appeared to be a Jetpack error, went there when they needed to go to DreamHost.

    Water hook up for a firetruckThese things happen. Code isn’t perfect, people aren’t perfect, and everyone makes mistakes. Of course, on the internet it’s unreasonable to assume a legit gaff, and I’ve seen people call out “Why was DreamHost pushing out these tweaks?” and “Didn’t they test?” so I thought perhaps it was time to explain why we use Mod Security and why, even though it’s my nemesis, I like it a lot.

    What is ModSecurity anyway?

    ModSecurity (aka modSec or mod_sec) is an open source web application firewall (WAF). That means it sits between your website and the world, blocking all the bad people. When we have those brute force attacks, ModSecurity is key in blocking them. It blocks people who attempt code injection attacks like this:

    http://www.example.com/wp-login.php?username=admin'">DROP%20TABLE%20wp_users--
    

    Now that would never work on WordPress core, but the Bobby Tables attacks have the potential to kill your site if you have a plugin or theme that’s insecure. Most hosts have customized their rules to check for things like hitting the wp-login page improperly or passing through credentials directly. That means if someone tries to log in to your site without clicking the submit button (yes, you can code that), it will block them.

    One of my favorite things about ModSecurity is that you can hook it into another firewall like ConfigServer, Fail2ban, or even the built in linux feature of IPTables, and block any IP that routinely trips your security rules.

    So why was DreamHost monkeying with it anyway?

    Every host is constantly monkeying with ModSecurity. As attack patterns grow and change, your host has to adapt. There’s a team at pretty much every host on the planet who watches logs, studies them, and improves the ModSecurity rules. Heck, we even share our rules with other hosts when the situation calls for it, like that Brute Force attack back in 2012. It was brand new, we were all surprised at the aggressiveness, and we quickly shared information.

    On any given week, your host is creating new rules and testing them in their dev environment, or on specific real servers that are designated “Go ahead, blow me up.” After all, we all know nothing beats real-world testing. And if push came to shove and one specific site was being hammered, we may push an experimental rule to them before we’re done testing everything, because it’s that or your site is down.

    We’re always working and improving. Security is a moving target after all.

    How come a typo slipped through?

    If you can find me someone who makes a 100% perfect product every single time, I’ve got a bridge for you to buy. We tested everything we could think up, and interestingly enough, that Jetpack error didn’t impact all Jetpack users! We have a test box, with Jetpack, and it worked fine there. Go figure.

    Flame from a laternBut I’ve often said your website is a pretty snowflake. It’s unique, and what you do with it is different from what everyone else does. Things I have and do on this server and this domain are wildly different from my other sites on this same server! The need for the site is different, and what it uses is different, so what it does when it communicates with the world? Different.

    I’ve had days where one domain is acting like a prat, but the others are fine. And I’ve sat there thinking “But it’s the same on these domains! They’re on the same server for God’s Sack!” only to realize that the usage pattern of the sites were very much not the same. And that takes everything longer to fix because you have to narrow things down over and over until you actually find out what the heck you did wrong.

    I can’t even tell you this will never happen again because I’m pretty sure someone will make a mistake again sometime in the future.

    Conclusion?

    I wouldn’t run a site without ModSecurity, but there are options.

    In February 2013, Zero Science Lab released a study comparing it to Incapsula and Cloudflare. While ModSecurity came out on top (though it was noted to be more aggressive and caused more false positives), Incapsula has been working hard to fix it’s issues. There was actually a Round 2: Incapsula vs Cloudflare study in October 2013, and in this one, Incapsula is the clear winner. Of note, you won’t get the WAF protection on either for free.

    The studies say, to me, that if you’re master of your own domain and want the firewall on your server to run yourself, use ModSecurity. If you’re going to farm that security out to the cloud, use Incapsula. There are, of course, benefits to putting the firewall on the cloud, and the major one is that you’ll be spared high CPU since the processing of the naughty people is done on their server, not yours. But of course, if they go down, you’re at risk, so you should probably have ModSecurity anyway.

    After all, your website is important, right?

  • It’s Better to Extend

    It’s Better to Extend

    If you’ve heard me answer the question “Why is this a plugin and not in core?” then you’ve probably heard me say “It’s better for WordPress to be extendable than to include everything.” And you’ve certainly heard me tell folks that the concept of Open Source development is different than many of you think.

    One of the many reasons I liked WordPress was that, unlike other apps, I didn’t have to spend the first week after install turning off a great number of features that I didn’t want, just to have the core application that I did want. WordPress stood apart by assuming very little. You want to publish content. That’s pretty much it in the beginning. As things changed with the times, comments and media uploading were added, but at it’s heart, WordPress has remained pretty on point.

    Simplicity.

    ExtendWordPress doesn’t want to get in the way of your content. It would rather make decisions, not options, to keep it simple. We constantly argue about better ways to simplify, how we can remove options to improve usability, how we can make things easier and faster.

    Earlier this month, my friend George ruminated on decisions and specifically talked about how to make his code serve two masters:

    To each according to their needs. Typical users need a simple, smooth, classy interface. Power users need to get under the hood. Why try to make something that doesn’t work well for either by trying to serve both?

    This is the route WordPress tries to take, and it has some pretty incredible payoffs. If you don’t need to get under that hood, your site is lean, fast, and perfect. If you do, you can totally monkey with your engine all you want to make changes. But that user who has no idea what we mean when we say “add a filter to the output…” doesn’t have to learn anything new. They can just install a plugin and go.

    By being extendable, WordPress is able to keep itself small and let you make the decision of what you need. It also lets you pick out what’s important to you, and this is a hard choice. We want a lot of bells and whistles on our sites, but we know they’ll possibly make things slow. We have to decide what we care about more, what can we sacrifice, and what must we keep.

    So when I tell people “It’s better that WordPress is extendable.” I do so understanding that I put the work on you, and not core. I’m making you do the hard part, the part of weighing options and features. The part of telling a client “No” because that awesome slider will make their page slow. I’m putting you on the spot.

    I think that may be why people get made about this whole thing, more so than the trials and tribulations of finding the right plugin. Of course finding a good plugin that won’t break is hard. You should be circumspect about plugins and themes, test them well, don’t just use them because they’re super pretty. But here I am saying that we’re lazy, over in WordPress land, and we want you to decide what you need.

    Man touching his iphoneMany of you use smartphones. Many of you buy in-app purchases. Many of you, like me, think that in-app purchases are kind of a terrible thing. Thomas Baekdal goes a step further and argues they are destroying the gaming industry. Many people argue WordPress does the same thing. The core is free and the add-ons may be free or they may cost money. Heck, I paid for this theme, it’s parent theme, and some plugins!

    Let’s take Easy Digital Downloads, a plugin I use. It’s free. I have six specific add-on plugins for it, though to do things I want. One I wrote, three are free, and two I paid more for. Why is that okay? Because unlike the model of paying to speed things up, EDD lets me pay to add what I NEED. I needed a PayPal alternative (PayPal is free by the way), so I bought Stripe for my users who can’t use PayPal. I wanted (not needed) a way to let people pick prices in some places, so I decided to buy that as well. But everything else has been free. That’s nothing like the In-App payments, that’s what they wanted to be but didn’t manage.

    So it’s better to extend because I decide what I want, and I decide where to spend money, and I decide what to do. WordPress without those extensions? Still works. There are hundreds of options to do what I did totally for free, legally and morally free of implications too. I paid for the speed and connivence, but I didn’t have to worry about things I didn’t want or need because I didn’t add them.

    I like the place where I decide what I need.