Sunday, July 13, 2014

Guava's I/O Sources and Sinks on Android

I love Guava's I/O wrappers - ByteSource, ByteSink, CharSource, and CharSink. They encapsulate I/O stream (or reader/writer) access in a way that makes it easy for me to open & close the stream in the same location; when I pass a stream directly, the points of opening it and reliably closing it may be far apart. They also have helper methods to sweeten some common tasks, like reading an entire char source.

Android provides an existing mechanism for accessing private files while controlling their access modes: Context.openFileOutput and Context.openFileInput. As a Source/Sink primer, here's a cool way to adapt between the two:

The usage would look like this:
AndroidPrivateFileGuavaAdapter adapter =
  new AndroidPrivateFileGuavaAdapter("filename", Context.MODE_PRIVATE, context);

 // Read all text
String contents = adapter.asCharSource().read();

 // Write some bytes
byte[] bytes = ...; // obtains bytes from somewhere
adapter.asByteSink().write(bytes);

Monday, November 11, 2013

Instantly migrate to a secure password hashing scheme

So your site uses terrible password hashing scheme H1 (perhaps MD5), and you want to migrate to secure password hashing scheme H2 (preferably scrypt, but possibly bcrypt or PBKDF2).

The standard migration approach is to upgrade users as they log in and enter their password. There are insecurities[1] and workarounds[2] doing this, but there's an alternative that instantly secures everybody using your service with no distruption:

Change your password hash to H2(H1(password)).

  • Can be done immediately for everyone, because you know H1(password).
  • Critical parameters such as salt, CPU-hardness (stretching), and possibly memory-hardness (scrypt FTW) are provided by H2.
  • Weaknesses in H1, such as collisions, don't affect the limited use case of password hashing.

I first heard of this idea from Avner Rosenan, and there's an interesting discussion about it on crypto.stackexchange.com.

Footnotes:

[1] e.g. old password hashes kept around
[2] e.g. delete old hashes and require a password reset

Monday, October 21, 2013

Android: backup and restore an app's data during development

During development, having an app with a realistic configuration and data set is really useful. Here's a trick that can help.

Connect a device with the app configured with lots of good data, turn USB debugging on, and then:
adb backup com.example.mypackage

Later, on another device (or the same device after a clean install):
adb restore backup.ab

W00t.

Monday, October 7, 2013

Versioning Android apps with git tags, using the new Gradle-based build system

At Onavo we version our Android and iOS apps with git tags (inspired by Fraser Hess). No more mucking about with manifests and plists in short-lived branches.
  • Our release git tags look like abc1.2.3-foo_15_bar, which translates to a version name of 1.2.3-foo and a version code of 15.
    • The 'abc' prefix differentiates between different apps on the same repo, and is ignored.
    • The 'bar' suffix differentiates between identical version names and version codes, and is also ignored. We sometimes need this when a a bad tag was made and pushed and we have to retag with the proper revision, since replacing a pushed tag in git isn't wise.
  • Our apk filenames look like appname-flavor-release-1.2.3-rc2-68fb97b.apk
Android's Gradle-based build system makes this super sweet. Here's how we do it:

To see something different, +Jake Wharton describes an awesome approach to versioning & git hacks with Gradle.
Soon I'll hopefully write about how we use Gradle with different flavors, and some some apk signing hacks.

EDIT: I forgot to explain the mysterious tagToBuildFrom - it's for the cases when we release a version of 2 different apps from the same git revision. There are 2 git tags, and "git describe --exact HEAD" will arbitrarily choose one. We can force gradle to use a specific tag by running:
./gradlew --daemon assembleRelease -PtagToBuildFrom=myapp4.5.6_31

Sunday, July 22, 2012

Python: change and restore the working directory

Occasionally a command should be run from a specific directory. Here's a Python helper for this:

  • try/finally ensures the original working directory is restored.
  • contextlib.contextmanager is a neat way to write things supporting the "with" statement ("Context Managers").

Wednesday, September 1, 2010

