A QLineEdit Replacement with Spell-Checking

TL;DR: Here’s the code

Today, I recevied a question which prompted me to revisit my old An Improved QPlainTextEdit for PyQt5 post and, along the way, I got a little nerd-sniped on the idea of adding spell-checking to QLineEdit too. (After all, I will need that for my own use sooner or later.)

Long story short, since QLineEdit doesn’t support syntax highlighting, you either have to re-implement the paint event yourself (which is a little too low-level for me to want to be responsible for shaking the bugs out of it) or you can just reconfigure QPlainTextEdit to look and act like QLineEdit.

It’s not perfect, since it can’t be used in situations like setting a custom QLineEdit subclass for a QComboBox… but since I already have a QPlainTextEdit that does spell-checking…

The process basically breaks down into two roughly equal parts: Working around the warts in how the QWidget APIs expect you to customize your widget sizing heuristics and everything else.

Start by turning off all word-wrapping and forcing the scrollbars to be hidden:

self.setLineWrapMode(QPlainTextEdit.NoWrap)
self.setWordWrapMode(QTextOption.NoWrap)
self.setHorizontalScrollBarPolicy(Qt.ScrollBarAlwaysOff)
self.setVerticalScrollBarPolicy(Qt.ScrollBarAlwaysOff)

Then, actually force the contents to stay on a single line. You’d think we could just use self.document().setMaximumBlockCount(1), but that disables Undo/Redo, makes Ctrl+V paste the last line when I think it’s more natural to preserve the first, and requires you to override keyPressEvent to prevent Enter/Key_Enter from erasing the contents of the field, so we have to go in manually:

def cb_textChanged(self):
    if self.document().blockCount() > 1:
        self.document().setPlainText(self.document().firstBlock().text())

self.textChanged.connect(self.cb_textChanged)

Going this route also makes it really easy to implement things like converting one-per-line lists of tags/keywords into comma-separated lists. Just replace self.document().firstBlock().text() with document().toRawText() or document().toPlainText() (depending on whether you want a little bit of Unicode normalization as described in the Qt docs) and do something like .replace('\n', ', ') before feeding it to setPlainText. (Though I’d probably use a QRegularExpression since it makes it easier to normalize whitespace while doing the conversion.)

Finally, the last difference I noticed and accounted for was the behaviour of the Tab key. That can be fixed as follows:

self.setTabChangesFocus(True)

def focusInEvent(self, e: QFocusEvent):
    """Override focusInEvent to mimic QLineEdit behaviour"""
    super(OneLineSpellTextEdit, self).focusInEvent(e)

    # TODO: Are there any other things I'm supposed to be checking for?
    if e.reason() in (Qt.BacktabFocusReason, Qt.ShortcutFocusReason,
                      Qt.TabFocusReason):
        self.selectAll()

def focusOutEvent(self, e: QFocusEvent):
    """Override focusOutEvent to mimic QLineEdit behaviour"""
    super(OneLineSpellTextEdit, self).focusOutEvent(e)

    # TODO: Are there any other things I'm supposed to be checking for?
    if e.reason() in (Qt.BacktabFocusReason, Qt.MouseFocusReason,
                      Qt.ShortcutFocusReason, Qt.TabFocusReason):
        # De-select everything and move the cursor to the end
        cur = self.textCursor()
        cur.movePosition(QTextCursor.End)
        self.setTextCursor(cur)

Now for the big hassle… redefining the widget sizing behaviour. You’d think that self.setSizePolicy(QSizePolicy.Preferred, QSizePolicy.Minimum) would be enough, but QPlainTextEdit defines unhelpful sizeHint and minimumSizeHint values and I don’t know where it’s getting them from.

I’ve seen other people doing various hacks, but I saw problems in all of them:

  1. Some people set the fixedHeight on the widget to the lineSpacing() given by the QFontMetrics from its font() … but that doesn’t properly account for the other various bits in the system like padding and borders from the QTextDocument and QStyle which become relevant when a widget is so short.
  2. Some people create a hidden QLineEdit with the same font settings, trigger layout calculations for it, and then harvest the values… but that’s just unacceptably hacky for me.

