Tuesday, December 14, 2010

Internet's Long War...

While reading an article about WinAmp availability on Android phone this morning, suddenly Napster came to my mind. Did a Google News search for Napster and found lot of articles about internet wars that happened recently. Of all the links, the most interesting one was an article by Tim Hwang from The Washington Post titled WikiLeaks and the Internet's Long War.

He (Tim Hwang) did an easy to understand summary about the series of battles between "Anonymous" and the establishment. It makes me interested to read more about the topic.

It started with the history of open source against the proprietary software

"In the early 1980s, Richard Stallman, then an employee at MIT's artificial-intelligence lab, was denied permission to access and edit computer code for the lab's laser printer. Frustrated, he kicked off what he calls GNU, a massively collaborative project to create a free and sharable operating system. His efforts sparked a widespread movement challenging the restriction of access to software through patents. Supporters asserted that they had a right to control the code in their own computers."

Then the story about Napster

"Another major milestone in the conflict arose in 1999, when Shawn Fanning launched Napster, allowing for seamless peer-to-peer sharing of content. The service ballooned, claiming more than 25 million users at its peak and resulting in mountains of copyrighted content flowing freely across the Web. The site was sued and shut down in 2001. However, the ensuing battle over copyright law drew a line between industry representatives, such as the Recording Industry Association of America, and the "hacker" advocates for the free flow of content."

Napster was forced down but then BitTorrent emerged

"Large-scale use of this technology emerged in 2003 in the form of the Pirate Bay, which indexes BitTorrent files en masse. The site's founders and operators, Gottfrid Svartholm Warg, Carl Lundstrom, Fredrik Neij and Peter Sunde, would emerge as the Assanges of this battle, permitting a massive and continuous leak of copyrighted content in the face of waves of police raids and lawsuits - persisting even beyond their eventual conviction on infringement charges in 2009."

And now, the WikiLeaks

"The WikiLeaks fight is in the tradition of these conflicts, just on a much vaster scale. As the Internet has become an integral part of our everyday lives, narrow and technical questions about who gets to run and edit computer code have morphed first into battles over copyrighted content, and now into fights at the highest levels of government secrecy and corporate power."

We'll see how this war will shape the internet in the future.

WinAmp is now an Android app...

There's no question that iTunes dealt some heavy blows to WinAmp over the years. But with a new Android app that aims to manage music between the smartphone and a computer, perhaps it's time for WinAmp to make a comeback.

WinAmp for Android is out of beta, TechCrunch reports. In addition to music playback and download management, the MP3 player now supports wireless syncing to the desktop and Shoutcast radio stations.

In fairness, WinAmp hasn't been living in total obscurity. It currently has 60 million users, says TechCrunch, but only 5 percent of them are in the United States. This was once the most popular program for listening to MP3s.

Click here for more and here for review.

Tuesday, November 23, 2010

Mike Galbraith's Linux kernel patch that does wonders...

Last week I came across a blog post "The Linux desktop may soon be a lot faster" by Steven J. Vaughan-Nichols. It's about the patch done by Linux kernel developer Mike Galbraith who adds a mere 233 lines of code to the kernel's scheduler that cuts desktop latency down by a factor of ten. Even Linus Torvalds himself praised the performance boost he gets from the patch.

Two days later, another post appear on Google News. Alternative To The "200 Lines Kernel Patch That Does Wonders" Which You Can Use Right Away by Andrew. Lennart Poettering, a RedHat developer replied to Linus Torvalds on a maling list with an alternative to this patch that does the same thing yet all you have to do is run 2 commands and paste 4 lines in your ~/.bashrc file.

Everybody seems excited with the improvement. As for the champ at the bit, they've started implement the workaround and I believe some even recompile the kernel with the patch. Wow!!!

Sunday, November 21, 2010

Customizing plymouth login screen background, fonts and gtk...

1) Open terminal, copy and paste the following command.
    $ sudo cp /usr/share/applications/gnome-appearance-properties.desktop /usr/share/gdm/autostart/LoginWindow
2) Close terminal and log out. Once at login screen you'll see an Appearance pop up. Make your changes and log in.

3) Now to disable Appearance pop up from login screen. Open terminal, copy and paste the following command.
    $ sudo unlink /usr/share/gdm/autostart/LoginWindow/gnome-appearance-properties.desktop
Note :
Tested on Ubuntu 10.04 and Linux Mint 10.

Monday, November 15, 2010

First Ubuntu and now Fedora, dumping X for Wayland...

When I first read about the news, as normal user I can't really tell what impact might hit to people like me. My understanding, it seems like there's a claim that X is too complicated, too slow, too filled with archaic junk and so on. That trigger the movement from X to Wayland, an OpenGL-based display management system.

I'm more concern about the apps that I love to use on Linux, because to run natively on Wayland it needs to be ported. Otherwise, it is stated that:
"If they don't, you can run a nested X server like on OSX. They'll still work as well as they ever did, and you even get to keep ssh [Secure Shell] forwarding of them. You can run a wayland server that does nothing but run a nested X server and you wouldn't ever know the difference."

Questions in my head:
  • How long will it take for all apps to get ported?
  • If need to run a nested X server, do I need to configure it myself?
  • With the hassle on the ported part (by developers of course) so that all apps can run natively on Wayland, is it going to improve graphical performance tremendously?
  • Since it is an OpenGL-based, is it going to improve gaming experience as well?

Changes are good but at what stake? If I hate to change, hell I'll just stick with Windows for the rest of my life. I don't mind learning, the advantages of using Linux are too enormous to be ignore. But if the change is too huge for me, I guess I'll stay on the safe side by reading more experience story by others. I'll do my best to avoid running a nested X server on Wayland because if I did that I personally feel it beats the purpose of the transition in the first place.

Sunday, November 14, 2010

Sharing html table with sum formula that works on Excel and web page...



I'm in a situation where I need to include Excel SUM formula when exporting data from html. Questions raised in my head. What's the purpose of exporting it to Excel in the first place? It gives us the ability to manipulate data with whatever formulas available in Excel. Then why do we want to have it in html? I have no idea but at least I've found a way that I won't need to generate it twice. That matters to me.

Here's the trick. When generating an html, add the id to the cell that needs to be calculate exactly like cell in Excel. As for the cell with the sum value, add css class to it (doesn't need to be exist in css, it's just for the sake of searching later on).
<table>
        <thead>
            <th>header 1</th>
            <th>header 2</th>
            <th>header 3</th>
            <th>total</th>
        </thead>
        <tr>
            <td id='A2'>1</td>
            <td id='B2'>2</td>
            <td id='C2'>3</td>
            <td id='D2' class='sum'>=SUM(A2,B2,C2)</td>
        </tr>
        <tr>
            <td id='A3'>4</td>
            <td id='B3'>5</td>
            <td id='C3'>6</td>
            <td id='D3' class='sum'>=SUM(A3,B3,C3)</td>
        </tr>
        <tr>
            <td id='A4'>7</td>
            <td id='B4'>8</td>
            <td id='C4'>9</td>
            <td id='D4' class='sum'>=SUM(A4,B4,C4)</td>
        </tr>
        <tr>
            <td class='sum'>=SUM(A2,A3,A4)</td>
            <td class='sum'>=SUM(B2,B3,B4)</td>
            <td class='sum'>=SUM(C2,C3,C4)</td>
            <td class='sum'>=SUM(D2,D3,D4)</td>
        </tr>
    </table>
Now if you copy the html above, paste it into a notepad and save it to .xls. You'll get an Excel sheet with calculated value based on the SUM formula provided. But then of course the formula won't work on the web site. You'll see table like shown below.

Demo

header 1 header 2 header 3 total
1 2 3 =SUM(A2,B2,C2)
4 5 6 =SUM(A3,B3,C3)
7 8 9 =SUM(A4,B4,C4)
=SUM(A2,A3,A4) =SUM(B2,B3,B4) =SUM(C2,C3,C4) =SUM(D2,D3,D4)


This is where JQuery come in handy. The logic,
  • Search for all the elements that has 'sum' class
  • Convert the formula into something that is understandable by JQuery
  • Loop through the elements and change the value from formula into calculated value
$(document).ready( function() {
        // search the elements that has 'sum' class
        $('.sum').each(function() {
            // convert the formula from =SUM(A2,B2,C2) into #A2,#B2,#C2
            var formula = convert($(this).html());
            var total = 0;

            $(formula).each(function() {
                total += parseInt($(this).html());
            });

            // replace with calculated value
            $(this).html(total);
        });
    });
    
    // converting from =SUM(A2,B2,C2) into #A2,#B2,#C2
    function convert(formula)
    {
        var newform = formula.substring(formula.indexOf("(") + 1, formula.indexOf(")"));
        var arrayform = newform.split(",");
        return "#" + arrayform.join(",#");
    }
