Half-Elf on Tech

Thoughts From a Professional Lesbian

Author: Ipstenu (Mika Epstein)

  • Representation of Code

    Representation of Code

    There’s a great many things to be learned from the drama of the recent Code of Conduct proposal. A great many people have demonstrated why one is needed, why ‘Just act professional’ is not a tenable long term solution, and why some people are exactly the sort of person who will fall afoul of the new guidelines.

    After all, who would really argue that these guidelines are ‘bad’:

    Examples of unacceptable behaviour by participants include:

    • The use of sexualized language or imagery
    • Personal attacks
    • Trolling or insulting/derogatory comments
    • Public or private harassment
    • Publishing other’s private information, such as physical or electronic addresses, without explicit permission
    • Other unethical or unprofessional conduct

    But that isn’t what it brought to my mind. The needs of a Code of Conduct are myriad, and the phrasing is complicated. It should be, at once, easy to understand and abide by, while being comprehensive and difficult to abuse. It should prevent rules-lawyers from gaming the system and min-maxing the hell out of their abhorrent behavior, while still permitting people to speak their mind. Anyone who’s played a table-top game with ‘that guy’ knows that pain.

    As I tweeted:

    Today PHP is learning that individuals bear the weight of representation of their groups.

    This is something everyone in a minority group has known for a long time. Not to throw politics into the mix, but compare the different reactions to the Baltimore protests of 2015 and the Malheur National Wildlife Refuge occupation of 2016. Consider the way some people are painted as ‘he should have known better’ and others are just ‘misunderstood.’

    One of the things I hate about WordPress is that I am now and forever representing it. Yes, forever. If WordPress is still around in 30 or 40 years, I will be representing it. If I leave it or say “Well I hate X” about it, I will reflect back on WordPress and my words will likely be taken and twisted around and contorted to mean something.

    Now and forever, I represent things that I am and things that I do. If I act like an ass online, it reflects on my company. A coworker of mine told a joke on Twitter and was subjected to attacks from someone who found it offensive. Whether or not the joke was tasteless, it reflected on him and our company. It doesn’t matter if the company endorsed it or not, nor does it really matter what our CEO may or may not have said regarding the situation. It matters that we represent myriad aspects of our life all the time.

    To give you a short list, I represent women, lesbians, LGBT as a whole, married people, childless families, Jews, Californians, Chicagoans, Canadians, Americans, caucasians, and please double the list and add ‘in tech’ to that. We haven’t even touched on things I work on and participate in the community like WordPress, Wikipedia, MediaWiki, Ada Camp, Hugo, Jekyll, PHP, ZenPhoto, etc etc and so on and so forth. Oh and DreamHost, the bank I used to work for, and possibly the guys I worked for before that. Then there are the games I play (D&D, Pern, WoD, etc).

    I don’t get to ‘stop’ being those things. Even though I’ve not played a MUSH in almost a decade, to some people I will forever be known as a MUSHer. And some people may change their opinions on me just hearing that. But also some people will say “Oh, she acts like that because she grew up on a MUSH.” And worse, “If she acts like that, then all MUSHers are assholes.”

    Look. We know it’s stupid. We all know that a person isn’t the sole representation of a thing, and yet we spend our lives looking over our shoulders because we will now and forever be what we are identified as being.

    It was hard for Leonard Nimoy to be Spock.

    Nimoy is so synonymous with his half-Vulcan alter ego that fans revolted upon seeing the title of his first memoir, “I Am Not Spock,” despite Nimoy’s insistence that behind the name was merely a nuanced explanation of the distinctions between himself and his character.

    When we think of him, we think of Spock, the role that made him famous. And it took him years to come to grips with understanding that he was now and always will be Spock to many of us. It’s a hard thing to accept, that you will forever represent yourself, a job you had for three years and a handful of movies, and that no matter what, whatever you say will reflect back on that.

    WordPress, PHP, those are our Star Treks and we are Spock.

    Live long and prosper.

  • GPL Isn’t Protecting You

    GPL Isn’t Protecting You

    Some days I know my plugin reviews are going to wreck me. January has had a lot of complaints from people about aspects of the GPL. Specifically they wanted to know how to protect themselves with the GPL.

    The truth is the GPL is not protecting anything except the right of the next guy to take your code and do stuff with it. And that terrifies people.

    I’m not entertaining a discourse on the merits or legality of the GPL here. Those comments will be deleted. Simply put, a requirement of the WordPress.org repositories is that to be hosted there you must be GPLv2 (or later). At that point, every other argument is moot. Your code has to be GPLv2 to be in the repositories. End of story.

    Okay. So what’s there left to discuss about protecting yourself and your code? Three things: Trademarks, copyright, and theft. Here we go.

    Trademarks

    GPLv2 doesn’t protect your trademark, but that doesn’t mean your trademark isn’t protected. While any image you put in your WordPress theme or plugin has to be given as GPLv2 compatible, that doesn’t void your trademark. A freely offered image that is trademarked (say, the WordPress logo) can be used in your plugin, but it comes with restrictions after all. The inclusion of the SVG of the logo in GPL code doesn’t change that.

    One of the things that changed in GPLv2 and GPLv3 was related to this. Remember, GPLv2 allows all code that does not include any restrictions that were not already in GPLv2. As long as license was as free (or freer) than GPLv2, it was deemed to be GPL-compatible (see the WTFPL). The issue with that is some licenses were very easy to comply with but had clauses like you couldn’t use certain trademarks. This caused confusion, as it was read as a restriction. The thing was that it wasn’t! Regardless of what the license said, you never had permission to use the trademark.

    This is good for companies. You can trademark your logo and, if someone takes it redistributes a fork with the logos still in it, they’ve violated trademark law. And you can protect yourself there. I suggest you read Joomla’s post on the matter of Trademark protection to get a better idea of how it all works.

    Copyright

    Copyrights are another thing that the GPL doesn’t protect. Except it does.

    GPLv2 and GPLv3 are both copyleft:

    To copyleft a program, we first state that it is copyrighted; then we add distribution terms, which are a legal instrument that gives everyone the rights to use, modify, and redistribute the program’s code or any program derived from it but only if the distribution terms are unchanged. Thus, the code and the freedoms become legally inseparable.

    What does that mean? Your copyright is yours. By the act of writing code, you own the copyright (with some exceptions, like if you’re hired to write the code). When you contribute code to an open source project like WordPress, you STILL retain the copyright unless you give it away, but the license is whatever the project’s license is. Most of the time this is fine, but as I recently saw with Hugo, this can be problematic when a project wants to change their license. Hugo had to get permission from every single person who had contributed.

    This is, by the way, why WordPress will probably always be GPLv2.

    One way around this is to require everyone to waive their copyrights in order to contribute. I believe DotNuke did this. Whomever owns the copyright, if the code is still licensed in a way that allows for free distribution then nothing’s really changed. The code is still open.

    Of course, then there’s the jQuery Foundation does with their Individual Contributor License Agreement – In order to contribute to jQuery’s code or website, you have to sign that and provide a valid email. This gives them a way to contact everyone and also makes sure you understand what you signed up for. WordPress just has a checkbox when you submit your code to remind you that you’ve given it up.

    If you’ve ever looked at the jQuery Foundation License, you may have noticed this line:

    You are free to use any jQuery Foundation project in any other project (even commercial projects) as long as the copyright header is left intact.

    This is not imposing a restriction more than GPLv2. See the bit in trademarks. Legally you had to do that anyway, they’re just reminding you not to be a tool and leave this simple line in:

    • Copyright jQuery Foundation and other contributors

    I bark at developers a lot for removing the license headers from javascript files. Don’t do it. You’re violating copyright and, if the original devs complain, you’ll lose your code until you fix it. Which is the point here. Copyright exists beyond GPL, so the fact that it doesn’t actively protect it doesn’t make it not enforceable.

    Theft

    I don’t mean legal here.

    A lot (a lot) of people argue that their plugin should be able to be encrypted or obfuscated to make it ‘harder to steal.’ I hear that about once a week, if not more. And my answer to all of them is “Not if you want to be hosted on WordPress.org.” WordPress.org has an ‘above and beyond’ understanding of the idea of distribution and allowing people to edit. It’s felt that the spirit of GPL means your code should be easy for someone to read and fork.

    I said a dirty thing there, I know. The ‘spirit’ of the GPL is probably causing some of my friends to roll their eyes so hard they’ve got migraines. Sorry about that. But it really is the one time I use it. When I say the ‘spirit’ I mean the intention of the license and it’s application to WordPress.org’s repositories only. Right or wrong, agree or disagree, it’s straightforward. If you want to have your code in the .org repos, it’s gotta be human readable.

    There’s a simple reason for this. The GPL Copyleft is all about freedom and keeping that freedom alive. The Copyleft says that anyone who redistributes the software, with or without changes, must pass along the same freedom to further copy and change it. In order to allow people to change the code, we want it to be human-readable. We want people to be able to look at your code and say “Oh I understand how this works. I will improve it!” When you take away, or overly complicate their ability to do that, we feel you’re intentionally impinging on that freedom. You’re trying to find a way around it, basically.

    About the only time I’ve heard someone not claim they were smushing the code up to protect it from being stolen is when someone has smashed their javascript into a p,a,c,k,e,d() type compression file. I actually hate those files. Javascript is hard enough as is! Stop making it harder. Plus I need to tell you something really important.

    While minifying your javascript will improve a website’s performing by decreasing the load time, it doesn’t make it run any faster for the majority of code out there. Of course there are situations (large libraries or limited devices) where this is not the case, but trust me here. Your 7 line javascript is not going to be significantly faster just because you compressed it. I advocate using the .min version of common libraries, but unless your code is huge, leave it alone and let other people see how to edit it.

    Bonus: Distribution

    GPL comes into play when your code is distributed. If I put my code on my server and never give it to anyone, it’s not been distributed so licenses don’t really matter. As the GPL FAQ explains:

    But if you release the modified version to the public in some way, the GPL requires you to make the modified source code available to the program’s users, under the GPL.

    It’s the big if there. What constitutes distribution? Is your browser downloading a javascript file in order to run my site distribution? Is handing you a zip file distribution?

    I always recommend people play it safe.

  • Mailbag: Why Do Cannonical URLs Mess Me Up?

    Mailbag: Why Do Cannonical URLs Mess Me Up?

    This came from a DreamHoster who said it was okay to blog it if I didn’t mention them by name. They were embarrassed about the mistake.

    Why was my site having a redirect loop, and why did changing the domain to force www in panel fix it?

    The ‘panel’ being mentioned here is DreamHost’s Panel. We don’t have cPanel, we have PANEL, and it’s our special, 100%, tool. In there, you can edit your domain settings. One of the settings has to do with your domain settings. Simply it asks “Do you want the www in your URL?”

    DreamHost Panel: Do you want www or not?

    In general I check “no” because I’m a no-www kind of person. I don’t like it.

    The issue this person was faceing was that you’d go to http://www.wordpress.dev and everything was fine, but his site went all over the place weird when you went to

    In order to fix that person’s website, I changed “Leave it alone” to “Add WWW” (their preference, not mine).

    Why did that work? Let’s understand the issue first. What was happening was that your server generally doesn’t care if you visit http://www.wordpress.dev or http://wordpress.dev because it knows that they both mean /home/user/wordpress/public_html/ (or whatever). But! Some servers (like DreamHost) let you prioritize and redirect. If they don’t, you can use nginx/htaccess to force www or not. As far as the server cares, none of this matters. If you force no-www and someone goes to www, they get redirected and everyone’s happy.

    Except WordPress. WordPress is picky. WordPress has special settings:

    Your home and site URLs in WP

    Recognize that? If you have WordPress set to use www and you go to the non-www URL, it won’t redirect you. It will, however, force all internal links and generated paths to have the www. The same thing happens if you don’t force https for your site. WordPress will still serve http://wordpress.dev but all the links on that page would be to https://wordpress.dev and so will your stylesheets and javascript.

    This may make you think that WordPress doesn’t care. You’d be wrong. WordPress cares deeply, and it shows up when you go a URL like http://wordpress.dev/i-am-fake/ – assuming you don’t have a page named that. If you’ve forced www, WordPress will look for that page and do a 404 redirect. Suddenly you’ll have www!

    Except in some cases, what happens is WordPress accepts the URL you gave it and shows without the www. Then it remembers it should have the www and redirects to that. Only it knows you told it non-www and redirects to that. And you get an endless 301 redirect loop. And you cry.

    If you force www in DreamHost’s Panel and you force it in htaccess and you set it your settings, this still may not be enough! You may have to do a search and replace to change all the non-www urls to www!

    Amusingly, when WordPress 4.4.1 dropped, we found a rare race condition with http and https and WooCommerce, born from a simple mistake.

    Woo lets you force http on post-checkout pages

    Everyone I know who looked at that went “Oh, right, if my site has https in the home and site URLs, maybe I shouldn’t try to force http here!” But Woo lets you shoot yourself in the foot. Or at least they did. There’s a ticket open where I suggested perhaps they prevent that.

    And for what it’s worth, I totally get how these things happen. You set up your domain and your WordPress site and your http/https settings at different times. It’s understandable that in 2013 you didn’t have SSL, but you added it in 2014. And at that time, you only put SSL on your checkout pages (right?) and since you wanted your cache to work better, you said “no https for checkout’ed!” That’s perfectly sane and logical. But since LetsEncrypt and HTTPS Everywhere became big in 2015, you changed the whole site over and simply forgot about that one, teensy, toggle…

    At least, until someone got that horrible 301 redirect on checkout.

    Like I told the people I fixed, don’t kick yourself over this. You have a lot of moving parts and the secret is understanding how each bit works. If you know that you set Panel properly, and .htaccess properly, and site/home URLs properly, and it only happens on checkout, you can zero in on what’s left and debug that.

  • Why CDN Media Needs a Plugin

    Why CDN Media Needs a Plugin

    I wanted to write a blog post for work (something I try to do once a month) so I thought “I should write about using a CDN for images. I wonder if you can do this without a plugin…”

    One hour later, and 1200 words, the answer is no. You cannot.

    My initial goal was to move media files (and only the media) from http://example.com/wp-content/uploads/ to http://static.example.com/wordpress/ on DreamObjects. I’ve written a plugin that does that, but to my frustration, I found you cannot do this without a plugin for one incredibly simple reason.

    But before the big reveal, let’s break down, in simple terms, what I would actually need to do in order to move the uploads. My two assumptions are that I already have a WordPress powered site (check) and I already have DreamObjects (check)

    1. Setup a bucket on DreamObjects (or AWS whatever) to house my images, and give it a CDN alias.
    2. Copy all the images to the bucket.
    3. Change the Upload URL to http://static.example.com/wordpress/ (my CDN alias for the bucket).
    4. Edit all posts and GUIDs to the new URL.

    The thing is, I can actually do all of that!

    Setup a Bucket on DreamObjects

    Log in to your Panel, click on Cloud, go to DreamObjects, and create a new bucket in DreamObjects. I called my domain-static because that’s easy for me to remember. Static content lives here. Once you have your bucket, click on the “Change Settings” link and add an alias of “static” to the domain you’re hosting all this on (example.com in this example).

    You can name your alias anything you want. I just picked static because I knew I wanted my URLs for images to be http://static.example.com/wordpress/2016/01/happynew.jpg and this makes it simple. I like to leave my CDN available for more than just WordPress, and doing this will let me have more folders like wiki or gallery.

    Next, scroll down to “DreamSpeed CDN” and turn on CDN Support. You’ll notice that tells you a special URL for CDN:

    Connect to the accelerated DreamSpeed CDN version of this bucket at: examplecom-uploads.objects-us-east-1.dream.io

    Don’t worry! You can use your custom URL too. You don’t have to, but most of us want to, to feel special. In order to use your custom alias that we just made, scroll up a little and check the box for ‘CDN’ on your alias. Press save and you’re good to go!

    Copy all the Images

    Set the bucket public first!

    Just trust me, here. Okay? Good. Set the bucket public and then upload all the images. I used Transmit. Cyberduck also works.

    Change the Upload URL

    This part was scary.

    We need a moment of history first. Up until WordPress 3.5 this was actually pretty easy to do. You went to your media page and you changed things. As of 3.5, WordPress decided that this was more trouble than it was worth. Too many people were accidentally doing silly things, breaking their sites, and it was too dangerous. So they removed the part of the screen that let you change this.

    I have issues with this, since for what I want to do, it makes it a hassle. But given the flaw in my great plan, I recognize the change as one that protects people who know less than I do.

    Using a plugin to restore this missing setting would be the easiest on many levels. And there are a few plugins that do this but I like Upload Url and Path Enabler. It’s simple and to the point.

    Of course, I love wp-cli and we have it on all our servers at DreamHost, so this command is similarly awesome:

    wp option set upload_url_path http://static.example.com/wordpress

    The last option for this is the secret WordPress page called “All Settings” — This is hands down the most powerful and dangerous page in all of WordPress. It lists all your options and settings that you have in the database. And yes, you can edit many of them in your browser at http://example.com/wp-admin/options.php

    Go ahead. Take a look. It lists a lot of things, most of which you should never, ever, ever, touch. If you were going to use this, search for upload_url_path, change the value from empty to http://static.example.com/wordpress, and press save.

    Edit All Your Posts

    This is a sucky part. You have to edit all your posts now to move the existing images. This is because those changes you made are only for images going forward. Which is really cool and means you didn’t break anything so far. But WordPress hardcodes the paths to images in your posts (for many reasons) so you need to change all of them.

    If you know how to use the command line, this is actually really easy:

    wp search-replace http://example.com/wp-content/uploads/ http://static.example.com/wordpress/

    Run that command and WP-CLI will magically fix all your posts.

    If you don’t want to use the command line, I recommend Velvet Blues Update URLs.

    Done!

    And to be clear on things, this worked perfectly. My media library showed properly, all my images showed, and everything looked perfect. So I decided to run some basic tests and upload new images…. and that’s where my house of cards fell apart.

    You cannot save files to another server.

    Actually You Can… if you sudo

    Now I have to tell you something. I lied. You totally can do this. The problem is that it’s hard and requires mounting your bucket as a local filesystem so that it would be available via the file-path of the server. You see, you could save files to /folder/location/wordpress/ anywhere on the server. I save mine to /home/user/public_html/static/ on one set up, and I have a static domain (domain-static.com) that runs from that folder.

    What that means if I had a location I could access, I could tell WordPress to save there, making it ‘local’ enough to trick it. You can do this with tools like s3fs-fuse, however they’re incredibly complicated and weird for the layman. And that right there was my problem.

    If you’re trying to present something as ‘Without a plugin’ then you don’t want to make the tradeoff be ‘..but with sudo access to a VPS.’ That’s unreasonable.

    And it’s why, right now, if you want to use a CDN for your media in WordPress, use a plugin.

  • Circular Arguments Need Research

    Circular Arguments Need Research

    There’s something I hate about the fact that they charge for tampons and pads in bathrooms. I understand the financial outlay of providing a ‘service’ but at the same time, the collection method means that most of us never use them. After all, on those occasions when a woman needs a tampon or pad from those machines right bloody now, we probably don’t have our purses with us. Most women I know keep at least one in there for just such a moment, after all. If we don’t have our purses, guess what else we don’t have? A dime! In my experience, any time any woman has stared at that machine with a look of hopelessness and despair over their lack of a dime, another woman has brandished her personal emergency tampon and handed it over without a second thought.

    So why do they charge? Well if they didn’t charge, then people would just take them and that would be a financial loss. I get that. Except, as my friend Mark Jaquith put it:

    Financial outlay is an imprecise way of validating the intensity of a need.

    The day I had my great-tampon-rant was the same day I’d argued with some folks about marketing. Someone who is a ‘known’ person in the WordPress community got a bog standard email from a hosting company. It was one of those emails that looked like it was meant to feel personal, but was really just a sales pitch about what the company was and how they worked.

    The thing about that is I’m pretty damn sure the person who got the email knew all of that already. He may have known it better than the ‘person’ who sent the email. I say ‘person’ in quotes because I’m sure it was an automated campaign set to hit up people who’d emailed or used a contact form and asked a question.

    And this bothered me.

    If the email hadn’t made an attempt to be personal, and instead just said “Hey, you used our form/emailed our service address recently. Did you get all the help you needed? Do you need to talk?” I would have been just fine with it. And if he’d checked a box to say “Please contact me about stuff!” I’d similarly say “Well you deserved that one, B.”

    The reality is that he filled in a form to get a ‘report’ that he wanted to read and got that personalized email within an hour. The company offered something for ‘free’ but the cost really was data collection. Furthermore, the penalization was immediate solicitation.

    It doesn’t matter who the company is. This could be mine (it’s not) or yours (it might be). Pretty much every company known to humanity has done this at least once. And every company uses the justifications that the marketing strategy converts people into sales, and thus it’s fine. We all accept that marketing automation is hard, that identifying people we should be reaching out to and separating them from the ones who will just be annoyed by our hard sells is extremely difficult.

    Remember what Mark said?

    Financial outlay is an imprecise way of validating the intensity of a need.

    Not enough women using the pay-for tampons and pads is (part of) why they’re never going to be free. Women don’t use them because they’re pay-for (and we rarely have the damned dime).

    The ‘need’ of tampons is not being correctly measured.

    With those marketing emails, I would say this:

    Financial boons are an imprecise way of validating the effects of a campaign.

    Yes, I’m aware I just said that “Making money doesn’t mean your campaign was successful.”

    Except that’s not what I’m saying. What I’m saying is that the effects of your marketing are more than just financial. If you send out 1000 emails and get 1 sale, that sounds like ‘free money.’ Very little output and work nets you money. Everyone wants this. The problem is how many people did you chase away? What net negative are you creating? We’re not tracking the information in a way that lets us know this. We’re just thinking that any news, any discussion, and any income means it was good and effective.

    Let me ask this differently. How many auto-play ads have you seen on a website that made you like a product less? How many websites have you quit visiting because you can’t stand their ad practices?

    Not all press is good press. Forbes recently had a snafu where they asked you to turn off adblocking only to serve up ads with malware. They had a rather immediate and vocal negative impact. I doubt that level of embarrassment and pain will hit this company, but at the same time, we should be looking towards other, better ways of attracting new customers.

    This Can Be Fixed

    Looking at the situation that led to this in the first place, requiring an email to download a report is an obvious ploy to gain a list of people to contact. There was no attempt to opt in and no information that the email would be used for marketing. Step one is to disclose that. Step two is to actually make that opt-in. Step three is to provide some additional reward. “Do you like reports? Click here and we’ll send you our next one right away!” Then when you send those next reports, you can put a little footer for sales. “Interested in our stuff?”

    Step four is the hardest. Curate the damned list. Remove all your customers. You already have their emails, you don’t need to email them about your services. Put them to the side. Next you want to remove people with emails like support or webmaster. In addition, you’ll want to check your list for people who already know about your product. WordPress is an incredibly small community. There are some people who just are not ever going to be your target audience, who aren’t going to need that sale, and you don’t need to bother them. They’re also the ones who will uncheck the marketing email, of course, but just in case…

    Step five is handling your existing customers (the ones you removed in step four). Put them on separate list to target with different emails. “Hey, you’re already our customer and we noticed you liked X. Would you be interested in Y and Z?” Of course if your customers have checked that box to say “Don’t email me with marketing stuff” then you damn well better respect it.

    For step six I want everyone to stop pretending these are personal emails. Shut up. Give up. We know, okay? We absolutely, 100%, without a doubt know that you automated this stuff. And that’s totally okay. But you cannot claim personal emails, from real people, while not vetting the people to whom you’re sending email in the first place. Okay? Good. Now go be quirky! “Hi Mika! I set up our robots to email people who downloaded X because I wanted to make sure they knew about Z and Y! Hate these emails? Click here and we’ll delete you from the database.”

    But Can It Be Automated?

    Not entirely. No. The real question is ‘Should it be automated?’

    This goes back to Forbes. They automated their ads. They set it and let it run without review. Obviously the answer there is ‘No, that should not have been automated.’ It’s easier to ignore them and trust the ad company. That said, regularly I go through the ads on my site and delete them when I find them annoying or offensive. Yes, I curate my ads. And if someone tells me “Hey there was an ad for porn” I go look for it!

    As much as we’d love to automate these things, we can’t. We just need a human taking a look now and then to go “Hang on…” Marketing cannot be set it and forget it. We have to look at the return on investment. We have to understand what impact, true impact, our campaigns have. We can’t just look at the net income, we have to be aware of the seemingly invisible loss.

    And as for those tampons? We need a better metric than just “Well some people pay for them, but not enough to make us think a lot of women will use them if we give them away for free….” Maybe they could just have a nice box of tampons and pads in every stall, where you can press a lever and one item falls out every X minutes. Or maybe that idea of a drop of menstrual blood works in place of a dime… At any rate. The point is assuming things as successful because of a lack of response does not actually mean they are.

    The circular arguments, that silence proves success, or at least an acceptable status quo, need to be thrown out on their ears.

  • Mailbag: How do plugins update?

    From Ken the Web Mechanic comes this:

    Hi! I wonder if you’d have any insight on this… I’ll mention Wordfence, though I imagine that it applies to any security plugin that compares plugin files with those in the WordPress repository… One of the most common things that Wordfence reports as a file “inconsistency” is the readme.txt of many plugins. Frequently, when using Wordfence’s compare feature, the readme of an installed and up-to-date plugin is shown as not the most current version and the repository shows the latest version – which is for the version that is installed!! If you delete the plugin and then download and install it anew from the repository, the readme is for the current, Wordfence has no complaint and all is right with the world… So I guess my question is… When a plugin is updated through WordPress, does the readme.txt file always get updated? It’s always been my understanding that during an update all of the old filed are deleted and then the new version is installed from the repository… It’s seeming like this may not be 100% of the case. It’s certainly only a minor irritation to me… but it makes me curious… Inquiring minds and all of that! 😉 Thanks!

    I put the whole question in because while the crux is “How are these buggers updating?” the whole picture is interesting. I’ve talked about this once before, but it was a very long time ago. How the WordPress Upgrade Works was posted in 2011, and Why does the WordPress background auto-upgrade work? was back in 2013. So it’s about time for a revisit.

    The short answer is “Actually, the readme.txt is deleted on plugin (and theme) upgrades.”

    The longer answer means first we should understand what’s going on with upgrades! How plugins (and themes) update is pretty basic and you can check out /wp-admin/includes/class-wp-upgrader.php to see all this code:

    1. Connect to the filesystem.
    2. Download a package.
    3. Unpack a compressed package file.
    4. Clears the directory where this item is going to be installed into.
    5. Install a package.

    These are all great failsafes, making sure multiple times that we’re not about to leave a user in a bad state. We check to make sure we can download and use the file before deleting and replacing. We check to make sure WordPress can find all the folders it needs, like plugins and wp-content and so on. If it can’t connect to any of the ones it needs, it will fail. We make sure we can download and unzip the file. Even when we look at the complex fourth step, we’re all checking over and over to make sure that when we really do delete these files, we have something to replace them with.

    The goal is that WordPress should never be able to leave you with a plugin deleted and not installed again, nor should it leave you with a half-deleted plugin. Obviously critical failures, like a server reboot mid-stream, will have some catastrophic effects. This is why WordPress tosses a .maintenance file down, mind you. Stops your site from looking like total poop while all this is going on.

    When we look at the class Plugin_Upgrader itself (line 766 or so), we get into some nitty gritty things. The public function upgrade does some interesting things:

    		add_filter('upgrader_pre_install', array($this, 'deactivate_plugin_before_upgrade'), 10, 2);
    		add_filter('upgrader_clear_destination', array($this, 'delete_old_plugin'), 10, 4);
    

    Here we are clearly deactivating and deleting safely before we upgrade. And at this point, I’m very confident that we’re deleting that readme.txt before we upgrade.

    Okay! So why is WordFence being a dillweed?

    I have a theory it’s related to the updates we do when WordPress core has a new version. You see, instead of updating the whole plugin, we update the readmes only to edit the “tested up to…” value. If there’s no code change, after all, why would we bother? No need to push an update! This means you no longer have a plugin that 100% matches what’s on Wordpress.org, you have a plugin where the code files match, but not the readme.txt files.

    And then poor WordFence notices that the readme you have and the readme on .org’s servers is out of whack, and tosses an error.

    I don’t know how WordFence would fix that, but I’m pretty sure this would hang ’em up.

    WordFence folks, got any ideas?