…so, here’s what I cobbled together from various sources. I don’t know if it’s 100% correct, but it seems to work:

def minimumSizeHint(self):
    """Redefine minimum size hint to match QLineEdit"""
    block_fmt = self.document().firstBlock().blockFormat()
    width = super(OneLineSpellTextEdit, self).minimumSizeHint().width()
    height = int(
        QFontMetricsF(self.font()).lineSpacing() +  # noqa
        block_fmt.topMargin() + block_fmt.bottomMargin() +  # noqa
        self.document().documentMargin() +  # noqa
        2 * self.frameWidth()
    )

    style_opts = QStyleOptionFrame()
    style_opts.initFrom(self)
    style_opts.lineWidth = self.frameWidth()
    # TODO: Is it correct that I'm achieving the correct content height
    #       under test conditions by feeding self.frameWidth() to both
    #       QStyleOptionFrame.lineWidth and the sizeFromContents height
    #       calculation?

    return self.style().sizeFromContents(
        QStyle.CT_LineEdit,
        style_opts,
        QSize(width, height),
        self
    )

def sizeHint(self):
    """Reuse minimumSizeHint for sizeHint"""
    return self.minimumSizeHint()

So… how well does it work? Well, here’s the full code. Try running it yourself. The demonstration will present it side-by-side with a regular QLineEdit.

(Let me know about any divergences in their behaviour that I missed so I can either fix them or document them as intentionally retained.)

Posted in Geek Stuff | Leave a comment

NT_STATUS_ACCOUNT_EXPIRED

TL:DR: Check that your system clock is set correctly …and use pdbedit -u accountname -K 0 to disable expiry for the account if that’s what it’s supposed to be in the first place.

…because I just spent an hour tearing my hair out before realizing the solution.

If you’ve just created an account named accountname with sudo smbpasswd -a accountname, under what should be the default Ubuntu settings for Samba, and you can’t log into your shares, and sudo pdbedit -vu accountname looks like this…

Unix username:        accountname
NT username:          
Account Flags:        [U          ]
User SID:             S-1-5-21-4147919797-2373757126-213116460-1000
Primary Group SID:    S-1-5-21-4147919797-2373757126-213116460-513
Full Name:            Your Name
Home Directory:       \\YOURPC\accountname
HomeDir Drive:        
Logon Script:         
Profile Path:         \\YOURPC\accountname\profile
Domain:               YOURPC
Account desc:         
Workstations:         
Munged dial:          
Logon time:           0
Logoff time:          Wed, 06 Feb 2036 15:06:39 UTC
Kickoff time:         Wed, 06 Feb 2036 15:06:39 UTC
Password last set:    Tue, 28 Sep 2088 08:03:11 UTC
Password can change:  Tue, 28 Sep 2088 08:03:11 UTC
Password must change: never
Last bad password   : 0
Bad password count  : 0
Logon hours         : FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF

…and smbclient --user=accountname '\\YOURPC\sharename' is saying NT_STATUS_ACCOUNT_EXPIRED, do two things:

First, figure out why the heck your system clock thinks the year is 2088. Second, if you don’t want the account to ever expire, actually ask for it:

sudo pdbedit -u accountname -K 0

I was so fixated on the assumption that I had NTP time synchronization set up properly that I didn’t notice the date in this log line and went straight to investigating check_samsec.c:206:

[2088/09/28 08:31:20.028105,  1] ../../source3/auth/check_samsec.c:206(sam_account_ok)
  sam_account_ok: Account for user 'ssokolow' has expired.

…of course, it really didn’t help that, when I actually tried some suggested ways to list expired accounts, nothing showed up.

Today I learned about a weird quirk of using the “try it out without installing” mode of a Lubuntu Linux LiveUSB stick as a hacky way to turn a small form factor PC with only one hard drive bay into a temporary network-attached external drive housing.

Posted in Geek Stuff | Leave a comment

Some Very Noteworthy YouTube Videos

For the last 11 months, I’ve been getting carried away with a draft… YouTube channels I recommend. It turns out that my sense of perfectionism ran away with me.

