contact

Archive for the ‘Tech Questions’ Category

Converting IP addresses to lat / lng and plotting them on a map with php / ajax

Monday, August 30th, 2010

I love google analytics but the data is quite “slow” meaning you can not get real time updates, so I decided to set up my own tracking service for the sites I maintain. But I did not want to just keep track of my visitors I also wanted to see where the come from.

The setup / What you need

A map – Its important to know that you have to use a mercator projection – otherwise the latitude and longitude do not convert correctly to x and y values on the map

A copy of the free GEO Ip database – there are two versions, an Apache module and a CSV version. I used the csv one and imported it into a sql database note:The sql version is much slower, but easier to set up.

How to use the GEO IP Database

Setting up the GEO IP database

I used sqlpro alongside this guide to import the csv file in a sql database. This is pretty straight forward.

Converting an IP address to lat / lng


function ip_to_lat_lng($ip){

$sql="SELECT * FROM geo_locations WHERE locId = (SELECT location_id FROM geo_blocks WHERE INET_ATON('".$ip."') BETWEEN ip_start AND ip_end)";

$result= mysql_query($sql) or die(mysql_error());

return mysql_fetch_object($result);

}

this sql statement takes an IP adress and returns a php object which has a latitude and longitude property

Mapping lat / lng to x and y on a 2D map

so not that we have our lat and long we need to map the on the 2d coordinate system on our map.

This is wrong:


x=map_width/2+map_width/360*lng
y=map_height/2+map_height/180*lat

This is right:


function lat_to_y(lat){return 180/Math.PI * Math.log(Math.tan(Math.PI/4+lat*(Math.PI/180)/2));}

shift_x= 0 // depending on your map, you might have to move the entire projection a bit
shift_y=0
x=map_width/2+map_width/360*lng +shift_x
y=map_height/2+lat_to_y(lat*-1)*map_height/180+shift_y

Its important to account for the distortion from projecting a spherical map on a 2d flat surface. The function lat_to_y takes care of that. If you are interested in the math behind it take a look at this wikipedia article.

How to integrate bb-press into your wordpress theme

Thursday, February 11th, 2010

If you run a wordpress blog bb-press is the forum of choice since it integrates so well with WordPress. The only thing it lacks is the ability to integrate into your wordpress theme nicely, there is however a rather simple hack that makes a tighter integration possible. For the general setup and integration of bb-press please checkout this guide.

Functional integration

I want to focus on the theme part of it, which I think is just as important. So once you have your blog and your forum running you need to add a few lines of code to your bb-config.php file.

/**
 * bbPress Database Table prefix.
 *
 * You can have multiple installations in one database if you give each a unique
 * prefix. Only numbers, letters, and underscores please!
 */
$bb_table_prefix = 'bb_';

require('PATH_TO_WORDPRESS/wp-blog-header.php');

note: PATH_TO_WORDPRESS has to be the absolute path to the root folder since it will be called from different files within bb-press and a relative path might throw an error.

Theme header

Ok now we can use all of the wordpress theme tags in the bb-press theme. I recommend building uppon the “kakumei” that you already have but you can start from scratch as well.

In most cases you will want to have the same header and footer used in your blogs theme. You basically have three options

You can call the get_header() method directly inside header.php file in the bb-press theme:

  • remove all bb-press html code or you will end up with two html headers and a huge mess
  • this has the advantage that you only have to change the header file and you do not have to alter the other files

You can remove all calls of bb_get_header() and replace it with get_header() inside every file in bb-press theme

  • straight forward, you only have to deal with the wordpress theme header from then on
  • many bb-press plugins rely on scripts to be included in the header. With this technique you loose some functionality

You can leave your bb_press header and simply alter it by adding specific wordpress theme tags like wp_list_pages() to create the menu.

  • its the most complicated option since you have to deal with two header files and two style sheets
  • it offers the greatest flexibility. I used it to integrate my support forum

A word on CSS

If you choose to use the third option you will have to manually add the wordpress themes stlye.css to the header.php in the bb_press theme. The included bb_press css file is standalone and complete but you probably want your own theme to take the lead. I recommend throwing out the entire global settings part of the bb_press style sheet. I ended up deleting half of the styles and only leaving the styles that apply to elements of the forum. Everything else should come from your wordpress stylesheet. Its just easier to maintain that way.

And there you go – you run a solid forum that fits nicely into your wordpress blog.

php and mysql full text search across multiple tables using a relevancy score

Wednesday, June 24th, 2009

the setup

I am currently building a paltfrom to host my air applications on. this is plattform includes a feedback and bug tracking forum application where users can post their thoughts and problems. In order for this to be helpfull i needed to implement full text search. the forum constists of basically two tables.

  • 1.) threads (title,date,author_id,forum_id,threadComment_id)
  • 2.) comments (text, author, date,thread_id)

