Walt Stoneburner's Ramblings

Currating Chaos

Apple's Pages: Layout Break

 •  • Pages, Apple, solved

Let's say you're working in Apple's Pages and you really want to create a multi-column section of text inside some other block of text.

In other word processors, you'd insert a section break (without a page break), something with two or more columns, and then again a section break (without a page break). You're aiming for something like this:

Two Columns Embedded in Text using Pages

And while Apple's documentation for Pages implies it's possible, comparing the invisibles to the menu items, you'd find a glaring omission in the application's menu.

Layout Break Does Not Appear in the Meny

In fact, no where in the Pages User Guide for Mac does it tell you how to do that.

Back in the days of iWork, it used to be possible engage in a little dance where you'd insert a section break, twiddle columns, and then delete the part that caused the page break. It was ugly, but it worked. But not in Pages.

Solution

Say you have a column of text. Select a block in the middle of it. Then, making sure you're on the Layout Tab, change the Columns.

Select, Layout, and Columns

The trick is that you have to alter the column count while you have the content selected. If it's not selected, it won't work.

What was that BaseSystem.dmg popup?

 •  • macOS, mystery

Every once in a rare while, for a split second, a dialog box will appear on my Mac saying that it's opening BaseSystem.dmg, and then the dialog automatically vanishes. The system itself is working fine, but there's no explanation of why this happened, what it's doing, or if it's a security risk.

Empirical evidence suggests they appear shortly after doing a system update or security patch, at other times it may appear after a Time Machine backup completes.

Turns out, this file does exist on Apple’s Time Machine volume(s). (Below /0/ may be /1/ on your system.)

/Volumes/YourTimeMachineVolumeName/Backups.backupdb/.RecoverySets/0/com.apple.recovery.boot/BaseSystem.dmg

The .RecoverySets directory contains boot information, EFI, and a lot of kernel material. It has that “if you need to reinstall on a blank system using just a TimeMachine volume alone, you can” feel to it.

You’ll also find it in places like:

/Applications/Install macOS Catalina.app/Contents/SharedSupport/BaseSystem.dmg

If you locate the disk image file, mount it, and look inside …it is indeed all the minimal stuff needed to reinstall the operating system.

Why macOS would need to open and mount this is unclear, perhaps it’s pulling or checking a resource from it. But it doesn’t appear to be a need for concern, other than it’s an annoyance if you’re trying to give a presentation or watch something full screen.

VueJS Hoisting HTML Elements

 •  • solved, VueJS, HTML

When using a VueJS template and trying to inject a component inside of a table, such as a tr, the rendered component is hoisted outside of the parent element.

This problem has bitten me repeatedly, again and again.

You write this:

<table>
    <my-component v-for=...>
</table>

And it renders like this:

<tr>...<tr>
<table>
</table>

In a nutshell, there are DOM Parsing Caveats and elements like table have restrictions on what elements can appear inside them. (FYI: ul, ol, select have this issue as well).

The solution is to use VueJS's is attribute:

<table>
  <tr is="my-component" v-for=...>
</table>

This causes the template parsing to be happy, as table (or even a nested tbody) will be getting a "true" tr element, but its content will be rendered by the named component.


UPDATE: In VueJS 3 the v-is tag now evaluates as a Javascript expression! This means you need to pass it a string, as in <tr v-is="'my-component'">. See workarounds.

Toggling Apple's Spotlight by the CLI

 •  • Apple, HowTo

Every once in a while, Apple does an update that causes the machine to eat up CPU cycles and go in a tail spin, filling the log with mds and mdsworker issues.

As of 2020-09-17 with macOS Mojave v10.14.16, the problem appears to have been introduced as of Security Update 2020-003, and people are very unhappy on Apple's forum in multiple topic about the same subject. The problem still exists as of Security Update 2020-004.

For instance, I'm seeing the error message below tens of thousands of times as launchd spins up a process, another process skills it, and the cycle repeats because launchd sees the process didn't start:

Sep 17 14:35:50 langbox com.apple.xpc.launchd[1] (com.apple.mdworker.shared.00000000-0000-0000-0000-000000000000[524]): Service exited due to SIGKILL | sent by mds[72]

This is the metadata service that's indexing your drives, and it's what's providing the information to SpotLight so you can easily find things.

