Friday, June 10, 2011

Book Safe

It has been a while since I've posted something not computer related: well, here you go! Have you ever wanted a book with a hollow middle you can hide things in? Well, I did. Anyhow, the computer science department at the university I attend gets rid of old books by laying them on a table outside the office; most are hard-covers from earlier days. I picked up one on electrical and electronic engineering, to my dismay when I got home I found it to be filled to the brim with calculus. For that reason, I didn't feel bad at all cutting it up.


Time for the recipe:

Materials:
  • Hard cover book.
  • Craft Knife
  • Saw
  • Glue
  • Tape
  • Clamp (optional)
  • Felt (optional)
Methods:
  1. Slice out the inside of the book by running a craft knife along the page that connects the inside to the spine on both the front and back covers, this will leave both the spine and inside pages intact.
  2. Starting from the binding use the saw to slice down the sides of the internal pages of the book about an inch from the edges, until you are about an inch away from the side opposite the binding. I found a clamp helpful in keeping the book still.
    Finished Sawing, Use the craft knife to cut the rest.

    Clamping The Book For Sawing

  3. Using the craft knife, cut through the remaining pages along the outside of the book a few at a time, discarding them as you go to make a U shaped piece of paper.
  4. Finally, glue the spine back in to the cover of the book, and one side of the insert to the cover; spread glue over the inside of the pages to keep them joined, or use tape. If you really want, once the glue has been spread use felt to line it.
    Nearly Done!

I won't show you the cover, because then you would know which book it is!

