Monday, August 13, 2012

mFlixter - an always on top browser

Such a simple functionality but none of the browsers have it out of box... sad story. So I got mad and made mine. And here I share it with you.

Very simple, browser based on IE component. Slightly buggy and slightly slow, but it does the job for me and hope it might be useful for you. It works great for watching Netflix and YouTube, which covers about 100% of my use cases, but it also can be useful for having your online mailbox or favorite social network site open on top of other windows. It minimizes to windows tray, near the clock making it very easy to hide/show and you can open as many instances as you like. 

And that's what it looks like. Probably the simplest browser you have seen in past 10 years. Oh wait it has something that all other's are missing! 

What you need for this thing to run is .NET 4, Silverlight, Internet Explorer. The installer is supposed to download and install all that for you. The program has built in auto-updater which will download and install updates when you start it. 

You can add feature requests and bug rage in comments. 

Wednesday, January 18, 2012

Why is SOPA bad?

Today is January 18th and the internet is exploding about SOPA... Google and Wikipedia are crying to tell people to do something about it. Well so whats the big deal... It is supposed to be for the good reasons right? Fight piracy and stuff you know...

What is SOPA?
I don't even know what it stands for, but the whole purpose seems to be limit the access of internet users to certain websites by forcing internet service providers to block these sites. Also there is whole lot about forcing big companies like google to exclude pirated content from their search results... not that it wasn't done already, they just want to streamline the process. So say there is a website piratedmusic.nom that illegally shares the music of Pop Star. Before SOPA what the Pop Star could do is file a thingy to say google, to exclude any results from priatedmusic.nom from appearing in the search results. Also they could sue the owners of the website, and if the owner happened to be in US or Canada chances are their website would go down... say in a month or something... one way or another, either the owner would close in fear of legal prosecution and loss reimbursement or the government would close it for them through court order. Now what happens if this site is registered in some third world country and the owner is friend of Borat living in some small village in Kazakstan? The search results would of course be excluded from google, but there is no chance that site would get closed, no matter how many lawyers or money the Pop Star has. Now what SOPA is trying to accomplish is that to allow Pop Star to send an email to the internet providers and have them block the access to piratedmusic.nom in a matter of hours or minutes.

Why it wouldn't work?
Now the computer guy in me is just laughing aloud... it's a dark evil laugh... The reason why it wouldn't work (at least in near future) is because the internet was built in a way to allow communicate 2 computers plugged on the internet no matter what obstacles are on their way. SOPA may block the access to piratedmusic.nom but anyone with basic understanding of how internet works would use the direct address of that site and would still be able to reach it. IP address anyone? Basically a dot separated combination of numbers.. like phone number. Now you'd ask why can't they block that too? Uh.. there is a lot of technical($$$$$$) problems with that and it would really violate your right of privacy. If blocking a site name would be similar to disconnecting someone's phone number from the call center so that you can't reach them, then blocking their direct(IP) address would be similar to tapping your phone to see who are you calling, and then disconnecting you based on that. And even if they eventually do that, there are so many ways around that... For someone determined to pirating working around this problem would be more of an enjoyable fun thing to do rather than a real obstacle.

So why is SOPA bad after all?
First of all it's inefficient in fight with piracy as I stated above. But the real concerning problem is that if SOPA becomes a reality the Internet providers and big companies like google would have to implement a global, streamlined lock-down mechanism to basically block any given website or computer on the internet. You'd think that US government has that capability already... websites hosted inside US - yes probably matter of a phone call, outside the country not really... In some cases it might be for them easier to bomb the communication point of the web server that provides a website than blocking it or hacking it... no joke. I am not anti-government or anything, just trying to present my understanding of facts. Also if you didn't know SOPA really would only affect US people... these blocked sites would be blocked only in US, while the rest of the world would still be able to access them without a problem. I am little afraid that once such powerful internet site blocking mechanism becomes a reality, these mechanisms may be misused one day to block websites like Wikileaks, etc... Who said government has the right to censor the information or prohibit someone's evening walks on the Pirate B...each... It's like preventing someone from walking on street at night, because they might be looking a robbery victim...