Turn Spotlight Indexing Off

It's not manadatory to have these services running, but it's very much part of the Apple operating system expereince.

When this kind of problem happens, sometimes it makes sense to just turn off Spotlight (until Apple fixes it with a patch):

$ sudo mdutil -a -i off

Without a drive provided as an argument, this will turn off Spotlight indexing for all connected drives, TimeMachine included.

Be forewarned, Spotlight is highly integrated with a lot of services, one of which is Mail. Turn off Spotlight and you'll discover you can no longer search your inbox.

Turn Spotlight Indexing On

Here's the catch, turning it back on again can take hours to reindex your drives, possibly days if you have huge drives of spinning rust (opposed to solid state drives).

$ sudo mdutil -a -i on

Just Force a Spotlight Index Rebuild

You can also force SpotLight to erase and rebuild the index via:

$ sudo mdutil -E

Note, again, if a volume isn't specified, it will affect them all.

Resolving a Redirect Error

 •  • Web, Configuration, Apache, DreamHost, Cloudflare

This morning I was greeted by a Google Search Console email stating there was a Coverage Issue on one of my domains. Specifically, there was a Redirect Error.

The problem, in slightly more detail, is that if one goes to http://mydomain.com/ it should redirect to https://mydomain.com/ and then serve the pages securely. The problem was that the site was getting into a redirection loop and not serving at all.

The domain happens to be hosted on DreamHost with its DNS and caching handled by Cloudflare, two services I can't say enough good things about.

This was particularly odd, as the domain had been working for quite a while, and according to the files, provider settings, and domain management tools, nothing had been significantly altered in about two years.

So, either I changed something one day and thought it'd have little consequence, or something at the provider's end changed, or there was an error that would either need waiting out or raising to support's attention. As I had other domains hosted the same way with the same providers, I went on the assumption it was a problem within my control.