You could potentially put a fake cover on this, something insane and boring, like "Multi-variable Calculus Pertaining to Optimal Cement Mixing" then stick it in the proper place in your library; a kind of cache for you. Anybody really interested in cement mixing will pass right over it knowing it is rubbish, while anybody new to the subject will go pale at the thought of doing calculus for such a seemingly simple problem.

    Wednesday, May 25, 2011

    Email Me At...

    I have long looked for a feature for Gmail that will delay sending a message until a certain time. Recently I wanted to send a good friend a Happy Birthday message, right when it was her birthday (one second after midnight). If only there was some way to do that...

    Luckily, I didn't have to stay up until midnight to do it, but rather cobbled together a nifty Python script that will wait until a given time, then send a message (including HTML if you have it).

    #!/usr/bin/env python

    import datetime
    import re
    import smtplib
    import time

    from email.mime.multipart import MIMEMultipart
    from email.mime.text import MIMEText

    gmail_user = "yourname@gmail.com"
    gmail_pwd = "MyP@$$W0Rd"

    def mail(to, subject, body):
    msg = MIMEMultipart('alternative')

    msg['From'] = gmail_user
    msg['To'] = to
    msg['Subject'] = subject

    if '<html>' in body:
    msg.attach(MIMEText(re.sub(r'<.*?>', '', body), 'plain'))
    msg.attach(MIMEText(body, 'html'))
    else:
    msg.attach(MIMEText(body, 'plain'))

    m = smtplib.SMTP("smtp.gmail.com", 587)
    m.ehlo()
    m.starttls()
    m.ehlo()
    m.login(gmail_user, gmail_pwd)
    m.sendmail(gmail_user, to, msg.as_string())
    m.quit()

    if __name__ == "__main__":
    while datetime.datetime.today() < datetime.datetime(2011, 5, 24):
    time.sleep(1)

    mail("someone_else@gmail.com", "subject",
    "<html><b>bold body</b> non-bold body</html>")

    Things to Note:
    • Line 11-12, you will need to enter your Gmail address, along with your password in plaintext, so be careful.
    • Line 21, If the body of the message you want to send has the tag <html> it will be sent as an HTML message, all tags will also be stripped and a plaintext version will be put in the document as well.
    • Line 36, The date you use needs to be in ISO format, YYYY-MM-DD, if you want you can even add HH, MM, and SS like this:
      datetime.datetime(2011, 5, 24, 13, 5, 19)
    • Line 39: The first param is the address you are sending to, the second is the subject, and the third is the body (with or without html).
    Making one of these read from a .csv file could be insanely useful.

      Wednesday, May 18, 2011

      Three Comics

      It is unlikely that I'll become Randall Munroe any time soon, but hey, I figure I'll just share these while my code is compiling for the "One Hour Linux Distribution With an X-Server" (if it works, I'll post it later).






      All made in Gimp.

      Saturday, May 14, 2011

      SVN Branch Copy

      I was recently in the position of needing a particular SVN branch copied including history. However I didn't have administrator access on the SVN machine, and using the SVNSYNC command was going to copy all eighteen thousand revisions, mine were about fifty scattered within the last thousand. That was less than ideal.

      I devised a way to do it though, and in a few hours came up with a handy script (yeah yeah, a few hours isn't exactly a one hour hack, but downloading the SVN branch you want should be).


      Essentially the script does this:
      1. INIT a new repo at the desired location.
      2. Check out the most current branch of the old repo.
      3. Check the history of the old repo to check which revisions to sync (the changed ones).
      4. For each changed one, check it out, rsync it to the checked out new repo, and commit it to the new repo with the old log message.
      5. Finish some time later after you have made yourself a cup of tea and watched the most recent Doctor Who.

      #!/bin/bash

      # Check for proper args
      if [ -z "$1" ];
      then
      echo -e "Usage:\n$0 URL_TO_COPY_FROM URL_TO_COPY_TO" && exit 1
      fi;

      SVNFROM=$1
      SVNTO=$2

      echo "Fetching branch from: $SVNFROM"
      echo "Copying branch to: $SVNTO"

      # Set up environment.
      if [ -e tempsvn ];
      then
      rm -rf tempsvn
      fi;

      mkdir tempsvn tempsvn/download tempsvn/upload tempsvn/current
      cd tempsvn

      echo "Checking out current..."
      svn co $SVNFROM current
      HISTORY=`svn log current | grep \| | cut -d\ -f1 | sed 's/r\([0-9]*\).*/\1/' | sort -k1,1n`

      # Init the new repo at the given location.
      svn import upload $SVNTO -m ""
      svn co $SVNTO upload

      num=`echo $HISTORY | wc -w`
      echo "There are $num revisions in this branch."


      for REVNO in $HISTORY; do
      rm -rf download
      echo "-----------------------------------------------------------------------"
      echo "Revision: $REVNO"
      echo "Fetching..."
      ENTRIES=`svn co $SVNFROM@$REVNO download`
      CHANGES=`echo $ENTRIES | wc -l`
      echo "Found $CHANGES change(s)."

      echo "Change Log:"
      cd download
      LOG=`svn log -r $REVNO | grep \- -v`
      echo $LOG
      echo ""
      cd ..

      echo "Exporting..."
      rsync -a --exclude='.svn' download/ upload/

      cd upload

      IFS_BAK=$IFS
      IFS=$'\n'
      for E in $ENTRIES; do
      BEGIN=`echo $E | cut -d\ -f1`
      END=`echo $E | cut -d\ -f5- | cut -d/ -f2-`

      case "$BEGIN" in
      'A') svn add -q $END ;;
      'D') svn del $END ;;
      esac
      done
      IFS=$IFS_BAK

      if [ -e log.log ]; then rm log.log; fi;

      echo $LOG > log.log
      echo "Commiting new..."
      svn commit -F log.log
      cd ..
      done
      # Tear down environment.
      cd ..
      rm -rf tempsvn

      One slight problem though, it removes and re-checks out the branch it is copying from every time because I was getting strange errors about branches being out of date, if anyone could fix that, it would increase the speed greatly.

      Tuesday, May 3, 2011

      Protocols #6, Character Generator Protocol

      In May of 1983, the Character Generator Protocol was introduced in RFC 864. It existed already on computers mainly as a test for terminals (TTYs in that image you can actually see a character test program) to make sure that they could properly display all of the characters in the vastly huge ASCII character set. Now ASCII is a bad joke. The protocol was introduced to do the same thing over networks (an early ping like utility).


      In the modern day Internet, the original protocol needs to be amended slightly: the RFC states that the protocol will continue sending information until the client closes the connection; however I made it auto-close after 1000 outputs because eventually node.js runs out of memory and dies. It would also be nice not to have all of your Internet connection lines taken up by three people that never closed their chargen. Without further ado:
      #!/usr/bin/nodejs

      var net = require('net');
      var dgram = require('dgram');

      var linewidth = 72; //Width of a line of text on the console.
      var str = "";

      //Generate from: ! to ~
      for(var i = 33; i < 127; i++) {
      str += String.fromCharCode(i);
      }

      //Make sure length is at least 512 bytes (max for udp)
      for(var i = str.length; i < 512; i += str.length)
      {
      str += str;
      }


      function getline(lineno) {
      return str.substr(lineno % (127 - 33), linewidth ) + "\n";
      }

      //TCP
      var tcpserver = net.createServer(function (socket) {
      var j = 0;
      while(j < 1000)
      {
      socket.write(getline(j));
      j++;
      }
      socket.end();
      })

      //UDP
      var udpserver = dgram.createSocket("udp4", function (msg, rinfo) {
      var ret = new Buffer(str.substr(0, Math.floor(Math.random()*(513))));
      udpserver.send(ret, 0, ret.length, rinfo.port, rinfo.address);
      });

      //Bind and serve (Port 19 is actual)
      tcpserver.listen(8019, "127.0.0.1");
      udpserver.bind(8019, "127.0.0.1");

      As usual the port numbers have been boosted by 8000, so before actually using, change those and the host computer IP addresses.

      Tuesday, April 19, 2011

      Protocols #5, Quote of the Day

      The quote of the day protocol, defined in RFC 865, specifies a standard that when implemented will return a quote when port 17 is connected to in TCP, or when a datagram is sent to it in UDP.

      This implementation in Node.js, is similar to the daytime protocol I built earlier, it introduces an array of quotes of which one is randomly chosen to
      #!/usr/bin/nodejs
      var net = require('net');
      var dgram = require('dgram');

      var quotes = [
      "Time is an illusion. Lunchtime doubly so.\n - Douglas Adams",
      "The quieter you become the more you can hear.\n - Baba Ram Dass",
      "Wisdom lies in knowing when to remember and when to forget.\n - Ayn Rand",
      "Chance favors the prepared mind.\n - Louis Pasteur",
      "The advertisement is the most truthful part of a newspaper.\n - Thomas Jefferson",
      "To communicate through silence is a link between the thoughts of man.\n - Marcel Marceau",
      "There are periods when...to dare, is the highest wisdom.\n - William Ellery Channing"
      ];

      function getquote() {
      randno = Math.floor ( Math.random() * quotes.length );
      return quotes[randno] + "\n";
      }

      //TCP
      var tcpserver = net.createServer(function (socket) {
      socket.end(getquote());
      })

      //UDP
      var udpserver = dgram.createSocket("udp4", function (msg, rinfo) {
      var ret = new Buffer(getquote());
      udpserver.send(ret, 0, ret.length, rinfo.port, rinfo.address);
      });

      //Bind and serve (Port 17 is actual)
      tcpserver.listen(8017, "127.0.0.1");
      udpserver.bind(8017, "127.0.0.1");

      Protocols #4, Daytime

      Time for another simple protocol: Daytime

      "A useful debugging and measurement tool is a daytime service. A daytime service simply sends a the current date and time as a character string without regard to the input." - RFC 867

      This time we will use a more complex Javascript function, the Date().toISOString(), which will return the date in an ISO compliant manner.

      As usual the actual port for this protocol is 13, but I don't want to run it as root, yet.
      //RFC 867 Daytime in Node.js
      var net = require('net');
      var dgram = require('dgram');

      function gettime() {
      var d = new Date();
      return d.toISOString() + "\n";
      }

      //TCP
      var tcpserver = net.createServer(function (socket) {
      socket.end(gettime());
      })

      //UDP
      var udpserver = dgram.createSocket("udp4", function (msg, rinfo) {
      var ret = new Buffer(gettime());
      udpserver.send(ret, 0, ret.length, rinfo.port, rinfo.address);
      });

      //Bind and serve
      tcpserver.listen(8013, "127.0.0.1");
      udpserver.bind(8013, "127.0.0.1");