Tuesday, February 8, 2011

I'm locked out of my Android phone and my Google Login won't work!!

Just experienced this problem today and here is how to fix it:

  1. Have a friend call you, accept the phone call.
  2. Hit the menu button and goto Contacts
  3. Hit the back button until you hit the home screen
  4. Goto Settings, then Goto Accounts & Sync
  5. Delete (click on contact, then "Remove Account") every account except for your Gmail account
  6. End phone call
  7. Type in your username (WITHOUT @gmail.com) and your password
  8. Make a new security code.
  9. Re-add synced accounts.
Enjoy! Note, this worked on Android 2.1, I don't know about compatibility on other versions.


Thanks,
James Hartig

Tuesday, January 18, 2011

Enabling real-time notifications in Cloudboard with Node.js

When Cloudboard was created, I had the popup load the "inbox" every time it was opened in an IFrame. Which not only was a complete waste of a server request, it was also a horrible UI experience on the user. If I could find a way to get real-time notifications, then the extension can be fed the pastes and will only have to get the "inbox" on boot. This will come in handy with the introduction of "auto pasting" which allows the user to right-click on any form field and paste the last paste from their Cloudboard.

I started off trying to do long polling from lighttpd+php, but this was horrible and wouldn't scale at all (thanks @yowgi). My biggest problem was that FastCGI cannot detect with the client connection is aborted unless you use https://gist.github.com/761520, which only works in nginx/Apache and not in lighttpd, but these commands aren't in phpredis. Thus, I had a ton of FastCGI threads waiting for a publish on Redis, even though the client already aborted.

I ended up switching to Node.js. The extension sends a request to "listen" to node.js and waits until data is returned. When a new post is made, node.js sends a request to all the listener's for a user. This works beautifully in a perfect world. But what happens with the client aborts? This was our FastCGI problem. Well, assuming that we have a good client, node.js will get the connection close (https://gist.github.com/762267) and then close the listen request. However, Chrome is not a "good client" and so we are stuck with the same problem. To work around this problem, each extension is given a client id and and sends this along with the "listen" request. If node.js gets a client id that is already associated with another "listen" request, it shuts down the former. Problem solved. In addition, the server now handles timeouts and not the client so this should reduce the number of closed connections.
To keep the listen connections "alive" every 2 minutes we make sure that we can write to each connection by sending a "-". When we are finally ready to send a post, we append the stream with a "$" before sending the post so then the client just looks for a "$" and then reads the json-encoded post. Plus, if we actually send something and we end up closing the connection (on timeout), we can read this in the client as a safe return and not a failure.

The client maintains an inbox and a lastUpdate time. When the browser is started, it fetches the lastUpdate time from node.js and if the lastUpdate time is newer, it pulls a new inbox. From then, posts are appended from the real-time polling. LastUpdate times are cached and updated in node.js when we get new post events. The client also requests lastUpdate times every 30 minutes to keep the local copy in line with the server copy. The server stores all the inboxes in an "inboxes" object and pushes it to disk every few minutes. When the node.js server is restarted, it loads the inboxes file from disk and resumes operation. It also periodically checks all the items for any that expired and can be deleted. This functions a lot like Redis except it is all done with JS objects and inside node.js.

The latest version of Cloudboard, 0.6.7 has been released and is using the aforesaid technology. You can look into all the source code on github. API documentation will be coming soon so you can make your own Cloudboard clients.

Thanks,
James Hartig

Thursday, December 30, 2010

Cloudboard: Share text between computers

When I received my CR-48 (read: Chrome notebook), I instantly noticed a need for a shared clipboard between my computer and the CR-48. I downloaded Google's Web Clipboard, however, it took a while for the pastes to appear on both machines and I had to sit and wait for it them to load. So I made my own extension that simplifies the process and allows you to share any type of text right from the context menu. Cloudboard was born.

Install the extension, login via Google to the Cloudboard site and get your token, then start sharing. You can right-click on images, urls, pages and text to share with your other computers and all you have to do is click on the clipboard next to the address bar to see a list of your pastes. If you want to refresh, hit the refresh button, or just open the popup again, it is updated instantaneously with your other Chrome installations.


Feel free to leave any comments that you have. I will be working on notifications, so you can be automatically notified when a new paste exists.

Thanks,
James Hartig

Thursday, December 16, 2010

See the User's IP Using Lighttpd Behind Cloudflare (Updated with Apigee)