Why are the big internet companies against SOPA?
This is so obvious... Implementing the lock-down mechanisms to comply with SOPA would require enormous amount of money... The way I see it, the government always wanted such system in place, but it would never be economically reasonable to do it... But now given that all major movie and music companies are complaining about piracy and their author rights, and there is a chance to lay the hard work on the rich internet companies - why not? But that's really not the only reason... many big internet companies have engineer's spirit, and from scientific point of view something like SOPA is against the whole idea of the internet.

DISCLAIMER: This article presents a personal, pretty much careless opinion about the internet censorship legislation. For more technical information about SOPA do your own research! And think about it, and make your own judgments!

Saturday, January 7, 2012

The very simple guide how to keep your PC and your digital identity safe - Part I

I am writing this guide because once in a while people I know would run into problems with viruses and other kinds of digital evil so I'm writing this guide to point 'em all to this article in future, and who knows maybe it would help some others on the internet. I am very lazy so I'll keep it short and as simple as I can. Generally keeping your PC safe and online stuff safe is extremely simple if you follow some extremely simple rules.

Part 1: Keeping your PC clean from viruses.

This part is intended pretty much for Windows users only, if your on Mac or Linux you are more safe against these. If you wan't to know more how to protect your Mac or Linux system just read on how to set proper user permissions for your system.

How do this viruses get into your computer:
Most of the viruses and malware come from the internet. General rule of safety is to download stuff/open email/etc. only from trusted sources. This is especially important when free stuff is concerned. There are millions of 'free' software out there which are malware and viruses in disguise. So if you want to download software do so from a trusted source, say something from Microsoft or Apple is pretty much guaranteed to be safe. Always pay attention to the address bar of your browser when you are downloading, make sure its the right website and not a 'mikrosoft.kom' or 'apple.pie'. If software you are about to download is from a company you never heard about, research it, check if it has a wikipedia article, check if it is ranked on websites like, or just put "TheAwesomeProgramYouWant is malware" in google search and see if anything will come up. By doing so you will eliminate 50% of virus threat that can come from the internet. Second virus threat from the internet comes from email attachments. You can't get a virus by just recieving it, but you can infect your computer if you open the email attachments. Every time you open an email attachment your pretty much tell your computer "I trust whatever is in there, and if will blow up my computer, so be it" <- and that's true about pretty much any other program you open your computer, most often you give it same level of control over your computer as you have... I got carried away, so email attachments - triple check from who the email came from, do you absolutely trust the sender? Generally text documents, images, spreadsheats are less likely to harm your computer, but you have to be able to distinguish between a program attachment and say image attachment before opening it. The good news is that most of the modern public email providers such as yahoo, gmail, gmx have built in virus scanners that scan the emails before you get them, but you can never be sure. So again, its all about trusting the sender of the email. Email viruses are I guess about 30%... or whateva% of virus threat for average internet user. The less common but yet very dangerous way of getting your computer sick is getting it infected from a flash drive or a CD that has been on someone else's computer. If the cd/usb flahs drive/memmory card is not your's, someone else has written on them than its better not to put em into your computer. Pictures/videos/audio are generally safe to copy from these, but the problem is that unlike with email attachments the virus can be sort of invisible for an unnarmed eye, they can be invisible, hidden, or affect your windows system before anyone knows it. I would probably be OK with a memmory card from friend's photo camera, but I would double check their flash drive with an antivirus before opening it. That's anothether 10%  of virus threats, and the last but not least are the viruses that spread through the local network, such as your home network or your office network, not the internet. The only good way to protect against these is to have your system firewall running. Just google "windows XYZ firewall" and learn how to check if it's on.

How to defend against viruses/malware/spyware etc.
1) Have your Windows updated! I can't stress enough how important is this. Always do windows updates whenever it asks you. Oh and if your are still on Windows XP or older then just forget about it... I know Windows XP is still corporate standard (as of December 2011) at many companies but really its just too old already. Move on to Windows 7. 
2) Have your Internet browser updated! Ok so unlike Windows which is preconfigured to run updates automatically your main favourite internet browser might not be, so check once in a while if your are running the latest version.
3) Have your every-day frequently running software updates. Such as office programs, email-client, instant messanger etc. 
4) Have a free decent antivirus program installed on your computer. Why free? well because since you are reading this article you are probably someone I care about so, I wouldn't want you to waste your money on something useless that just makes your computer run  2 times slower. As of today my recomendations are: Microsoft Security Essentials or Avast! There are plenty of other good ones but these two happend to be my favourites.
5) Have an emergency malware wiper instelled on your computer. Ok so antivirus protects your computer by constantly scanning it and tracking all programs you are using in real time, and surprise - it misses sometimes. So your computer gets infected and your antivirus is unaware. There are other sorts of protection software that specialize in quick scanning and recovering your system in on-demand fashion. Now go get Malwarebytes. The free version is all you need, just run whenver your computer is in trouble or you suspect it's been infected. 