JQuery save the day...again...

Friday, November 12, 2010

Converting int to base26 string in C#...

For my own reference.
    public string ToBase26(int number)
    {
        char[] base26 = { 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z' };

        int remainder = number % base26.Length;
        int value = number / base26.Length;

        return value == 0 ?
            String.Format("{0}", base26[remainder]) :
            String.Format("{0}{1}", ToBase26(value - 1), base26[remainder]);
    }
Alternatively I can code it this way
    public string ToBase26(int number)
    {
        if (number < 0) return String.Empty;

        int remainder = number % 26;
        int value = number / 26;

        return value == 0 ?
            String.Format("{0}", Convert.ToChar(65 + remainder)) :
            String.Format("{0}{1}", ToBase26(value - 1), Convert.ToChar(65 + remainder));
    }

Wednesday, November 10, 2010

Highlighting table row on mouse over using JQuery...



<table border='0'>
        <thead>
            <tr>
                <th>head 1</th>
                <th>head 2</th>
                <th>head 3</th>
            </tr>
        </thead>
        <tbody>
            <tr>
                <td>data 1</td>
                <td>data 2</td>
                <td>data 3</td>
            </tr>
            <tr>
                <td>data 1</td>
                <td>data 2</td>
                <td>data 3</td>
            </tr>
            <tr>
                <td>data 1</td>
                <td>data 2</td>
                <td>data 3</td>
            </tr>
            <tr>
                <td>data 1</td>
                <td>data 2</td>
                <td>data 3</td>
            </tr>
        </tbody>
    </table>
Demo

head 1 head 2 head 3
data 1 data 2 data 3
data 1 data 2 data 3
data 1 data 2 data 3
data 1 data 2 data 3

Piece of cake...
$(document).ready( function() {
        $('tbody tr').hover(
            function() { $(this).css('background', '#cecece'); },
            function() { $(this).css('background', '#ffffff'); }
        );
    });

Monday, November 8, 2010

Managing distributed transactions without enabling MSDTC...

Is it possible? Short answer is no. Long answer is yes, but only to certain extend. Another stupid attempt to solve problem in a situation where developers are the lowest being in the organisation. In the perfect world where things working as expected, dealing with distributed transaction is a snap.
    ...
    using(TransactionScope scope = new TransactionScope())
    {
        using (SqlConnection conn1 ...)
        {
            ...
        }

        using (OracleConnection conn2 ...)
        {
            ...
        }

        scope.Complete();
    }
    ...
However the nightmare begin when your Server/DB admin give you a big "NO" to MSDTC but the other party insisted for data rollback if anything goes wrong during the process. So what I did was to create my own transaction manager class. Before I begin, I need to have a wrapper class that contain a connection and transaction objects, this is where the begintransaction happen. The class will be manage by the transaction manager. Technically it's just managing a group of local transactions.
    using System;
    using System.Data;
    
    public class EnlistedDBConnection : IDisposable
    {
        private IDbConnection _connection;
        private IDbTransaction _transaction;
        
        public IDbConnection Connection
        {
            get { return _connection; }
        }
        
        public IDbTransaction Transaction
        {
            get { return _transaction; }
        }
        
        public EnlistedDBConnection(IDbConnection connection)
        {
            _connection = connection;
            
            if (_connection.State == ConnectionState.Closed) _connection.Open();
            _transaction = connection.BeginTransaction();
        }
        
        internal void Commit()
        {
            _transaction.Commit();
        }
        
        internal void Rollback()
        {
            _transaction.Rollback();
        }

        #region IDisposable Members

        public void Dispose()
        {
            if (_connection != null && _connection.State == ConnectionState.Open) _connection.Close();
            if (_connection != null) _connection.Dispose();
            if (_transaction != null) _transaction.Dispose();
        }

        #endregion
    }
Code for the transaction manager. Before commiting, I need to ensure all connections are alive, if any of it down, cancel everything. However there's still one worst case scenario that this code couldn't handle, after done with connection checking, while committing suddenly one connection down in the process. It is not possible to rollback the committed transaction. So chances for orphan data are still there.
    using System;
    using System.Data;
    using System.Collections.Generic;
    
    public class BasicTransactionManager : IDisposable
    {
        private bool _isCommited;
        private List<EnlistedDBConnection> _enlistedConnections;
    
        public BasicTransactionManager() : this(new List<EnlistedDBConnection>())
        {
        }
        
        private BasicTransactionManager(List<EnlistedDBConnection> enlistedConnections)
        {
            _enlistedConnections = enlistedConnections; 
        }
        
        public EnlistedDBConnection Enlist(IDbConnection connection)
        {
            EnlistedDBConnection item = new EnlistedDBConnection(connection);
            _enlistedConnections.Add(item);
            
            return item;
        }
        
        public void Complete()
        {
            Commit();
        }
        
        /// 
        /// While in the loop, worst case scenario that this logic couldn't handle is that
        /// if the first transaction committed, then the second one failed, chances for orphan data
        /// to occur are there because we couldn't rollback something that has been commited.
        /// 
        private void Commit()
        {
            // if one of the db connection failed, cancel everything
            if(!VerifyConnection()) throw new Exception("DB connection failed.");
            
            string message = String.Empty;
            foreach (EnlistedDBConnection enlistedConnection in _enlistedConnections)
            {
                try
                {
                    enlistedConnection.Commit();
                }
                catch(Exception ex)
                {
                    message += String.Format("{0}\r\n", ex.Message);
                }
            }
            if(!String.IsNullOrEmpty(message)) throw new Exception(message);
            
            _isCommited = true;
        }
        
        private void Rollback()
        {
            string message = String.Empty;
            foreach (EnlistedDBConnection enlistedConnection in _enlistedConnections)
            {
                if(enlistedConnection.Connection != null && enlistedConnection.Connection.State == ConnectionState.Open)
                {
                    try
                    {
                        enlistedConnection.Rollback();
                    }
                    catch (Exception ex)
                    {
                        message += String.Format("{0}\r\n", ex.Message);
                    }
                }
            }
            if (!String.IsNullOrEmpty(message)) throw new Exception(message);
        }
        
        private bool VerifyConnection()
        {
            bool _allOpened = true;
            
            foreach(EnlistedDBConnection enlistedConnection in _enlistedConnections)
            {
                if(enlistedConnection.Connection == null || enlistedConnection.Connection.State != ConnectionState.Open)
                {
                    _allOpened = false;
                    break;
                }
            }
            
            return _allOpened;
        }

        #region IDisposable Members

        public void Dispose()
        {
            if (!_isCommited) Rollback();
            
            _enlistedConnections.ForEach( delegate(EnlistedDBConnection item) { item.Dispose(); } );
            // _enlistedConnections.ForEach( item => item.Dispose() );
        }

        #endregion
    }
This is how I use it in my business object. EnlistedDBConnection exposed connection and transaction property. That's how I obtain the instance and pass it to Command object.
    using (BasicTransactionManager transaction = new BasicTransactionManager())
    {
        EnlistedDBConnection dbcon1 = transaction.Enlist(/* your db connection object */);
        EnlistedDBConnection dbcon2 = transaction.Enlist(/* your db connection object */);

        ...

        transaction.Complete();
    }
Note:
This solution is not by any mean to be a replacement to MSDTC (not even in your wet dream). However, it is better to have something rather than nothing. I'd rather use this solution instead of executing another command to undo the changes manually which I feel ridiculous.

Saturday, November 6, 2010

JQuery pluggins summary and best practices...

Writing jQuery plugins allows you to make the most out of the library and abstract your most clever and useful functions out into reusable code that can save you time and make your development even more efficient. Here's a brief summary of the post and what to keep in mind when developing your next jQuery plugin:
  • Always wrap your plugin in (function( $ ){ // plugin goes here })( jQuery );
  • Don't redundantly wrap the this keyword in the immediate scope of your plugin's function
  • Unless you're returning an intrinsic value from your plugin, always have your plugin's function return the this keyword to maintain chainability.
  • Rather than requiring a lengthy amount of arguments, pass your plugin settings in an object literal that can be extended over the plugin's defaults.
  • Don't clutter the jQuery.fn object with more than one namespace per plugin.
  • Always namespace your methods, events and data.
  • jQuery.fn is pronounced jQuery effin'

Monday, November 1, 2010

Compress and Decompress text using System.IO.Compression...

I'm lazy today. This code was copied directly from internet for my personal reference.
    using System;
    using System.Text;
    using System.IO;
    using System.IO.Compression;

    public static class GZipStreamUtility
    {
        public static string Compress(string text)
        {
            if (String.IsNullOrEmpty(text)) return String.Empty;

            byte[] buffer = Encoding.UTF8.GetBytes(text);
            MemoryStream ms = new MemoryStream();
            using (GZipStream zip = new GZipStream(ms, CompressionMode.Compress, true))
            {
                zip.Write(buffer, 0, buffer.Length);
            }

            ms.Position = 0;
            MemoryStream outStream = new MemoryStream();

            byte[] compressed = new byte[ms.Length];
            ms.Read(compressed, 0, compressed.Length);

            byte[] gzBuffer = new byte[compressed.Length + 4];
            System.Buffer.BlockCopy(compressed, 0, gzBuffer, 4, compressed.Length);
            System.Buffer.BlockCopy(BitConverter.GetBytes(buffer.Length), 0, gzBuffer, 0, 4);

            return Convert.ToBase64String(gzBuffer);
        }

        public static string Decompress(string compressedText)
        {
            if (String.IsNullOrEmpty(compressedText)) return String.Empty;

            byte[] gzBuffer = Convert.FromBase64String(compressedText);
            using (MemoryStream ms = new MemoryStream())
            {
                int msgLength = BitConverter.ToInt32(gzBuffer, 0);
                int length = gzBuffer.Length - 4;
                ms.Write(gzBuffer, 4, length);

                byte[] buffer = new byte[msgLength];

                ms.Position = 0;
                using (GZipStream zip = new GZipStream(ms, CompressionMode.Decompress))
                {
                    zip.Read(buffer, 0, buffer.Length);
                }

                return Encoding.UTF8.GetString(buffer);
            }
        }
    }

Friday, October 29, 2010

Retrieving checkboxes values using JQuery...

I have an html like this in my page
    ...
    <div id="container1">
        <input type="checkbox" value="1" /> a
        <input type="checkbox" value="2" /> b
        <input type="checkbox" value="3" /> c
        <input type="checkbox" value="4" /> d
        <input type="checkbox" value="5" /> e
        <input type="checkbox" value="6" /> f
    </div>

    <div id="container2">
        <input type="checkbox" value="11" /> a1
        <input type="checkbox" value="12" /> b1
        <input type="checkbox" value="13" /> c1
        <input type="checkbox" value="14" /> d1
        <input type="checkbox" value="15" /> e1
        <input type="checkbox" value="16" /> f1
    </div>
    <input id="mybutton" type="button" value="click me" />
    ...

Demo

container1
a b c d e f

container2
a1 b1 c1 d1 e1 f1

result


Now what I want is, whenever I click the button I want to retrieve all the values from the checked checkboxes. This is pretty easy in JQuery. Here's how my JS will look like
    ...
    $("#mybutton").click( function() {
        var myarray = [];
        
        $('input:checkbox:checked').each( function() {
            myarray.push($(this).val());
        });
        
        alert(myarray.join(', '));
    } );
    ...
What if I want it only from the first <div>? I just need to pass context to the selector
    ...
    $("#mybutton").click( function() {
        var myarray = [];
        
        // passing container1 as context to selector
        $('input:checkbox:checked', '#container1').each( function() {
            myarray.push($(this).val());
        });
        
        alert(myarray.join(', '));
    } );
    ...
JQuery makes my life a lot easier :).

Tuesday, October 26, 2010

The beauty of JQuery...

Query by element tag name
    $("div")
Query by element id
    $("#myid")
Query by css class name
    $(".css-whatever")
Query by input type
    $("input:checkbox")
Query by a set of element ids
    $("#myid1,#myid2,#myid3")
Query by input type but exclude the one with 'whatever' id
    $("input:checkbox:not(#whatever)")

Monday, October 18, 2010

Creating DBHelper that can support various types of database...

Yes I know there's a framework (EF, NH and whatever name that I've never heard before) that can solve the problem. Unfortunately, EF only works on new technologies (at least with .NET framework 3.5). What if we're stucked with an old Microsoft technologies (NH is another option, but I still couldn't figure out on how and where to begin with - ~ I ain't a .NET superstar ~)? Is it possible to do it then? Yes!!! back to basic stuff!!!

I've try it on .NET framework 2.0. IDBConnection, IDBTransaction and IDBDataParameter are available in System.Data namespace since .NET framework 1.1 however, DBDataReader in System.Data.Common was available not until .NET framework 2.0 (DBDataReader was derived by SqlDataReader, OracleDataReader and OleDbDataReader). Those are the important interfaces and class needed.

Basically we need to create an abstract layer to our db helper. Let's just call it IDBHelper. Define all basic methods that can support various databases. It's important not to have a method that is specific to any data provider such as ExecuteXmlReader.
    ...
using System.Data;
using System.Data.Common;

public interface IDbHelper
{
IDbConnection CreateConnectionInstance(string connectionString);

...

DbDataReader ExecuteReader(IDbConnection connection, string query, CommandType cmdType, params IDbDataParameter[] commandParameters);

...

IDbDataParameter CreateParam(string paramName, object paramValue);
}
For concrete implementation. Create a class that implement IDBHelper interface. I named the class as SqlClientHelper.
    ...
using System;
using System.Data;
using System.Data.SqlClient;
using System.Data.Common;

public class SqlClientHelper : IDbHelper
{
public IDbConnection CreateConnectionInstance(string connectionString)
{
return new SqlConnection(connectionString);
}

...

public DbDataReader ExecuteReader(IDbConnection connection, string query, CommandType cmdType, params IDbDataParameter[] commandParameters)
{
...
}

...

public IDbDataParameter CreateParam(string paramName, object paramValue)
{
SqlParameter param = new SqlParameter(paramName, paramValue);
...
}

...
}
Then, the code for OracleClientHelper.
    ...
using System;
using System.Data;
using System.Data.OracleClient;
using System.Data.Common;

public class OracleClientHelper : IDbHelper
{
public IDbConnection CreateConnectionInstance(string connectionString)
{
return new OracleConnection(connectionString);
}

...

public DbDataReader ExecuteReader(IDbConnection connection, string query, CommandType cmdType, params IDbDataParameter[] commandParameters)
{
...
}

...

public IDbDataParameter CreateParam(string paramName, object paramValue)
{
OracleParameter param = new OracleParameter(paramName, paramValue);
...
}

...
}
Noticed that the instantiation of connection and parameter object has been done in the class itself. Ideally, if we don't use any specific data provider namespaces in DAL layer, it should be flexible enough to use any database without the need to change the code logic. The concern is more on the abstract layer method signature.

Create an object factory that'll return the helper instance. This is the only place that we need to change if the project owner aka our client suddenly decided to use different data provider in future (reality is cruel).
    ...
public static class SomeObjectFactory
{
public static IDBHelper GetHelperInstance()
{
return new SqlClientHelper();

// uncomment the code below for oracle client
// return new OracleClientHelper();
}
}
The code at DAL
    ...
using (IDbConnection connection = SomeObjectFactory.GetHelperInstance().CreateConnectionInstance(connectionString))
{
connection.Open();

string query = "SELECT * FROM tblSomething WHERE Id = @Id";
IDbDataParameter param = MyObjectFactory.GetDBHelperInstance().CreateParam("@Id", id);

DBDataReader reader = SomeObjectFactory.GetHelperInstance().ExecuteReader(connection, query, CommandType.Text, param);

...
}
...
This way, adding System.Data and System.Data.Common namespace should be sufficient enough to our DAL.

Thursday, October 14, 2010

Creating custom event in JavaScript...

First, define custom event.
    var CustomEvent = function() {
//name of the event
this.eventName = arguments[0];
var mEventName = this.eventName;

//function to call on event fire
var eventAction = null;

//subscribe a function to the event
this.subscribe = function(fn)
{
eventAction = fn;
};

//fire the event
this.fire = function(sender, eventArgs)
{
if(eventAction != null)
{
eventAction(sender, eventArgs);
}
else
{
alert('There was no function subscribed to the ' + mEventName + ' event!');
}
};
};
Then create an event handler.
    var myEvent = new CustomEvent("helloworld event");
myEvent.subscribe(event_triggered);

function event_triggered(sender, eventArgs)
{
alert("hello world");
}
Now, the triggering part.
    ...
if(typeof(myEvent) != "undefined")
{
myEvent.fire(null, {
message: 'you just witnessed the firing of a custom event called ' + this.eventName + '!'
});
}
...

Wednesday, September 29, 2010

Removing wgatray from Windows XP...

1) Stop the process
    - To start Task Manager you need to click on the Start button and from the Start menu select 'Run' and type in 'taskmgr' command. Hit 'OK'.
    - Now you need to click the 'Processes' tab and click on the 'wgatray.exe' process.
    - After the wgatray.exe is highlighted, you have to press 'End Process' and after wgatray.exe is closed, you can close the TaskManager.