Using Cloudflare to protect your website is a great choice, however, it can break your existing applications because the IP that your server sees is not the user's, it is Cloudflare's. Cloudflare has a module for Apache to rewrite the IP with the correct one (here), but not for lighttpd. The following 3 steps will get your IP rewritten and have your access logs printing out the correct IP for the connecting user.

Step 1: Open your lighttpd.conf file and append "mod_extforward" to the end of the server.modules list.

Step 2:  Paste the following code block anywhere in the file (well at least after the server.modules lines)
$HTTP["remoteip"] == "204.93.240.0/24" {
extforward.forwarder = ( "all" => "trust" )
extforward.headers = ("CF-Connecting-IP")
}

$HTTP["remoteip"] == "204.93.177.0/24" {
extforward.forwarder = ( "all" => "trust" )
extforward.headers = ("CF-Connecting-IP")
}

$HTTP["remoteip"] == "199.27.128.0/21" {
extforward.forwarder = ( "all" => "trust" )
extforward.headers = ("CF-Connecting-IP")
}

$HTTP["remoteip"] == "173.245.48.0/20" {
extforward.forwarder = ( "all" => "trust" )
extforward.headers = ("CF-Connecting-IP")
}

$HTTP["remoteip"] == "103.22.200.0/22" {
extforward.forwarder = ( "all" => "trust" )
extforward.headers = ("CF-Connecting-IP")
}


Step 3: Restart lighttpd and you're good to go!

You should now see the actual user IPs in the access logs and in your applications.

If you want to add Apigee as well:
$HTTP["remoteip"] == "75.101.150.28/32" {
extforward.forwarder = ( "all" => "trust" )
extforward.headers = ("CF-Connecting-IP")
}

$HTTP["remoteip"] == "174.129.236.240/32" {
extforward.forwarder = ( "all" => "trust" )
extforward.headers = ("CF-Connecting-IP")
}

Thanks,
James Hartig

Thursday, December 9, 2010

Chrome Notebook. My Hands-on Review


I received my very own Chrome Notebook today and so far, I love it. Yes it has its quirks, but... its a Google notebook! For the most part everything works, there are just some odd things that fail to work. 

  • First of all, the "Next tab" button, doesn't do anything but jump/bump the side of the screen (odd?).  Once you open a new Window, it switches between windows, but it should not have been labeled a next tab button if it switched windows. 
  • Sync does work, it just takes forever to load.
  • There is a slight lag to the keyboard.
  • Selecting text doesn't work in all cases (read: text boxes). Fixed on restart.
  • Cursor sometimes doesn't change until you click feverishly.
  • Trackpad is hard to get used to, sometimes freaks out.
  • Flash player does not work very well on YouTube, Hulu, etc. Works fine for Grooveshark.
  • USB/SD cards do not work at all. The content browser comes up but it is empty.
  • Can take screenshots but there doesn't appear to be any purpose yet except to send them along with a bug report.
  • Shortcuts to move to next or previous tab do not work.
  • Battery time never finishes "Calculating".


Those are all the issues I noticed so far. But otherwise, the startup time was less than 10 seconds. I haven't ran into any extensions that don't work and websites seem to load and run very smoothly. Also, bettary life seems to be very good. I miss the delete button, but you can do Alt+Backspace to achieve the same thing. Dedicated search button is sweet, especially since it saves me time trying to work the trackpad.


Sent from my Chrome notebook.

Thanks,
James Hartig

Wednesday, December 8, 2010

Woopra in your Tumblr

Tumblr used to not allow third party Javascript in their custom HTML, but this seems to have been lifted. I do not know when but I just tried last night and it seems to work fine now. Woopra is a website that allows you to view your website traffic in real-time. You can now add Woopra to your Tumblr blog to watch your visitors and get detailed information on how they read your blog.


  1. Go to https://www.woopra.com/members/ and get the Setup code for the JS script.
  2. Go to http://www.tumblr.com/dashboard and goto Customize on the right side.
  3. At the top of the customize page, hit Theme, and then click Enable custom HTML
  4. Scroll down to the bottom of the HTML box (also under Theme option) till you see
  5. Paste the Woopra setup code right above then click Save + Close
  6. Watch the results in Woopra!

Enjoy!

Thanks,
James Hartig

Thursday, December 2, 2010

2 Random PHP Array Functions

Convert an Array into XML
http://jhartig.pastebin.com/B5sZ0rkK

Convert an Array into text like print_r
http://jhartig.pastebin.com/J6QWJCTW

Don't know what you would use them for. But, enjoy!

Thanks,
James Hartig