неделя, 5 октомври 2014 г.

Bot for sexgangsters game.

I love to write user scripts. These days I have some fun to write bot for a very nice online game. From the programming perspective interesting part is the use of MutationObserver, with his help the programmer easily can detect changes in the DOM structure.
I made the bot as a add-on for Mozilla Firefox and set as a project in github. There are some issues, which I'll fix in my spare time.
https://github.com/gonaumov/sexGangstersBizBot

вторник, 12 август 2014 г.

Dynamic routing in AngularJS App.config method.

Some time ago I had a work task required to make dynamic routing in App.config method of AngularJS application. Initially I wanted to do something like this:

someApp.config(['$routeProvider', '$httpProvider', 
    '$compileProvider', 'settings',
    function ($routeProvider, $httpProvider, 
        $compileProvider, settings) {

        var $http = angular.injector(['ng']).get('$http');
        var $q = angular.injector(['ng']).get('$q');
        var isUserLogged = $q.defer();

        $http.get(settings.apiUri + settings.loginStatus).
          success(function (data) {
            if (data.status == "NOT_LOGGED") {
                isUserLogged.reject();
            } else {
                isUserLogged.resolve();
            }
        });

        isUserLogged.promise.
          catch(function () {
             $routeProvider.
                 when('/home', {
                     templateUrl: 'partials/home.html',
                     controller: 'HomeController'
                 }).
                 otherwise({
                 redirectTo: '/home'
             });
        });

        isUserLogged.promise.
         then(function () {
            $routeProvider.
                when('/accountsettings', {
                    templateUrl: 'partials/accountsettings.html',
                    controller: 'AccountSettingsController'
                }).
                otherwise({
                    redirectTo: '/accountsettings'
                });
        });
    }]);

But routing did not work because .config method behaves as synchronous. When I remove the http query and promice logic everything worked perfectly. I asked a question in stackoverflow, but there was no answer. After reading the documentation and digging I came to the decision that satisfy me. I did a manual bootstrapping of the application. First I make request to determine whether the user is logged or not. Then I trigger custom event listener whose call .config method of application and do routing in accordance whether the user is logged or not. Below is the code of the decision to which I got (with abbreviations).

angular.element(document).one("userStatusIsCheked", 
                        function(event, userIsLogged) {
    appName.config(['$routeProvider', 
        '$httpProvider', '$compileProvider',
        function ($routeProvider, 
         $httpProvider, $compileProvider) {
            if (userIsLogged == true) {
                $routeProvider.
                    when('/resetpassword/:hashValue', {
                        templateUrl: 'partials/home.html',
                        controller: 'ResetPasswordController'
                    }).
                    when('/accountsettings', {
                        templateUrl: 'partials/accountsettings.html',
                        controller: 'AccountSettingsController'
                    }).
                    when('/changepassword', 
                      {
                        templateUrl: 
                        'partials/accountsettingschangepassword.html',
                        controller: 'ChangePasswordController'
                    }).
                    when('/edit', {
                        templateUrl: 'partials/accountsettingsedit.html',
                        controller: 'EditAccountController'
                    }).
                    when('/apikeymanagement', {
                        templateUrl: 'partials/apikeymanagement.html',
                        controller: 'APIKeyManagementController'
                    }).
                    when('/dashboard', {
                        templateUrl: 'partials/dashboard.html',
                        controller: 'DashboardController'
                    }).
                    when('/pipelines', {
                        templateUrl: 'partials/pipelines.html',
                        controller: 'PipeLinesController'
                    }).
                    when('/preferences', {
                        templateUrl: 'partials/preferences.html',
                        controller: 'PreferencesController'
                    }).
                    when('/reports', {
                        templateUrl: 'partials/reports.html',
                        controller: 'ReportsController'
                    }).
                    when('/logout', {
                        templateUrl: 'partials/logout.html',
                        controller: 'LogoutController',
                        resolve: {
                            logout: function (logout, $q) {
                                var deferred = $q.defer();
                                logout()['finally'](
                                    function() {
                                        deferred.resolve();
                                    }
                                );
                                return deferred.promise;
                            }
                        }
                    }).
                    when('/privacy', {
                        templateUrl: 'partials/privacy.html',
                        controller: 'PrivacyController'
                    }).
                    when('/tos', {
                        templateUrl: 'partials/tos.html',
                        controller: 'TosController'
                    }).
                    when('/currentStatus', {
                        templateUrl: 'partials/currentStatus.html',
                        controller: 'CurrentStatusController'
                    }).
                    otherwise({
                        redirectTo: '/dashboard'
                    });

            } else {
                /**
                 * If user is not logged default action is
                 * home.
                 */
                $routeProvider.
                    when('/home', {
                        templateUrl: 'partials/home.html',
                        controller: 'HomeController'
                    }).
                    when('/resetpassword/:hashValue', {
                        templateUrl: 'partials/home.html',
                        controller: 'ResetPasswordController'
                    }).
                    when('/privacy', {
                        templateUrl: 'partials/privacy.html',
                        controller: 'PrivacyController'
                    }).
                    when('/tos', {
                        templateUrl: 'partials/tos.html',
                        controller: 'TosController'
                    }).
                    when('/currentStatus', {
                        templateUrl: 'partials/currentStatus.html',
                        controller: 'CurrentStatusController'
                    }).
                    otherwise({
                        redirectTo: '/home'
                    });

            }
        }]);

        angular.bootstrap(document, ['appName']);
});

