Kip QuickReplace

It’s amazing how often, as a programmer, I find myself pasting something into Notepad, then pressing Down, Home, Ctrl+V, over and over and over. (Or a variant, like Down/End/Ctrl+V, or End/Comma/Delete, or F3/Ctrl+V/Enter, etc.) It gets very tedious, and sometimes requires me to write an adhoc Perl script to do it. Yesterday I had the idea to finally just take a few hours to write a simple tool that I should have written years ago.

I give you: QuickReplace

It’s really simple. Just paste text into the first big text area, and then it will be filtered and displayed in the lower text area. There are three types of filters: text that is prepended or appended to each line; a simple search/replace (with \n and \t allowed), and a full-on regex substitution. And everything is updated as you type it, so you can see the effects of the filters as you enter them. (This really helps when you haven’t written a regex in a month or so.)

Everything is done in Javascript so the page is completely self-contained—you can view source and save a local copy if you wish. (It does require an internet connection, as it uses Google-hosted jQuery.) It’s also kind of a work in progress that might at any time be edited on the fly. Consider yourself warned.

No Comments | Add Comment
Kip Photostorm

I have uploaded eighty-nine new photos from the first three weeks of Grayson’s life, in addition to the twenty-one I already told you about. All 110 photos can be found in the Grayson is born album.

No Comments
Kip How to programmatically update your Twitter status using OAuth in PHP

Earlier this week I was informed that Twitter will soon be ending its support for “BasicAuth” in the Twitter API, in favor of OAuth authentication. This affects me because I use the API to automatically post a “just blogged!” link to Twitter after every new blog post. Using BasicAuth, this was super simple:

1
2
3
4
5
6
7
8
9
10
11
function postStatus($status, $username, $password)
{
  $ch = curl_init();
  curl_setopt($ch, CURLOPT_URL, 'http://www.twitter.com/statuses/update.xml');
  curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, 2);
  curl_setopt($ch, CURLOPT_POST, 1);
  curl_setopt($ch, CURLOPT_POSTFIELDS, 'status=' . urlencode($status));
  curl_setopt($ch, CURLOPT_USERPWD, $username . ':' . $password);
  
  return curl_exec($ch);
}

OAuth is a little more complicated, but I got it to work after about four or five hours of banging away it with the help of this article.1 Since I couldn’t find anywhere that this was described in detail, I decided I would document the whole process here on my blog. I don’t claim that this code is great, but it gets the job done. If you couldn’t care less about the workings of OAuth, and just want a give-me-teh-codez solution, then this is for you.

The first thing you have to do is register a new app. This sounds scary but it’s actually very easy. When filling out the form, note the following fields:

  • Application Name: this is what will show up under your tweets. In my case, I chose “vacantnebula.com” since all tweets from my app are announcements of new posts on this site.

  • Application Website: this is the URL that application name will link to.

  • Application Type: I’m not sure if it matters, but I chose “client”.

  • Default Access Type: you must select “read & write” to be able to update status (i.e. “write”).

After registering your application, you can view application details. Here you will see your consumer key and your consumer secret. You will need these keys later.

For a single-user application (which is what I’m describing), you will need to click on my access token. This will give you the access token (oauth_token) and access token secret (oauth_token_secret). Again, you will need these later.

And without further ado, here is the code:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
<?php

class twitter
{
  //FILL IN THESE VALUES!!
  private $consumerKey      = '???';
  private $consumerSecret   = '???';
  private $oauthToken       = '???';
  private $oauthTokenSecret = '???';
  
  /**
   * Posts status to a twitter account. Returns true if successful, result
   * of curl_getinfo() if failure. 
   */ 
  function postStatus($status)
  {
    return $this->apiCall('https://api.twitter.com/1/statuses/update.xml'
                         , array('status'=>$status));
  }
  
