How safe is an MD5 hash of a plain password?

First of all, I hope that you've moved beyond MD5 hashes and hashing passwords by themselves, adding salts, etc., but I do recall systems in which an MD5 hash of a password by itself was "good enough".

You can look up some md5 hashes on this md5 cracker page. I found many two word combinations that were crackable.

You can play with generating md5 hashes of questionable passwords (such as your name and p@ssw0rd) with this md5 Hash Generator

Bundler gave the error "Could not find {some gem} in any of the sources", processing Gemfile in wrong directory

Problem

I was persistently getting the error:

Bundler gave the error "Could not find json-1.8.1 in any of the sources" while processing "/Users/tpowell/projects/some_other_project/Gemfile". Perhaps you forgot to run "bundle install"?

While trying to fix a bug in paperclip_database that was similar to Paperclip Gerenator - No Method Error in paperclip

I eventually found an issue referencing this problem in the rbenv github repo.:

It is recommended to not use the rbenv-bundler plugin, as it has been the source of many problems

Solution

I ended up uninstalling the rbenv-bundler plugin as a result.

But hey, kudos to rbenv-bundler author for taking the complaint in stride.

Enums in ActiveRecord 4.1 and options_for_select

Update: This StackOverflow answer provides a better way to use a drop-down with enums. I could've sworn I tried that, but maybe not.

I discovered something interesting about the way ActiveRecord 4.1 enums work. If you're trying to use them with options_for_select, you may need to do some little acrobatics with your enums.

Assume your model provides:

class Car < ActiveRecord::Base
  # body_style is an integer in the database
  enum body_style: [:coupe, :convertible, :van, :suv, :sedan]
end

And your update route for cars_controller does this:

class CarsController < ApplicationController
  before_action :set_car, only: [:show, :edit, :update, :destroy]
 
  # PATCH/PUT /cars/1
  # PATCH/PUT /cars/1.json
  def update
    respond_to do |format|
      if @car.update(car_params)
        format.html { redirect_to @car, notice: 'Car was successfully updated.' }
        format.json { head :no_content }
      else
        format.html { render action: 'edit' }
        format.json { render json: @car.errors, status: :unprocessable_entity }
      end
    end
  end
  private
    # Use callbacks to share common setup or constraints between actions.
    def set_car
      @car = Car.find(params[:id])
    end
 
    # Never trust parameters from the scary internet, only allow the white list through.
    def car_params
      params.require(:car).permit(:body_style)
    end
end

Then, using the enumeration in a form_for block in your view requires a deviation from what Car.body_styles will give you.

The value submitted by this form snippet won't validate because update is expecting the "string" key, and not the underlying numerical value of the table.

<%= form_for(@car) do |f| %>
  <%= f.label :body_style %>
  <%= f.select :body_style, options_for_select(Car.body_styles) %>

Instead, a little bit of transformation needs to be done so that the description/value pair for the elements are both the text value of the enum.

<%= form_for(@car) do |f| %>
  <%= f.label :body_style %>
  <%= f.select :body_style, options_for_select(Car.body_styles.map {|k,v| [k,v]}) %>

Or, with the selected value included:

<%= form_for(@car) do |f| %>
  <%= f.label :body_style %>
  <%= f.select :body_style, options_for_select(Car.body_styles.map {|k,v| [k,v]}, @car.body_style) %>

Git wrapper for vim: fugitive.vim

Today's browsing through "plugins that I haven't made good enough use of" brings me to vim-fugitive:

:Gstatus pulls git status output into a vim split window. Pressing - on the line that a file is listed on either adds or removes a file from staging, and :Gcommit commits it.

:Gdiff opens a vertical split next to a file and uses vim's diff facility to compare working copy to staged version.

:Gblame opens a vertical split next to a file with an interactive git blame output that tracks the source file as you scroll. Pressing on a line opens the commit that changed the code (or o to open in a split.)