…so, in the spirit of my old The Most Eye-Opening Things I’ve Ever Read post, and since I’m not sure when that’ll be ready, I’m going to pare it back and just post an updated version of the initial concept. The stuff I found most eye-opening or most unusually well-researched, which is already ready to go right now.

Here are some YouTube videos which I thought deserved more attention, grouped by the channels that uploaded them:

Ahoy

A British YouTuber who does high-quality documentary videos on the history of things relating to video games.

Barely Sociable

Barely Sociable does thoroughly researched detective-y videos, mostly about “Internet mysteries”,… sort of like Down The Rabbit Hole, but focused on a different slice of the Internet. I’ll let some of the example titles say all that needs to be said.

Slightly Sociable is his secondary channel and I also recommend some of the content on there which feels like it could have gone on his main channel if not for it only requiring a shorter and/or lower-effort video to answer to the same standard. (However, because it’s lower-effort compared to his primary channel, things do occasionally slip through that I wouldn’t recommend.)

Bedtime Stories

While I normally wouldn’t recommend a Fortean channel, because their credulity tends to put logic and lunacy on equal footing in the viewer’s mind, these particular Bedtime Stories videos are a special case.

Yes, Bedtime Stories is a guilty pleasure at best, because they do still often put logic and lunacy on an even footing to make things spookier. (See, for example, their videos on Flight 19 and the Ourang Medan, compared to LEMMiNO’s and Skeptoid’s more thoroughly researched takes, respectively.) However, in these particular videos, they actually did manage to research them better than any of the other YouTube videos I’ve seen so far, and managed to spend more time debunking pervasive misconceptions than propagating them.

EEVBlog

Run by an infectiously enthusiastic and friendly aussie named David L. Jones, EEVBlog is a channel full of useful lessons and advice for electronics hobbyists, cool teardowns of retired tech, debunkings of electronics and electrical engineering nonsense, and all sorts of other fun stuff that you’d expect out of someone who’s passionate about his work.

Joe Scott

Joe Scott is a relatable, ordinary-sounding guy who makes educational videos on a variety of topics, but without the tendency to fall for bad information that I see on so many similar channels.

LEMMiNO

Aside from being a bit too credulous about UFOs (he’s still in the process of improving on that front, but compare Joe Scott’s or Thunderf00t’s coverage), this Swedish YouTuber does an amazing job of providing heavily researched, high-quality documentary content of the “let’s watch it again, just for leisure value” type, about topics that are usually covered in a wishy-washy, overly-credulous way.

Some of my favourite videos include:

Nexpo

Another YouTuber like Barely Sociable (in fact, I think he inspired Barely Sociable) who investigates mostly “Internet mysteries”, some real and some Alternate Reality Games, but has been getting into more real-world topics. Here are a few of my favourite of his videos:

Night Mind

If you like the Alternate Reality Games side of Nexpo’s work, you’ll also like Night Mind. I recommend this video of his most:

Numberphile

Another great channel I hadn’t written an introduction for yet.

Paper Skies

While relatively young, this channel is a beautiful example of what happens when someone with a passion for a niche of history makes documentary videos. In this case, interesting events in the history of aviation. These videos don’t just cover events themselves, but put them in context and, aside from maybe a little break-in period to get used to the narrator’s accent, they’re very relaxing to listen to. Highly recommended.

PBS Eons

This product of PBS Digital Studios is a high-quality free show about paleontology that I can watch for hours without it starting to wear on me. (As opposed to SciShow which, while good, just has something about its style that does start to wear on me after a while.)

Examples of good Eons videos include:

PBS Space Time

This channel is to SciShow Space as PBS Eons is to SciShow… a deeper, more academic, less whizbang (yet not still dry) look at astronomy, physics, and astrophysics. It’s fascinating on its own, but it’s also an invaluable resource if you’re an aspiring sci-fi author who wants to catch up on the state of things.

(Though, if your local library has it, the quickest way to get up to speed would probably be to start with this illustrated Stephen Hawking omnibus and then to jump to Space Time for the discoveries and details beyond what it covers.)

There are far too many excellent videos, so I’ll just present a few of the most mind-bending:

Accursed Farms

