If you have added a custom Enable Rule to the Application Ribbon using a custom JavaScript already (Show Global Notification on Load of Model-driven App in Dynamics 365 [Linn’s Power Platform Notebook]), it’s easy to add a function to dynamically change the text at the top based on the URL host name. If a new update of D365 changes the underlying DOM that this affects, you will have to modify the JavaScript to match, so this is an unsupported change.

//call this from an Enable Rule
function dynamicallySetColor() {
//set the NAV bar color - https://www.rapidtables.com/web/color/RGB_Color.html
LZW = LZW || {};
var setColorByEnv = function setColorByEnv(br, bg, bb, fr, fg, fb) {
//Background RGB: br, bg, bb
//Font RGB: fr, fg, fb
//unsupported change
if (fr === null || fg === null || fb === null) {
//just set as white
fr = 255;
fg = 255;
fb = 255;
LZW.colorCustomized = true;
console.log("Setting color");
var style = window.parent.document.createElement('style');
style.innerHTML = `.pa-v {
background-color: rgb(` + br + ',' + bg + ',' + bb + `) !important;
.pa-k {
color: rgb(` + fr + ',' + fg + ',' + fb + `) !important;
var setTitleBar = function setTitleBar(newText) {
try { //unsupported change
var parentDiv = window.parent.document.getElementById("id-19");
if (parentDiv) {
var spans = parentDiv.getElementsByTagName("span");
if (spans && spans.length === 1) {
var theSpan = spans[0];
if (theSpan.innerHTML.indexOf('SANDBOX') !== -1) { //only replace this on SANDBOX
theSpan.innerHTML = newText;
[0].innerHTML = newText;
} catch (e) {
try {
var thisDn = window.parent.location.host;
if (thisDn.indexOf("-dev") !== -1) {
setColorByEnv(0, 100, 0, 0, 0, 0); //dark green with black font
} else if (thisDn.indexOf("-qa") !== -1) {
setTitleBar("QA ENVIRONMENT");
setColorByEnv(128, 0, 0, 255, 255, 255); //maroon/white
} else if (thisDn.indexOf("-int") !== -1) {
setColorByEnv(210, 105, 30, 0, 0, 0); //Chocolate/black
} else if (thisDn.indexOf("-preprod") !== -1) {
setColorByEnv(0, 128, 128, 0, 0, 0); //Teal/black
} catch (e) {

When setting up EdgeOS with PPPoE (Centurylink) with Hairpin NAT, ensure that the Port Forward Source on the LAN interface is switch0, even if eth1 is the only one being used. Not sure what switch0 means (one would think it is the combination of eth1-4), but this appears to have fixed an issue with not allowing access to custom (>1024) ports.

When trying to do a git clone on a new installation of git behind a corporate firewall (with MITM on SSL), I got this error:
# git clone https://github.com/zptaylor/public-repo.git
Cloning into 'public-repo'...
fatal: unable to access 'https://github.com/zptaylor/public-repo.git/': SSL certificate problem: self signed certificate in certificate chain

First I tried switching the backend to sslchannel, but that threw a different error:
# git config --global http.sslbackend schannel
# git clone https://github.com/zptaylor/public-repo.git
Cloning into 'public-repo'...
fatal: unable to access 'https://github.com/zptaylor/public-repo.git/': schannel: next InitializeSecurityContext failed: Unknown error (0x80092012) - The revocation function was unable to check revocation for the

Of course the reason no SSL validation will work is because the SSL is for all intents and purposes invalid, so the easiest way is to just turn it off, although it completely eliminates https verification:
# git config --global http.sslbackend openssl
# http.sslVerify= false

A similar solution that breaks security, but for schannel:
# git config --global http.schannelCheckRevoke "false"
# git config --global http.sslbackend schannel

A more precise fix that would allow SSL would be to use openssl, create some sort of trust store of valid certs, and then add the MITM’s cert for github.com in its place. I think these fixes are reasonable for a developer machine who is on a controlled network that could not possibly allow github.com to be spoofed.

Read up more at

##Gets the ip details of "wifi" net adapter, and if has 192.168.0, then it sets to first DNS; 
##otherwise will just reset the DNS!!
##Needs error handling

$currentDir = (Get-Item -Path ".\").FullName+"\"
$wifiPrivateSubnet = "192.168.0."
$wifiPrivateDNS = ",,,"
$wifiName = "wifi"
$wifiIp = Get-NetIPConfiguration -InterfaceAlias $wifiName | select IPv4Address, InterfaceAlias

# Details for logging
$LogPath = $currentDir
$LogFile = $LogPath+"SetWifiDNS.log"
$LogTime = Get-Date -Format "MM-dd-yyyy_hh-mm-ss"

Write-Host $wifiName $wifiIp.IPv4Address.IPAddress "is checking to match" $wifiPrivateSubnet

$matchesThePrivate = $wifiIp.IPv4Address.IPAddress -Match "192.168.0."

If ($matchesThePrivate) {
#if network:
Get-NetAdapter -Name $wifiName | Set-DnsClientServerAddress -ServerAddresses $wifiPrivateDNS
$msg = $wifiName+" being set to DNS "+$wifiPrivateDNS
Else {
Get-NetAdapter -Name $wifiName | Set-DnsClientServerAddress -ResetServerAddresses
$msg = $LogTime+$wifiName+" being reset, logging to "+$LogFile

if(-Not [IO.Directory]::Exists($LogPath))
    New-Item -ItemType directory -Path $LogPath

$LogTime+" - "+$msg | Out-File $LogFile -Append -Force

If you get the error for port 53 being used when starting Pihole, you can disable dnsmasq using these commands:

virsh net-autostart --disable default
virsh net-destroy default



In the latest version of PrimeFaces they apparently made the regex validation for “allowTypes” more restrictive.

Previously we had allowTypes="/(\.|\/)(gif|jpe?g|png)$/"

This will allow .gif/.jpg/.jpeg/.png files but not allow .GIF/.JPG/.JPEG/.PNG files.

To remove the case sensitivity you just add the i flag, for insensitivity:


What is particularly bad about PF 7.0 is that it will allow it to run the uploader as it will pass the first step of the client-side validation, but when it sends to the server it will fail the validation and not alert the user that it failed (!!!), thus making a silent error that will cause users a lot of grief.

The Programmer’s Oath by Robert C. Martin (Clean Coder Blog, 2015-11-18)

In order to defend and preserve the honor of the profession of computer programmers,
I Promise that, to the best of my ability and judgement:

I will not produce harmful code.

The code that I produce will always be my best work. I will not knowingly allow code that is defective either in behavior or structure to accumulate.

I will produce, with each release, a quick, sure, and repeatable proof that every element of the code works as it should.

I will make frequent, small, releases so that I do not impede the progress of others.

I will fearlessly and relentlessly improve my creations at every opportunity. I will never degrade them.

I will do all that I can to keep the productivity of myself, and others, as high as possible. I will do nothing that decreases that productivity.

I will continuously ensure that others can cover for me, and that I can cover for them.

I will produce estimates that are honest both in magnitude and precision. I will not make promises without certainty.

I will never stop learning and improving my craft.

It’s shameful to admit it, but I have known that these are the ethics I should live by, but I often let deadlines, expectations, and laziness come in the way. I hope to work in the next few months to uphold this oath. The hardest part is my tendency to people-please, and my low threshold for the “boring” parts of software development — writing tests, and peer reviews.

I know that logically there are no shortcuts; writing bad code to get a product out ASAP ultimately causes more frustrations and time wasted by myself and others. It is hard for me to fully digest that I will have to slow down in order to save time, but I have seen it happen, literally every day on the job, that fixing a problem in hastily developed code ultimately takes much longer than getting it right the first time.
Just got to remember to breathe every now and then.

I stumbled on this when trying to run the new version of STS (Eclipse) on my work computer, which currently does not have Administrative Rights, yet has Windows 10 “Smart Screen” set to prevent running “unrecognized” applications.

If you try to run an application and the Smart Screen is preventing it from running, right click on the application, click Sent to Compressed File (.zip), then Extract the file and run it. Because Windows Smart Screen sees that you created the .zip file, it will assume that you can trust the contents when you extract it. Replace the original file with this file, and you are off to the races.

YMMV, do not do this at home, or on a computer that you are trusted to protect, etc.

Recently I found myself migrating, again, my cloud hosting provider.  I like to keep a complete backup of all files so that in case I miss something it’s not forever lost in the ether.

This command comes in handy to rsync everything from one host to a backup location, which I can then use to migrate to the new cloud provider. This command skips the docker device mapper along with the other non-FS files in /dev /proc and /sys. It also uses a specified port (–rsh=’ssh -p XXXXX’) in case of non-standard SSH ports. Worked for me!

rsync -av --numeric-ids --exclude='/dev' --exclude='/proc' --exclude='/sys' --exclude='/var/lib/docker/devicemapper/' --progress --inplace --rsh='ssh -p22221' / [email protected]:/backups/backupdirectory

Another set, for skipping a lot more stuff, and focusing on the www:
rsync -av --rsh='ssh -p 22444' --progress --inplace / --exclude='/bin' --exclude='/boot' --exclude='/dev' --exclude='/initrd.im*' --exclude='/lib/' --exclude='/lib64/' --exclude='/lost+found' --exclude='/media' --exclude='/mnt' --exclude='/proc' --exclude='/run' --exclude='/sbin' --exclude='/srv' --exclude='/sys' --exclude='/tmp' --exclude='/usr' --exclude='/var' --exclude='/vmlinu*' --include='/var/www' [email protected]:/mnt/user/backups/ovh/rsync
rsync -av --rsh='ssh -p 22222' --progress --inplace /var/www/ [email protected]:/mnt/user/backups/ovh/rsync/var/www