angular.element(document).ready(function() {
    var injector = angular.injector(['appName']);
    var settings = injector.get('settings');
    var $http = injector.get('$http');

    var functionFactory = function (userStatus) {
        return function () {
            this.lUserStatus = userStatus;
            return this.lUserStatus;
        }
    };

    /**
     * So here we will check if user is logged or
     * not and after this construct conditional routing
     * into config method (above).
     */
    $http.get(settings.apiUri + settings.loginStatus).
             success(function (data) {
        if(angular.isDefined(data.status) && 
            data.status == "NOT_AUTHENTICATED") {
            appName.service('userIsLogged', functionFactory(false));
            angular.element(document).trigger("userStatusIsCheked", [false]);
        } else if(angular.isDefined(data.status) && data.
                status == "AUTHENTICATED") {
            appName.service('userIsLogged', 
            functionFactory(true));
            angular.element(document).trigger("userStatusIsCheked", [true]);
        }
    });
});


Hope this helps someone with a similar problem.

New site dedicated to web development

My wife and I started to create a website dedicated to the development for the web. We hope that this site will be useful to all interested in the subject design and programming. http://codinghunters.com/

събота, 24 май 2014 г.

Bulgarian state institutions - a home for slackers and incompetents.

I am writing this material reluctantly. Unfortunately, in Bulgaria people that work in important state institutions are mostly illiterate and irresponsible. Yesterday I was shocked by a criminal negligence. Ministry of Education and Science is maintaining a web site service , located at this url: http://www2.mon.bg/adminrhe2/. In the question url, user can checks whether there are any university diploma on his behalf. Me, who last year defended a thesis in SULSIT as an upgrade over professional bachelor, did check that I have been in the register and noticed something that made me 'amazed' (I'm a web developer with years of experience). It's that uniform civil numbers of the users are sent to the system for inspection, using uncoded Protocol (http). This means that each route to a question asp script (http://www2.mon.bg/adminrhe2/default.asp), eg ISP user can access and capture sensitive personal information. This information is confidential and extremely important for the user. The screenshot below shows how easy it is to be caught this element of the request. I hid only the last digits of my number to protect my safety.
That so called "technical support", which takes place within the project "Information and telecommunication technologies in education" or ICT in Education (BG051PO001/3.1-01), is implemented by the Bulgarian company AdminSoft. Who knows how much money had been sunk into this project, which obviously was made by incompetents. My wife wrote this into a facebook group 'Marketing and Webmastering' and there was immediate reaction by an internet blogger, who wrote an article, explaining the importance of HTTPS and where were given another examples of the government institutions websites, which also don't have encryption.
The story has a sequel. I sent a complaint to the Bulgarian Commission of Protection of Personal Data, and after six months I received a response from them. I'm attaching here the document received by them only hiding my address and theirs documentation numbers. This document confirms that there was indeed a problem and it was resolved after intervention by the Commission.

събота, 5 април 2014 г.

Canonical will shutting down the Ubuntu One file services.

I really like the operating system Ubuntu. I'm very sorry that I got this email today. Maybe Canonical have any financial problems.

From: Ubuntu One noreply@one.ubuntu.com
Subject: Ubuntu One file services

Hi,

We are writing to you to notify you that we will be shutting down the
Ubuntu One file services, effective 1 June 2014. This email gives
information about the closure and what you should expect during the
shutdown process.

As of today, it will no longer be possible to purchase storage or music
from the Ubuntu One store. The Ubuntu One file services apps in the Ubuntu,
Google, and Apple stores will be updated appropriately.

As always, your content belongs to you.  You can simply download your files
onto your PC or an external hard drive.  While the service will stop as of
1 June, you will have an additional two months (until 31 July 2014) to
collect all of your content. After that date, all remaining content will
be deleted.

If you have an active annual subscription, the unused portion of your fees
will be refunded. The refund amount will be calculated from today's
announcement.

We know you have come to rely on Ubuntu One, and we apologise for the
inconvenience this closure may cause.  We've always been inspired by the
support, feedback and enthusiasm of our users and want to thank you for
the support you've shown for Ubuntu One. We hope that you'll continue to
support us as together we bring a revolutionary experience to new devices.

The Ubuntu One team

събота, 15 февруари 2014 г.

Incorrect chess sold in the shop Jumbo.

I like to play chess. In my work I along with my colleagues wanted to buy a nice chess set package including the pieces and a board and play chess sometimes after working time. Today I went to a nearby shop Jumbo located at Sofia Drujba-2 11, Obikolna str. and find chess set that is sold at a good price. This shop is owned by Jumbo Group. Chess set is nice, but the board is wrong. I viewed the set, but did not buy it. Below can be seen a picture of the set.
As can be seen here, when you sit at your side of the board, on your right corner there is always a white square.
My conclusion from this case is that users need to be careful and check chess sets in the shop before buy them. It seems that the manufacturer of these chess sets never played chess.