While best known for his comedy machinima series Freeman’s Mind and Civil Protection, and his Ross’s Game Dungeon series which draws attention to lesser known old games, Ross Scott is also an opinionated man who’s not afraid to do his research, with some very insightful things to say and some strong opinions on game preservation. Honestly, I dare you to disagree with his video titles after watching them.

SciShow

SciShow is a general-interest science channel with a style that feels targeted at teenagers. The information is still very interesting but I find that, if I binge-watch too much of it, it starts to grate on me. Not nearly as rich in mind-blowing stuff as something like PBS Space Time or Veritasium, but still worth considering.

Smarter Every Day

Along with channels like SciShow, VSauce, and Veritasium, Smarter Every Day is one of the big names in YouTube popular science channels. While the others focus on stuff that’s either more theoretical or further from home, Destin tends to focus on more personally relatable stuff and, when he does travel abroad, his focus is still distinctly down-to-earth compared to the other channels.

Technology Connections

Aside from the fun, engaging, and admirably dedicated lessons about what makes things work, Technology Connections is also admirable for the high-quality content with none of that irritating “Like and Subscribe!” nonsense. Just a silent roll of Patreon supporter names over the blooper reel at the end of each episode. Now that’s classy.

If you like this, you’ll almost certainly also like engineerguy.

Tom Scott

I said this was what I already had ready, but this video is too good to omit, just because I didn’t have time to write an introduction to the man who made it:

TREY the Explainer

TREY does videos on dinosaurs, mythology, and cryptids.

While his dyslexia occasionally trips him up (read the names on screen yourself), his scriptwriting isn’t ideal, and he could use some enunciation practice, that fades from my attention after a minute or so.

More importantly, as seems to be a recurring theme among formerly Christian rationalist YouTubers, it’s hard to find someone on YouTube more dedicated to doing the research properly, including actually getting in touch with real scientists and paleo-artists.

More importantly for his inclusion on this list, it’s hard to find youtubers this dedicated to research who spend time on cryptids.

I find his cryptid videos to be both entertaining and a source of knowledge that’s surprisingly difficult to encounter elsewhere on the ‘net.

Finally, it’s very satisfying to see how engaged and contributory his audience is in the videos themselves, and I like his sense of humor, as best demonstrated in his series of videos on sea monster carcasses. (“A globster, also knows as a blob by racists, …”)

Veritasium

Along with channels like SciShow, Smarter Every Day, and VSauce, Veritasium is one of the big names in YouTube popular science channels. However, his turn to sponsorships has hurt his credibility recently, so, aside from applying the usual critical thinking, my advice is to stick to the “mind-blowing/expanding introductions to science/history stuff with minimal financial interest behind it” stuff, like these… especially the earlier ones For the rest, maybe Tom Scott, since he’s British and their laws on advertising and sponsorships require you to be more overt about your potential financial conflicts of interest.

Vsauce

Just as SciShow Space is sort of like PBS Space Time, but with a punchier, more whizbang scriptwriting style, Vsauce is sort of like Veritasium, but with a punchier, more whizbang style.

Vsauce episodes are fascinating… but also hard to summarize because they’re characterized by a rambling style that wanders through a bunch of loosely related topics, like a Wikipedia crawl in video form. They do technically have multiple channels, but I’m specifically recommending Michael’s content on vsauce1.

  • How Earth Moves (Calendaring, perspective, shadows at noon, and a visualization of how we’re moving through space.)
  • Spooky Coincidences? (Coincidences, pareidolia, selection bias, confirmation bias, the law of truly large numbers, etc.)
  • What Is The Speed of Dark? (Why shadows can move faster than light, a kind of eclipse you never realized you experienced, stages of twilight, etc.)
  • The Brachistochrone (Circles, rolling, acceleration, refraction, the speed of light, and actually building a practical demonstration with Adam Savage to show a ramp that takes the same amount of time to roll down no matter where you start.)
  • The Banach–Tarski Paradox and How To Count Past Infinity (Thinking about infinity)
  • Dord. (All sorts of stuff about language, copyrightability of facts, ancient puns, irony, etc.)
  • The Zipf Mystery (Zipf’s law, the Pareto principle, hapax legomena, and more about power law statistics)
  • Supertasks (Ends with a powerful argument for why we ask and answer “pointless questions”)