so the way this works is that a user can open up a thread , which stores a new thread and a comment in the database. the two are linked by adding the thread Id to the comment and the comments unique id to the thread. any futur comments that are posted to this thread will simply have the thread Id stored in them.

Philips USB rechargeable Power Pack – SCE4420

Thursday, May 28th, 2009

sce4420

Update 28.6.2009: I just got my iPhone 3GS and Iplugged it in and nothing happend. It appears that apple changed something on the power management so the iPhone 3GS can not be charged with it. Crap!

Today I received my external USB Power pack from Amzon. I got it because my phones battery is crap and the iPod Touch does not get through a day of wifi and gaming either. I am currently charging it for the first time so I can not report on the devices performance, but I read in reviews that it is capable of completely recharging an iPhone up to 2 times. The charging it self takes a qutie while. I have it hooked up to my computer for about 4 hours now and it is still not done, but I guess that this kind of charging will increase the overall lifetime of the battery inside. I find this kind of powerpack more convenient that the ones specifically made for the iphone and Ipod Touch since I can charge every gadget that takes power via usb and most other cellphones as well.

Pros:

  • small form factor
  • looks quite nice – I generally like the appearance of philips products
  • low price 24? at amazon, the kensington one costs about 40?
  • comes with a ton of adapters ( Nokia,Samsung, Motorola, Nintendo DS, Sony Ericsson,Blackberry and mini USB)
  • has 2 ports, one for charging the device and one standard USB jack to plug in your gadgets
  • is advertised with 30 hours of battery life( I will test that and post)
  • Retractable cable, no additional cable clutter !!!!
  • for simple LEDs indicate the level of charge
  • comes with a small black cloth bag to keep verything together

Cons:

  • charging takes quite some time
  • nothing else really

Update 3.6.2009 – Battery performance

the battery works really well. I was able to charge my ipod touch 2 times with one charge. I could charge my girlfriends ipod nano without even noticing a decline in charge.

How to only listen to the audio of a video on an iPhone and iPodtouch

Wednesday, May 6th, 2009

update 28.6.2009 :this does not work anymore with the 3.0 firmware and an iPhone. It still works on my iPod touch though.

I subscribe to many video podcasts and most of the time I watch them, but sometimes I want to do something else like playing a game while just listening to the audio of a news video podcast. The problem is that video playback stops when you close the videoplayer, whereas audio continues to play in the backgroud if you run another app. After the latest software upgrade even if you selected a video podcast from the audio library it would launch into the videoplayer, which is a good thing most of the time.

To just get the audio of a video, start playing the video –> close the player(the video stops) –> double click the home button so the small media controll buttons come up and hit play –> the audio of the video is still in the audio que and will start playing for your enjoyment

invalid BS_jmpBoot error on Mac OS X disc utility

Monday, April 27th, 2009

This error showed up when a friend asked me to fix this 2 TB Western Digital MyBook Studio Edition Drive. The drive can not be mounted, repaired or verified.

invalid BS_jmpBoot error

invalid BS_jmpBoot error

Long story short there is no way to simply fix this error. You can try with TestDisk but I had no luck with it. Don’t jump out of the window just yet since your data is most likely still there. Only the partition table on the drive is damaged and all your data is still in place. Any Data Recovery tool will be able to get your data out of that damaged partition.

If this happend to you consider reading this link

Why RAID is not a good backup solution for private users

Monday, April 27th, 2009

A sad but typical story about why one needs to use backups when dealing with computers

Last Night a friend of mine gave me his almost full 2 TB Western Digital Studio Edition that has a 2 drive RAID 0/1 built in. He told me that he used it with his mac and everything worked just fine. When he connected it to his PC and tried to move some data to the drive it stoped working, which is no surprise since the drive is formated as HSF+ in a RAID 0 configuration. Windows can not handle HFS and somehow managed to serverly damage the pratition table on the drive. After using all tools known to me such as TestDisk, Mac OS X disc utility and Ubuntus partition manager i gave it up as damaged beyond repair. The next step will be to use a data recovery tool to pull out the data, that is still intact on the drive, but all of these programs cost at least 100$. In addition we have to finde 2 Terabytes of free space to recover the data to which also will not come cheap.

Since he used the drive in a RAID 0 mode there was no backup anyway but the very same thing could have happened if it was set up as a RAID 1.

When putting together my home server setup I was considering using one of these RAID drives vs. two stand alone drives and I am glad I chose the two single drives.

Pro RAID

  • the consumer versions like the western digital ones are really easy to set up
  • good protection from hardware failure
  • automatic data restoring
  • only Raid 1 will give you some sort of backup
  • RAID 0 gives you speed gains
  • usually the read feature is a bit more costly than two stand alone drives