2) Delete / Remove wgatray file from your computer
    - Go to 'My Computer' and browse to both 'C > Windows > System32' and 'C > Windows > System > dllcache' folders.
    - Locate the 'wgatray.exe', right-click it and select delete.
    - Now you need to right-click on the Recycle Bin and press 'Empty the Recycle Bin', so that wgatray.exe files are completely deleted.

3) Remove entry from registry
    - Click on Start button and select Run.
    - Type in 'regedit' and hit the OK button.
    - Go to the following registry entry : 'HKEY_LOCAL_MACHINE > SOFTWARE > Microsoft > Windows NT > CurrentVersion > Winlogon > Notify'.
    - In here you have to delete the Winlogon folder.
    - Close Registry Editor and Wgatray EXE has been completely removed from your computer.

Tuesday, September 28, 2010

IE9: Microsoft reverse statement...

Question:
When Microsoft releases Internet Explorer 9, will it require Windows 7 Service Pack 1?

Old answer:
Yes. Internet Explorer 9 will require Windows 7 Service Pack 1 (SP1). Therefore, organizations must plan, pilot, and deploy Internet Explorer 9 as part of or after a Windows 7 SP1 deployment.

New answer:
No. Internet Explorer 9 will install on systems that have either Windows 7 RTM or Windows 7 with Service Pack 1 (SP1) installed.