Xiph.org

While not technically officially on YouTube, these videos by the creator of the Ogg Vorbis audio format (.ogg files) are so neat and worthwhile that I just had to make an exception.

  • Episode 1: A Digital Media Primer for Geeks (A friendly explanation of all the terms you might need if you want to understand how digital audio and video work or experiment with them, and need to be able to google up further answers.)
  • Episode 2: Digital Show & Tell (An explanation and live demo of analog-to-digital and digital-to-analog conversion to explain the Nyquist sampling theorem and band-limiting more deeply and explain why, if 24-bit 192kHz audio sounds better than 44.1kHz and you’re not using very special ultrasound-rated speakers, it’s because it was mixed and mastered with more care, not because 44.1kHz with 16-bit samples is insufficient.)

…and the miscellaneous scraps

  • Moon Landings Faked? Filmmaker Says Not! (A very entertainingly presented explanation of why, in the 1960s, film-making technology hadn’t yet reached the point where they could fake a moon landing.)
  • How Road Barriers Stopped Killing Drivers by Andrew Lam (Just a really fascinating video about engineering from someone who usually doesn’t do this kind of video.)
  • Ancient Aliens Debunked (Aside from 15 minutes at the end of this 3-hour film, when its creator lets his skeptical rigour slip on flood stories and the nephilim, this is a perfect example of how to do a rigorous, well-cited documentary and I highly recommend it. Even if you don’t watch Ancient Aliens, and I don’t, it’s a fascinating and entertaining watch.)

    (Note that it’s usually hosted on YouTube, and you’re granted permission to save and share copies non-commercially, but I think Ancient Aliens fans like to send false DMCA complaints, because it’s been taken down several times and flipped back and forth between YouTube and Vimeo. The embedded player on the website will always be up to date with that.)

    Regarding the last 15 minutes, see TREY the Explainer’s videos on the nephilim and Leviathan to see what it would have looked like if the author of Ancient Aliens Debunked didn’t let his faith cause his skeptical rigour to falter.
  • We Stopped Dreaming (Neil deGrasse Tyson) Parts 1 + 2 (A very moving and insightful compilation of Neil deGrasse Tyson explaining the history of NASA and its effects on our culture.)
  • Carl Sagan – Pale Blue Dot (A very powerful excerpt from the audiobook version of Carl Sagan’s “Pale Blue Dot”, set to music from his series, Cosmos.)
  • A Universe Not Made For Us (Carl Sagan on religion) (A very powerful excerpt from the audiobook version of Carl Sagan’s “The Demon Haunted World: Science as a Candle in the Dark”. I also like the quote from Kurzgesagt that one commenter posted: “In a way, it seems like the cruelest joke in existence has been played on us. We became self-aware only to realize this story is not about us.”)
  • Science Saved My Soul. by philhellenes (An incredibly powerful description of what the universe is.)
  • Titanic’s Final Mystery (I don’t normally link to an unofficial upload, but I highly recommend this. See also the IMDB Page. Also known as Titanic: Case Closed.)

    I’ve watched a lot of Titanic documentaries over the years, and this one is the only one new enough to show off a relatively recent explanation for the sinking which just fits all the evidence so well.
  • …and I hadn’t gotten around to digging up video-specific links yet, but:
    • Thunderf00t has excellent videos going into the science of why various Kickstarter projects are impossible, why various Elon Musk claims are scientifically impossible, why batteries with energy density higher than LiPo batteries are both unlikely to be possible and not a good idea anyway, etc.
    • NativLang has fascinating videos on things like the letter Yogh, the “lost other letter Z” used in names like MacKenzie, and features English is missing but most other languages have.

Posted in Web Wandering & Opinion | Leave a comment

The Role of Anger

Now another note that’s been sitting in my bin of writing advice drafts for a while, that should really be on this blog instead.

When you’re writing a character and they get angry, it’s very important to understand the root causes, both when and why, because anger is a very special emotion, not quite like the others.

While most emotions come naturally, anger is, on some level, chosen as an alternative to just accepting some other emotion… and that’s also why it’s so exhausting. Even if it’s become a habit, when anger tires you out, it’s because of the mental effort involved in forcing your mind toward one state, when it would more naturally try to be in another state you’re trying to reject.