  //separate function to leave the door open to other API calls...
  private function apiCall($url, $params)
  {
    $method = 'POST';
    
    //postString covers what will *actually* be posted
    $postString = $this->joinParams($params);
    
    //now adding to $params other OAuth properties...
    $params['oauth_nonce']            = sha1(time() . mt_rand());
    $params['oauth_timestamp']        = time();
    $params['oauth_signature_method'] = 'HMAC-SHA1';
    $params['oauth_version']          = '1.0';
    $params['oauth_consumer_key']     = $this->consumerKey;
    $params['oauth_token']            = $this->oauthToken;
    
    ksort($params); //IMPORTANT!
    $paramString = $this->joinParams($params);
    
    $signatureBaseString = $method
                         . '&' . rawurlencode($url)
                         . '&' . rawurlencode($paramString);
    $signatureKey = $this->consumerSecret . '&' . $this->oauthTokenSecret;
    $params['oauth_signature'] =
            base64_encode(hash_hmac('sha1', $signatureBaseString, $signatureKey, true));
    
    $authHeader = 'Authorization: OAuth realm=""';
    foreach($params as $key => $val)
      $authHeader .= ", $key=\"" . rawurlencode($val) . "\"";
    
    
    $ch = curl_init();
    curl_setopt($ch, CURLOPT_URL, $url);
    curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, 2);
    curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
    curl_setopt($ch, CURLOPT_POST, 1);
    curl_setopt($ch, CURLOPT_POSTFIELDS, $postString);
    curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false); //required for HTTPS URL
    curl_setopt($ch, CURLOPT_HTTPHEADER, array($authHeader));
    
    $content = curl_exec($ch);
    $resultInfo = curl_getinfo($ch);
    curl_close($ch);
    
    if ($resultInfo['http_code'] == 200)
      return true;
    
    $resultInfo['content'] = $content;
    return $resultInfo;
  }
  
  //Join key/value pairs together in url string format, encoding values.
  private function joinParams($params)
  {
    $paramString = '';
    foreach($params as $key => $val)
    {
      if($paramString !== '')
        $paramString .= '&';
      $paramString .= $key . '=' . rawurlencode($val);
    }
    return $paramString;
  }
}

And I assume you know this, but to use the API it’d look like this:

1
2
$twitter = new twitter();
$result = $twitter->postStatus('hello world!');
1 I could have saved myself over an hour by realizing that I had to call rawurlencode rather than urlencode; the former encodes spaces as %20, whereas the latter encodes them as +.
Kip Mexican food

I have devised a very simple scale for evaluating Mexican restaurants. There are only two points of evaluation:

1. Are the fajitas sizzling when they are brought to your table? If so, the restaurant gets 25 points.

2. Are the tortillas there as soon as the fajitas are brought to the table? If so, the restaurant gets 75 points. (Score no points if you have to sit there and watch your fajitas sizzle out (assuming they were sizzling in the first place) waiting on the waiter to bring out the tortillas.)

For those of you who aren’t mathematically inclined, the only scores possible are 0, 25, 75, and 100.  0 and 25 are equivalent to an F-.  75 is a C. 100 is an A+.

No Comments
Kip Just for my cousin Kaylor

I’ve been asked to post more pictures and video of Grayson, as it has been over a month since I last shared anything. The problem is that he’s still at the age where he doesn’t particularly do anything... besides eat, sleep, poop, and cry. But we tried. I’ve also posted eleven new photos of Grayson and Emma from the past month. And I also have two videos. The first is a rather lengthy video of Emma playing with Grayson, and the second is actually a video of me coming home from work to be greeted by Emma two days before Grayson was born.

No Comments
Kip Accented memories

Over the weekend I went to my ten-year high school reunion, and I noticed something interesting when catching up with people. When I haven’t talked to someone in a long time, I forget that they speak with an accent. I guess it’s because I don’t remember their voice, and my brain fills it in with “accentless” Midwesterny broadcast English. Then they talk and I’m thinking “oh wow, you have a southern accent that I totally don’t remember1.” Which shouldn’t surprise me, most of these people spent most of their childhood in North Carolina.

1 Not that there’s anything wrong with that, I have one too
RSS feeds: Kip's - Stephanie's - Both