Knowledge Base

Preserving for the future: Shell scripts, AoC, and more

enable paste on website with javascript

I'm directly quoting/ripping off here. Because it's incredibly useful.

I found this simple script did work [for enabling "paste" on website]:

document.addEventListener('paste', function(e) {
  return true;
}, true);

Which was found here:

Edit: May need to stop propagation for keydown as well for some websites.

document.addEventListener('keydown', function(e) {
  return true;
}, true);

Paste that into the console of devtools (F12) and carry on with business.

python3 urllib3: ignore certificates

In python3 urrlib3, when you set up a pool manager, you can tell it to use your ca cert bundle, or even just ignore certs.

import urrlib3
webpool = urllib3.PoolManager(cert_reqs="CERT_NONE")
webpool = urllib3.PoolManager(cert_reqs="CERT_REQUIRED",ca_certs="/path/to/cacerts.pem")

You can change the settings later too (but I haven't actually tested this yet!):

webpool.connection_pool_kw["cert_reqs"] = "CERT_NONE"

If you use certifi:

import certifi, urllib3
webpool = urllib3.PoolManager(ca_certs=certifi.where())

And also to suppress the warnings (HERE BE DRAGONS):


Use at my own risk.

My FreeFileSync package is rebased on the Debian one


I have been maintaining a package of FreeFileSync for a long time, first as an rpm and currently only a dpkg (source on cgit and possibly gitlab).

I was even asked to participate in maintaing FreeFileSync in Debian by the maintainer! He uses my work, although less and less as he has started writing better patches than I maintain.

I have now rebased my dpkg on his work. He obviously understand debianized build and package processes better than I do, and also he's better at solving the C++ problems that show up.

Notes on patches

So in the whole list of patches (whew, Debian tends to have a lot, doesn't it?), I reviewed what Bastif has and what I wanted too. He implements them in a different order than I do.

  1. pkg-config.patch: I implement in makefile-improvements.patch
  2. wx-config-version.patch: also in makefile-improvements.patch
  3. ffs_devuan.patch is a smaller, lesser version of my main patch that allows me to compile on Devuan. It did show me to add CPPFLAGS and clean up the LDFLAGS.
  4. remove_upstream_build_optimization.patch is very small and I implement in my ffs_devuan.patch.
  5. ffs_devuan_gtk3.patch really should just get folded into the ffs_devuan.patch. It just switches gtk2 to 3, like mine
  6. zlib-dep.patch: also in makefile-improvements.patch.
  7. reproducible-build.patch: I skip this one. I'm sure that's important for Debian, but I'm lazy and don't care. It just fixes a timestamp to be some consistent (static?) value. This sort of thing is why I wasn't willing to sign up for all this work. This seems like a good idea, but takes mental overhead and repo space and .3 seconds for quilt to apply/unapply every time so I just don't care. I'm glad people like Bastif do this for the rest of us though!
  8. ffs_dpkg_vendor_specific_about.patch: This turns into a variable my previously hard-coded "for Devuan" string I would put in the app. I implement this now too, in my ffs_devuan.patch, and stick my vendor name in the Makefile and not just a debian/rules file. I test compiling with make directly, and not just debuild, so I don't want to depend only on the debuild.
  9. ffs_no_check_updates.patch: I didn't actually even read this one. I'm the upstream for ffs_no_check_updates.patch anyways.
  10. ffs_sftp.patch: same as mine, or close enough.
  11. ffs_traditional_view.patch: same as mine. I'm the upstream author of this one too.
  12. ffs_icon_loader.patch: Woops, he wrote this one better than mine. I should replace mine.
  13. skip-missing-Animal.dat.patch: I implement the bare minimum amount of this in ffs_devuan.patch. His is more thorough but mine is minimal and is good enough for me.
  14. fix-gtk3-kde-hang-and-dialog-size.patch: I think I implement this in revert_buggy_gtk3_change_in_12.1.patch, but I also don't use KDE so cannot test.
  15. libssh2_relax_dep.patch: This one is so far superior to mine; he handles it based on different version numbers of the library. I threw mine away and use his now.
  16. Disable_wxWidgets_uncaught_exception_handling.patch: I implement something similar enough in disable_wxuse_Exceptions.patch. I'm willing to guess Bastif's patch is better, but mine works too.
  17. deactivate_google_drive_button.patch: I don't implement this. That means that I don't deactivate the button, but I don't have a google key and secret to plug in, so technically my package doesn't work with Google Drive either. I probably should use this patch, but again, I'm lazy.
  18. libcurl_improve_supported_error_codes.patch: This was so far superior to my old version that I threw mine away and just use this now.

And leave it to Debian to have 18 patches for a program like this!

stackrpms-diff: a complex example

To install my printer shared from my one server, just run this shell script.

files/2024/listings/ (Source)

# File:
# Location: /mnt/public/Support/Platform/printer/
# Author: bgstack15
# SPDX-License-Identifier: GPL-3.0-only
# Startdate: 2024-02-08-5 08:15
# Title: Install my printer on Devuan
# Purpose: oneliner install printer
# History:
# Usage:
# Reference:
#    http://localhost:631/
#    man lpadmin
# Improve:
# Dependencies:
#    run on Devuan. Sudo access.
# Documentation:
#    if you need printing with `lpr -P ml1865w /path/to/file`, then install cups-bsd
# install cups
if ! dpkg -l | awk '$2=="cups" && $1~/^i./' 1>/dev/null ;
   sudo apt-get update
   sudo apt-get install --no-install-recommends -y cups
ensure_printer() {
   status="$( sudo lpstat -v )"
   if ! echo "${status}" | grep -qiE "${_url}"  ;
      sudo lpadmin -p "${_name}" -E -v "${_url}" -L "${_location}"
# printer list
ensure_printer "ml1865" "ipp://" "computer room"
# display status
sudo lpstat -v

This reduces my need to install system-config-printer just to get my one printer set up.

Cups is a beautiful project, isn't it?

X11 wine window not visible: Jazz Jackrabbit 2

One of my applications, Jazz Jackrabbit 2, had a problem where the window would not be visible, but the game is running.

After testing with using a wine virtual desktop environment (failed) and a different wine context (worked), I realized the problem lies between wine and the game. I learned that by deleting the registry key the game uses to store its window state (full screen or windowed) was somehow invalid or incorrect.

HKLM\Software\Epic MegaGames\Jazz Jackrabbit 2 Special Edition

And anywhere else this Software path would be in the registry, such as HKCU. And then run the game, and you can view the game.

And a link to the JJ2 community: Jazz Jackrabbit Online - Jazz Jackrabbit News, Information and Downloads on Jazz Jackrabbit 1, Jazz Jackrabbit 2, and Jazz Jackrabbit Advance - Jazz2Online

Alternate research

I had done a lot of searching for x11 make window visible. How you would do that is with xdotool:

$ xwininfo -root -children | grep -i mktrayicon
     0x1c00001 "mktrayicon": ("mktrayicon" "Mktrayicon")  10x10+10+10  +10+10

And then you can plug in the id force it to be visible.

$ xdotool windowmap 0x1c00001

But even after doing that with JJ2 did not make the game contents display.

Rescan Jellyfin library from cli

I use Jellyfin (see the tags link below), and when I add new media, sometimes I want to see it right away. In order to do that, you need to tell the library to re-scan, or you can have a library configured to watch for filesystem changes. (I assume it uses inotify or something.) I use the "watch" option, but it doesn't seem to work [fast enough?] for me. I use nfs so that might have something to do with it.

So, you can log in to the web/mobile app with an account that can tell the library to scan now for new/changed files, but that takes quite a few clicks. So I spent way more time to write a oneliner that does all that for me, and it even has bash tab autocompletion! Check out the whole project at my cgit/jellystack, but here are some highlights:

Dot-source the autocomplete-rescan.bash script:

test -f /path/to/project/autocomplete-rescan.bash && . /path/to/project/autocomplete-rescan.bash

And after setting the ~/.jellyfin.password (with contents of password) and ~/.config/jellystack (shell script that exports username, password, and server) dependency files, you can use:

rescan-library <TAB>

stackrpms-diff: a complex example

I maintain packages for a number of projects. Some of them are redressings of existing packages by other netizens. My best example is waterfox-g (upstream by hawkeye116477).

I like to maintain a patch that shows the differences between the upstream and my work. This is for transparency, as well as to show the differences so I can recreate those differences for the next version of the package. I don't version-control my debian/ directory in the proper way. I've been chided for this before, but I understand this janky way and you are welcome to re-do my work the correct way!

For a package like waterfox-g where I drop the -kpe ending because I don't use KDE and company (just not my style; they seem nicer than gnomes in general though), some of the filenames change too, which messes up a diff. So here is my complex (original in my scm). files/2024/listings/ (Source)

# Startdate: 2024-01-25-5 15:11
# Reference: scite/
# Usage: stackrpms/waterfox-g/ | vi -
# Purpose: handle the renamed files because of dropping the -kpe suffix
cd ~/dev
# do diff color=always if this is going to a terminal
\test -c /proc/$$/fd/1 && _diff_color="always"
{ test -n "${DIFF_COLOR}" || test -n "${DIFF_COLORS}" ; } && { _diff_color="always" ; }
diff -x '.*.swp' \
   --exclude-from="${right}/../diff-excludes" \
   --color="${_diff_color}" \
   -aur "${left}" "${right}"
for word in dirs dsc install links lintian-overrides manpages postinst postrm preinst prerm links ;
   _result="$( diff --color="${_diff_color}" -aur "${left}/waterfox-g-kpe.${word}" "${right}/waterfox-g.${word}" )"
   test -n "${_result}" && {
      echo diff -aur "${left}/waterfox-g-kpe.${word}" "${right}/waterfox-g.${word}"
      echo "${_result}"

Random notes on this cool script:

I have a separate file, diff-excludes that lists all the old and new filenames to exclude from the first diff, one per line. I didn't want to just have a dozen -x FILENAME entries because that clutters the otherwise useful output of the long command, with the full command line before each diff entry.

I probably need to come up with a programmatic way to generate this from line 17, but I haven't done that yet.

Line 11 escapes the test so it uses the executable test and not any possible built-in. I know it forks a new process and all that, but I'd rather not depend on a bash or other shell built-in.

I do my own stdout evaluation to determine color. Half the time, I'm running the command in a terminal, and the other half the time I'm sending it to a file to then view with $EDITOR (guess which one). So I wrote all this extra logic to handle adding or excluding the color.

If anybody has a better method for diffing two directories that experiences file renames (with possible content changes too; that's why I'm running the diff!), please let me know.

My newer-in-debian script

I wanted to use the really cool site to help track the packages I maintain in Devuan, so I don't get too behind. LeePen feels obligated to tell me when I'm behind, and that shouldn't be his job; I should be doing a better job.

So I wrote this script I can run whenever I feel like it.

files/2024/listings/ (Source)

# File:
# Location: /mnt/public/Support/Programs/
# Author: bgstack15
# Startdate: 2023-12-28-5 17:42
# SPDX-License-Identifier: GPL-3.0-only
# Title: Newer in Debian script
# Purpose: List newer packages in debian than devuan that I maintain
# History:
# Usage: ./
# Reference:
# Improve:
# Dependencies:
#    req-devuan: jq, curl, devscripts
#    req-raw: jq, curl, rmadison
# Documentation: read repology

test -z "${CACHE_DIR}" && CACHE_DIR="${XDG_CACHE_DIR:-${HOME}/.cache}"
test -z "${CACHE_FILE}" && CACHE_FILE="${CACHE_DIR}/newer-in-debian.cache"
test -z "${EMAIL}" &&
BAD_COLOR='\033[0;31m' # red
GOOD_COLOR='\033[0;32m' # green
NEUTRAL='\033[0m' # no color

# invalidate cache older than 23 hours
_cache_is_too_old="$( find "${CACHE_FILE}" -maxdepth 0 -mmin +$(( 60 * 23 )) -print -quit 2>/dev/null )"
test -n "${_cache_is_too_old}" && rm "${CACHE_FILE:-NOTHINGTODEL}"

# test and rebuild cache if necessary
_cache_contents="$( cat "${CACHE_FILE}" 2>/dev/null )"
test -z "${_cache_contents}" && {
   curl --silent --header 'User-Agent: bgstack15-cli' "${EMAIL}&inrepo=devuan_unstable" > "${CACHE_FILE}"
   _cache_contents="$( cat "${CACHE_FILE}" 2>/dev/null )"
} || {
   printf '%s\n' "Using cached package list." 1>&2

# if cache is still empty, then something broke with curl statement.
test -z "${_cache_contents}" && {
   printf '%s\n' "Fatal! Cache is still empty. Re-run with debugging. Aborted." 1>&2
   exit 1

_check_status() {
   # this only uses amd64. If I ever change personal architectures that I care about, I would need to update this.
   # The purpose is to avoid the "source" listing, which might not be the same version as a built architecture, due to binary repacks, e.g., lightdm_1.32.0-4+b1 in debian.
   # --source-and-binary converts "freeipa" source into "freeipa-client" amd64, and a few others but since the versions are all the same we just take the first one (head -n1)
   _deb="$( rmadison              --source-and-binary --architecture=amd64 --suite unstable "${package}" | awk -F'|' '{print $2}' | head -n1 | xargs | sed -r -e 's/\+b[1-9]$//;' )" ;
   # only do anything if the package exists in Debian.
   if test -n "${_deb}" ;
      _dev="$( rmadison --url devuan --source-and-binary --architecture=amd64 --suite unstable "${package}" | awk -F'|' '{print $2}' | head -n1 | xargs | sed -r -e 's/\+b[1-9]$//;' )" ;
      echo "${_dev}" | grep -qE "${_deb}\+?devuan-?[0-9]" && {
      printf '%4b\t%s\t%s\t%s\n' "${_result}" "${package}" "${_deb}" "${_dev}"
      printf '%4s\t%s\t\n' "none" "${package}" 1>&2

_package_list="$( <"${CACHE_FILE}" jq --raw-output 'keys[]' )"
# do not double-quote variable in next line with the for statement.
for package in ${_package_list} ;
   if test -n "${PARALLEL}" ;
      _check_status "${package}" &
      _check_status "${package}"
test -n "${PARALLEL}" && {

I use cache invalidation (which I hear is hard; I hope I did it right!). The web url is Some of these are original packages and don't have an upstream from Debian.

$ ./ 
good    freeipa 4.10.2-2    4.10.2-2devuan1
good    lightdm 1.32.0-4    1.32.0-4devuan1
good    oddjob  0.34.7-2    0.34.7-2devuan1
none    pam-mkhomedir   
none    sgm 
none    systemctl-service-shim

I even added colors, and parallelization (but not really necessary now that we only run rmadison for Devuan if the rmadison for Debian returned anything), just for this blog post. You're welcome, future self.

Librewolf 121.0.1 now in OBS

I don't normally post on my blog merely when an application is updated in my OBS slice, but it's a big deal for this one because multiple pipeline problems have plagued this application.

I provide debianized LibreWolf sources so anyone can build his own package. I also use the public LibreWolf CI infrastructure to build the assets that then also get used by OBS to build the package.

Problem 1

The public (and only, that I know of) CI for librewolf hasn't worked in a few versions, and I haven't bothered to find my alt browser to sign in to whatever chat room it was to ask the LibreWolf folks what's up. I think it was a free instance or something and they probably reached their quota.

Problem 2

Due to the usrmerge drama in Debian, the OpenSUSE-focused Open Build Service doesn't have a great way to work with dpkgs. But finally, after enough project config modulations that include preinstall: systemd amongst a few other things, I can build packages again.

preinstall: usrmerge
prefer: usrmerge
prefer: libjpeg-dev, libjpeg62-turbo-dev
prefer: libjack-dev
prefer: libavcodec60
prefer: libavformat60
prefer: libavfilter9
Preinstall: libsystemd0
Preinstall: systemd

So I manually uploaded the 121.0.1 assets I built locally and dropped the _service file for now which tells the OBS worker node to fetch the publicly-built assets.

  <service name="download_url">
    <param name="protocol">https</param>
    <param name="host"></param>
    <param name="path">/artifacts/0/prepared/librewolf_120.0.1-1.debian.tar.xz</param>
    <param name="filename">librewolf_120.0.1-1.debian.tar.xz</param>
  <service name="download_url">
    <param name="protocol">https</param>
    <param name="host"></param>
    <param name="path">/artifacts/0/prepared/librewolf_120.0.1-1.dsc</param>
    <param name="filename">librewolf_120.0.1-1.dsc</param>
  <service name="download_url">
    <param name="protocol">https</param>
    <param name="host"></param>
    <param name="path">/artifacts/0/prepared/librewolf_120.0.1.orig.tar.xz</param>
    <param name="filename">librewolf_120.0.1.orig.tar.xz</param>

And with my 3 manual assets, the package has now built. You're welcome, Infinity128, and everybody else!

An aside

The reason I use an alternate browser to visit the chat room with the LibreWolf guys is because it used to be which used gitlab and wanted full access to your account, so I made a bgstack150 account on gitlab and used that to talk. I didn't want having full access to whatever I have left on gitlab, so I used that alt account, and since it tied in SSO-like (read: Borg-like) to gitlab, I needed a different browser session and I've been too lazy to learn how to use multiple profiles in the same browser. But the last time I was in there, it was powered by matrix and is probably not necessary, but I still haven't bothered. The one other Librewolf CI project is alpine and that hasn't built in 2 months either so clearly they just weren't using it.

Codesign Powershell script

I work with some Powershell, and sometimes I even have to run Windows systems. Loading a function library was more complicated than it should have been, because I hadn't gotten my powershell script signed with a certificate. So here's how to do it with a valid cert.

$cert = (Get-ChildItem Cert:\localmachine\My -CodeSigningCert)[0]
Set-AuthenticodeSignature -File C:\Path\To\File.ps1 -Cert $cert -IncludeChain "All" -TimestampServer


  1. How to Sign Digitally PowerShell Script With Code Signing.