What's next???

More info at arstechnica.com.

Bing Rewards: another attempt to increase search share...

On the heels of canceling its Bing Search Cashback program, Microsoft is trying its hand at another attempt to increase search share using rewards.

The newest program, Bing Rewards, is similar to credit card or airline loyalty programs that offer users points that can be redeemed for products, gift cards or charitable donations, Search Engine Land explained.

Points don’t come cheap, however. To participate,
1) users need to be running Windows
2) to sign up for a Windows Live ID
3) use Internet Explorer
4) and have the Bing Bar toolbar.

No other browsers or operating systems are allowed.

More info at zdnet.com.

Note:
Available for US residents only.

WordPress: default blogging platform for Windows Live...

Microsoft and WordPress.com announced Monday that WordPress will be the default blogging platform for Windows Live.

The partnership will allow Windows Live Spaces customers to upgrade to WordPress.com, let WordPress users notify friends about blog posts via Messenger, and let Windows Live users easily create new blogs on WordPress.com.

"WordPress powers over 8.5 percent of the web, is used on over 26 million sites, and WordPress.com is seen by over 250 million people every month," Microsoft said in a blog post. "So rather than having Windows Live invest in a competing blogging service, we decided the best thing we could do for our customers was to give them a great blogging solution through WordPress.com."

Microsoft currently has 30 million people using its Windows Live Spaces blogging platform. Those users can port their blog posts, comments, and photos to WordPress, and redirect their old Spaces URLs to the new blog, Microsoft said.

More info at pcmag.com.

Friday, September 24, 2010

Transparent box with non-transparent text css...

    div.box
{
/* Any properties you'd want the box to have. */
/* Would probably be position, dimension type stuff. */
border: 1px solid #000000;
width: 500px;
height: 500px;
position: relative;
}

div.box_contents
{
background-color:transparent;
height: 100%;
position: relative;
width: 100%;
z-index: 101;
}

div.box_background
{
background-color: blue;
height: 100%;
opacity: 0.5;
filter:alpha(opacity=50); /* IE's opacity */
position: absolute;
left: 0px;
top: 0px;
width: 100%;
z-index: 100;
}
Opacity effect accross browsers
    opacity: 0.5;
filter:alpha(opacity=50); /* IE's opacity */

Wednesday, September 22, 2010

Kernel exploit on 64-bit Linux...

Linux is well-known for its security advantages over many other operating systems, but that doesn't mean it's immune to problems.

A Linux kernel flaw first discovered earlier this month, for example, gives hackers a way to not just gain root privileges in 64-bit Linux operating systems but also to leave a "back door" open for further exploitation later.

CVE-2010-3081, as the high-profile vulnerability is known, affects virtually all users of 64-bit Linux distributions, including RHEL, CentOS, Debian, Ubuntu, CloudLinux, SuSE and more. It was introduced into the Linux kernel back in 2008, and a hacker by the name of 'Ac1db1tch3z' last week published details on exploiting it.

Click here for more info.

Note:
Text copied from PCWorld news.

Tuesday, September 21, 2010

Using linear gradient effect accross browsers...

    filter: progid:DXImageTransform.Microsoft.gradient(gradienttype=1, startColorstr='#739AC5', endColorstr='#ffffff'); /* for IE */
background: -webkit-gradient(linear, left center, right center, from(#739AC5), to(#fff)); /* for webkit browsers */
background: -moz-linear-gradient(left, #739AC5, #fff); /* for firefox 3.6+ */
Note:
Click here for codes and colour table.

Vulnerability in the ASP.NET encryption...

The Impact of the Vulnerability
ASP.NET uses encryption to hide sensitive data and protect it from tampering by the client. However, a vulnerability in the ASP.NET encryption implementation can allow an attacker to decrypt and tamper with this data.

But what can the attacker do with this capability? Part of the answer depends on the ASP.NET application being attacked. For example, if the ASP.NET application stores sensitive information, such as passwords or database connection strings, in the ViewState object this data could be compromised. The ViewState object is encrypted and sent to the client in a hidden form variable, so it is a possible target of this attack.

If the ASP.NET application is using ASP.NET 3.5 SP1 or above, the attacker could use this encryption vulnerability to request the contents of an arbitrary file within the ASP.NET application. The public disclosure demonstrated using this technique to retrieve the contents of web.config. Any file in the ASP.NET application which the worker process has access to will be returned to the attacker.

How the Vulnerability Works
To understand how this vulnerability works, you need to know about cryptographic oracles. An oracle in the context of cryptography is a system which provides hints as you ask it questions. In this case, there is a vulnerability in ASP.NET which acts as a padding oracle. This allows an attacker to send chosen cipher text to the server and learn if it was decrypted properly by examining which error code was returned by the server.

By making many requests the attacker can learn enough to successfully decrypt the rest of the cipher text. The attacker can then alter the plain text and re-encrypt it as well.

The Workaround - Silencing the Oracle
The workaround for this vulnerability is to use the customErrors feature of ASP.NET to configure applications to return the same error page regardless of the error encountered on the server.

By following the steps in the advisory to map all error messages to a single error page, you make it difficult for the attacker to distinguish between the different types of errors, effectively limiting access to the oracle.

How to Detect Vulnerable ASP.Net Applications
Script can be obtain from the original article.

Note:
Text copied from blogs.technet.com.

The vulnerability affects all versions of .NET Framework. Click here for detail.

Monday, September 20, 2010

64-bit Adobe Flash Player for Linux is back...

Adobe has finally made the announcement a lot of Linux users have been waiting for, a 64-bit version of the Adobe Flash Player is again available. Not only that, it's a significant improvement over previous releases.

This should appease most Linux users and it's clear that Adobe is committed to creating a native 64-bit plugin. A stable version should be coming soon now.

Unfortunately, although part of the announcement was support for hardware acceleration in Internet Explorer 9, there is still no support whatsoever for GPU acceleration on Linux.

Note:
Text copied from Softpedia news.

Wednesday, September 8, 2010

Numeric textbox javascript...

    <input type='text' onkeydown='text_keydown(event)' />

<script language='javascript' type='text/javascript'>
function text_keydown(e)
{
var key;
document.all ? key = e.keyCode /*IE*/ : key = e.which /*FF*/;
if(!(key > 47 && key < 58) && key != 8 && key != 37 && key != 39 && key != 16 && key != 46)
{
cancelevent(e);
}
}

function cancelevent(e)
{
if(window.event) // IE
{
window.event.returnValue = false;
}
else // FF
{
e.preventDefault();
}
}
</script>

Tuesday, September 7, 2010

What's new in Ubuntu 10.10...

1) Simpler Installer.
Ubuntu 10.10 is expected to use a new installer that makes the installation process simpler than ever. Startup options are now placed right in the installer itself, and they include just two options: Try Ubuntu and Install Ubuntu. A simplified partitioner, meanwhile, lets users choose between automatically using the whole disk and manual partitioning, while a new Wireless Network Selection page will be added as well. These features will be particularly helpful for newer Ubuntu users.

My response:
I've started with 6.10 (Edgy Eft) and never felt it's difficult to install Ubuntu (it's the same 6 clicks process, except for the partitioning part might be a little bit tricky for newbie). Overall installing desktop Linux couldn't be more difficult than Windows unless if you're talking about pre Red Hat 7 era in 90s.

2) Processor Support.
It sounds like the Maverick Meerkat will not run on processors older than i686, or anything before Intel's P6 microarchitecture. For most business users this probably won't be an issue, but it could affect some occasional users of older machines.

My response:
I don't need to worry about this because I don't have that kind of old machine. :)

3) Default Environment and Applications.
Ubuntu 10.10 Beta uses version 2.6.35.3 of the Linux kernel, which includes numerous security enhancements over previous versions. It also updates the GNOME desktop environment to version 2.31.