Hg vs. Git in the workplace

This post is based on the following mail I sent to the ALT.NET Israel list. I'm discussing a Windows development environment.

I'm much better at git than hg, and I use git a lot for real work, and it's great (no ifs or buts).
I also helped originate the move to git at work, because the transition plan was much better. I evaluated hg first and loved it, but the transition plan wouldn't have been half has smooth (a better hg-svn bridge may have been written since then).

Still, here are - in order - the reasons I thing hg would fit better at my workplace (and had we found a good transition plan we'd probably be using hg instead of git):

  1. Friendlier commands and interface. With git I feel like I need to research how to do straightforward things. Git is extremely powerful and I can do anything with it, and I'm strange so I like the arcane, but git requires more of an investment from people to use it effectively when they have other things to do. Some things are arguably easier to understand in git (rebasing, for example, vs. hg's patch queues - although that's debatable) but the whole package leans heavily to hg IMO. This is the least-loved aspect of git among the teams.
  2. In hg, commits remember the named branch they were committed to (see here). I would LOVE to have this in git, but no cigar - we're still playing with different schemes of approximating this.
    With many people working at times on several branches, and with merging done between branches, then given commit XYZ it's nontrivial in git to figure out which branch it belongs to.
    This is especially true in some scenarios we encountered - e.g. human error caused an older release branch to be fast-forwarded to the head of the latest devel branch - few traces are left in the repository itself of the previous state, and we had fun a few times fixing this (can take hours). Now we have a hook to prevent this.
    If we'd have cherry-picked between different branches instead of merged then this would be easy (and this is equivalent to svn's merging, only better), but we like git's merge and we want to use that.
  3. hg has less quirky Windows support. Points to consider:
    • msysgit gets sporadic releases and is usually months behind the stable git version, the latest hg versions just work.
      • This hit us a few times (bug has been fixed but not available in msysgit).
      • Current example: Git 1.7.2 has improved crlf handling but msysgit isn't there.
    • Being able to "hg serve" your repository is incredibly cool, but "git daemon" doesn't work with msysgit
      • Think continuous integration that watches your local repository and runs builds with your current code, giving up-to-date feedback
      • collaborating with someone without pushing a publicly-visible branch (I've actually wanted to do that a few times)
      • developing and testing on more than 1 machine simultaneously. There are workarounds, but "git daemon" would have been perfect.
    • automating hg, including hooks, run in a Windows environment (vs. git where it runs in mingw's MSYS environment)
What doesn't bother me much for the long run is tooling. Right now hg seems to have better tools for our scenarios (even including much better Trac support), but I think git's extreme popularity will cause better and better tools to be written. Some people were very sad to let go of their VisualSvn / Ankh plugins, but they manage with Git Extensions (mostly) and occasionally TortoiseGit. I was surprised at how few people use git from the command-line, I can't live without it.

Monday, June 28, 2010

jQuery Validate: Required If Visible

I needed a generic "required if visible" rule for use with the jQuery Validation plugin. This is the result:


// jQuery.validate.requiredIfVisible.js
// Copyright (c) 2010 Ori Peleg, http://orip.org, distributed under the MIT license
(function($) {
$.validator.addMethod(
"requiredIfVisible",
function(value, element, params) {
function isVisible(e) {
// the element and all of its parents must be :visible
// inspiration: http://remysharp.com/2008/10/17/jquery-really-visible/
return e.is(":visible") && e.parents(":not(:visible)").length == 0;
}

if (isVisible($(element))) {
// call the "required" method
return $.validator.methods.required.call(this, $.trim(element.value), element);
}

return true;
},
$.validator.messages.required
);
})(jQuery);

Notes:

  • Using required:"#myinput:visible" could have worked, but ":visible" doesn't check for hidden parents, and I didn't want to repeat the element selector.
  • ":hidden" is false for elements with the "visibility:hidden" CSS rule, so I couldn't use ":not(:hidden)" either.
  • Technique for checking element visibility from Remy Sharp's blog.