Coffee to go

Icon

var thisBlog = getGlobalContext().buildFromTemplate(PERSONAL | PROGRAMMING | RANDOM_THOUGHTS);

android – Renaming output APK when building using ANT

By default when using ant build file generated by Android to build release package, it names android_rules-release.apk to final output APK file.
In order to change the name to a dynamic file name i.e. either provided as a property value on command line or specifying a property in .properties file, we can use additional ant task, make it dependant on release task and then rename the output APK file using <copy file /> task.

For example:

<target name="deploy" depends="release">
	<copy file="${out.dir}/android_rules-release.apk" tofile="${out.dir}/${appname}.apk" overwrite="true"/>
</target>

Now from command prompt run:

ant deploy -Dappname=MyApp

And on successful build it will generate MyApp.APK in bin/ folder

Share on Twitter

MongoDB: Changing a field type from String to Array

In order to change the field’s data type, first retrieve the document using the correct $type value (the possible values of $type can be found here: http://www.mongodb.org/display/DOCS/Advanced+Queries#AdvancedQueries-%24type), cast the field to new data type and then save the document again.

Below code snippet changes the String data type (notice $type : 2, where 2 indicates the category fields containing data of type String) to an array of String:

db.collection.find( { "category" : { $type : 2 } } ).forEach( function (x) {
    x.category = [ x.category];
    db.collection.save(x);
});
Share on Twitter

Facebook android sdk, invalid_key & key store alias

If you are getting this error ‘invalid_key: Android key mismatch. Your key “xxxxxxxxxxxxxx” does not match the allowed keys specified in your application settings’ then it clearly means that there is something wrong either with the key you generated or the key you have listed in facebook application page.

Although, the error description is very clear and straight forward but it took me some good amount of time to discover the actual cause. In my case, I was using wrong key store alias for generating the key, resulting in key mismatch when application is executed. So if you also have forgotten the key alias then there this command which returns details of a key in key store:

C:\Users\Waqas>keytool -list -v -keystore c:\path-to-keystore\key.store

enter the password if required and if all goes well you get’ll something like this:

Keystore type: JKS
Keystore provider: SUN

Your keystore contains 1 entry

Alias name: sample-app
Creation date: May 13, 2012
Entry type: PrivateKeyEntry
Certificate chain length: 1
Certificate[1]:
Owner: CN=Waqas Hussain Siddiqui, C=PK
Issuer: CN=Waqas Hussain Siddiqui, C=PK
Serial number: 4faf9730
Valid from: Sun May 13 16:12:48 PKT 2012 until: Tue May 06 16:12:48 PKT 2042
Certificate fingerprints:
MD5: 00:00:00:00:00:00:00:76:52:27:42:D3:72:96:84
SHA1: BA:BA:EF:XX:XX:XX:8B:0A:94:1D:E7:XX:B5:72:AA:59:88:XX:F7:XX
Signature algorithm name: SHA1withRSA
Version: 3

*******************************************
*******************************************

Share on Twitter

node.js & Error: listen EACCES

For one of my own ‘technology venture’ I have recently started getting my hand dirty with node.js and mongodb- I followed a great step by step blog post (whose link has got been missing, sorry) about setting up node.js and mongodb on amazon ec2 server and luckily it went smooth and I was able to run node.js web server at port ’80′-

But after couple of days when i resumed from where I stopped last time, did some changes in my webserver to make it more useful rather printing ‘Welcome’ message, when I tried running following command

node my_server.js

It always ended up with following exception:

node.js:201
        throw e; // process.nextTick error, or 'error' event on first tick
              ^
Error: listen EACCES
    at errnoException (net.js:642:11)
    at Array.0 (net.js:728:28)
    at EventEmitter._tickCallback (node.js:192:40)

I banged my head quite a while, try changes bits here and there but nothing worked out- so i decided to google it and as always found a similar post and solution posted on StackOverflow- so basically it turned out that Error: listen EACCES occurs when user doesn’t have enough rights to start web server on certain ports- and obviously my ec2-user doesn’t have permission to start server on port ’80′. So for solving this all i did was gave the appropiate rights to logged-in user and … happy ending…

Share on Twitter

Getting (Reddit) authentication cookie and then using it – Apache HttpClient

Recently I was working on Java application to scrap Reddit data using their api, although performing read-only operations (such as reading listing data) doesn’t require authentication but after reading a comment on StackOverflow I decided to use send authenticated request even if it isn’t necessary. Comment by the way says that for requests from robots/automatic scrappers without a reddit_session id, reddit returns limited amount of data and some time data is inconsistent too.

Anyways to get started first step is to send HTTP POST request to http://www.reddit.com/api/login along with required parameters ‘user’ and ‘passwd’ for username and password. If username and password combination matches reddit server will return authentication cookie containing reddit_session along with other different stuff like domain, path etc…

Code here show how to make an HTTP POST request using Apache HttpClient, read and store cookie for further use:

public class RedditClient {

    private List<Cookie> cookies = null;

    public boolean Login() throws ClientProtocolException, IOException {
		List<NameValuePair> loginParams = new ArrayList<NameValuePair>();
		loginParams.add(new BasicNameValuePair("api_type", "json"));

        //Set values of form fields
		loginParams.add(new BasicNameValuePair("user", userName));
		loginParams.add(new BasicNameValuePair("passwd", password));

		UrlEncodedFormEntity entity = new UrlEncodedFormEntity(loginParams, "UTF-8");

		HttpPost httpPost = new HttpPost("https://ssl.reddit.com/api/login");
		httpPost.setEntity(entity);

		DefaultHttpClient httpClient = new DefaultHttpClient();

		HttpResponse httpResponse = httpClient.execute(httpPost);				

        //Save cookie in List of Cookies so we can use it later
		cookies = httpClient.getCookieStore().getCookies();						

		httpClient.getConnectionManager().shutdown();

		return false;
	}
}

Now in order to make a subsequent request which require authentication for example submitting a new post or posting a comment we have to pass attach this cookie with the request; Otherwise server will respond with an error.
Below is how to make a subsequent request, in this case a request to retrieve top 100 post from funny category, along with cookie.

public class RedditClient {
    ....
    public void readListing() {
         URI feedUrl = new URI("http://www.reddit.com/r/funny/top/?sort=top&t=month");
         DefaultHttpClient httpClient = new DefaultHttpClient();

         HttpGet httpGet = new HttpGet(feedUrl);

         //Check if cookie list is not empty
         //attach it with current request
         if(this.cookies != null) {
             for(Cookie c : this.cookies)
	         httpClient.getCookieStore().addCookie(c);
         }

         HttpResponse response = httpClient.execute(httpGet);

         String strResponse = "";

         BufferedReader rd = new BufferedReader(new InputStreamReader(response.getEntity().getContent()));
         String line = "";
         while ((line = rd.readLine()) != null) {
	    strResponse += line;
         }

         httpClient.getConnectionManager().shutdown();
    }
}

In order to check if our request was treated as a trusted request look for the value of ‘modhash’ in response it should be a long encrypted string, for unauthenticated requests it’s always empty.

{"kind": "Listing", "data": {"modhash": "bjxvddjbxaac5b494bc70000000000000000000000",........ }

And finally putting it all together:

public class RedditClient {
    private List<Cookie> cookies = null;

    public boolean Login() throws ClientProtocolException, IOException {
		List<NameValuePair> loginParams = new ArrayList<NameValuePair>();
		loginParams.add(new BasicNameValuePair("api_type", "json"));

        //Set values of form fields
		loginParams.add(new BasicNameValuePair("user", userName));
		loginParams.add(new BasicNameValuePair("passwd", password));

		UrlEncodedFormEntity entity = new UrlEncodedFormEntity(loginParams, "UTF-8");

		HttpPost httpPost = new HttpPost("https://ssl.reddit.com/api/login");
		httpPost.setEntity(entity);

		DefaultHttpClient httpClient = new DefaultHttpClient();

		HttpResponse httpResponse = httpClient.execute(httpPost);				

        //Save cookie in List of Cookies so we can use it later
		cookies = httpClient.getCookieStore().getCookies();						

		httpClient.getConnectionManager().shutdown();

		return false;
	}

    public void readListing() {
         URI feedUrl = new URI("http://www.reddit.com/r/funny/top/?sort=top&t=month");
         DefaultHttpClient httpClient = new DefaultHttpClient();

         HttpGet httpGet = new HttpGet(feedUrl);

         //Check if cookie list is not empty
         //attach it with current request
         if(this.cookies != null) {
             for(Cookie c : this.cookies)
	         httpClient.getCookieStore().addCookie(c);
         }

         HttpResponse response = httpClient.execute(httpGet);

         String strResponse = "";

         BufferedReader rd = new BufferedReader(new InputStreamReader(response.getEntity().getContent()));
         String line = "";
         while ((line = rd.readLine()) != null) {
	    strResponse += line;
         }

         httpClient.getConnectionManager().shutdown();
    }
}
Share on Twitter