:Glog opens the log in the quickfix window:

  • :copen to open the quickfix window to scroll through the versions
  • :ccl close the quickfix window
  • :cn go to the next error in the quickfix window (append a number to jump # steps)
  • :cp go to the previous error in the quickfix window (append a number to jump # steps)

:Gmove performs a git mv and modifies the buffer location as well.
:Gremove performs a git rm and removes the buffer as well.

Other commands of interest that I haven't considered for my current workflow:
:Ggrep
:Gbrowse
:Git performs any other git command not already covered.
:Gedit, :Gsplit, :Gvsplit, :Gtabedit appear to open a repository object directly... not quite ready to pick at individual objects on that level.

Thanks for Making it Unnecessarily Hard to Get a Harry Potter Book on My Daughter's Kindle

Exclusive Dealers

Apparently, JK Rowling made a deal with Sony to exclusively sell Harry Potter e-books on the Sony e-book through the Pottermore site, through January 2012.

What I found out today was that I still had to go to that site in order to buy any e-book version of the Harry Potter books. That posed a major inconvenience in itself because my daughter got $35 in Amazon gift cards to buy Kindle books for her new Kindle that her grandfather bought her. She said she wanted to buy the Harry Potter books with those. The (first) problem with the Pottermore Shop site? Those gift cards would be useless.

User Unfriendliness

I went ahead and went through the motions to set up a Pottermore Shop account to buy the boxed set and then decided, just before checkout but after creating an account, to bail out of the process and go and buy the individual books at Amazon instead. If you go to the page for Harry Potter on the Kindle Store, you'll find that all links go back to the Pottermore store.

Screen Shot 2013-12-26 at 2.03.49 PMSo, I resigned myself to going to the Pottermore.com site (manually typing it in.) I found that the site no longer recognized me as signed in. So, I used the username and password that I had previously created and stored (of course, the initial sign-up wouldn't allow copy-and-paste) and found that my login wasn't accepted. I tried copying and pasting and manually typing to no avail, until I was locked out of that "account". In between attempts, I even tried a password reset. I was able to "reset" my password, but not able to use it to login.

I decided to sign my daughter up for an account and try again. It was then that I discovered that Pottermore.com apparently doesn't use emails as usernames, but instead, gives you an option to pick one of five randomly generated [two-word + number] usernames. So, the login process for the shop and the main site are different.

Sony's Half-Baked Download Control

Once I had purchased the boxed set, I still had to download the individual books separately. For that I had to link an account. Fortunately, Kindle was one of the options available, and I could authorize downloads to that account. Weird part of the download process is that you're given 8 downloads per book, so you have some limitation as to how many places you can send it. Weirder still is that "direct download" is one of those options (I'm assuming that means a DRM-less copy). Why bother with the limitation? If someone is going to steal, they just have to do the unrestricted download once, but if someone legitimately chooses crappy e-book services that shut down, then they might (amazingly) run out of downloads.

Kudos for Sticking it to Amazon or Whomever, JK Rowling, But...

I can't really fault JK Rowling for finding a way to break free of Amazon's e-book cost structure. There are many smaller authors wary of getting sucked into Amazon's vise grip. However, I can imagine that there are many young fans out there that got a Kindle for Christmas or their birthday along with an Amazon gift card, and they just wanted to have Harry Potter on their Kindle. Their gift card is no good outside of Amazon.

I go shopping on The Pragmatic Bookshelf for many of my technical books, so I can appreciate the value that can come from an independent publisher of books, but those books have no download restrictions on them. The only copyright enforcement on the e-book version of Pragmatic Bookshelf is the honor system (and the intended recipient's name at the bottom.) I jump through hoops to download those books, but the audience of a Pragmatic is highly technical, so a few technical hurdles isn't unreasonable.

Maybe the only kids who ever get e-book readers are kids whose dads are willing to contribute cash when the gift cards are of no use and willing to jump through hurdles to get the books downloaded and set up. I hope so, because then the minor inconveniences of 1000s of fans are worth the sweetened deal you got, and your fans will never know the difference.

zsh grep and mvim: search for a string in a directory in file type, and open that point

open_all {pattern} {extension}

#!/bin/zsh
grep -n $1 **/*$2 | sed 's/^([a-zA-Z_/.]*):([0-9]*).*$/2 1/' | while read line file
do
  mvim --remote-tab-silent +$line $file
done

Usage:

# find all occurrences of "def" as a whole word and open the files in separate tabs:
open_all '<def>' .rb

Creating a Readable List of Playlist songs on Mac

1. Select Export... by two-finger/right-clicking on the playlist.

2. Export as plain text.

3. I had to do a little command-line scripting to change carriage returns to new lines and select only the first two tab-limited columns:

cd ~/Desktop
cat Power of Two.txt | tr 'r' 'n' | awk -F 't' '{print $1 "::" $2}' > powerOfTwo.txt

Shell / awk script to generate getter / setter stubs for .java file

I realize many IDEs do this, but I felt like writing a few lines of script to spit this out instead. This will grab every line marked "private", whether method or member variable and generates a default getter/setter.

Note: it doesn't insert the code for you or even capture to a file. Maybe next I'll do a Javascript version.

	private Date businessDate;
	private String eventTypeCode;
	private String sourceCode;
 
// becomes the following
 
	public Date getBusinessDate(){ 
		return businessDate;
	}
	public void setBusinessDate(Date businessDate){ 
		this.businessDate = businessDate;
	}
	public String getEventTypeCode(){ 
		return eventTypeCode;
	}
	public void setEventTypeCode(String eventTypeCode){ 
		this.eventTypeCode = eventTypeCode;
	}
	public String getSourceCode(){ 
		return sourceCode;
	}
	public void setSourceCode(String sourceCode){ 
		this.sourceCode = sourceCode;
	}

Script source:

#!/bin/env sh
 
# takes a single filename of a .java file and generates a default getter/setter stub for each private variable
cat $1 | grep private | awk '{
	varName=substr($3, 1, length($3) - 1);
	print "	public " $2 " get" toupper(substr(varName,1,1)) substr(varName, 2) "(){ ";
	print "		return " varName ";";
	print "	}"
 
	print "	public void set" toupper(substr(varName,1,1)) substr(varName, 2) "(" $2 " " varName "){ ";
	print "		this." varName " = " varName ";";
	print "	}"
}'

Count Outlook Inbox Unread / Total From Ruby

Well, Track your unread items/total items count in Outlook on startup, except for the pesky Outlook Macro disabled security problem. Besides, I never restarted Outlook often enough for it to track much of anything.

Instead, I decided to create a Ruby script to track the count. I've left reference URLs and test notes in place in this script. Yes, I had to look up how to write a file in Ruby... It's essentially my 4th programming language after C, Java, Perl, PHP... okay... let's say it's pretty deep on the list.

require 'win32ole'
outlook = WIN32OLE.new('Outlook.Application')
# http://rubyonwindows.blogspot.com/2007/07/automating-outlook-with-ruby-tasks.html
mapi = outlook.GetNameSpace('MAPI')
# http://msdn.microsoft.com/en-us/library/aa220100%28office.11%29.aspx
# olFolderCalendar
# olFolderContacts
# olFolderDeletedItems
# olFolderDrafts
# olFolderInbox
# olFolderJournal
# olFolderJunk
# olFolderNotes
# olFolderOutbox
# olFolderSentMail
# olFolderTasks
# olPublicFoldersAllPublicFolders
# olFolderConflicts
# olFolderLocalFailures
# olFolderServerFailures
# olFolderSyncIssues
 
# http://msdn.microsoft.com/en-us/library/aa210918%28v=office.11%29.aspx
# OLEObject.ole_methods
 
class OutlookConst
end
# http://rubyonwindows.blogspot.com/search/label/outlook
WIN32OLE.const_load(outlook, OutlookConst)
 
# p "OlFolderInbox = #{OutlookConst::OlFolderInbox}"
 
inbox = mapi.GetDefaultFolder(OutlookConst::OlFolderInbox)
 
new_messages = 0
total_messages = 0
 
inbox.Items.each {
	| msg |
	begin 
		if msg['UnRead']
			new_messages += 1
		end
		total_messages += 1
	rescue
		puts " Unable to open"
	end
}
puts "You have #{new_messages} new message(s)"
t = Time.now
 
line="#{t.strftime("%m/%d/%Y %I:%M:%S %p")},#{new_messages},#{total_messages}"
 
localname="#{ENV['USERPROFILE']}\My Documents\outlookunread.csv"
 
# http://snippets.dzone.com/posts/show/5051
File.open(localname, 'a') {|f| f.puts(line) }