iCloud Drive: Don’t do what I did!

Being deeply immersed in the Apple ecosystem, a couple of years ago I made a decision:

I’ll move all of my work files onto iCloud Drive!

I work (as in, write code and edit image files) mainly on my Mac. But I was seduced by the possibility of accessing all of my work files in a pinch on my iPad (which I still had at the time) or even my iPhone. Plus, since my files would be in “The Cloud”, I could even access them from another computer (or from my Mac when booted into Windows) if I needed to, by logging into my iCloud account from a web browser.

It seemed… so obvious. So perfect.

Umm… maybe not.

For the past two years, I have been constantly fighting with iCloud Drive. One of its signature features is that it can manage disk use on your Mac automatically, so as your hard drive fills up, it deletes files you haven’t used in a while, keeping them safely in the cloud while freeing up disk space on your Mac. And with my MacBook Pro sporting a (meager?) 256 GB hard drive, with 40-odd GB allocated for a Windows partition, and over 60 GB occupied by Logic Pro X sound samples, my drive is filling up constantly.

While this is great in principle, it is completely unworkable in practice for three interrelated reasons:

  1. If you have a large amount of data in play here (for me, it’s in the vicinity of 100 GB), iCloud Drive may get to a point where it is constantly transferring data. If you’re not on a gigabit fiber connection, this can both use up all of your Internet bandwidth and take ages.
  2. Because #1 is taking place constantly, if you do find yourself needing to grab one of those files that has been deleted locally (as indicated in the Finder by a cloud icon with a down-pointing arrow), you may find yourself waiting several minutes for the file to become available, even if it’s small (as in, under 1 MB).
  3. In an effort to make this all appear seamless to the user, the Finder represents cloud-only files as… regular files. But they’re actually just pointers with a hidden .icloud filename extension… as you’ll find if you ever try to perform Finder actions inside another program, such as syncing files to a web server using Transmit.

All of this might be tolerable if Apple gave you any control whatsoever over which files get deleted locally. But they don’t.

It gets worse.

What’s worse than getting stuck in this situation? Trying to get out of it. It’s like quicksand… the more you struggle against it, the faster and deeper you sink into it.

I made the decision earlier this week to extricate myself from the iCloud Drive nightmare, by buying a 250 GB SanDisk external SSD. First off, a little unpaid plug for this drive… it is awesome. It’s super light and small, seemingly at least as fast as the internal SSD in my MacBook Pro (in that I am able to transfer multiple gigabytes of data in seconds), and it even looks cool. I’m going to be using it all the time, so I’m actually considering putting adhesive Velcro on both it and the top of my MacBook Pro so I can keep it permanently attached. (Which says a lot about how much my regard for Apple has fallen lately — in the past I would never have sullied the exterior of an Apple laptop with something adhesive.)

So anyway, external SSD acquired, my goal was to start transferring my files from iCloud Drive over to the SSD.

Uh… good luck with that.

Because I’m now at a point where I have more than double the amount of data stored on iCloud Drive as I have available space locally, a majority of my files are now only in “The Cloud.” Ugh. Which means waiting for all of that data transfer stuff to happen. If only I could, somehow, bypass this broken process, I thought.

There has to be a way.

tl;dr Nope.

So, here’s the thing. I’ve been using iCloud Drive for the bulk of my cloud-based file storage, but I do use other services as well. I have Google Drive. I have Dropbox. I know how they work.

Specifically, I know that you can, y’know, like, select a folder and download the entire thing as a zip file.

So I thought to myself, I’ll just go to iCloud in a web browser and do that! Download the whole friggin’ thing as a big zip file, or maybe a few zip files, and be done with it.

Nope.

For whatever reason, iCloud doesn’t let you do that. Probably because of the whole seamless “It just works” Kool-Aid drinking song everyone in Apple land has been singing. (Myself included, mostly.)

You can only download individual files, not folders, from the iCloud web interface. It does let you select multiple files at once, but only within one folder.

