Automated backups in windows with Robocopy

Short post :) I needed a simple way to backup my photos to an external drive and I couldn't find a simple & free solution so I ended up using the Robocopy tool in windows. What you need to do to mirror a directory structure is:
robocopy d:\users\fredrik\desktop\kamera f:\backup\foto /MIR
This will mirror everything in the directory d:\users\fredrik\desktop\kamera to f:\backup\foto. The second part of this is to automate it using the windows task scheduler. It can be found under Control Panel > Administrative Tools > Task Scheduler depends a bit on windows version and installed language pack.
  1. Choose to create a Basic Task, give it a name.
  2. Choose how often is its to run (once a week is good for me).
  3. In Action select Start a program, the path to robocopy is C:\Windows\System32\Robocopy.exe
  4. Enter arguments for robocopy in the arguments text box
After this just hit finish and if you want give it a test run.

Using CookieSyncManager

Tumblr has a mobile version of the user dashboard, http://tumblr.com/iphone, it can easily be embedded in mobile apps to remove the need to build a custom dashboard. In the tumblr api documentation they have a example in Objective-C:
NSString *email           = @"example@email.com";
NSString *password        = @"password";
NSString *destination_url = @"/iphone";

NSMutableURLRequest *request = [[NSMutableURLRequest alloc]
    initWithURL:[NSURL URLWithString:@"http://www.tumblr.com/login"]
];
[request setHTTPMethod:@"POST"];
NSString *request_body = [NSString
    stringWithFormat:@"email=%@&password=%@&redirect_to=%@",
    [email           stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding],
    [password        stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding],
    [destination_url stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding]
];
[request setHTTPBody:[request_body dataUsingEncoding:NSUTF8StringEncoding]];
/* Load the request here with an NDA-covered iPhone component
   that can view the web.
*/
[request release];
Since I build Android applications I had to port the basic function. What I had to do was to authenticate using a DefaultHttpClient and get the cookies the server returns for me to set, then use those cookies when I load a WebView with the dashboard URL. This was I can avoid the login page and just send the user to the dashboard.
public List authenticateAndReturnCookies() {
		DefaultHttpClient httpclient = new DefaultHttpClient();
		HttpPost httppost = new HttpPost("http://www.tumblr.com/login");

		try {
			List nameValuePairs = new ArrayList(2);
			nameValuePairs.add(new BasicNameValuePair("email", getUserName()));
			nameValuePairs
					.add(new BasicNameValuePair("password", getPassword()));
			httppost.setEntity(new UrlEncodedFormEntity(nameValuePairs));

			httpclient.execute(httppost);

			return httpclient.getCookieStore().getCookies();
		} catch (ClientProtocolException e) {
		} catch (IOException e) {
		}

		return null;
	}
To be able to sync cookies you need to create a instance of the CookieSyncManager, after that it's just to take the cookies that was returned from login and set them on the CookiesSyncManager instance. Once that is done the cookies can be used in a WebView. In my case since the cookies are set the iPhone dashboard works and I don't end up at the login page.
public void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		CookieSyncManager.createInstance(this);

		webView = new WebView(this);
		setContentView(webView);
		setupCookies();
		webView.loadUrl("http://www.tumblr.com/iphone");
}

private void setupCookies() {
		TumblrApi api = new TumblrApi(this);
		List cookies = api.authenticateAndReturnCookies();

		if (cookies != null) {
			for (Cookie cookie : cookies) {
				String cookieString = cookie.getName() + "="
						+ cookie.getValue() + "; domain=" + cookie.getDomain();
				CookieManager.getInstance().setCookie(cookie.getDomain(),
						cookieString);
			}
			CookieSyncManager.getInstance().sync();
		}
	}
The only thing here, they really should have named the URL mobile and not iPhone :) The full implementation for this can be found in the ttTumblr repository on github.

ttTumblr

A couple of days ago I uploaded the first version of ttTumblr on Android Market. It's a small app that allows the user to create content on a tumblr blog. At the moment, release 3, supports posting images from both gallery and by taking an image with the camera, creating text, quote, link and chat posts. I'm working on video upload but it's disabled for now until I figure out why the uploaded videos break during transcoding. Features planned include (in no particular order)
  • Working video uploading
  • View the users dashboard (both on entries and those from people you follow)
  • Support for other character sets (Russian, Chinese etc)
  • Posting audio, unsure if there's any real use/need for this
It's an open source project under the MIT license so the source can be found here: github

Running Selenium with multiple browsers from Rake

When your working with selenium tests in rspec you might want to run them in multiple browsers. The basic code generated by the selenium ide tool doesn't quite cover it and I couldn't find a good solution on google or stackoverflow, so here's mine: First you need a Rakefile that can start & stop selenium-rc and you need a task to run all the spec files. Start and stop tasks are covered in the documentation for the selenium-client gem. To that I've added a list of browsers to test, in my file FireFox, Google Chrome & Internet Explorer, and a rake task that runs the same specs for all browsers, the current settings for cucumber and spec generates a lot of text in it's output so you might want to clean it up a bit. Also I pass the browsers to use to the spec files in a environment variable, there might be better ways of doing it but it works and was the fastest way of getting it done.
#Rakefile
require 'selenium/rake/tasks'
require 'rake'
require 'rake/testtask'
require 'spec/rake/spectask'

selenium_jar_file_path  = './tools/test/selenium-server-1.0.3/selenium-server.jar'
browsers = ["*firefox", "*googlechrome", "*iexplore"]

desc "start the selenium-rc server"
Selenium::Rake::RemoteControlStartTask.new("rc") do |rc|
  rc.port = 4444
  rc.timeout_in_seconds = 2 * 60
  rc.background = true
  rc.wait_until_up_and_running = true
  rc.jar_file = selenium_jar_file_path
end

Selenium::Rake::RemoteControlStopTask.new("rc:stop") do |rc|
  rc.host = "localhost"
  rc.port = 4444
  rc.timeout_in_seconds = 3 * 60
end

task :selenium_spec_wrapper do
  browsers.each do |browser|
    ENV['s_browser'] = browser
    rake_system("spec spec/*_spec.rb")
  end
end

task :default => [:rc, :selenium_spec_wrapper, "rc:stop"]
In the before(:all) there the client driver is setup I get the environment variable set by the buildscript and use it, the fallback to *firefox is there to use when the script i run from my ide or just by spec.
#spec file
  before(:all) do
    @verification_errors = []
    @selenium_driver = Selenium::Client::Driver.new \
      :host => "localhost",
      :port => 4444,
      :browser => if ENV['s_browser'].nil? == false
					ENV['s_browser']
				else
					"*firefox"
				end,
      :url => 'http://localhost:3000/sommarkort/',
      :timeout_in_second => 20
  end