Lets Encrypt / Dehydrated retry – August 02, 2022 (read more)
I get sporadic errors when running dehydrated -c from my regular cron job. The errors I get vary from time to time, but they are:
ERROR: Problem connecting to server (get for https://acme-v02.api.letsencrypt.org/directory; curl returned with 35)
ERROR: Problem connecting to server (post for https://acme-v02.api.letsencrypt.org/acme/authz-v3/xxxx; curl returned with 35)
It seems to happen to some servers more than others, particularly newer ones (Debian 11).
Receiving MMS Messages Is More Reliable Now – April 06, 2022
After a long time of not being able to figure out why some MMS messages don't come through well, and others are fine, I finally figured it out.
PHP's mail() function doesn't do anything with line-wrapping and some email clients and servers have trouble with long lines. The RFC standard is 80 characters (78 plus the carriage return/line feed), and Amazon (which is where the MMS images get hosted temporarily) uses really long lines in their URLs - over 1,000 characters, so I suppose it is reasonable that mail servers don't like emails that go past the standard by 12X. There was an extra space being added for the 998th character, which was breaking the URL into two pieces and causing the image to give a strange licensing/login error, which when I asked the upstream provider, they said I wasn't downloading the image soon enough, which seemed pretty strange, but I finally figured it out, because today I tried to download an MMS message seconds after receiving it, and it still didn't work.
So, I'm happy to report that the images work for a much longer period of time (I'll have to test it to see if it is back to 24 hours or more, which it used to be), or if I should still be downloading them locally right away and then storing them for your retrieval later.
In any case, the images should be working more reliably now.
Programming Classes – October 05, 2021
I've done informal programming classes in the past, but I've been thinking lately of making it more formal. There are a few professional coding classes available, and we've tried some with our own kids Khan Academy is great, though Jonathan was disappointed when he discovered the "fake" javascript world that coding system lives in isn't that practical for making actual programs. Scratch is pretty great too, and I think the best introduction to programming that currently exists, particularly for young kids, because you don't even need to be able to read that well to be able to program proficiently there. And they are starting to have modules that can interact with real hardware, which is pretty neat. Learn Python the Hard Way appears to be a good model for older programmers.
If you are interested in enrolling in a programming course, check out our course page and contact me and we'll see what makes sense for you depending on your skill level, etc. Payments will be pre-paid, and we do accept state-funded programs like ClassWallet.com, etc.
Gourmet Printing – December 20, 2020
For those of you using Gourmet on a system that doesn't have python-poppler that was removed and so then printing no longer works, there is an easy solution. Simply find an older version of the package python-poppler, and reinstall it. I looked into why poppler was removed, but I forgot the reason, but I need to be able to print my recipes...
This will probably break at some point, but hopefully gourmet will be updated to python3 by that point and we'll get to keep using it.
PINE / Alpine Decrypting Old-Style Password Files – October 26, 2020 (read more)
I have an instance of Alpine 2.0 that still has the old-style .pine-passfile that is fairly insecure, but I couldn't find a utility to decrypt it for me, so I grabbed the source code from imap.c from version 2.01 of the alpine source, and modified it to just read in a password file and output the passwords in it.
Amazon Fresh API: PHP/cURL Woes and a Final Solution! – July 29, 2020
I just spent four hours trying to get the Amazon API to work properly. The documentation is pretty poor, and just has the one example, which as I finally figured out in the end, works completely differently than the "landing" URL, which is the one you actually need to use.
How I thought it would work is that I would send my ingredients off to Amazon and they would return a customized link (in the form of the green button like on the verify page) and then I could display that to the visitors. So, I worked on cURL using various methodologies of encoding, etc. and when it finally started to work, I realized that Amazon doesn't actually return the HTML for a form or button, but the whole HTML of the page, so what they really want you to do is to setup an HTML form on your page with a hidden input and then have the user press on the submit button and hope for the best (rather than me see if the items are available and in stock, etc, and provide a better user experience for the visitor).
So, without further ado, here is the code you want to take a PHP array of ingredients and display an HTML form that your visitor can click on to link to Amazon's Fresh API.
$list = array();
foreach($ingredients as $ingredient) {
$list[] = array("name" => $ingredient['name'],
"quantityList" => array(array("unit" => $measurement = $ingredient['measurement'],"amount" => $ingredient['amount'])));
}
$result = '<form method="POST" action="https://www.amazon.com/afx/ingredients/landing">'.
'<input type="hidden" name="ingredients" value=\''.json_encode(array("ingredients" => $list)).'\'>'.
'<input type="submit" value="Buy on Amazon">'.
'</form>';
As always, if you are looking for a professional developer to help you get your projects done, I'm available for consulting.
Script to Generate Self-Signed Certificates Automatically – July 26, 2020
I always have trouble remembering how to make self-signed certificates, and there are a million different webpages devoted to doing so, but they all do it a little differently, and don't always, work, so here is the millionth-and-one web page, but at least it will work for me.
The features I care about are using private IP addresses, private DNS names, public DNS names, a root authority that needs to be imported into the browser's trusted certificates, and remembering/auto-filling passwords automatically.
Here is my config:
#!/bin/bash
set -e
set -u
ROOT=MyRootCA
SERVER=MyClient1
if [ -f $ROOT.pem ] ; then
echo "Regenerate root certificate too? (Y/n)"
read confirm
fi
if [ "${confirm:-Y}" == "Y" ]; then
echo "Generating root certificate..."
openssl genrsa -out $ROOT.key 2048
openssl req -x509 -new -nodes -key $ROOT.key -sha256 -days 1024 -out $ROOT.pem -config $ROOT.req
fi
echo "Generating server certificate..."
openssl genrsa -out $SERVER.key 2048
openssl req -new -key $SERVER.key -out $SERVER.csr -config $SERVER.req
openssl x509 -req -days 730 -CA $ROOT.pem -CAkey $ROOT.key -CAcreateserial -out $SERVER.pem -in $SERVER.csr -extfile $SERVER.req -extensions v3_req
if [ "${confirm:-Y}" == "Y" ]; then
echo ""
echo "Remember to import the certificate into your browser: chrome://settings/certificates."
fi
And then the two .req files:
MyRootCA.req:
[req]
distinguished_name = req_distinguished_name
prompt = no
[req_distinguished_name]
C = US
ST = NH
L = Hillsboro
O = Lime Daley Root
CN = limedaley.comMyClient1.req:
[req]
distinguished_name = req_distinguished_name
x509_extensions = v3_req
prompt = no
[req_distinguished_name]
C = US
ST = NH
L = Hillsboro
O = Lime Daley
CN = lemon.limedaley.com
[v3_req]
subjectAltName = @alt_names
[alt_names]
IP = 10.243.0.10
DNS.1 = lemon.local
DNS.3 = localhost
DNS.4 = lemon.limedaley.com
DNS.5 = lemon
To use, edit the two .req files as appropriate, and then run the generate script (you shouldn't need to edit it) and then import the *root* certificate, not the server certificate into the "Authorities" section in the certificate management section of your browser.
You also need to put the appropriate lines into your webserver. Here is an example for Apache:
SSLCertificateFile /etc/ssl/limedaley/MyClient1.pem
SSLCertificateKeyFile /etc/ssl/limedaley/MyClient1.key
When you want to make changes to the $SERVER.req file, you don't need to regenerate the root certificate, but just use the old one, and then you won't need to import it into your browser.
ltsp-build-client error on tcsh: VENDOR environment variable set to unknown – March 08, 2017
I'm not sure where VENDOR gets set - maybe just in the default tcsh binary, but when I su to root (bash) it saves the environment variable, and the ltsp-build-client script looks to see if the VENDOR variable is set, and if it is, uses that value, which in my case is set to "unknown" which then results in the output of ltsp-build-client to be:
/usr/share/ltsp/plugins/ltsp-build-client/common/010-etc-hosts: line 3: /opt/ltsp/amd64/etc/hosts: No such file or directory
error: LTSP client installation ended abnormally
Google didn't help, so hence the reason for this post.
Simply running "unsetenv VENDOR" in my tcsh environment fixed the problem. And as a side bonus, all of the options in the --extra-help are now visible. I wondered why the options didn't match what I was reading in documentation online.
Fun with Pointers (or maybe Fun with Engineering Students) – September 20, 2016
I was a teaching assistant for 18-349, Introduction to Embedded Engineering for three semesters in college and I really enjoyed it. One semester, the professor asked each of the TAs to create a test problem, and I had quite a lot of fun with that, though my students didn't. Only two students out of 100+ got it entirely correct, though maybe 30% got most of the problem correct. Students always have trouble with pointers, and understanding how their are addressed, de-referenced, etc.
Here is the problem (note that you are at a disadvantage compared to the students because they should have known what size integers and integer pointers are):
Playing with pointers with ARM 7
Given:
int str[10] = {0,1,2,3,4,5,6,7,8,9};
int i, j, tmp;
int *K, *L;
For the code examples of A, B, C, and D below, mark which samples correctly reverse the order of "str". If not correct, explain why for each such sample. Assume 32-bit words.
A. for (i=0, j=9; i<5; i++, j--){
tmp = str[i];
str[i] = str[j];
str[j] = tmp;
}
B. for (i=str,L=i+36; i<L; i=(int*)i+1; L--){
tmp = *(int*)i;
*(int*)i = *L;
*L = tmp;
}
C. for (K=&str[1]; L = &str[10]; L-K+1 != str[9]; K++, L--){
tmp = *(K-1);
*(K-1) = *(L-1);
*(L-1) = tmp;
}
D. for (K=&str[0], L=K+9; K<L; K++,L--){
tmp = *K;
*K = **(&L);
*L = tmp;
}
The reason for the test problem is that I saw students writing things like *&var and if it didn't compile, add another * or & until it did, but without any understanding of what those symbols actually meant. Though almost everyone got it wrong, some students did take the time afterwards to go through the code and actually understand what was happening. It is my belief that if you can understand these code samples, you understand pointers completely.
Some students objected to the answer on moral or philosophical grounds, and I think the professor didn't end up weighting this question all that much when he scaled the grades.
One student went to office hours with the professor and managed to convince the professor that I was wrong, but I met with the student and we typed it into a compiler and ran it so he could see how it worked.
Note that I'm not saying this is the right way to write code. Also, note that despite this test problem, students always rated me really high on the evaluations...
Planet Memory Review – March 17, 2014 (read more)
I have a server that is apparently considered "old", as in, the RAM in it is old enough that manufacturers aren't making much of it any more, and so the prices are starting to go up.
I had purchased the machine only half full of processors and RAM with the idea that it would be a cheap upgrade later once I needed it. I'm getting to the point of "needing" the upgrade, and so went out looking for the parts.
The processors were easy enough to come by, but the RAM was not, and the brand new price of the RAM sticks (4GB, ECC, Buffered, DDR2, 800Mhz) was up around $50-$100 a stick, but I found them on Ebay from PlanetMemory for much cheaper - $16!