Check out this delightful thread full of know-it-all asshats whose response to a legitimate question — why doesn’t Apple allow this thing that every competing service does? — is to challenge the validity of the question and the intelligence of the questioner. (That thread is now closed so I’ve just opened my own new thread on the topic. Watch this space for trolls!)

There. Are. Plenty. Of. Reasons. A. Person. Might. Have. For. Needing. To. Do. Something. That. You. Have. Not. Previously. Considered. Stop challenging their premises and answer their question, or shut the hell up.

Whew.

I ended up “solving” the problem by resigning myself to the fact that it wouldn’t be completely solved. So instead I took the drastic approach of temporarily logging out of iCloud completely, just so I could strand the files I did have saved locally, and copied them to the SSD.

Then I logged back into iCloud Drive and tried to get it to stop syncing my files by unchecking the Desktop and Documents Folders option.

The only problem is, I didn’t have my work files in those folders. I had them in a separate top-level folder in the iCloud Drive that I created myself. Because, you know, you can do that and it didn’t seem like a crazy idea or anything.

It was.

I discovered this morning that even though I had done all of this and tried to purge the nightmare of constant iCloud Drive syncing from my Mac life, once I had logged back into iCloud, the Mac went right back to quietly, constantly, syncing that iCloud Drive data on my Mac. As I type this, I have a Finder window open to my iCloud Drive and in the status bar it says “downloading 120,079 items (36.14 GB of 48.66 GB)”. Fun!

So, my new plan for today is to watch that window, and as the little cloud icons next to individual folders goes away, I’m copying those folders to my SSD and then deleting them from iCloud. My assumption is that as I do this, I am freeing up more local space and iCloud will continue to download the remaining items, and eventually I’ll have everything transferred over.

But please… do yourself a favor and don’t do what I did. iCloud Drive is not suitable for professional use.

Fixing a redirect loop on WordPress sites with WooCommerce when converting the site to all-SSL

Best practice these days is to run sites on all-SSL, not just the parts of the site that “need” it. But not long ago, it was common to apply SSL only when it was absolutely necessary, because SSL encryption meant a performance hit. Not anymore.

You may find, if you’re trying to convert an existing WordPress / WooCommerce site to all-SSL, that reconfiguring your URLs, by using a tool such as interconnect/it’s super-slick, powerful (and dangerous) Search Replace DB tool, that once you’ve made the changes, your home page kicks into a redirect loop, indefinitely cycling between http:// and https:// versions of your URL.

WooCommerce may be to blame!

Specifically, a setting in WooCommerce called “Force HTTP when leaving the checkout”. Head on over to WooCommerce > Settings > Checkout and… um… check it out.

Simply uncheck that box, and, while you’re at it, uncheck “Force secure checkout” since it’s unnecessary on an all-SSL site, save your changes, and your home page should come back to live!

Internet Explorer and the centered background SVG problem

We are rapidly approaching, I believe, a time when we no longer need to worry about things that don’t work in Internet Explorer.

But we’re not there yet.

I’ve started using SVG images on the web a lot, especially for logos, which I tend to put into a flexible-width container at the top left corner of pages. Which is great, except IE has this annoying habit of resizing the canvas for SVGs to fill the container they’re in. The whole logo appears on the page, and scaled properly… but it’s horizontally centered in the container, rather than flush against the left edge.

There appear to be many possible solutions, but for a solution that is 100% fluid/responsive (that is, it will scale with the container), this does the trick.

It does involve manually editing the SVG code, but it’s simple and you only need to do it once as part of the image prep process. In the <svg> tag, look for the viewbox attribute. It will most likely consist of four numbers… 0 0 followed by the width and height of the canvas. After this attribute, simply add width="x" height="y" with the same x and y values from the viewbox attribute.

It works!

Noted for future reference (by me): How to reset the MySQL root password in Ubuntu 18.04

As a bleeding-edge early adopter, here in June 2018 I am already using Ubuntu 18.04 LTS for new sites I’m setting up for clients. (How daring!)

I ran aground this afternoon with a new server setup, because I couldn’t log into phpMyAdmin as root (or, therefore, as anyone, since I hadn’t set up my own user yet).

