redgoose.ca

Plex Songza plugin

Plex Media Server is awesome, but I noticed a lack of good music channels for us folk in Canada. Songza’s been blowing up in Canada, so decided to scratch my itch the other day to build my own Plex Media Server plug-in. Plex has a decent plugin API and utilizes Python which made it pretty straightforward.

It’s not perfect (I’ll explain later), but here’s a link to the repository on Github.

https://github.com/redgoose/Songza.bundle

It works, but due to a limitation of how Plex plug-ins operate and Songza’s track expiration, while you’re listening to a playlist, it’ll just stop playing. Pretty annoying if you’re looking to listen to music continuously.

Visualising Workrave data

If you've never heard of Workrave, it's an application that among other things helps prevent Repetitive Strain Injury (RSI) by prompting you to take mini breaks. When I first started using it I kept the breaks on, but slowly curtailed those (even though I know I really shouldn't!). Nothing worse than being in flow and getting interrupted to take a break!

That said, I did end up leaving Workrave running in the background for two reasons.

First, it logs your activity so you can determine when you started your day and based on that decide when to end it--very important! In lots of cases I've lost track of time at work and then turned to Workrave as a reminder.

Also, since Workrave is logging your activity (key clicks, mouse clicks, etc.) you can use it to view your stats for the day which is kinda neat.

Here's what the last 3 years of "work" at Kanetix looks like.


I used the following PHP code to parse the data I wanted out of the historystats log file generated by Workrave into a JSON object and used Flot to make a pretty chart.

public function parse_historystats(){
		$file = "historystats";
		$lines = file($file);

		$data = array(
			array(
				"label"	=> "mouse clicks",
				"data"	=> array()
			),
			array(
				"label"	=> "keystrokes",
				"data"	=> array()
			)
		);
		
		$time = "";
		
		foreach ($lines as $line_num => $line) {
			if (preg_match("/^D\s(\d+)\s(\d+)\s(\d+)/",$line,$m)) {
				// is a date line, parse date

				$day = $m[1];
				$month = $m[2] + 1;
				$year = $m[3] + 1900;
				
				$time = strtotime("$year-$month-$day UTC");
			} else if (preg_match("/^m.*?(\d+)\s(\d+)\s*$/",$line,$m)) {
				// is a stats line, parse stats
				
				$dow = date("w",$time);
				if ($dow == 0 || $dow == 6 || $m[1] == 0) {
					continue;
				}

				// mouse clicks
				array_push($data[0]["data"],array($time*1000,$m[1]));

				// key clicks
				array_push($data[1]["data"],array($time*1000,$m[2]));
			}
		}

		return json_encode($data);
	}

2012 Globe Roll 1 Review

For two years now, I’ve been riding my bike between home and work which meant Shannon had to rely on the TTC (we both work at Kanetix). That all changed when she purchased a new bike, a 2012 Globe Roll 1. Now I’m happy to say I am the owner of two bikes! (just don’t tell her that)

From a style standpoint, this bike stands out. I’ve gotten more stares, compliments, and questions about this bike than my Fuji Track Classic which is cool, but makes me jealous. Girls seem to dig the colour scheme, but somehow it still manages to appeal to me. Specialized/Globed showed some restraint by not going to town with decals, which adds to the bike’s minimalist look.

The moment I first tried it, I liked how it felt and compared to my Fuji, it has a more relaxed, upright riding position, almost a bit cruiser-esque which I didn’t expect. The bike feels light, fast, and responsive.

On the other hand, the stock 42/17 gear ratio feels too low for me as I’m used to riding at a higher 46/15 ratio, but this would vary between riders. I’ve only tried riding this bike in free-wheel mode, perhaps it’ d be okay riding fixed, but I’d be afraid of spinning out.

Sadly the bike also weighs in on the heavy side, you can definitely feel a difference between the Fuji and the Globe, although it’s not deal breaker. I’d also recommend looking for a new seat as the stock seat isn’t all that great. Speaking of the seat, since it’s white you may end up with some colour transfer from your clothes. If that happens, simply use a magic eraser.

Pros
Cool stock styling
Smooth, responsive ride
Comfortable riding geometry

Cons
Uncomfortable seat
Heavier than it looks
Low crank position means pedal strikes

Perl and pre-filled PDFs

A client at work required some PDF functionality to reduce the wasted time and effort required to take data from a webapp and handwrite it on a printed PDF form. Since we already had the necessary data in place, I figured it would be pretty easy to do with Perl since I had done it in the past using the Adobe FDF Toolkit and C#.

Thankfully, there are several Perl PDF libraries on CPAN that can help do the job. I checked out four of them with varying results.

PDF::Reuse
Looked like a popular option, but I failed miserably with this module. The interface made me cry and in the end I wasn't able to "reuse" a single existing PDF with it and just got cryptic errors instead.

CAM::PDF
This module worked well at filling text fields, but not much else. Theres a hacky undocumented interface for filling checkboxes and absolutely no support for radio buttons. I also ran into some annoying text positioning issues where the rendered text in each field would display a few pixels lower and hide surrounding elements of the document. Manually modifying the text field (ie. entering a space) in the outputted PDF would reposition the text at the right height and reveal obscured elements. Didn't find anyone having similar issues so I'll give this module the benefit of the doubt and chalk this up to my setup or the PDFs I'm using (hopefully).
use CAM::PDF;
my $file = "/test/form.pdf";
my $pdf = CAM::PDF->new($file);

# get a list of all fields 
my @f = $pdf->getFormFieldList();

my %form = (
    name 	=> "John Doe",
    street 	=> "20 Camden Street",
    gender	=> "Male", # oops radios dont work
    agree	=> "Yes", # oops checkboxes need a hack

);
$pdf->fillFormFields(%form);

# hacky way to fill checkbox
$pdf->getFormField("agree")->{value}->{value}->{AS}->{value} = 'Yes';

print $pdf->toPDF();

PDF::FDF::Simple
This module is a very simple alternative to using the full blown Adobe FDF Toolkit. A FDF (Forms Data Format) file is just a standard file format containing your fields and corresponding text values along with a link associating it with a PDF form. This module will build FDF files for you, but since they are so simplistic, you can be a ninja and build them yourself as follows.
my $file = "http://www.mysite.com/form.pdf";
print qq|
    \%FDF-1.2

    1 0 obj
    <<
    /FDF << /Fields 2 0 R/F ($file)>>
    >>
    endobj
    2 0 obj
    [<< /T (name) /V (John Doe) >>
    << /T (street) /V (20 Camden Street) >>
    << /T (city) /V (Toronto) >>
    << /T (gender) /V (Male) >>
    << /T (agree) /V (Yes) >>
    ]
    endobj
    trailer
    <<
    /Root 1 0 R

    >>
    \%\%EOF
|;
This method supports text fields, checkboxes and radio buttons and results in a perfect looking PDF (unlike CAM::PDF).

Stopping here will require a confusing workflow for your users because they will need to first download a FDF file that will prompt them to download a PDF file at which point they are presented with a merged PDF. Ideally, you'll want to do this merging server side with Pdftk so your users just have to download one final, merged PDF.

You also don't want to do client side merging since you'll have to deal with compatibility issues as FDF files aren't supported by all PDF readers (ie. Preview on OSX).

PDF::API2
PDF::API2 is a feature packed module that let's you do some awesome stuff. Unfortunately, filling form fields isn't one of them. However, what you can do is render text anywhere within an existing, "dumb" PDF. This saves you the trouble of having to spend time setting up a proper PDF form. An obvious drawback of course is that text isn't going to be modifiable by the user.
use PDF::API2;
my $file = "/test/form.pdf";
my $pdf = PDF::API2->open($file);

my $pdf_page = $pdf->openpage(1);
my $pdf_text = $pdf_page->text();

# set font
my $pdf_font = $pdf->corefont('Helvetica');
$pdf_text->font($pdf_font, 12);
	
# draw some text
$pdf_text->translate(200,400);
my $text = "John Doe";
$pdf_text->text($text);

# look ma! i done a checkbox
$pdf_text->translate(100,200);
my $text = "X";
$pdf_text->text($text);

print $pdf->stringify();
$pdf->end();
Rendering requires you get acquainted with PDF style coordinates where 0,0 is the bottom left corner rather than the top left. An easy way to find coordinates for placing text can be done by opening a PDF in Photoshop with no cropping, and a 72dpi setting. Then show the Rulers, and drag them to the bottom left of the PDF. Show the Info panel and you'll get x,y coordinates.

In my case all I needed to do was to pre-fill some text, check some checkboxes and pre-select radio buttons. The PDF I was given wasn't initially setup as a PDF form so depending on what module/method I chose, I would have needed to spend some time setting up interactive form fields within the PDF using Adobe Acrobat. If you don't have access to fully fledged PDF creation software, PDF::API2 text rendering would be your only option.

In the end I went with PDF::API2 as the client just wanted something simple and didn't require the text to be modifiable after the fact. Going forward I'd either use PDF::API2 or PDF::FDF::Simple depending on the requirements.

AES256 encryption with Perl and Oracle

Recently I had to implement some AES256 encryption for a project I was working on and needed to do it with Perl, but also have it play nice with Oracle just in case the encryption/decryption needed to be done on the database side with SQL.

Sounds simple, but I struggled for a day or two because I wrongly chose Crypt::OpenSSL::AES instead of Crypt::Rijndael. Google seemed to fail me on that one as searching for "aes encryption perl" brings up the former package. I also tried #perl on irc.freenode.net, but that was a big fail as well. Seems you can't expect much help from the monks unless you need simple regex help.

Anywho, here's how you can accomplish this using Perl and Oracle SQL. First we'll use Perl to encrypt a string and then Base64 encode it so it's easy to manipulate and store (otherwise you'll have to deal with binary data).