When this kind of problem crops up, it's because DreamHost wants to manage the domains's DNS (since it knows what the machines' IP addresses really are) and Cloudflare wants to manage the domain's DNS (since it is providing high-speed responses for users at the edge). As long as both systems are in agreement about the contents of the DNS, all is fine. But, if DreamHost moves machines (very rare, but it happens), then the two fall out of sync and the DNS records must be manually synchronized again.

The easiest way to check is using dig.

dig @ns1.dreamhost.com mydomain.com

This asks DreamHost's DNS, to which I can compare the entries on Cloudflare's DNS. In this case, they were all the same.

Logging on to DreamHost's server, which I first expected would use its own DNS overriding Cloudflare but that seemed not to be the case, which also makes sense because of what the domain name's registry entries say is authoritative, I got this:

$ lynx http://mydomains.com/

Looking up mydomain.com
Making HTTP connection to mydomain.com
Sending HTTP request.
HTTP request sent; waiting for response.
HTTP/1.1 301 Moved Permanently
'A'lways allowing from domain '.mydomain.com'.
Data transfer complete
HTTP/1.1 301 Moved Permanently
Using https://www.mydomain.com/
Looking up www.mydomain.com
Making HTTPS connection to www.mydomain.com
Verified connection to www.mydomain.com (subj=*.mydomain.com)
Certificate issued by: /C=US/O=Cloudflare\, Inc./CN=Cloudflare Inc ECC CA-3
Secure 256-bit TLS1.2 (ECDHE_ECDSA_CHACHA20_POLY1305) HTTP connection
Sending HTTP request.
HTTP request sent; waiting for response.
HTTP/1.1 301 Moved Permanently
Data transfer complete
HTTP/1.1 301 Moved Permanently

lynx: Start file could not be found or is not text/html or text/plain
      Exiting...

Sure enough, we see the redirection loop happening. The HTTP request lands at a HTTP 301 that says to use HTTPS. That gets a secured connection, which ...makes an HTTP request? ...that results in the 301, and we're in cycles, so it quits.

Just to make sure, I saw there was nothing in .htaccess and that the index.html file was present. File dates, again, showed it had been about two years since anything had changed, so this very much was some configuration issue.

It turns out if you go to Cloudflare's Speed Test tab, it will tell you if something is wrong. You can then go to the help center, check your specific domain, and see what it says.

I found this page to be a little tricky to get to, it's title is "Are you experiencing a problem with Cloudflare" and the button you want is "Error Analytics".

  • https://dash.cloudflare.com/{some-hex-key-here}/support
  • https://dash.cloudflare.com/{some-hex-key-here}/support/error-analytics

Cloudflare also has a Cloudflare system status page, if you want to check their services overall. DreamHost also has a DreamHost system status as well.

In my case, it confirmed I had a redirect loop and pointed me to Cloudflare's Troubleshooting redirect loop errors page.

Here's where things appear to get sticky. When one utilizes Lets Encrypt with DreamHost, DreamHost as the site provider will automatically redirect any HTTP traffic to HTTPS, which is actually what I want.

Meanwhile, Cloudflare in their SSL/TLS Overview table has a Flexible SSL encryption mode that encrypts traffic between the browser and Cloudflare even if the request is HTTP. Clever. It does this by sending requests to the origin web server unencrypted over HTTP, but your connection to Cloudflare is encrypted. However, that means redirect loops can happen if the origin server is redirecting HTTP to HTTPS, perhaps never answering the original HTTP request.

What also threw me was that direct HTTPS requests were not being served either, although this could merely have been a cached response.

Just to incrementally check things, on Cloudflare I put the server into Development Mode and cleared the cache; I didn't expect it to help, but sometimes glitches happen.

While this wasn't going to be the final solution, I went to disable the automatic redirect to HTTPS on DreamHost. Again, this didn't help and I turned it back on.

The Solution

Assuming that DreamHost was doing the Rewrite rules on the domain automatically, this left making changes on CloudFlare.

Comparing to another site I was working, I saw the working site's Cloudflare SSL option (in the SSL/TLS Overview tag) was set to Full.

One should use Full if there is a SSL certificate configured at the origin web server, which there was, the Let's Encrypt certificate.

However my setting was currently Flexible.

Because this was an "older" website, I suspect the following happened:

  • I set up the site originally as HTTP long ago
  • Let's Encrypt came onto the scene and I added it
  • When I moved to CloudFlare, it had an automatic HTTP to HTTPS redirection that I turned on at some point
  • DreamHost in improving its service also opted to turn on HTTP to HTTPS redirection at their end as well
  • Where ClouldFlare was doing the redirect itself before, now both systems were in conflict

The solution was to change the setting to Full, letting the origin server's certificate do all the HTTPS magic, and therefore let the origin server's HTTP redirect where it wanted. Meanwhile, Cloudflare could still intercept and translate any originating HTTP requests to HTTPS as well.

Default value for bash argument

 •  • bash, psychology

Sometimes we see what we want to see. Take this incorrect code fragment, which attempts to get the value of the first parameter passed to a script and store it in ARG1, using the literal string "DefaultValue" if no parameter was provided:

ARG1=${$1:-DefaultValue}

This produces a 'bad substition' error with bash. The question is, why.

We know that it's possible to get defaults this way:

XYZZY=MagicWord
FOO=${XYZZY:-MumbleFrotz} # FOO gets set to "MagicWord"

unset XYZZY
FOO=${XYZZY:-MumbleFrotz} # FOO gets set to "MumbleFrotz"

So, clearly our bash notation of :- is correct for handling defaults. Taking us back to, again, why?

The answer is that we're seeing what we want to see. Look again. Closer.

We can be so used to thinking that the "first argument" to a script is $1 that we treat it that way, as a single token.

But it's not. $ retreives the value. That means the first argument is actually... 1. And it doesn't help that "1" on its own usually means a value, adding to our cognative blindness, but the context of its usage matters. This means:

ARG1=${$1:-DefaultValue}   # wrong
ARG1=${1:-DefaultValue}    # right

The outer $ handles it, just as ${1} would, without the default clause ':-` provided.

As such, the inner $ associated with "$1" is not just unnecessary, but wrong, and due to code writing habits can be visually hard to spot, even when its staring us in the face.

Update, but Don't Upgrade, macOS

 •  • macOS, configuration

I've run in to several problems with OS X and macOS. The first being that macOS wants to always upgrade itself to the latest version. However, that's not good for test machines, it's problematic for development machines that need to stay stable, and it's not good for user desktops which might want 32-bit applications, certain kernel modifications for user customization, support for older applications that Apple itself just abandoned, or third party applications that are incompatible with newer operating system versions, have altered their licensing in unfriendly ways, or simply aren't around any more to resolve license keys. Or, in the case of Microsoft Office, just stop working because of the operating system version number and not any particular technical reason as a means to push a subscription you don't need down your throat.

The second is that some of the applications and operating system updates can be huge and if you're working on a project which consumes a lot of diskspace, you don't need Apple filling it up in the background. Additionally, if you're working on something with a lot of network traffic, you don't need your bandwidth being consumed.

The third is having Apple perpetually toss notifications in your face while you're trying to work to say it has an upgrade ready, want it now or a little bit from now. There really needs to be a way to say "not until I ask for it."

Parallel to this, it's highly important that an operating system get security patches and bug fixes, but it doesn't need to upgrade to do this. It needs to update.

What worse is that there are cases where Apple's macOS will try to sneak an upgrade of itself on your system, you'll discover it during a reboot, and get stuck because your hardware is too old to upgrade (seriously, why'd it try) but meanwhile your boot cycle won't let you login until you've done the upgrade. Catch-22.

If you boot and see "MacOS Could Not Be Installed On Your Computer", that's the macOS installation loop failure, and of course the prescribed methodology to get out of it, usually results in hoping you have a recent Time Machine, SuperDuper!, or Carbon Copy Cloner backup.

However, you can avoid all those woes.

The following settings in Apple / System Preferences / Software Update will instruct your machine to let you know when there are operating system updates to be had, go get them when you ask for them and not to premptively download them, but stay away from upgrading the operating system as a whole.

Apple / System Preferences / Software Update

Once you've got those settings done, press the Advanced button and make these changes too.

Apple / System Preferences / Software Update, Advanced

Longest Line with wc on macOS

 •  • macOS, gnu, homebrew, utils

The version of wc that comes with macOS doesn't provide the -L option that provides the length of the longest line.

Upgrading or changing tools provided by Apple's operating systems tend to break other pieces of the operating system in strange ways or cause integrity problems when upgrading the operating system. Best not to do that.

Instead, work in a sandbox. And as it turns out, Homebrew does just that.

The GNU version of wc would be a naming collision (as would other utilities), so Homebrew lets the GNU utilities install with a g prefix. The GNU utilities reside in the coreutils package.

Install like so:

$ brew update
$ brew upgrade
$ brew install coreutils

Then use the gwc utility like so to show the longest line in a file:

$ gwc -L filename

Affinity Photo: Can't Paint on Mask

 •  • Affinity Photo, mask

Ran into a problem where I had two layers, added a mask, and discovered very quickly that with the mask layer selected, I was unable to use the certain Brush tools to paint on the mask, while I could others.

Turns out the solution is pretty simple. Turn off the Protect Alpha checkbox in the tool bar.

It's not obvious to me at the moment what this would even accomplish on a mask layer that is represented as a gradient from pure black (transparent) to pure white (opaque), but the brush setting certainly matters.

Enabling PHP in home user public_html directories

 •  • apache, php, public_html

Newer versions of PHP will disable PHP from working in user's public_html directories.

Find which file needs editing: ls -l /etc/apache*/mods-enabled/*php*.conf

It should result in a specific file pointed by the symbolic link (e.g., /etc/apache2/mods-available/php7.4.conf). Inside that file, locate a section that looks like this:

# Running PHP scripts in user directories is disabled by default
#
# To re-enable PHP in user directories comment the following lines
# (from <IfModule ...> to </IfModule>.) Do NOT set it to On as it
# prevents .htaccess files from disabling it.
<IfModule mod_userdir.c>
    <Directory /home/*/public_html>
        php_admin_flag engine Off
    </Directory>
</IfModule>

And comment out the section that turns of PHP.

# Running PHP scripts in user directories is disabled by default
#
# To re-enable PHP in user directories comment the following lines
# (from <IfModule ...> to </IfModule>.) Do NOT set it to On as it
# prevents .htaccess files from disabling it.
# <IfModule mod_userdir.c>
#    <Directory /home/*/public_html>
#        php_admin_flag engine Off
#    </Directory>
#</IfModule>

Then, restart the web server:

sudo apachectl restart

Looks like this happened to me a while back in late 2017, too.