All of the old familiar ways I had been trying, and the tutorials I had referred to for at least the past two years, were not working. So then I specifically searched for a solution for Ubuntu 18.04 and found this excellent tutorial.

First off, mysql_secure_installation wasn’t working. That was one of the “old familiar ways” I had already tried thrice. THRICE I TELL YOU!

The key, I think, was these two unexpected lines:

$ sudo mkdir -p /var/run/mysqld
$ sudo chown mysql:mysql /var/run/mysqld

Because that folder didn’t exist and/or didn’t have the proper permissions, some other steps were failing silently or giving error messages that failed to point me in the direction of the actual problem.

The other thing to note is that with the version of MySQL included in Ubuntu 18.04, these are the proper MySQL commands to run:

USE mysql;
UPDATE user SET authentication_string=PASSWORD("linuxconfig.org") WHERE User='root';
UPDATE user SET plugin="mysql_native_password" WHERE User='root';

And it is actually important to run both of those UPDATE commands, because in the tutorial the results displayed show that the first one updated a record for them, while the second didn’t. I had already run the first command (but not the second) in one of my failed updates. So when I ran these, the first one didn’t update any records and the second one did.

How to modify WooCommerce to prevent users from selecting UPS shipping for P.O. Box addresses

Anyone who’s dealt with e-commerce in any capacity probably knows that UPS won’t deliver to P.O. boxes. Well, technically they can’t deliver to P.O. boxes. And apparently they’ll forward packages on to the box owner’s physical address, but they charge a big extra fee to do it. So, you want to avoid it.

Unfortunately, WooCommerce and its UPS Shipping add-on do not account for this, and will accept UPS orders to P.O. box addresses. Not good.

The official WooCommerce developer documentation has an article on how to block P.O. box shipping, but it applies to all shippers. Not what we want.

Also, I’m not sure if the documentation is outdated or what, but their code sample didn’t work for me with the latest version (3.4.3) of WooCommerce, because of the wc_add_notice() function.

I’ve modified the original code to add a check for UPS shipping, and also to use the $errors variable. (I also considered removing the global $woocommerce; line since it seems unnecessary, but I didn’t take the time to test whether or not it’s definitely safe to remove, so I left it in.)

add_action('woocommerce_after_checkout_validation', function($data, $errors) {
  global $woocommerce;
  if (isset($data['shipping_method'][0]) && strpos($data['shipping_method'][0], 'ups') === 0) {
    $address1 = (isset($data['shipping_address_1'])) ? $data['shipping_address_1'] : $data['billing_address_1'];
    $address2 = (isset($data['shipping_address_2'])) ? $data['shipping_address_2'] : $data['billing_address_2'];

    $replace = array(” “, “.”, “,”);
    $address1 = strtolower(str_replace($replace, '', $address1));
    $address2 = strtolower(str_replace($replace, '', $address2));

    if (strstr($address1, 'pobox') || strstr($address2, 'pobox')) {
      $errors->add('shipping', __('Sorry, UPS cannot deliver to P.O. boxes. Please enter a street address or choose another shipping method.' . $datadump, 'woocommerce'));
    }
  }
}, 10, 2);

Important notes:

1. This code may not immediately work for you; I believe the 'ups' string in the conditional line may vary depending on your Shipping Classes settings, so you may need to investigate exactly what values are returned in $data['shipping_method']. Since this code is fired off by an AJAX call, it can be difficult to debug. I was able to crudely debug it by commenting out the conditional, then appending print_r($data) to the error string.

2. This is using an anonymous function, so it won’t work in PHP versions below 5.3. But you’re not using a PHP version that old, are you? ;)

3. The original version checked the address line 1 and the postcode field, rather than address lines 1 and 2. I’ve United States-ified my code because that’s what I needed. If you’re part of the other 95% of the world, you may need to add that back in, with appropriate adjustments to the nested conditional. (I’m not really sure if this issue is as UPS-specific outside the US, so my modifications may not be relevant.)