Among application changes, meanwhile, is that Firefox 3.6.8 will be the default, as will OpenOffice 3.2.1, for example. Photo tool F-Spot has been replaced with Shotwell, while a new sound indicator has been enhanced to include music player controls.. The Evolution mail and collaboration software will be updated to the 2.30.2 version, which reportedly is much faster than the one in Ubuntu 10.04 LTS, or Lucid Lynx.

My response:
I never use F-Spot and Evolution mail. For image editing, Gimp is my preference. Sound indicator to include music player controls sounds cool to me.

4) The Ubuntu Software Center
In version 10.10, the Ubuntu Software Center--the tool for browsing, installing and removing software on Ubuntu--will gain "Featured" and "What's New" choice icons on the front page, along with a "History" tab displaying recently installed software. It is also said to be faster and more responsive. Taken together, these improvements promise to make it much easier to track and find new software options.

My response:
This should be interesting. Might change to this instead of Synaptic.

5) Multitouch
Making the biggest splash, of course, will be the new multitouch and gesture capabilities, which will apparently make it possible for basic gestures to be chained, or composed, into more sophisticated "sentences." Toward that end, Canonical has created an open source gesture recognition engine and defined a gesture API that provides a way for applications to respond to users' gestures.

Canonical is currently targeting the Dell XT2 as a development environment for this new feature, but by release it expects it to be compatible with a range of devices from major manufacturers, and with add-ons like Apple's Magic Trackpad. Needless to say, this will pave the way toward a host of new capabilities on the Linux desktop and beyond.

My response:
Unfortunately I don't have any hardware with the capability to benefit this feature.

Note:
Text copied 97% from PCWorld news with a reference to The Fridge.

Monday, September 6, 2010

VB.NET vs C#, why bother? We're .NET developers after all...

I can't believe that people are still debating on this topic. While searching for anonymous methods in VB.NET, I came across to this article "Top 10 reasons VB.NET is better than C#". It was posted on August 23rd 2004 and the last comment was on August 31st 2010!!!

Update:
Did a search further with keyword "vb.net vs c#" and found out that there's another article from the same person on the same day, but this time it's the other way around. "Top 10 reasons C# is better than VB.NET".

Exposing DTO to javascript in ASP.NET...

This post is a continuity from my previous post related to Calling a webservice from javascript in ASP.NET 2.0. Fundamentally it's sharing the same concept. This time I've written the code in ASP.NET 3.5 (Visual Studio 2008). There's no prerequisite required compare to when I did it in ASP.NET 2.0 (Visual Studio 2005).

Once I knew how to call a webservice from javascript in ASP.NET (regardless of version). I've search google to check whether it's possible to pass an object as a parameter to webservice method. Indeed it is possible to do that, but I must make sure that the object should be simple enough without any business logic and with limited behaviour. The object known as Data Transfer Object or in short DTO. Now here's the step by step on how to do it.

1) Using Visual Studio 2008, create new web site. Select ASP.NET Web Site.

2) To create DTO object, add new class under App_Code folder. Lets name it as Student. Paste the code below.
    using System;

///
/// Summary description for Student
///

public class Student
{
public Student()
{
}

public string Id
{
get;
set;
}

public string Name
{
get;
set;
}
}
3) Create new webservice call MyWebService. Add System.Web.Script.Services namespace then add GenerateScriptType and ScriptService attribute to the webservice class. Notice that what I did here is almost the same as my previous post. The only extra code is at line 7 which is to expose Student class to javascript.
    ...
using System.Web.Script.Services;

///
/// Summary description for MyWebService
///

[GenerateScriptType(typeof(Student))]
[WebService(Namespace = "http://tempuri.org/")]
[WebServiceBinding(ConformsTo = WsiProfiles.BasicProfile1_1)]
[ScriptService]
public class MyWebService : System.Web.Services.WebService
{
...
}
4) Add two methods call GetStudents and TestSubmit. GetStudents method will return a list of students to the caller. Since I want to return it as a JSON object, I've set the ResponseFormat to JSON.
    ...
[WebMethod]
[ScriptMethod(ResponseFormat=ResponseFormat.Json)]
public List<Student> GetStudents()
{
var students = new List<Student>();

for (int x = 0; x < 10; x++)
{
students.Add(new Student
{
Id = x.ToString(),
Name = "Name" + x.ToString()
});
}

return students;
}

[WebMethod]
public string TestSubmit(Student student)
{
return String.Format("You've submitted Student object with Id: {0} and Name: {1}", student.Id, student.Name);
}
5) Go to Default.aspx, add ScriptManager (again another same step as my previous post in ASP.NET 2.0).
    ...
<asp:ScriptManager ID="ScriptManager1" runat="server">
<Services>
<asp:ServiceReference InlineScript="true" Path="~/MyWebService.asmx" />
</Services>
</asp:ScriptManager>
...
6) Now add the html control
    ...
<div>
<input id="btnLoad" type="button" value="Get Students" onclick="javascript:btnLoad_Click();" />

<input id="txtId" type="text" /><input id="txtName" type="text" />
<input id="btnSubmit" type="button" value="Submit" onclick="javascript:btnSubmit_Click();" />

<table id="myTable" border="1" cellpadding="1" cellspacing="1"></table>
</div>
...
7) and the javascript
    ...
<script language="javascript" type="text/javascript">
function btnLoad_Click()
{
try
{
MyWebService.GetStudents(OnGetStudentsComplete);
}
catch(e)
{
alert("error " + e);
}
}

function OnGetStudentsComplete(result)
{
var htmlVal = "";

for(var x=0; x<result.length; x++)
{
htmlVal += "<tr><td>" + result[x].Id + "</td><td>" + result[x].Name + "</td></tr>";
}

$get("myTable").innerHTML = htmlVal;
}

function btnSubmit_Click()
{
try
{
var stu = new Student();
stu.Id = $get("txtId").value;
stu.Name = $get("txtName").value;

MyWebService.TestSubmit(stu, OnTestSubmitComplete);

var htmlVal = $get("myTable").innerHTML;
htmlVal += "<tr><td>" + stu.Id + "</td><td>" + stu.Name + "</td></tr>";
$get("myTable").innerHTML = htmlVal;
}
catch(e)
{
alert(e);
}
}

function OnTestSubmitComplete(result)
{
alert(result);
}
</script>
Now I have a web site that can call a webservice and passing an object as a parameter via javascript.

Sunday, September 5, 2010

Evolution of data query in C#...

One of the most common operation in programming is data query. In C# 1.2, normally I would use a custom collection class that derived from System.Collections. But for sake of example here, I'll show it with an ArrayList instead.

Here's a class that'll become an element of the collection (yes, I know Auto-Implemented Properties).
    public class Student
{
private int _id;
private string _name;
private string _gender;

public Student()
{
}

public int Id
{
get { return _id; }
set { _id = value; }
}

public string Name
{
get { return _name; }
set { _name = value; }
}

public string Gender
{
get { return _gender; }
set { _gender = value; }
}
}
This is how I normally code in C# 1.2 (.NET Framework 1.1) with an ArrayList.
    private ArrayList SomeFilterMethod(ArrayList myList)
{
ArrayList result = new ArrayList();

for (int x = 0; x < myList.Count; x++)
{
if (((Student)myList[x]).Gender == "Male")
{
result.Add(myList[x]);
}
}

return result;
}
Generic list with action and predicate was introduced in C# 2.0 (.NET Framework 2.0). This is how my code will look like.
    private List<Student> SomeFilterMethod(List<Student> myList)
{
return mylist.FindAll(GetMaleStudents);
}

