• TIL for July 14, 2016

    Inverse regex filtering with varnishtop

    I was curious which user agents were accessing a side project of mine, but I wanted to exclude user agents that contained the string “Mozilla.” Luckily, Varnish includes a tool called varnishtop which is exactly designed for this sort of question.

    To view all user agents, the command would be: # varnishtop -C -I ReqHeader:User-Agent. Pretty simple and actually taken directly from the man page.

    My hope was then that something like # varnishtop -C -I ReqHeader:User-Agent -X Mozilla would include all request headers that contained User-Agent and then exclude any that contained “Mozilla” but this didn’t work. Basically, each -I and -X option is “OR’d” together, not “AND’d” together.

    After picking up some tips from StackOverflow, I figured out the syntax that I needed. Basically, I had to negate directly within the include (-I) option: # varnishtop -C -I 'ReqHeader:User-Agent: (?!Mozilla)'.

  • TIL for June 17, 2016

    Missing MySQL headers when compiling PHP

    On Ubuntu, MySQL header files are located in the “libmysqlclient-dev” package.

  • TIL for June 15, 2016


    My Vagrant/Homestead box started consuming tons of CPU, so I ran vagrant halt. This hung for 5-10 minutes without progress, so I Ctrl+C’d it and tried again. Quickly exited without any sort of error message.

    At this point I tried vagrant up but it complained “Stderr: VBoxManage: error: The machine ‘homestead-7’ is already locked for a session (or being unlocked)”.

    After a bit of Googling, found this. Running VBoxManage startvm homestead-7 --type emergencystop got it to shut down properly and vagrant up worked after that.

  • TIL for June 14, 2016

    SecLists by Daniel Miessler

    This repository is “a collection of multiple types of lists used during security assessments. List types include usernames, passwords, URLs, sensitive data grep strings, fuzzing payloads, and many more.”

    Stumbled upon it while trying out wpscan. Within wpscan, you can pass in a wordlist of potential passwords and it’ll loop through them all against a given user.

    Revert to a previous theme via MySQL

    If you install a new WordPress theme and it doesn’t work and it even breaks wp-admin, you can revert back to the previous theme by modifying a few values in the wp_options table:

    update wp_options set option_value = '<old theme basename>' where option_key in ('template', 'stylesheet');
    update wp_options set option_value = '<old theme proper name>' where option_key = 'current_theme';

    Where “basename” is the name of the directory within /wp-content/themes/ and “proper name” is the name metadata as provided in style.css.

  • TIL for June 09, 2016

    Silence notices when WP_DEBUG is true

    Setting WP_DEBUG to true in wp-config.php turns on errors, warnings, and notices so you can see all the places your code needs attention. This is fine as far as it goes, but WordPress makes it very cumbersome to modify the error reporting level so only errors and warnings are displayed while notices are silenced.

    However, after much trial-and-error I figured it out. In a nutshell, you need to create a PHP file in /wp-content/mu-plugins/ that contains the following:

    error_reporting( E_ALL ^ (E_NOTICE | E_USER_NOTICE) );

    Setting this in php.ini and wp-config.php never worked, I believe, because WordPress would override the value when it saw that WP_DEBUG was set to true.

    But by setting the error_reporting level by way of a “must use” plugin, it happens late enough in the request cycle to actually make a difference.


    (I came across the above article early in the debugging process, but it didn’t seem to work at the time. Only once I remembered it and tried after about an hour of debugging did it work.)

    Making changes to php.ini FPM

    A big chunk of the time I spent debugging the above issue was because I couldn’t get the php.ini config file inside Homestead to pick up any changes I made to it.

    Long story short: sudo kill <pid of php-fpm master process> did the trick.

  • TIL for June 07, 2016

    Permissions errors with rsync

    An rsync error message of “rsync: failed to set permissions on “/path/to/some/file”: Operation not permitted (1)” occurs when the user you’re logging into the machine with tries to change permissions on a file owned by another user.

    To fix, change the remote file’s ownership to the user you log in via rsync with.

  • TIL for May 27, 2016

    Using empty() in PHP

    Here’s a gotcha I did not know existed: PHP’s empty before version 5.5 only works on variables. If you try to pass in an expression, it will fail hard (like HTTP 500 hard).


  • TIL for May 26, 2016

    Add FontAwesome icon with only CSS

    I wanted to add a check mark provided by the FontAwesome project to a bunch of <li> items, but without mucking around in the HTML. Here’s how I did it:

    li::before {
      font: 20px FontAwesome;
      content: "\f058";

    Because FontAwesome is just a specialized font (think Wingdings 2.0), it’s easy to plug it into the content property. Coupled with the ::before psuedo-selector, and it’s a piece of cake.

  • TIL for May 20, 2016

    Python slugify function

    I often need to transform a string to something usable in a URL. Over the years I’ve used this snippet a bunch to do just that:

    >>> import re
    >>> def slugify(s):
    ...   s = re.sub('[^\w\s-]', '', s)
    ...   s = re.sub('[\s-]+', '-', s)
    ...   return s.lower().strip('-')
    >>> slugify(" Hello  World - and, this'   shows? ALL. the neat (<stuff>) that slugify can do! ")

    (nb: “slug” is a a newspaper term that is much used throughout Django, the web framework I cut my teeth on. As a concept, it maps very nicely to URLs).

    The thing I like most about this snippet is 2/3 of the function body is about removing characters instead of adding/replacing them.

    Like if the input string already has a dash, it removes it before going any further.

    If, after the first line, there is one or more dashes in a row, it collapses them into a single dash.

    This all results in a very clean output.

  • TIL for May 17, 2016

  • TIL for May 05, 2016

    Increase media library max upload filesize

    When working with a multisite Wordpress installation, to increase the max upload filesize you have to change the setting in the “Network Settings” dashboard.

    post_max_size and upload_max_filesize don’t seem to have any effect.


  • TIL for April 25, 2016

    Simple CLI date calculator

    I needed to know the date of something that occurred 30 days prior to the UNIX timestamp value. Here’s how I did it.

    First, I converted the UNIX timestamp using the GNU date command found in coreutils:

    $ gdate -d @1459966497
    Wed Apr  6 11:14:57 PDT 2016

    From there, gdate is pretty flexible on input formats:

    $ gdate -d 'Apr 6 - 30 days'
    Mon Mar  7 00:00:00 PST 2016

    (nb: I used Homebrew to install GNU coreutils, and it prefixed all the utilities with “g” to differentiate them from their BSD equivalients. On GNU/Linux systems, regular date should probably be used.)

  • TIL for April 18, 2016

    Negative background positioning

    To set a background image just a little bit off the bottom right, use calc:

    background-position: calc(100% - 5px) calc(100% - 40px);

    background-position: bottom right is synonymous to background-position: 100% 100% which would put the image at the bottom right of its container.

    All the calc does is move the image 5px to the left and 40px up.

    Delete a problematic character

    I was trying to parse some XML but it kept failing. Eventually tracked it down to a “substitute character” in the file that was messing everything up.

    Because the file was over 140,000 lines, editing it with text editor was not something I wanted to mess with.

    Eventually remembered the tr command-line tool that normally translates character sets but can also delete them:

    $ tr -d '\032' < input.xml > output.xml

    032 is the octal character codepoint of the “substitute character.”

  • TIL for April 06, 2016

    Set CSS width to given number of characters

    I have a block of text in a <pre> element rendered with font-family: monospace. I want to set the width of the <pre> element to be 86 characters wide, the length of the longest line in the block.

    width: 86em doesn’t work here because it takes the current element’s font-size, multiplies by 86, and sets that as the width. This would work if, for a font-size: 13px, each character was exactly 13px wide but in my experience that won’t be the case.

    What works, instead, is width: 86ch which is the width of the “0” (zero) character. But because we’re using a monospace font, “0” will be the same width as all the other characters.

  • TIL for April 05, 2016

    Hide folders from view in Finder

    There are some folders in my $HOME directory that I only access through the command-line. Here’s a command to hide them from Finder:

    $ chflags hidden <path>

    To unhide, use the nohidden command. This also works on files.

    Quickly delete a lot of files

    $ mkdir -p /tmp/empty/
    $ rsync -aP --delete /tmp/empty/ </path/to/delete/>
  • TIL for April 04, 2016

    VLOOKUP with error-checking in LibreOffice

    I’ve used this before but it’s been ages and I always forget the syntax:

    =IFNA(VLOOKUP(A1, Sheet2.$A$1:$B$1000, 2), "")

    LibreOffice requires a dot to separate sheet names from cell references. I believe Excel and Google Sheets uses an exclamation point.

    The IFNA tells LibreOffice to use the lookup if found, otherwise use empty string.

  • TIL for April 02, 2016

    Fix Flask app after upgrading to Heroku’s cedar-14 stack

    After upgrading my cedar stack to cedar-14 and trying to push some new code I added to hnrss, Heroku error’d out in spectacular fashion comaining about pip vendor, a bad hashlib, and a missing urllib3.

    After some searching around, I finally found a solution on Stack Overflow:

    $ heroku plugins:install
    $ heroku repo:purge_cache -a <project>

    After running this, I ran git push again. It built everything from scratch and worked like a charm.

  • TIL for March 25, 2016

    Subresource Integrity

    To ensure the scripts and stylesheets you load aren’t maliciously altered, tack on an integrity attribute that returns a base64-encoded string of one or more SHA digests:

    <script src=""
            integrity="sha384-ECTndYny330R2jlSXBiZkdXzAVi0Z/iDXJTwV6cp39HECmalqg6+b2sFZFf/Y2m6 sha512-epzJ9ms+0Pq+zFMrG1lXVNvjEXgtfKx9iuEWqz3hmbaU2m/Dp1pcmpYzuSdDLqX6PMIjzMOyGFwMc+SkgFhMFg=="

    With the integrity attribute, the browser will not load the script unless the base64-decoded digest matches the content of the script source. This also works on <style> tags. The crossorigin attribute is to enable CORS support.

    To speed up the creation of SRI digests, I whipped up a small script that spits out SHA384 and SHA512 digests:

    #!/usr/bin/env bash
    echo -n "sha384-"
    curl -s "$1" | openssl dgst -sha384 -binary | openssl base64 -A
    echo -n "sha512-"
    curl -s "$1" | openssl dgst -sha512 -binary | openssl base64 -A
  • TIL for March 24, 2016

    Hello again!

    Been quiet here at TIL headquarters. Combination of deadlines and maybe a little of burnout contributed to that. But back at it thanks to some gentle prodding by my TIL brother-in-arms, Chuck Grimmett.

    Custom HTML checkboxes via CSS

    See the Pen PNmrJv by Eric Davis (@edavis215) on CodePen.

    The HTML has three elements: a input[type=checkbox], a label, and a span describing the checkbox value. It’s important here that label has a for=id0 attribute that maps to the checkbox id=id0 attribute. Doesn’t have to be id0, of course, just has to map.

    The CSS has three parts. First, the checkbox is hidden completely. Second, the label is transformed into the “new checkbox” by setting width, height, and a display property. Finally, the label is given a certain set of properties when the checkbox is unchecked and another set of properties when it is checked.

    The checkbox receives the :checked psuedo-selector because we’re now clicking on the label itself which has the connection to the input[type=checkbox] field via the for=id0 attribute.

    Set an image source via CSS

    This falls on the “hacky” side of the ledger – content should only be used with psuedo-selectors, no Firefox support – but I think it’s pretty cool:

    .selector img {
      content: url(/path/to/image.png);

    My initial goal with this was to use one header on pages A, B, C and another header on X, Y, Z.

    But the lack of Firefox support led me to drop this approach and go with a Javascript solution.

  • TIL for March 08, 2016

    Enabling larger uploads in WordPress

    To increase the size limit on file uploads in PHP/WordPress, set two PHP config variables inside the <VirtualHost>:

      # ...
       upload_max_filesize 50M
       post_max_size 50M
      # ...

    Git checkout previously checked out branch

    To quickly switch to your previously checked out branch without explicity naming it, run git checkout -.

    $ git branch
    * master
    $ git checkout fix-header
    Switched to branch 'fix-header'
    $ git checkout -
    Switched to branch 'master'

    This was useful to me as I was testing the effects of some undeployed code on master while also checking how things worked on an earlier commit.

    To switch branches, all I had to type was Ctrl+P and hit enter. This pulled up git checkout - and I was able to quickly bounce back-and-forth between revisions.

  • TIL for March 07, 2016

    Fix Homebrew permissions after El Capitan upgrade

    I upgraded to El Capitan over the weekend and today hit an error about /usr/local not being writable. Running brew doctor said to run the following to fix the issue:

    $ sudo chown -R $(whoami):admin /usr/local

    After that, the error went away and everything worked perfectly.

    Changing domains on a WordPress multisite installation

    If you get a “Cannot establish a database connection” error while trying to move a WordPress multisite installation to a new domain, you have to update the domain column in wp_blogs to your new domain:

    UPDATE wp_blogs SET domain = '<NEW DOMAIN>';

    You also have to update the home, siteurl, and fileupload_url values in the wp_X_options tables.

    I don’t know all that much about WordPress multisite, so maybe this method is hacky and should be avoided. But it worked for me with no downsides, so I went with it.

    Redirecting www subdomain to bare domain

    I normally like doing this in a <VirtualHost> block, but the client is on shared hosting and I only have access to .htaccess:

    RewriteCond "%{HTTP_HOST}" ""
    RewriteRule ^{REQUEST_URI} [R,L]
  • TIL for March 04, 2016

    Manage WordPress plugins with composer

    Haven’t had a chance to try this out on a live site yet, but I’m intrigued by the idea of using composer to manage WordPress plugins.

    One issue we’re working through at work is how best to track external, third-party code on WordPress sites.

    I’m of the mind that our git repositories should only contain the code that we’re responsible for. WordPress core, plugins, and other dependencies should sit on top of our checked-out git tracked files to comprise a fully functional site.

    But, yesterday, our lead sysadmin had the good point that this technique prevents us from being able to fully re-create the environment at any given commit.

    Enter composer.

    With composer, we would list our plugins and dependencies in a config file and composer would take care of installing them.

    This way we have a record of the site dependencies without having to track the files themselves.

    Still need to think through how to handle WordPress proper with this technique. It’s technically a dependency but the only way to install it via composer is through third-party projects not blessed by the official project. Not crazy about that.

    But installing plugins is our biggest hurdle right now, which composer handles just fine.

    Remove email message that can’t be moved to Trash

    No idea how bulletproof this is, but it worked for me on Apple Mail v6.6 using a Microsoft Exchange email account.

    I had an email message that was out of my inbox and inside a “Smart Folder.” I tried deleting it but it could not be moved to trash.

    On a whim, I marked it as “Unread” and it removed itself immediately.

    Best hunch is setting the unread flag syncs with the server and since there was just a mis-sync between the server and the client, it was enough to tell the client the message shouldn’t be there.

  • TIL for March 02, 2016

    WordPress and enclosures

    When you publish or update a post in WordPress, it checks the post body for any audio or video URLs. If any are found, WordPress creates an _encloseme row (pointing to the post ID) in wp_postmeta and schedules a one-time WP-Cron event.

    This WP-Cron event looks for any _encloseme fields in wp_postmeta and for each one it finds, fetches any of the found audio or video URLs to determine file size and MIME type. It then inserts this data as a enclosure post meta variable and deletes the _encloseme.

    When rendering any RSS/Atom feeds, these enclosure post meta variables are included as <enclosure> elements.

    Safely remove hosts from known host list

    $ ssh-keygen -R <host>

    This is useful if a host changes their SSH keys and you need to get their new ones.

    Reset ID sequences in PostgreSQL


    This is useful if you DELETE FROM <table> a bunch of data and also want the sequence to start from the default value next time you start inserting data.

    Get the “Posts page” in WordPress

    $blog = get_option ( 'posts_for_page' );

    You can designate a given page as the “Posts page” in a WordPress site. If you need access to this page, use ‘posts_for_page’ to avoid hardcoding page lookup parameters.

  • TIL for March 01, 2016

    Display a file from another git branch

    If you have one branch checked out but want to see what a file looks like on another branch or a previous revision, use git cat-file:

    $ git cat-file -p <branch>:</path/to/file>

    It’s a slicker technique than checking out the branch and viewing the file directly. Especially if you have local edits that you’d otherwise have to stash or discard before changing branches.

    (git cat-file is actually a very versatile for examining objects in the Git database. Along with the gitrevisions manpage, you can inspect just about anything in the Git database.)

    Disabling WP-Cron

    Set the DISABLE_WP_CRON constant in wp-config.php to prevent WordPress from spawning its pseudo-cron implementation:

    define ( 'DISABLE_WP_CRON', true );

    If you set this, need to make sure /wp-cron.php is hit periodically, otherwise scheduled tasks won’t execute.

    Adding metadata to fields created by Advanced Custom Fields

    Use add_post_meta and update_post_meta and the field name provided when creating the custom field. ACF is smart enough to figure it out.

  • TIL for February 29, 2016

    Setting cookies via Javascript

    js-cookie is a great little library for setting cookies client-side:

    $(document).ready(function() {
      Cookies.set('foobar', 'quuz', {expires: 2});

    A particular use-case is when you need to send cookies but a server’s infrastructure restricts the use of Set-Cookie HTTP headers.

    CSS “all” property

    The all CSS property can be used to reset all of an element’s properties. Useful when an element has a bunch of properties and you want a clean slate for whatever reason:

    .desc {
      width: 85%;
      margin: 0 auto;
      padding: 10px;
      box-sizing: border-box;
      /* a dozen more properties */
    .page-42 .desc {
      all: initial; /* "inherit" and "unset" also valid */

    Biggest drawback to this technique is the total absence of Safari/iOS support.

    CSS :not() with attributes

    If you want a CSS selector that applies to everything except certain attribute names and/or attribute values, use the :not() selector:

    input:not([type=checkbox]) {
      /* apply to all inputs except those with a type of "checkbox" */

    Chrome CSS inspector tracks changes

    When tweaking CSS via the Chrome inspector, it keeps a running log of every change you make.

    Press ESC to open up the console window. Next to the “Console” tab there should be a “History” tab. As you make changes to CSS (either via the Elements or Sources main tabs), they’re reflected here.

  • TIL for February 26, 2016

    Enable WordPress maintenance mode

    Create a .maintenance file and include the following:

    <?php $upgrading = 1455233470; ?>

    Place the file in the root of a WordPress installation.

    The number is a UNIX timestamp. If the timestamp is less than 10 minutes ago, the “maintenance mode” screen will be displayed. After 10 minutes, WordPress bypasses maintenance mode and loads the site as normal.

    Maintenance mode will also be bypassed if the file exists but is empty.

    Use Apache Redirect for simple redirects

    Sometimes mod_rewrite is overkill and you just need a simple redirect put in place:

    <IfModule mod_alias.c>
      Redirect "/foo/" "/bar/"

    So a request for “/foo/” returns a HTTP status code 302 (temporary redirect) pointing to “/bar/”.


    Enable SSL on nginx

    Somehow I’ve used nginx for years but never got around to setting up HTTPS on it until now.

    Luckily it’s very simple. Here are the unique bits. Everything else was a pretty standard nginx server block:

    server {
      listen 443 ssl;
      ssl on;
      ssl_certificate /path/to/certificate;
      ssl_certificate_key /path/to/key;
      # ...



    • Jekyll’s highlight feature accepts “apache” and “nginx” as languages.
    • Safari doesn’t understand transform, have to use -webkit-transform.
  • TIL for February 25, 2016

    Disable SSL for a given host in lftp

    Add set ftp:ssl-allow/<host> false to ~/.lftprc

    I had a client’s FTP server that was redirecting me to FTP-SSL after the initial connection was made, but there was some mismatch on the certificates so lftp would error out. This setting prevents the redirection from happening.

    Hide untracked files in Git status output

    Use git status -uno or git config status.showUntrackedFiles no.

    I’m trying out a technique of only tracking the active theme files in Git and not touching anything else. This left me with tons of untracked files (other themes, uploads, plugins, core files, etc). Instead of fiddling with .gitignore (what I usually do), I’m keeping all of that untracked and just hiding it.

    Set the cache key for nginx’s uwsgi caching

    Add uwsgi_cache_key "$request_method $scheme://$host$request_uri" to the nginx config.

    By default, “uwsgi_cache_key” is an empty string. This leads to the first cachable response being delivered for all future requests (because the same key is always used).

    With this, cache each response under a key like: GET​

    (I like this style because it mirrors what a proper HTTP request looks like.)

    (h/t to Chuck Grimmett for the style and format of this TIL post. And for getting me to finally move to jekyll.)

subscribe via RSS