You feel angry because you don’t want to accept what the situation is forcing you to feel, be it embarrassment, or helplessness, or despair, or grief, or any of countless other unpleasant emotions. Anger is the last action available to you in a powerless situation… the one last “f___ you” your brain offers when the alternative is to accept that there’s nothing you can do. (You can be punished for being angry, but nobody can deny you the option to feel it without resorting to medication.)

I’ve had it argued to me that this doesn’t feel quite right for things like impulsive rage, and I’d be thrilled to discuss further, but, for now, I think that this is a good approximation, even if it turns out to not be perfectly correct.

Even if a character’s rage has become so impulsive that it skips right over the emotion it would otherwise be fighting to replace, it’s useful to always think of anger as being in reaction to something that the character would more naturally feel.

This is also why it’s so important to properly understand why a character is feeling angry. It’s not just a question of what makes them angry, but what they’re trying to reject and why they felt it was better to feel angry and compromise their judgment than to accept that other emotion.

John/Jane Doe would feel fear or despair or some other thing because of backstory element A, but, instead, they feel anger or rage or whatever because of backstory element B.

There’s also one other interesting observation that came to me while preparing this: Depending on the situation and how you look at it, you might say that feeling angry is an act of cowardice. The sign of someone who, on some level, isn’t brave enough to confront and accept the emotion it’s replacing. Not always a useful way to look at things… but potentially the lead-up to a novel twist to a character. Anger may exist as part of our motivation structure to solve problems, but society has made it much more common to run into a problem where anger just prevents you from seeking or accepting the help you need.

Posted in Writing | Leave a comment

Fanfiction – Changeling

Changeling by GoWithTheFlo20

This is an interesting case. It’s a Harry Potter – Star Trek: Deep Space 9 crossover that’s quite early in its arc, and has a lot of potential, but it’s also a bit of an “OC named Harry Potter” story.

Specifically, it’s a femHarry story where Harry Potter is a changeling and winds up on Deep Space 9 early in the story arc.

It’s not a bad story by any means, but you can probably get a sense for what I mean when I say that this is an “OC named Harry Potter” story. The story changed Harry’s gender and species, and presents her in a narrative that, while engaging, doesn’t leap to introduce details that are strongly associated with who canon Harry Potter is as a person, and she winds up letting the DS9 crew continue to use the temporary name they gave her… Bu.

Yes, the parts before Harry arrives on Deep Space 9 have a lot of Harry Potter details, but I get a sense that they lean more toward justifying using Harry Potter in a role that already had an identity of its own, rather than establishing that the narrative fundamentally needs who Harry already was.

Sure, “Bu” is Harry Potter because her initial “play dead” response was conditioned by the Dursleys, and she’s got Harry’s hero complex when she refuses to join the Great Link so long as doing so would leave Odo alone again, and she knows enough about glasses to ask the replicator for some test pairs for Weyoun, but that combination of traits isn’t particularly unique to Harry Potter and combining the name “Bu” with the personality she has makes it harder to see why this character should have begun as a femHarry, rather than an interesting OC. (And, to be honest, I can’t remember the story even trying to justify why a changeling Harry would know that much about glasses.)

So, does it need to be a Harry Potter crossover at all? Well, at the moment, the story arc isn’t far enough in to have seen “Bu” do anything a muggle couldn’t do, so I’ll have to give it the benefit of the doubt that magical ability is going to be significant and that’s why it’s a Harry Potter crossover rather than a non-crossover DS9 story.

With all that focused on, what about the good parts? Why did I think this felt worth a review? Well, OC in disguise or not, there’s something about how Harry/Bu and her interactions with others are portrayed which I really like. It’s got that touch of innocent warmth to the tone of the writing that I’ve seen in various “character as a little kid” stories in various fandoms.

It’s also a story with a main character who is very distinctly not human (something else I like)… which it’s already using to good effect for character exploration and development… and, even without the author’s note telling me the intended pairings, I can already feel that it’s going to be a story which explores and develops Weyoun as a very interesting main character.