private bool GetMaleStudents(Student item)
{
return item.Gender == "Male";
}
Not to forget an anonymous methods.
    private List<Student> SomeFilterMethod(List<Student> myList)
{
return mylist.FindAll( delegate(Student item) { return item.Gender == "Male"; } );
}
In C# 3.0 (.NET Framework 3.5), there's LINQ with 2 flavours.
1) Lambda Expression
    private List<Student> SomeFilterMethod(List<Student> myList)
{
return mylist.FindAll( item => item.Gender == "Male" );
}
2) Query Expression
    private List<Student> SomeFilterMethod(List<Student> myList)
{
return (from student in mylist
where student.Gender == "Male"
select student).ToList<Student>();
}
Between the two, personally I prefer the former.

Saturday, September 4, 2010

Huawei modem undetected on Ubuntu 10.04...

Scenario:
Plug-in modem, Ubuntu detect it as data storage only instead of modem. Only happen on Ubuntu 32bit, working as expected on 64-bit version.

Solution:
Install usb-modeswitch package.
    $ sudo apt-get install usb-modeswitch
Note:
Tested on Ubuntu 10.04 32-bit Desktop and Netbook Edition.

Wednesday, September 1, 2010

Calling a webservice from javascript in ASP.NET 2.0...

Prerequisite:
In Visual Studio 2005, to make a web project template available, you need to upgrade to SP1. The "other alternative" is to install VS80-KB915364-X86-ENU.exe and WebApplicationProjectSetup.msi. If you choose SP1 than ignore the "alternative" way.

1) For Ajax-Enabled Web Site, install ASP.NET Ajax 1.0.

2) Create new ASP.NET Ajax-Enabled Web Site.

3) Add reference System.Web.Extensions ver 1.0.61025.0.

4) On server side, create new WebService, add System.Web.Script.Services namespace and add ScripService attribute to your webservice class.
    ...
using System.Web.Script.Services;
...

[ScriptService]
public class MyWebService : WebService
{
public MyWebService()
{
//Uncomment the following line if using designed components
//InitializeComponent();
}

[WebMethod]
public string HelloWorld()
{
return "Hello World";
}
}
5) On client side, create new web form and add ScriptManager to the aspx file that pointing to your webservice (MyWebService.asmx).
    ...
<asp:ScriptManager ID="ScriptManager1" runat="server">
<Services>
<asp:ServiceReference InlineScript="true" Path="~/MyWebService.asmx" />
</Services>
</asp:ScriptManager>
...
6) Add an html button and its eventhandler.
    ...
<input id="btnOk" type="button" value="Ok" onclick="javascript:btnOk_Click();" />
...

<script language="javascript" type="text/javascript">
function btnOk_Click()
{
try
{
MyWebService.HelloWorld(OnHelloWorldComplete);
}
catch(e)
{
alert("error " + e);
}
}

function OnHelloWorldComplete(result)
{
alert(result);
}
</script>
Done!!! Your first Ajax-Enabled Web Site.

Here's the full source code:
MyWebService.asmx.cs
    using System;
using System.Web;
using System.Collections;
using System.Web.Services;
using System.Web.Services.Protocols;
using System.Web.Script.Services;

///
/// Summary description for MyWebService
///

[WebService(Namespace = "http://tempuri.org/")]
[WebServiceBinding(ConformsTo = WsiProfiles.BasicProfile1_1)]
[ScriptService]
public class MyWebService : WebService
{
public MyWebService()
{
//Uncomment the following line if using designed components
//InitializeComponent();
}

[WebMethod]
public string HelloWorld()
{
return "Hello World";
}
}
Default.aspx
    <%@ Page Language="C#" AutoEventWireup="true" CodeFile="Default.aspx.cs" Inherits="_Default" %>

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN" "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head runat="server">
<title>Untitled Page</title>
</head>
<body>
<form id="form1" runat="server">
<!-- to include webservice proxy, set inlinescript=true, it's much more easier compare to adding script src=webservice.asmx/js -->
<asp:ScriptManager ID="ScriptManager1" runat="server">
<Services>
<asp:ServiceReference InlineScript="true" Path="~/MyWebService.asmx" />
</Services>
</asp:ScriptManager>

<div>
<input id="btnOk" type="button" value="Ok" onclick="javascript:btnOk_Click();" />
</div>
</form>
</body>
</html>

<script language="javascript" type="text/javascript">
function btnOk_Click()
{
try
{
MyWebService.HelloWorld(OnHelloWorldComplete);
}
catch(e)
{
alert("error " + e);
}
}

function OnHelloWorldComplete(result)
{
alert(result);
}
</script>

Monday, August 30, 2010

Stupid default setting in SQL Server 2008...

I've created a table in SQL server 2008, then decided to change one of the column size from varchar(10) to varchar(50). When I try to save the changes I'm getting the error below:

"Saving changes is not permitted. The changes you have made require the following tables to be dropped and re-created. You have either made changes to a table that can't be re-created or enabled the option Prevent saving changes that require the table to be re-created."

Solution:
In Management Studio, go to Tools -> Options then go to the Designer Page and uncheck "Prevent saving changes that require table re-creation".

Thursday, August 26, 2010

Installing VMware Player 3.1.1 on Ubuntu 10.04...


Screenshots...



1) Install build-essential and linux-headers (for my case I skip this step because I had these two packages installed before)
$ sudo apt-get install build-essential linux-headers-`uname -r`
2) Change the installer mode
$ chmod +x ./VMware-Player-3.1.1-282343.x86_64.bundle
3) Execute the installer
$ gksudo bash ./VMware-Player-3.1.1-282343.x86_64.bundle
When popup appear, click Install.

Note:
Tested on Ubuntu 10.04 Lucid Lynx and Linux Mint 10 64-bit.

Update (20/11/2010)
Command to uninstall.
sudo bash vmware-installer -u vmware-player
Update (01/03/2011)
Tested VMWare Player 3.1.3 on Linux Mint 10 64-bit

Connecting SQL Server 2008 from VS 2005 server explorer...

You need to install Service Pack 1 for Visual Studio 2005. The installer can be obtain from here.

Then install Visual Studio 2005 Update for SQL Server 2008 support.

Done.

Wednesday, August 25, 2010

Installing latest ATI display driver on Ubuntu...

Before start, please uninstall the previous version driver if there's any because the installer doesn't have the capability to auto uninstall. Otherwise proceed to installation step.

To uninstall, open terminal and run this command:
$ cd /usr/share/ati
    $ sudo sh ./fglrx-uninstall.sh
Then restart your machine.

To install, open terminal, go to the installer location and run this command:
$ sudo sh ./ati-driver-installer-.run
Follow the instruction. Once completed run this command:
$ sudo /usr/bin/aticonfig --initial
Restart your machine.

Note:
I did the installation process in "recovery mode". That's the only way the correct driver will get install. Otherwise it'll use the previous existing driver (sucks!!!).

Honestly, I hate ATI graphic card. The only reason I'm using it is because I urgently need a laptop and Dell doesn't have an option other than Mobility Radeon HD 4xxx series for it Studio XPS product line.

It's a shame that my ATI card with 1 GB memory can't even get the effects below to work but my NVidia 7600 GS with 256 MB memory perfectly can. ATI driver for Linux really sucks!!!!

1) Win 7 virtual machine on VMWare Player with Accelerate 3D graphics option on, is not working in fullscreen mode
2) Compiz Blur effect not working
3) Compiz Water effect not working
4) Compiz Fire effect not working

Update (28/03/2011)
I've been using CCC version 10.10 with driver packaging version 8.783 on Linux Mint 10 64-bit. So far it's the best driver. All the effect mentioned above working as expected (especially Gaussian blur). For VMWare machine with Aero effect to work on fullscreen, need to disable Compiz.

Update (11/10/2011)
For 64-bit installer to work, you must install the 32-bit library (ia32-libs).

Thursday, August 12, 2010

Ubuntu 10.04 on HP Mini 110, no wireless and audio from speakers...

Note (21/10/2011):
Settings below are not required for Ubuntu 11.10. Everything work out of the box.

Solution:
for wireless:
Download package from https://launchpad.net/~markus-tisoft/+archive/rt3090/+files/rt3090-dkms_2.3.1.3-0ubuntu0~ppa1_all.deb install and reboot.

for audio:
Run the command below then reboot
    $ sudo apt-get install linux-backports-modules-alsa-lucid-generic

Update 14/11/2010:
Just found out that after updating the system, wireless is broken again. To fix this, reinstall rt3090-dkms package.

Monday, August 2, 2010

Installing Subversion server on Ubuntu...