Wednesday, March 2, 2011

Getting unique ids of Android device

Pretty simple and generally painless. If device is a phone you can get
  • IMEI number
  • Phone number
  • Subscriber id
  • SIM card's serial id
If its not a phone, the only other sensible thing to do is to get the MAC address of the WiFi. And here is the code:

  String infos = "";
  TelephonyManager tManager = (TelephonyManager)this.getSystemService(Context.TELEPHONY_SERVICE);
  infos+= "Device ID"+tManager.getDeviceId()+"\n";
  infos+= "Phone Number"+tManager.getLine1Number()+"\n";
  infos+= "SIM Serial Number"+tManager.getSimSerialNumber()+"\n";
  infos+= "Subscriber ID"+tManager.getSubscriberId()+"\n";
  WifiManager wifiMan = (WifiManager) this.getSystemService(
  WifiInfo wifiInf = wifiMan.getConnectionInfo();
  infos+= "WiFi MAC: "+ wifiInf.getMacAddress()+"\n";
  Toast t=Toast.makeText(this, infos, Toast.LENGTH_LONG);;

And of course the following permissions have to be added to the manifest:

Tuesday, February 22, 2011

File upload in through WebView on Android

Getting <input type="file" /> to work on Android in WebView of custom app is pain, but doable. I have googled for hours and found nothing about this, eventually I got Android's stock browsers source from their git repository, and found out they are using undocumented method of WebCrhomeClient to support this functionality. Note this method is hidden with @hide annotation which means it is not supposed to be used. It works well on 2.2 and 2.3, and I had limited success on 2.1. So here is the code which should give you idea:

public class MyAwesomeActivity extends Activity {
 private WebView wv;
 private ValueCallback<Uri> mUploadMessage;
 private final static int FILECHOOSER_RESULTCODE=1;
 protected void onActivityResult(int requestCode, int resultCode,
                                    Intent intent) {
   if (null == mUploadMessage) return;
            Uri result = intent == null || resultCode != RESULT_OK ? null
                    : intent.getData();
            mUploadMessage = null;
 public void onCreate(Bundle savedInstanceState) {

  wv = new WebView(this);
  wv.setWebViewClient(new WebViewClient());
  wv.setWebChromeClient(new WebChromeClient()
         //The undocumented magic method override
         //Eclipse will swear at you if you try to put @Override here
         public void openFileChooser(ValueCallback<Uri> uploadMsg) {
          mUploadMessage = uploadMsg;
          Intent i = new Intent(Intent.ACTION_GET_CONTENT);
          MyAwesomeActivity.this.startActivityForResult(Intent.createChooser(i,"File Chooser"), FILECHOOSER_RESULTCODE);


Edit (response to comments): 

Since there are still so many people interested in implementing this, and I am not very often on here, I'll try to respond the comments here:

1) I don't have a full code package with this that I can share. I don't do Android development lately (unfortunately) so I don't even have eclipse on my workstation at moment. Maybe I will do that some day. But I can assure you that this snippet worked and the apps I developed using this technique are still on the market.

2) Step by step process? Probably not... If you dig basics of how Activities and Intents work this code should be pretty self explanatory.

3) I am not 100% sure what file types would work using this technique. I used it for images only. I assume that everything that would work through the Browser app should work through here as well. Try experimenting with the types, follow the standards. Most likely the problem is on the web-server end rather than on Android, you could use Wireshark to see what's really going on.

4) The warning about openFileChooser never used locally is normal, in fact I'm pretty sure it is supposed to give you the warning. If it's not working out for you the problem is somewhere else.

5) I'd be surprised it'd work out of box on honeycomb. There is no source code for honeycomb available as far as I know so I guess no way to check out how the Browser app does it there. But the SDK is still available and someone with reverse engineering skills could quickly determine what methods are they calling there and give it a try.

Wednesday, May 12, 2010

Little Distraction: Knight vs Keypad

Last night I was browsing posted projects one of freelance programming website and I came across one project which they described as "classical knight problem." These was very interesting for me, because I have never solved a problem like this, nor I had a clue how to solve it. So I started from scratch and went till the very end without looking up previous solutions. I like to learn things this way. On top of it the guy offered $250 for this program, which would be an awesome bonus. Briefly the problem is to calculate all possible combination of code for a security keypad where the keys each next key-press has to be a 'knight-move' from previous key. Someone with solid knowledge in discreet math would probably recognize the algorithm right away, but I didn't which made it even more interesting. One of the requirements was that the program hast to be in C# .Net 2.0, so I couldn't take advantage of LINQ, which didn't really affect the process.  So I will write here how I solved this problem.... Btw I just drew the knight figure above which was lots of fun... he the 1337 keypad bruteforcer knight!

  • We can move on the keypad only in 'knight-moves' ie., 2 keys vertically and 1 key horizontally, or 2 keys horizontally and 1 key vertically.
  • We can start from any key
  • Length of the key-code is 10 keys
  • Only 2 vowels allowed in each key-code
  • Layout of the keypad is the picture on the right
  • ***********************************
  • FIND all possible key-codes
Understanding the problem:

So whats going on? Nothing really complicated... we get to start from any key, and for each key we get a set of keys where we can move next. So the problem is to walk each possible knight route with length 10, and of course we have to check that the route is valid in terms of our rules, which in this case is that it contains no more than 2 vowels. From now on I will refer to the keypad as a 'board', and the keys will be 'cells', and the key-presses will be 'moves', I guess its little more intuitive in chess terms.

So first of all it would be cool to get the set of possible moves foe each cell. We can see clearly that for A the set will be {L, H}, for B it will be {I, M, K} for M {F, B, D, J} and so on... I have no idea what would be the most efficient way to set up the data structures for this, but my choice was following: values of cells namely A,B,C...3 as strings; the sets of values like List, and the association of each key with the set Dictionary>. Ok... so now with this setup in order to solve the problem we will have to walk the dictionary in following manner: for each key in the dictionary -> take the key and add to sequence then for each value in subset(list) take the value add to sequence and that's the next key so take the subset and do the same for each value until we get a sequence of length 10... once we got it we check if it matches the condition of 2 vowels if so then this sequence is a solution. Smells like a recursion... be we haven't got there yet :P

Design of the program

Ok so lets stop the math/structure nonsense and start program design :D

Like any programmer that wants to be a good programmer I wanted to design this program to be bit more abstract... so we can solve for any kind of board and any rule of moves. So my approach in design was to write following classes and structures:

  • Cell2D - just a pair of  x,y coordinates.
  • Board - encapsulates our values and their coordinates on the board, provides means to access values by given coordinates, determine if coordinates, or a cell is a valid cell for this board, provides means to access the coordinates(cell) of the a value. (Important, I assume that there are no duplicate values)
  • Figure - and abstract class for a figure... it encapsulates the position of the figure on the board, and what most important the moves of a figure.
  • Knight - a concrete implementation of knight figure. (Inherits figure)

Ill start with implementation of classes, and then the solution calculation routine will follow.

Cell2D structure is pretty simple
struct Cell2D
        public int X;
        public int Y;

        public Cell2D(int c1, int c2)
            X = c1;
            Y = c2;

The Board class is little more complex. Some notes:
Constructor takes a 2 dimensional array as a parameter, and the 'empty' parameter is string which designates cells which should not be considered as part of the board.
class Board
        public int SizeX { get; private set; } //maximal width
        public int SizeY { get; private set; } //maximal height

        public string Empty { get; set; } //empty string value

        private string[,] arr;

        Dictionary < string, Cell2D > coords=new Dictionary < string, Cell2D >();

        public Board(string[,] Array, string emptyCellString="")
            arr = Array;

            SizeX = arr.GetLength(0);
            SizeY = arr.GetLength(1);
            Empty = emptyCellString;


        private void buildCoords()
            for(int i=0 ; i< SizeX ;i++)
                for (int j = 0; j < SizeY; j++)
                    Cell2D cel = new Cell2D(i, j);
                    if (IsValid(cel))
                        coords.Add(GetValue(cel), cel);


        public bool IsValid(int x, int y)
            if ((x < 0) || (y < 0))
                return false;
            if (arr == null)
                return false;
                return false;
                return false;

            return true;


        public bool IsValid(Cell2D cell)
            return IsValid(cell.X, cell.Y);

        public string GetValue(int x, int y)
            if (IsValid(x, y))
                return arr[x, y];
                throw new System.ArgumentOutOfRangeException();

        public string GetValue(Cell2D cell)
            return GetValue(cell.X, cell.Y);

        public Cell2D GetCoords(string value)
            Cell2D cel=new Cell2D();
            if (coords.ContainsKey(value))
                cel = coords[value];
            return cel;

As you can see a Figure takes a Board parameter, and initial position of the figure on the board. List of delegates to encapsulate figure moves here is something I pride myself... this way for each concrete implementation we just can write functions for all possible kinds of moves.

abstract class Figure
        protected delegate Cell2D Move(Cell2D position);

        private Board myBoard;

        protected List < Move> moves=new List < Move>();

        public Cell2D Position{get;set;}

        public Figure(Board board, Cell2D position)
            this.Position = position;
            myBoard = board;

        public Figure(Board board, int x, int y)
            this.Position = new Cell2D(x,y);
            myBoard = board;

        public List < string> AvailableMoves()
            List < string> list=new List < string>();
            foreach (Move m in moves)
                Cell2D cell = m(Position);
            return list;

        protected abstract void SetMoves();

And here is the Knight class... notice the delegates to anonymous methods. Basically moves are functions, which take the current position of the figure and return a cell where the figure can be moved. Clearly one way to improve this is to allow each move function to return a set of cells. After all all that routine could be done by one function call I guess... but I believe this strategy is better.

class Knight: Figure
    public Knight(Board board,Cell2D cell)
            : base(board, cell)

    public Knight(Board board, int x, int y)
            : base(board, x, y)

    protected override void SetMoves()
      moves.Add(delegate(Cell2D cel){return new Cell2D(cel.X+1,cel.Y+2);});
      moves.Add(delegate(Cell2D cel){return new Cell2D(cel.X+2,cel.Y+1);});
      moves.Add(delegate(Cell2D cel){return new Cell2D(cel.X+2,cel.Y-1);});
      moves.Add(delegate(Cell2D cel){return new Cell2D(cel.X+1,cel.Y-2);});
      moves.Add(delegate(Cell2D cel){return new Cell2D(cel.X-1,cel.Y-2);});
      moves.Add(delegate(Cell2D cel){return new Cell2D(cel.X-2,cel.Y-1);});
      moves.Add(delegate(Cell2D cel){return new Cell2D(cel.X-2,cel.Y+1);});
      moves.Add(delegate(Cell2D cel){return new Cell2D(cel.X-1,cel.Y+2);});

So that much for the design...

Now the actual program

string[,] arr = { {"A","B","C","D","E"},
                  {"","1","2","3",""} };
Board myBoard = new Board(arr, "");
Knight myKnight = new Knight(myBoard, new Cell2D(0, 0));
TimeSpan ts = new TimeSpan();
DateTime startTime;
TextWriter tw = new StreamWriter("knight.txt", false);
startTime = DateTime.Now;
prinTheValidSequencesFile(myBoard,myKnight,tw); //does the calculations
ts = DateTime.Now - startTime;
tw.WriteLine("Execution time: {0} min {1} sec {2} millisec", ts.Minutes, ts.Seconds,ts.Milliseconds);

The following method builds the dictionaries of possible moves and calls the recursive function sequencerFile that actually creates the sequences of possible moves.
static void prinTheValidSequencesFile(Board board, Knight knight,TextWriter wt)
 Dictionary < string, List < string > > dic = new Dictionary < string, List < string > >();

 int count = 0;

 for (int i = 0; i < board.SizeX; i++)
    for (int j = 0; j < board.SizeY; j++)
            if (board.IsValid(i, j))
                knight.Position = new Cell2D(i, j);
                List < string > moves = knight.AvailableMoves();
                dic.Add(board.GetValue(i, j), moves);



  foreach (KeyValuePair < string, List < string> > pair in dic)
      sequencerFile(dic, 0, new List < string > (), pair.Key, ref count,wt);

  wt.WriteLine("Total count: " + count);

So here it is the magic recursive method that pretty much does the job. Notice it calls checkSequence which checks if the sequence is valid and outputs to a file
static void sequencerFile(Dictionary < string, List < string > > dic, int depth, List < string > sequence, string key, ref int count,TextWriter writer)


            if (depth == 9)
                if (checkSequence(sequence))
                    foreach (string s in sequence)
                    writer.Write(s + " ");

            foreach (string s in dic[key])
                sequencerFile(dic, depth + 1, new List < string>(sequence), s, ref count,writer);


And the last but not the least important method to check for valid sequence. All we have to do here is to check that the sequence doesn't contain more than 2 vowels
int Count=0;
            foreach (string s in seq)
                if ((s == "A") || (s == "E") || (s == "I") || (s == "O"))

            //var i = (from x in seq where (x == "A" || x == "E" || x == "I" || x == "O") select x).ToList();
            if (Count > 2)
                return false;
                return true;

The Result

The result is a 21 megs large file which contains all possible combinations that match the requirements. Also the number of those combinations and the time it took to run... here they are:

Total count: 1013398
Execution time: 0 min 2 sec 702 millisec

I just hope I got it all right :D

Performance-wise ~3 secs IMHO is ok for this problem, however it can be drastically improved utilizing multithreading. My guess is that it would do in half of this time if we'd launch 4 threads each of them doing the recursive routine... the only problem there is to remember about 1 mb stack size limit...


The code clearly needs some heavy re-factoring... and design can use some enhancement. To be honest I have no plans on working on it... it was just a small experiment. The program was written by a n00b programmer in 3 hours all I can say. Funny thing is that I just spent more time writing this post than actually writing the program... makes me double question why in the world do I do this blogging.

However any comments are welcome... if there are some mistakes on my side I'm willing to fix those. If someone needs the whole source code, just let me know Ill upload the VS project somewhere. If you need to help understanding the code again just let me know.


I never got any money for this project D: but I still enjoyed wasting my time on it ;)