(Though I am mildly worried about whether the author will be successful at whatever is meant by putting “Garak/Julian” in the pairing chart. As close friendship, yes… but, if more is intended, it may require a kind of character-writing skill that would have noticed and avoided “OC named <canon character>” writing before it happened.)

It’s hard to say more, given how early in its arc it is, but, from what I’ve seen so far, I’d say that it’ll be somewhere between 4.0 and 4.5 out of 5 once it’s got more chapters under its belt and, as long as you’re willing to not be distracted by expectations of who Harry Potter is as a character, it’s something you should check out.

P.S. If you want to see something similar to this done by a professional author, check out the Web Shifters series by Julie E. Czerneda. It’s been at least a decade since I’ve read it, so I can’t write a full review from memory, but I remember enjoying it.

Posted in Fanfiction | Leave a comment

Warning about a new comment spam scam

This morning, I found a message in my comment moderation queue which I thought I should warn people about.

Like most comment spam these days, it listed a genuine-looking e-mail address at a big-name provider, but instead of trying to be SEO spam, the URL field was pointed at the front page of Shutterstock and the message body tried to scare me with claims that they were a certified photographer (what does that even mean?), I had photos on my site that were infringing their copyrights, and if I didn’t take them down, I’d be reported to my hosting provider and/or sued.

Now I find this to be a hilarious piece of scam-work for three reasons:

  1. My site has almost no images of any kind in order to keep bandwidth consumption down
  2. There’s only one image on the entire site that isn’t either part of the bundled-with-WordPress theme I’m using, a screenshot I took of non-photographic content, or a diagram I drew.
  3. That single photo is the picture of me in the sidebar, which was taken by a member of my immediate family out behind our house, not some random stranger on the Internet.

…so why am I bringing this up? Well, the threat tries to drive you to download something off Google Drive which is supposedly a list of what you’ve infringed.

First, that should already be ringing alarm bells. If they could customize the URL, why couldn’t they just say what I’ve infringed in the message like a DMCA takedown message would?

…and why wouldn’t they mention the DMCA or EUCD, which have the force of law behind them, when so many people are over-eager to do so? Probably because sending such a takedown requires you to list what you want to be taken down and swear under penalty of perjury that you hold the rights to it.

(Not to mention, why would a legitimate sender post a comment on a random post with no images in it, rather than using the contact form.)

Second, a line like “Take a look at this document with the links to my images you used at blog.ssokolow.com and my earlier publications to obtain the evidence of my ownership.” is classic form-letter spam… though, granted, spam usually just uses ssokolow.com in place of actually referring to the site in a way that would require a human to compose.

This is clearly a message that’s trying to come across as written by a human, but has the markers of being submitted by a bot. Obvious botspam if you know what to look for.