I need a source control in my local network. No need for fancy http or https. Custom svn protocol should be sufficient.

1) Install Subversion
    $ sudo apt-get install subversion
2) Create directory for my repository
    $ mkdir /home/dirn/svn
    $ cd /home/dirn/svn
    $ mkdir my-repo
3) Create repository by using svnadmin command
    $ sudo svnadmin create /home/dirn/svn/my-repo
4) Create a new group called subversion
    $ sudo groupadd subversion
5) Add your username and www-data into the group
    $ sudo usermod -a -G subversion www-data
    $ sudo usermod -a -G subversion user_name
6) Set permission
    $ cd /home/dirn/svn
    $ sudo chown -R www-data:subversion my-repo
    $ sudo chmod -R g+rws my-repo
7) Edit svnserve.conf file
    $ nano /home/dirn/svn/my-repo/conf/svnserve.conf
8) Uncomment the following line and save the file
    # [general]
# password-db = passwd
9) Edit passwd file
    $ nano /home/dirn/svn/my-repo/conf/passwd
10) Add your svn username and password and save the file
    username = password
11) Run svnserve service
    $ svnserve -d --foreground -r /home/dirn/svn
12) To access the project repository, run the following command
    $ svn co svn://hostname/my-repo my-repo --username user_name
Note:
Tested on Ubuntu 10.04 64-bit and Linux Mint 10 64-bit.

Saturday, July 24, 2010

Subversion: the simplest way, cheapest and reliable source control solution on Windows platform...

It's challenging to work in an IT department for a non IT company when there's no proper software development process. "Best practices" would be listed as a low priority item in the list.

The first thing that I would look for before I start coding is a source control. Without it, we're in a risk of loosing the code or spending more time to undo changes that we did which had caused the application to broke.

Since it's a non IT company, requesting budget for software purchase might not take you to the smooth path journey. So, with only 3 options I have in hand and mind which is:

1) Visual SourceSafe 6.0d - unreliable and an obsolete product
2) Perforce - love it, unfortunately the license fee is damn expensive
3) Subversion - it's free but never use it, learning curve needed

Since Subversion is the only option left for me, did some googling and I was overwhelmed with the information. There are so many tools can be use to work with Subversion. To make my life easier, I've listed the best free 4 (at least for me) tools.

VisualSVN Server Standard Edition
Server side tool which is available freely for commercial use. Check out the difference between Standard and Enterprise editions here.

TortoiseSVN
A windows shell extension for Subversion. It is not integrated to any specific IDE and can be use with whatever development tools you like.

AnkhSVN
A Subversion Source Control Provider for Microsoft Visual Studio 2005, 2008 and 2010.

SVNMonitor
A tool to monitor changes made to the repository.

Update (27/07/2010)
I've tried SVNMonitor and it's a great tool for monitoring changes made to the repository. Unfortunately all the svn action will be disable if you monitor the source via URL.

Wednesday, June 23, 2010

How to always use a text-based location bar in nautilus...

Open terminal and type the command below
    $ gconftool-2 --type=Boolean --set /apps/nautilus/preferences/always_use_location_entry true
To switch back
    $ gconftool-2 --type=Boolean --set /apps/nautilus/preferences/always_use_location_entry false

Thursday, June 10, 2010

How to fix plymouth bootup resolution...

After installed proprietary driver for NVidia or ATI, plymouth bootup screen has turned large and ugly. Here's how to fix it

1) Install v86d and hwinfo package
    $ sudo apt-get install v86d hwinfo
2) Check maximum resolution supported when running Plymouth
    $ sudo hwinfo --framebuffer
3) Edit the resolutions in the GRUB2 files
    $ sudo gedit /etc/default/grub
Assuming your monitor can support 1280x1024, otherwise change it to whatever resolution supported by your monitor
4) Change the text below
    GRUB_CMDLINE_LINUX_DEFAULT="quiet splash"
to
    GRUB_CMDLINE_LINUX_DEFAULT="quiet splash nomodeset video=uvesafb:mode_option=1280x1024-24,mtrr=3,scroll=ywrap"
then look for the text below
    #GRUB_GFXMODE=640x480
and change it to
    GRUB_GFXMODE=1280x1024
5) Edit another file
    $ sudo gedit /etc/initramfs-tools/modules
6) Add the following line at the end of the file
    uvesafb mode_option=1280x1024-24 mtrr=3 scroll=ywrap
7) Run
    $ echo FRAMEBUFFER=y | sudo tee /etc/initramfs-tools/conf.d/splash
8) Update Grub
    $ sudo update-grub2
9) Generate new splash screen
    $ sudo update-initramfs -u

Monday, May 31, 2010

No sound from headphone jack...

Model: Dell Studio XPS 16 - 1647 (reported on 1645)
OS:
Linux Mint 17 - Qiana (64-bit)
Linux Mint 13 - Maya (64-bit)
Linux Mint 10 - Julia
Ubuntu 10.04 - Lucid Lynx

Symptom: no sound when plug-in headphone

Solution:
1) open alsa-base.conf file
$ sudo nano /etc/modprobe.d/alsa-base.conf
2) add the text below to the file (last line)
options snd-hda-intel model=dell-m6
3) restart your machine

Note:
Tested on Ubuntu Lucid Lynx 64-bit.

Update (19/11/2010):
Tested on Linux Mint 10 64-bit.

Update (15/11/2014):
Tested on Linux Mint 17 64-bit.

Tuesday, April 20, 2010

Retrieving data from LDAP...

    //person 
strFilter = String.Format("(&(objectCategory=person)(objectClass=user)({0}={1}))", strFieldNm, strValue);
//distribution group
strFilter = String.Format("(&(objectCategory=group)(objectClass=group)({0}={1}))", strFieldNm, strValue);

private SearchUsersList GetUsersOrDistributionGroups(string strFilter, string strLDAPPath, bool blnIsGroup)
{
SearchUsersList objResult = new SearchUsersList();
DirectorySearcher search = null;

try
{
if (strFilter != String.Empty)
{
search = new DirectorySearcher(new DirectoryEntry(strLDAPPath), strFilter);
}
else
{
search = new DirectorySearcher(strFilter);
}

if (search != null)
{
foreach (SearchResult result in search.FindAll())
{
DirectoryEntry entry = result.GetDirectoryEntry();

if (entry.Properties["mail"].Value != null && !String.IsNullOrEmpty(entry.Properties["mail"].Value.ToString()))
{
SearchUsers objUser = new SearchUsers();
objUser.ID = entry.Properties["samaccountname"].Value.ToString();
objUser.MailAddress = entry.Properties["mail"].Value.ToString();
objUser.UserName = entry.Properties["name"].Value.ToString();
objUser.UserType = blnIsGroup ? "LDAP Distribution Group" : "LDAP User";

objResult.Add(objUser);
}
}
}
}
catch
{
throw;
}
return objResult;
}

Monday, April 19, 2010

My first programming in Linux...

I just realized that in my entire career life, I've written thousand lines of code just to solve other people's problem (my employee). Never once I did it for myself. Sometime it makes me wonder, can't my problem (computer related) be solve with my programming skills? Today for the first time, I solved my own problem with programming. Though it might sounds odd, but yeah, I did it :)

I have a collection of Bleach anime series. Filename was in format with prefix "Bleach - xxx.avi". I wanted to remove the prefix and try to do it manually, but doing so with 200 over files is kind of annoying. I knew there's a way to rename file extension from uppercase to lowercase or even adding prefix easily with just one single line of command. But I'm not sure whether it's possible to remove the prefix (if there's a linux command guru out there knows how to do it, kindly show it to me).

Since I'm crazy learning Perl scripting lately (thanks to my latest assignment), I've created a script for my problem. My first programming in Linux!!!
    #!/usr/bin/perl

use strict;

my $directory = @ARGV[0];

opendir(DIRECTORYHANDLER, $directory) || die("Cannot open directory");
my @thecontents = readdir(DIRECTORYHANDLER);
closedir(DIRECTORYHANDLER);

my $counter = 1;

foreach my $content (@thecontents)
{
if($content =~ /Bleach\s-\s\d+.avi/i)
{
my $fullpath = "$directory/$content";
print "$fullpath\n";

my $newname = sprintf("%03d.avi", $counter);
my $newpath = "$directory/$newname";

rename($fullpath, $newpath);

$counter++;
}
}

To be honest, once I knew how simple it is to read a file and passing it to a variable in Perl script, I've started to love it. My understanding on regular expression is getting better and thanks to Ady for encouraging me to use Perl instead of .NET console app for the assignment.

Thursday, April 15, 2010