AngularJS $http, CORS and http authentication

Some time ago I had a task for the company where I work. The task had to use CORS. I am writing this article to share lesson learned.
You want to send POST request to different domain with AngularJS $http service? There is several tricky thing into AngularJS and server setup.
First: In your application config you must to allow cross domain call

    /**
     *  Cors usage example. 
     *  @author Georgi Naumov
     *  gonaumov@gmail.com for contacts and 
     *  suggestions. 
     **/ 
    app.config(function($httpProvider) {
        //Enable cross domain calls
        $httpProvider.defaults.useXDomain = true;
    });

Second: You must specify withCredentials: true and username and password into request.


     /**
      *  Cors usage example. 
      *  @author Georgi Naumov
      *  gonaumov@gmail.com for contacts and 
      *  suggestions. 
      **/ 
       $http({
      url: 'url of remote service',
      method: "POST",
      data: JSON.stringify(requestData),
      withCredentials: true,
      headers: {
       'Authorization': 'Basic bashe64usename:password'
      }
     });

Тhird: Server setup. You must provide:

    /**
     *  Cors usage example. 
     *  @author Georgi Naumov
     *  gonaumov@gmail.com for contacts and 
     *  suggestions. 
     **/ 
    header("Access-Control-Allow-Credentials: true");
    header("Access-Control-Allow-Origin: http://url.com:8080");
    header("Access-Control-Allow-Methods: GET, POST, PUT, DELETE, OPTIONS");
    header("Access-Control-Allow-Headers: Origin, X-Requested-With, Content-Type, Accept, Authorization");

For every request. When you receive OPTION you must pass:


    /**
     *  Cors usage example. 
     *  @author Georgi Naumov
     *  gonaumov@gmail.com for contacts and 
     *  suggestions. 
     **/ 
    if($_SERVER['REQUEST_METHOD'] == 'OPTIONS') {
       header( "HTTP/1.1 200 OK" );
       exit();
    }


HTTP authentication and everything else comes after that. Here is complete example of usage of server side with php.

   /**
     *  Cors usage example. 
     *  @author Georgi Naumov
     *  gonaumov@gmail.com for contacts and 
     *  suggestions. 
     **/ 
    header("Access-Control-Allow-Credentials: true");
    header("Access-Control-Allow-Origin: http://url:8080");
    header("Access-Control-Allow-Methods: GET, POST, PUT, DELETE, OPTIONS");
    header("Access-Control-Allow-Headers: Origin, X-Requested-With, Content-Type, Accept, Authorization");
    
    if($_SERVER['REQUEST_METHOD'] == 'OPTIONS') {
       header( "HTTP/1.1 200 OK" );
       exit();
    }
    
    
    $realm = 'Restricted area';
    
    $password = 'somepassword';
    
    $users = array('someusername' => $password);
    
    
    if (isset($_SERVER['PHP_AUTH_USER']) == false ||  isset($_SERVER['PHP_AUTH_PW']) == false) {
        header('WWW-Authenticate: Basic realm="My Realm"');
    
        die('Not authorised');
    }
    
    if (isset($users[$_SERVER['PHP_AUTH_USER']]) && $users[$_SERVER['PHP_AUTH_USER']] == $password) 
    {
        header( "HTTP/1.1 200 OK" );
        echo 'You are logged in!' ;
        exit();
    }
    ?>

Here can be found me question in stackoverflow.

събота, 8 февруари 2014 г.

Arrows in GIMP.

I like GIMP. Gimp is very useful for people that don't like commercial software. When you get accustomed to it GIMP is very pleasant for using software. In my work I often have to annotate screen shots. For this I was slightly unpleasantly surprised when I learned that GIMP has  no arrows. I found this very good plugin that adds this feature in GIMP.  You must put the script under gimp/2.0/scripts directory. Under Ubuntu 12.04 (my current working box) you can install it using this one liner:

 sudo wget -O /usr/share/gimp/2.0/scripts/arrow.scm http://registry.gimp.org/files/arrow.scm

The above shell command works correctly also under Ubuntu 13.10.

How to use it: 
1.You must make a path with  Path tool. 

 2. From Tools select Arrows ..

 3. Settings dialog appears. 

4. After playing with settings and press OK you can see finished arrow.
Have fun.

петък, 3 януари 2014 г.

Disable notifications on skype only for particular contact under Linux.

Sometimes we need to switch off skype notifications but for particular contact only. In windows there is easy solution «Conversation» -> «Notification settings ...» -> «Do not notify me» unfortunately this option is missing under Linux version. I googled for solutions but there is no results. All articles shows that this is possible under Windows and Mac versions of skype. Once I thought I noticed that some of the commands for group chat is available for personal.
I did some experiments and came to a solution. When you want to disable notifications on skype only for particular contact under Linux you can use this command in chat window:
/alertsoff
. If you want to activate notifications you can use:
/alertson
. Hope this helps someone with a similar problem.