Friday, May 7, 2010

Day 1

Preface to definition of the program

     Last night lecture at physics class was quite slow, so I did some brainstorming on paper and came up with an idea for the program. As I said in "The begging," I was looking for something useful. One thing that always been annoying me working in windows is the repetitive traversal or browsing of folders or directories to access files spread around the computer. Some people like to use special programs like "Explorer" or "Windows Commander" or even in command prompt or shell when working with the file-system, but the thing is when I am not actually working on the computer I like to be in comfort... I like clicking, drag and dropping... easy approaches. Some create tons of shortcuts to folders on their desktop, but I like to keep my desktop clean and nice. So I ended up thinking in dashboard/toolbar style direction. It will be more clear when Ill define it more technically. Yeah and the pic above is the great sketch in my notepad. Now you can tell I'm not and artist.
Definition of the program.

    The program will consist of a main window and a windows tray icon. The main window will allow to drag and drop folders, files, hyperlinks and plain text on it. For any of those it will generate a specific icon. Dashboard window will have a nice toolbar that will allow to create, switch and select tabs/pages.  All tabs and entries are saved. The window itself will be draggabable, resizeable, and what is most important dockable so that the user can attach it to sides of the screen. Clicking on the windows tray icon will show the main window on top of all windows or will hide it.
   So far Ill stick with folders and files only. Clicking on these will open them as if they were links. Also when holding the mouse over the certain part of a folder element it will populate a sub-window with the contents of that folder, similar to how windows Start worked in Windows XP. This behavior should persist for the sub-windows as well.

   The toolbar will have buttons to add add and remove tabs, switch between these, pin/keep on top button and options button which will pop up configuration window. I want to keep the main window as simple as possible.

    Right click on the main window will populate a context menu, something like
  • Add
  • Configure
  • Hide
  • About
  • Quit
    Same kind of(maybe exactly the same) menu will pop up when right clicking the task-bar icon.

   For now Ill stick with creating rather simple interface, but later on I want to make it customizable... For example letting user to customize how many rows or columns of elements they want... list layout or item layout... maybe even allowing them to set it look like the Mac OS dashboard as a option. Also I want to make it skinnable later on.

   One last thing.... the name of the program will be "instaLink"... just cause I want so.

   So the way I want to proceed with this is that first Ill build up the UI(user interface) in WPF(windows presentation foundation), then Ill add the business logic, and then... then Ill try to add all cool customization features. Next post will cover the whole process of building the user interface.