Perl trim function...

    # Perl trim function to remove whitespace from the start and end of the string
sub trim($)
{
my $string = shift;
$string =~ s/^\s+//;
$string =~ s/\s+$//;
return $string;
}

# Left trim function to remove leading whitespace
sub ltrim($)
{
my $string = shift;
$string =~ s/^\s+//;
return $string;
}

# Right trim function to remove trailing whitespace
sub rtrim($)
{
my $string = shift;
$string =~ s/\s+$//;
return $string;
}

Tuesday, April 13, 2010

How to remove cvc/v value from transaction log...

My first Perl script!!!
    use strict;
use Fcntl qw(:flock :seek);

ProcessDirectory($ARGV[0]);

sub ProcessDirectory
{
my $directory = shift;

opendir(IMD, $directory) || die("Cannot open directory");
my @thecontents = readdir(IMD);
closedir(IMD);

foreach my $content (@thecontents)
{
my $fullpath = $directory . "\\" . $content;

if ((-f $fullpath) && (-r $fullpath) && (-w $fullpath) && (-T $fullpath))
{
ProcessFile($fullpath);
}
elsif(-d $fullpath && $content ne "." && $content ne "..")
{
ProcessDirectory($fullpath);
}
}
}

sub ProcessFile
{
my $filename = shift;

print "Processing $filename ...\n\n";

open(DAT, $filename) || die("Could not open $filename");
my @raw_data = <DAT>;
close(DAT);

my $threedigitcount = 0;
my $fourdigitcount = 0;

foreach my $linedata (@raw_data)
{
if($linedata =~ /<cvc>\d{3}<\/cvc>/i)
{
$linedata =~ s/<cvc>\d{3}<\/cvc>/<cvc>***<\/cvc>/i;
$threedigitcount++;
}
elsif($linedata =~ /<cvc>\d{4}<\/cvc>/i)
{
$linedata =~ s/<cvc>\d{4}<\/cvc>/<cvc>****<\/cvc>/i;
$fourdigitcount++;
}
elsif($linedata =~ /CVV2=\d{4}/i)
{
$linedata =~ s/CVV2=\d{4}/CVV2=****/i;
$fourdigitcount++;
}
elsif($linedata =~ /CVV2=\d{3}/i)
{
$linedata =~ s/CVV2=\d{3}/CVV2=***/i;
$threedigitcount++;
}
}

print "Number of occurences for 3 digits: $threedigitcount\n";
print "Number of occurences for 4 digits: $fourdigitcount\n\n";

open(DAT, ">$filename") || die("Cannot open $filename");
flock(DAT, LOCK_EX);
seek(DAT, 0, SEEK_SET);
print DAT @raw_data;
close(DAT);
}
Here's an update version.
    use strict;
use Cwd;
use Fcntl qw(:flock :seek);

my ($sec, $min, $hour, $mday, $mon, $year, $wday, $yday, $isdst) = localtime(time);

my $LOG_FILE_DIRECTORY = UnixPath2NTPath(getcwd()) . "\\Filter_Log";
my $LOG_FILE_PATH = "$LOG_FILE_DIRECTORY\\" . sprintf("%4d-%02d-%02d_log.txt", $year + 1900, $mon + 1, $mday);
my $EXCLUDE_LOG_DIRECTORY = sprintf("%4d-%02d-%02d", $year + 1900, $mon + 1, $mday);

# Check for log folder, if not there then create it
if (! -d "$LOG_FILE_DIRECTORY")
{
mkdir ("$LOG_FILE_DIRECTORY") || die("Cannot create folder $LOG_FILE_DIRECTORY!");
}

my $timeStamp = localtime time;

Log("\n----------------- Logging started $timeStamp -----------------\n\n");
ProcessDirectory($ARGV[0]);
$timeStamp = localtime time;
Log("\n---------------------- Ended $timeStamp ----------------------\n\n");

sub ProcessDirectory
{
my $directory = shift;

opendir(IMD, $directory) || Log("Can't open $directory directory\n");
my @thecontents = readdir(IMD);
closedir(IMD);

foreach my $content (@thecontents)
{
# if foldername has _ or equal to today's date, skip the process
if($content =~ /_\d{4}-\d{2}-\d{2}/ || $content eq $EXCLUDE_LOG_DIRECTORY)
{
Log("Skip $content\n");
next;
}

my $fullpath = "$directory\\$content";

if ((-f $fullpath) && (-r $fullpath) && (-w $fullpath) && (-T $fullpath))
{
ProcessFile($fullpath);

my @dirname = split(/\\/, $directory);
my $newdirectory = $directory;
$newdirectory =~ s/\\\d{4}-\d{2}-\d{2}/\\_@dirname[-1]/i;

rename($directory, $newdirectory);
}
elsif(-d $fullpath && $content ne "." && $content ne "..")
{
ProcessDirectory($fullpath);
}
}
}

sub ProcessFile
{
my $filename = shift;

Log("Processing $filename ...\n");

open(DAT, $filename) || Log("Can't open $filename\n");
my @raw_data = <DAT>;
close(DAT);

my $threedigitcount = 0;
my $fourdigitcount = 0;

foreach my $linedata (@raw_data)
{
if($linedata =~ /<cvc>\d{3}<\/cvc>/i)
{
$linedata =~ s/<cvc>\d{3}<\/cvc>/<cvc>***<\/cvc>/i;
$threedigitcount++;
}
elsif($linedata =~ /<cvc>\d{4}<\/cvc>/i)
{
$linedata =~ s/<cvc>\d{4}<\/cvc>/<cvc>****<\/cvc>/i;
$fourdigitcount++;
}
elsif($linedata =~ /CVV2=\d{4}/i)
{
$linedata =~ s/CVV2=\d{4}/CVV2=****/i;
$fourdigitcount++;
}
elsif($linedata =~ /CVV2=\d{3}/i)
{
$linedata =~ s/CVV2=\d{3}/CVV2=***/i;
$threedigitcount++;
}
}

Log("Number of occurences for 3 digits: $threedigitcount\n");
Log("Number of occurences for 4 digits: $fourdigitcount\n");

open(DAT, ">$filename") || Log("Can't open $filename\n");
flock(DAT, LOCK_EX);
seek(DAT, 0, SEEK_SET);
print DAT @raw_data;
close(DAT);

Log("$filename completed.\n\n");
}

sub Log($)
{
my $text = shift;
open(LOG_HANDLER, ">>$LOG_FILE_PATH") || die("Can't open $LOG_FILE_PATH");
print LOG_HANDLER "$text";
close(LOG_HANDLER);

print "$text";
}

sub UnixPath2NTPath($)
{
my $string = shift;
$string =~ s/\//\\/g;
return $string;
}

Credit card numbers for testing...

American Express
378282246310005
371449635398431

American Express Corporate
378734493671000

Diners Club
30569309025904
38520000023237

Discover
6011111111111117
6011000990139424

JCB
3530111333300000
3566002020360505

MasterCard
5555555555554444
5105105105105100

Visa
4111111111111111
4012888888881881
4222222222222

Friday, January 22, 2010

Recovering partition table...

There's a tool call TeskDisk. To make your life easier simply download latest GParted LiveCD, TestDisk is included in it. TestDisk executable file also available for DOS, Win32, MacOSX and Linux. Executable TestDisk will run on top of the OS, but there's an disadvantage especially for legacy Windows OS.

By using TestDisk from GParted LiveCD you don't even need to bother about the OS and all other craps like below.

Windows 2000 SP3 added support for 48-bit Logical Block Addressing (LBA), which allows the OS to access hard disks larger than 137 GB. But, 48-bit LBA support must be 'enabled' in Windows 2000 SP3 or above! To do so, the EnableBigLba value must be defined and set properly in the Windows Registry. (text copied from http://www.cgsecurity.org/wiki/OS_Notes#Windows_2000_and_48-bit_LBA)

Windows XP Service Pack 1 (SP1) adds support for 48-bit Logical Block Addressing (LBA), which allows you to access hard disks larger than 137 GB. (text copied from http://www.cgsecurity.org/wiki/OS_Notes#Windows_XP_and_48-bit_LBA)

gtk/gtk.h: No file or directory found when compiling...

To do the checking, run this command
    $ pkg-config --cflags gtk+-2.0
If the output is something like this
    Package gtk+-2.0 was not found in the pkg-config search path.
    Perhaps you should add the directory containing `gtk+-2.0.pc'
    to the PKG_CONFIG_PATH environment variable
    No package 'gtk+-2.0' found
Install libgtk2.0-dev package
    $ sudo apt-get install libgtk2.0-dev