Perl code
use Crypt::CBC;
use MIME::Base64;

my $cipher = Crypt::CBC->new({
	key			=> "NSTl4XsUKcOWzHVgci9vPF5jZ8Szscz7", # 256 bits
	cipher		=> "Crypt::Rijndael",
	iv			=> "a41ag2wqDSQjzexC", # 128 bits
	literal_key	=> 1,
	header		=> "none",
	keysize		=> 32 # 256/8
});

my $encrypted = $cipher->encrypt("string to encrypt");

# base64 encode so we can store in db
$encrypted = encode_base64($encrypted);

# remove trailing newline inserted by encode_base64
chomp($encrypted);

print "encrypted result: $encrypted \n";

Note that I used a static initialization vector (IV) in my example. Depending on your implementation you may want to let Crypt::Rijndael generate an IV for you. Just remove the iv and header parameters in that case.

Now you can use Oracle SQL to do the decryption. Just replace S06LglP0qfqHVcYXsLeDd1dsCQUrfCpZpJ4tYckk6Ic= with the output of the Perl encrypted string and you should be good to go.

Oracle SQL code
SET serveroutput on;

DECLARE
    encryption_type PLS_INTEGER :=
        DBMS_CRYPTO.ENCRYPT_AES256
        + DBMS_CRYPTO.CHAIN_CBC
        + DBMS_CRYPTO.PAD_PKCS5;
    key_bytes_raw       RAW (32);           -- 256 bit encryption key
    iv                  RAW(32);            -- 128 bit initialization vector
    encrypted_raw       RAW (2000);         -- stores encrypted binary text
    decrypted_raw       RAW (2000);         -- stores decrypted binary text
    decrypted_string    VARCHAR2 (200);