Contra RAID

  • no protection from software errors
  • if the RAID it self craps out on you there is very little chance on restoring things
  • if you delete stuff it is gone on both RAID discs instantly
  • if the partition is damaged both drives are affected
  • the physical proximity of these raid drives makes it more likely to die together in case of power surge for example
  • not very flexible – I can always grab one of my two storage drives and go to a friends house to get some data and when I get back home it just syncs to the other drive and everything is fine unless the unlikely case of both drives die at the same time

I do not recommend a single RAID 0,1 or 5 setup as a sufficient backup solution. Backup often, on different devices in different locations!!

time machine back up to remote macs over lan and internet

Sunday, April 5th, 2009

BACK UP OFTEN!!!!

Now that I have my mac mini set up as my home server I also wanted to backup its system drive to preserve all the configuration. I have an Airport extreme basestation that has a 500GB hard drive hooked up to it. I have used it to back up my mac book pro over the air and it worked just fine. When I tried to select it as the backup drive for my mac mini the time machine preference pane would crash every time. So I played arround with it and it appears that time machine is now able to backup to any afp:// file server. It is important that you mount it using the following instructions and not just click on it in the finder. It appears that apple does something differently when using the shares in finder.

Setting up time machine with a remote destination

This is done by pressing command + K in finder and using OS X built in ability to connect to different file servers

connect to server

connect to server

You might get prompted for user name and password. Once connected the afp source shows up in your finder.

afp source

afp source

In my case that is the airport extreme base station called chrillo.Airport with the hard drive. This could also be another mac. Now head over to your time machine preferences and the click the change drive button.

remote time machine backup

remote time machine backup

As you can see it shows up with its Ip address. In my case I used the internal Lan IP

adding Mac OS X like Application Behaviour to your Air Application

Tuesday, March 31st, 2009

In Mac OS X when you close the window of an application the app usually keeps running in the dock. Wheter this is a good thing or not is totally different story, but for apps like mail and ical it certainly is since I want my mail app to keep checking for new mail without the window cluttering up my screen. So what if I want to add such behaviour to an Adobe Air Application.

 	var appIsPersistant:Boolean=false
 	var app=NativeApplication.nativeApplication
 	var window=stage.nativeWindow;

public function set appPersistant(b:Boolean):void{ // adding a simple property to your app b:Boolean whether its stays on or not
 appIsPersistant=b
 	if(b){
 		if(app!=null){
 			app.autoExit=false // preventing the app to exit if all windwows are closed
 			window.addEventListener(Event.CLOSING,hideWindow) // listening for the closing event of the main window
 			app.addEventListener(InvokeEvent.INVOKE,initWindow) // listening for the invoke event if the user clicks on the dock icon
 			app.addEventListener(Event.EXITING,appClose) // listening if the app should be terminated, to prevent the hiding of the window and allow termination
 		}
 	}else{
 		if(app!=null){
 		app.autoExit=true // if app is not persistant the app can close just as usual
 		}
 	}
 }
 public function appClose(e:Event):void{
 	window.removeEventListener(Event.CLOSING,hideWindow) // if the app should terminate with command + Q we have to remove the listener for the Closing event. Otherwise only the window will close but the app will not terminate
 }
 public function hideWindow(e:Event):void{
 	if(window.visible){ // if the window is visible the event behaviour is canceld and the window is hidden
 		e.preventDefault()
 		window.visible=false
 	}
 }
 function initWindow(e:Event=null):void{
 	window.activate() // if the user clicks on the dock icon the window commes back up
 }
 public function get appPersistant():Boolean{
 	return appIsPersistant // just the getter for the appPersistant propery
 }

by adding these few methods your app will exit just fine with command + Q but if you click the close button only the window will close and the app keeps running and comes back up if you click the dock icon

onReleaseOutside in Actionscript 3

Thursday, January 29th, 2009

actionscript 3 does not nativly support a onReleaseOutside Event. When creating things like a scrollBar or other UI elements this can be quite annoying.

Here is a simple work around that uses a simple movieClip as a button:

import flash.display.MovieClip
 import flash.events.*

var myBtn:MovieClip=new MovieClip()
 myBtn.graphics.beginFill(0x003366,1)
 myBtn.graphics.drawRect(0,0,50,50)
 addChild(myBtn)
 myBtn.addEventListener(MouseEvent.MOUSE_DOWN,downHandler)

function downHandler(event:MouseEvent):void{
 stage.addEventListener(MouseEvent.MOUSE_UP,upHandler)
 trace("mouse went down")
 }
 function upHandler(e:MouseEvent):void{
 if(e.target==stage){ // this checks to see if the event is coming from the stage or not
 stage.removeEventListener(MouseEvent.MOUSE_UP,upHandler)
 trace("mouse went up outside")
 }else{
 trace("mouse went up")
 }
 }

pretty simple :-)

heres the fla for download