In fact, I’ve been meaning to rework my anti-spam code to require filling out an hCaptcha if a message mentions the domain name of the site the message is being submitted to without it being part of a proper URL (i.e. blog.ssokolow.com instead of http://blog.ssokolow.com/ or whatever), because it’s such a common spam tactic to copy-paste the domain into the form letter to make it sound more official.

I decided to see what they were pushing, so I spun up an up-to-date copy of Chromium in Incognito Mode in a sandbox on Linux and pasted in the URL… it immediately asked me to log into my Google Account.

Now, I’m not familiar with Google Sites, but it wouldn’t surprise me if there’s some way for them to get a log of which Google accounts accessed a file that’s been marked private (enterprise customers would want that), and this is some attempt to scrape e-mails to sell to spammers.

I didn’t feel like creating a throwaway Google account just to investigate further, so I left it there.

The takeaway?

Don’t let spammers goad you into revealing your contact information… especially when their messages look so unlike real legal threats.

UPDATE 2021-05-25: Received another one today which actually did do the DMCA boilerplate and didn’t require login to get to the “download proof” button when I opened it in a sandboxed copy of Chromium in Incognito Mode.

Unfortunately, “Your download should begin automatically.” didn’t, no matter how many times I clicked the “Download my file” button, so, unless they’re trying to exploit my browser to infect my system, I still have no idea what the scam is.

…and since they’re still posting random comments on fanfiction reviews with no images (rather than using the contact form), on a blog with almost no images, and all the images are things I own the rights to, and they still won’t say what they claim I’m infringing in the message itself, I’m still convinced that it’s a scam.

(Plus, the DMCA boilerplate seems to be addressing me as “a service provider”, which suggests they copy-pasted somebody’s example of DMCA text that would be sent to a service like WordPress.com or Blogger, rather than to the blogger themself.)

To be clear how serious I am about these people acting in bad faith, here’s a breakdown of all the image files that show up outside the the stock WordPress theme I’ve extended and the common WordPress plugins I’m using, when I check my local backup of my WordPress install:

  1. The site’s favicon, which I created from scratch by clicking pixels together in GIMP.
  2. One photo of me taken by a family member out behind our house.
  3. A bunch of screenshots of open-source programs I created, none of which display photos.
  4. A bunch of screenshots (often annotated) showing the effects of custom CSS userstyles I wrote, none of which depict anything more photographic than a 23px-by-42px thumbnail of a game box in a cropped and annotated screenshot of an Amazon wishlist.
  5. A bunch of Inkscape drawings and flowcharts I did from scratch.
  6. A few cropped screenshots of things like my custom system tray icons and my Conky theme.
  7. One screenshot of a Chameleon Twist error message that is eligible for fair use under the same terms Wikipedia uses to justify their screenshots, and which would certainly have nothing to do with a copyright claim which links to the front page of shutterstock in the comment form’s URL field.
  8. A bunch of old icons for sites like del.icio.us, FriendFeed, StumbleUpon, and Google Code from a plugin I removed ages ago, which I forgot to delete… and those haven’t actually been displayed by the site in a decade… just loose files sitting on the server taking up space.

Unless a WordPress plugin author turned evil and slipped something in as part of a routine update, just so they could extort downstream users, that’s it. Those are all the images I’ve uploaded in the 16 years I’ve been running this blog.

…so don’t pay these scammers any attention. (After all, depending on how a blog is configured, submitting something like this to a comment form may go straight to public display without the author ever getting an e-mail notification. If that’s not spam, then it’s unbelievable, record-breaking incompetence.)

Posted in Web Wandering & Opinion | 4 Comments

Nicer Terminal Commands For Flatpak-Installed Applications

If you’re like me, you probably like to launch your GUI applications from the terminal at least occasionally… or from scripts… or from a quick launcher which doesn’t search .desktop names because you find it annoying to have your intent second-guessed by poor ergonomics in “multiple things match” situations.

However, as shown by the Flatpak developers closing #1188: Improve cli application experience and then locking it because real-world reports of how awkward the current situation is (eg. for invoking a Flatpak-installed copy of Meld from git merge) are apparently “abusive comments”, /var/lib/flatpak/exports/bin is the best we’ll get out of them, and I don’t like typing org.inkscape.Inkscape in the terminal.

I still think Flatpak is the best solution for a lot of other things which I don’t want to have to do myself (especially when paired with using Flatseal to lock down app permissions further), but this is ugly, it’s a usability regression, and it doesn’t even tab-complete well.

Fortunately, since I’m an end-user who doesn’t have to solve all the edge-cases, it’s easy for me to hack together a solution that works in all my use-cases.

Just…

  1. Query Flatpak for the list of installed application IDs (flatpak list --columns=ref)
  2. Run flatpak info -m on each application ID and parse out the application’s actual command name (if one exists) from the .ini-esque output (not perfect, since some app developers/maintainers will use/omit launcher wrappers when they don’t expect you to have to type the name, but it gets you 99% of the way. For example, Flatseal‘s actual binary name is com.github.tchx84.Flatseal, not flatseal, and Flatpak is a perfect way to distrust something like JDownloader that you still need to use, but its command is jd-wrapper.)
  3. Add a folder to the end of your PATH containing exec flatpak run ... "$@" scripts named after the extracted command names. (Better than using alias because you don’t have to coordinate re-source-ing the file in each open terminal for updates to apply.)

…and so, I present to you a proof of concept. It’s got shortcomings, but those are all fixable when I have time to come back to it and rewrite it in a language with a proper .ini parser:

Posted in Geek Stuff | Leave a comment