BEGIN
    key_bytes_raw := UTL_I18N.STRING_TO_RAW('NSTl4XsUKcOWzHVgci9vPF5jZ8Szscz7', 'AL32UTF8');
    iv := UTL_I18N.STRING_TO_RAW('a41ag2wqDSQjzexC','AL32UTF8');

    encrypted_raw := UTL_I18N.STRING_TO_RAW('S06LglP0qfqHVcYXsLeDd1dsCQUrfCpZpJ4tYckk6Ic=','AL32UTF8'); -- base64 encoded and encrypted output from perl code above
    encrypted_raw := utl_encode.base64_decode(encrypted_raw);

    DBMS_OUTPUT.PUT_LINE ('Encrypted binary string: ' || encrypted_raw);

    decrypted_raw := DBMS_CRYPTO.DECRYPT
    (
        src => encrypted_raw,
        typ => encryption_type,
        key => key_bytes_raw,
        iv  => iv
    );

    decrypted_string := UTL_I18N.RAW_TO_CHAR(decrypted_raw, 'AL32UTF8');

    DBMS_OUTPUT.PUT_LINE ('Decrypted string: ' || decrypted_string);
END;

So far so good, we can decrypt a value, but really it's not that useful if we wanted to decrypt a whole bunch of rows in a table. We can take care of that by creating a Oracle function that takes an encrypted string and returns the decrypted value we need.

CREATE OR REPLACE
  FUNCTION aes256_decrypt(
      str    IN VARCHAR2,
      key IN VARCHAR2,
      iv  IN VARCHAR2)
    RETURN VARCHAR2
  IS
  BEGIN
    DECLARE
      encryption_type PLS_INTEGER := DBMS_CRYPTO.ENCRYPT_AES256 + DBMS_CRYPTO.CHAIN_CBC + DBMS_CRYPTO.PAD_PKCS5;
      key_bytes_raw RAW (32);
      iv_raw RAW(32);
      encrypted_raw RAW (2000);
      decrypted_raw RAW (2000);
      decrypted_string VARCHAR2 (200);
    BEGIN
      key_bytes_raw := UTL_I18N.STRING_TO_RAW(key, 'AL32UTF8');
      iv_raw            := UTL_I18N.STRING_TO_RAW(iv,'AL32UTF8');
      encrypted_raw := UTL_I18N.STRING_TO_RAW(str,'AL32UTF8');
      encrypted_raw := utl_encode.base64_decode(encrypted_raw);

      decrypted_raw    := DBMS_CRYPTO.DECRYPT ( src => encrypted_raw, typ => encryption_type, KEY => key_bytes_raw, iv => iv_raw );
      decrypted_string := UTL_I18N.RAW_TO_CHAR(decrypted_raw, 'AL32UTF8');
      RETURN decrypted_string;
    EXCEPTION
    WHEN OTHERS THEN
      RETURN str;
    END;
  END aes256_decrypt;

You'll notice I also included 2 additional parameters, key and iv since you might not want to leave sensitive information like that in your database. Now we can do fun stuff like decrypt an entire column in a table.

-- select all rows from users table and decrypt the email column
select aes256_decrypt(email,'NSTl4XsUKcOWzHVgci9vPF5jZ8Szscz7','a41ag2wqDSQjzexC') from users;

« Older

Hello

My name is Tariq. I am a twenty something website developer based in Toronto, Canada, working at kanetix doing what I love to do. Yeppers, I like turtles and get on (the TTC) daily.

Popular Posts

Subscribe

RSS Feed