コード例 #1
0
ファイル: test_auto_update.py プロジェクト: HamzaKo/w3af
 def tearDown(self):
     XpresserUnittest.tearDown(self)
     
     # Just in case... we don't want to break other tests
     startup_cfg = StartUpConfig()
     startup_cfg.last_upd = datetime.date.today()
     startup_cfg.save()
コード例 #2
0
    def test_get_prompt(self):
        # We want to get the prompt, not a disclaimer message
        startup_cfg = StartUpConfig()
        startup_cfg.accepted_disclaimer = True
        startup_cfg.save()

        # The easy way to do this was to simply pass 'python' to Popen
        # but now that we want to run the tests in virtualenv, we need to
        # find the "correct" / "virtual" python executable using which and
        # then pass that one to Popen
        python_executable = which('python')[0]

        p = subprocess.Popen([python_executable, 'w3af_console', '-n'],
                             stdout=subprocess.PIPE,
                             stdin=subprocess.PIPE)

        # Wait for the subprocess to start and the prompt to appear
        time.sleep(15)

        expected_prompt = 'w3af>>>'
        prompt = non_block_read(p.stdout)

        msg = 'Failed to find "%s" in "%s" using "%s" as python executable.'
        msg = msg % (expected_prompt, prompt, python_executable)
        self.assertTrue(prompt.startswith(expected_prompt), msg)

        p.kill()
コード例 #3
0
ファイル: test_disclaimer_accept.py プロジェクト: weisst/w3af
    def tearDown(self):
        XpresserUnittest.tearDown(self)

        # Just in case... we don't want to break other tests
        startup_cfg = StartUpConfig()
        startup_cfg.accepted_disclaimer = True
        startup_cfg.save()
コード例 #4
0
 def tearDown(self):
     XpresserUnittest.tearDown(self)
     
     # Just in case... we don't want to break other tests
     startup_cfg = StartUpConfig()
     startup_cfg.accepted_disclaimer = True
     startup_cfg.save()
コード例 #5
0
ファイル: test_w3af_console.py プロジェクト: Adastra-thw/w3af
    def test_get_prompt(self):
        # We want to get the prompt, not a disclaimer message
        startup_cfg = StartUpConfig()
        startup_cfg.accepted_disclaimer = True
        startup_cfg.save()

        # The easy way to do this was to simply pass 'python' to Popen
        # but now that we want to run the tests in virtualenv, we need to
        # find the "correct" / "virtual" python executable using which and
        # then pass that one to Popen
        python_executable = which('python')[0]
        
        p = subprocess.Popen([python_executable, 'w3af_console', '-n'],
                             stdout=subprocess.PIPE,
                             stdin=subprocess.PIPE)
        
        # Wait for the subprocess to start and the prompt to appear
        time.sleep(15)
        
        expected_prompt = 'w3af>>>'
        prompt = non_block_read(p.stdout)
        
        msg = 'Failed to find "%s" in "%s" using "%s" as python executable.'
        msg = msg % (expected_prompt, prompt, python_executable)
        self.assertTrue(prompt.startswith(expected_prompt), msg)
        
        p.kill()
コード例 #6
0
ファイル: console_ui.py プロジェクト: HamzaKo/w3af
    def accept_disclaimer(self):
        '''
        :return: True/False depending on the user's answer to our disclaimer.
                 Please note that in w3af_console we'll stop if the user does
                 not accept the disclaimer.
        '''
        startup_cfg = StartUpConfig()

        if startup_cfg.accepted_disclaimer:
            return True

        QUESTION = 'Do you accept the terms and conditions? [N|y] '
        msg = DISCLAIMER + '\n\n' + QUESTION
        try:
            user_response = raw_input(msg)
        except (KeyboardInterrupt, EOFError):
            print ''
            user_response = ''

        user_response = user_response.lower()

        if user_response == 'y' or user_response == 'yes':
            startup_cfg.accepted_disclaimer = True
            startup_cfg.save()
            return True

        return False
コード例 #7
0
ファイル: console_ui.py プロジェクト: daemon13/w3af
    def accept_disclaimer(self):
        '''
        :return: True/False depending on the user's answer to our disclaimer.
                 Please note that in w3af_console we'll stop if the user does
                 not accept the disclaimer.
        '''
        startup_cfg = StartUpConfig()

        if startup_cfg.accepted_disclaimer:
            return True

        QUESTION = 'Do you accept the terms and conditions? [N|y] '
        msg = DISCLAIMER + '\n\n' + QUESTION
        try:
            user_response = raw_input(msg)
        except (KeyboardInterrupt, EOFError):
            print ''
            user_response = ''

        user_response = user_response.lower()

        if user_response == 'y' or user_response == 'yes':
            startup_cfg.accepted_disclaimer = True
            startup_cfg.save()
            return True

        return False
コード例 #8
0
ファイル: test_auto_update.py プロジェクト: weisst/w3af
    def tearDown(self):
        XpresserUnittest.tearDown(self)

        # Just in case... we don't want to break other tests
        startup_cfg = StartUpConfig()
        startup_cfg.last_upd = datetime.date.today()
        startup_cfg.save()
コード例 #9
0
ファイル: test_auto_update.py プロジェクト: HamzaKo/w3af
 def test_disclaimer_shown_accept(self):
     startup_cfg = StartUpConfig()
     startup_cfg.last_upd = - datetime.timedelta(days=3)
     startup_cfg.save()
     
     self.find('update_window')
     self.click('update')
     
     self.find('owasp_top_10_profile') 
コード例 #10
0
 def test_disclaimer_shown_not_accept(self):
     startup_cfg = StartUpConfig()
     startup_cfg.accepted_disclaimer = False
     startup_cfg.save()
     
     self.find('accept_terms_conditions')
     self.click('simple_no')
     
     self.not_find('owasp_top_10_profile')
コード例 #11
0
ファイル: test_disclaimer_accept.py プロジェクト: weisst/w3af
    def test_disclaimer_shown_not_accept(self):
        startup_cfg = StartUpConfig()
        startup_cfg.accepted_disclaimer = False
        startup_cfg.save()

        self.find('accept_terms_conditions')
        self.click('simple_no')

        self.not_find('owasp_top_10_profile')
コード例 #12
0
ファイル: test_auto_update.py プロジェクト: weisst/w3af
    def test_disclaimer_shown_accept(self):
        startup_cfg = StartUpConfig()
        startup_cfg.last_upd = datetime.date.today() - datetime.timedelta(
            days=3)
        startup_cfg.save()

        self.find('update_window')
        self.click('update')

        self.find('owasp_top_10_profile')
コード例 #13
0
ファイル: test_version_manager.py プロジェクト: weisst/w3af
    def test_update_not_required_not_forced(self):
        '''
        Test that we don't perform any extra steps if the local installation
        was already updated today.
        '''
        self.vmgr._start_cfg = start_cfg = StartUpConfig()
        start_cfg._autoupd = True
        start_cfg._freq = StartUpConfig.FREQ_DAILY

        last_upd = datetime.date.today() - datetime.timedelta(days=0)
        start_cfg._lastupd = last_upd

        on_update_check_mock = MagicMock()
        on_already_latest_mock = MagicMock()
        on_update_mock = MagicMock()

        self.vmgr.register(VersionMgr.ON_UPDATE_CHECK, on_update_check_mock,
                           None)
        self.vmgr.register(VersionMgr.ON_ALREADY_LATEST,
                           on_already_latest_mock, None)
        self.vmgr.register(VersionMgr.ON_UPDATE, on_update_mock, None)

        self.vmgr.update()

        self.assertEqual(on_update_check_mock.call_count, 0)
        self.assertEqual(on_already_latest_mock.call_count, 0)
        self.assertEqual(on_update_mock.call_count, 0)
コード例 #14
0
ファイル: test_version_manager.py プロジェクト: weisst/w3af
    def test_no_need_update(self):
        vmgr = self.vmgr
        vmgr._start_cfg = StartUpConfig()
        vmgr._start_cfg._autoupd = False

        # Test no auto-update
        self.assertFalse(vmgr._has_to_update())
コード例 #15
0
ファイル: test_version_manager.py プロジェクト: weisst/w3af
    def test_update_required_not_forced(self):
        '''
        Test that we check if we're on the latest version if the latest
        local installation update was 3 days ago and the frequency is set to
        daily.
        
        The local repository is in the latest version (git pull is run before)
        '''
        git_client = GitClient('.')
        git_client.pull()

        self.vmgr._start_cfg = start_cfg = StartUpConfig()
        start_cfg._autoupd = True
        start_cfg._freq = StartUpConfig.FREQ_DAILY

        last_upd = datetime.date.today() - datetime.timedelta(days=3)
        start_cfg._lastupd = last_upd

        on_update_check_mock = MagicMock()
        on_already_latest_mock = MagicMock()
        on_update_mock = MagicMock()

        self.vmgr.register(VersionMgr.ON_UPDATE_CHECK, on_update_check_mock,
                           None)
        self.vmgr.register(VersionMgr.ON_ALREADY_LATEST,
                           on_already_latest_mock, None)
        self.vmgr.register(VersionMgr.ON_UPDATE, on_update_mock, None)

        self.vmgr.update()

        self.assertEqual(on_update_check_mock.call_count, 1)
        self.assertEqual(on_already_latest_mock.call_count, 1)
        self.assertEqual(on_update_mock.call_count, 0)
コード例 #16
0
    def test_save(self):
        scfg = StartUpConfig(self.CFG_FILE)

        scfg.last_upd = date.today()
        scfg.accepted_disclaimer = True
        scfg.last_commit_id = '3f4808082c1943f964669af1a1c94245bab09c61'
        scfg.save()
コード例 #17
0
ファイル: version_manager.py プロジェクト: weisst/w3af
    def __init__(self, localpath=W3AF_LOCAL_PATH, log=None):
        '''
        w3af version manager class. Handles the logic concerning the
        automatic update/commit process of the code.

        :param localpath: Working directory
        :param log: Default output function
        '''
        self._localpath = localpath
        self._client = GitClient(localpath)
        self._client.add_observer(self._client_progress)

        log = log if log is not None else om.out.console
        self._log = log

        # Set default events
        self.register_default_events(log)
        # Startup configuration
        self._start_cfg = StartUpConfig()
コード例 #18
0
    def test_load_not_exist(self):
        '''
        This is a test to verify that the defaults are loaded when the file does not
        exist.
        '''
        scfg = StartUpConfig('foo.conf')

        self.assertEqual(scfg.last_upd, date.today() - timedelta(days=31))
        self.assertEqual(scfg.accepted_disclaimer, False)
        self.assertEqual(scfg.last_commit_id, '')
        self.assertEqual(scfg.freq, 'D')
コード例 #19
0
    def accept_disclaimer(self):
        '''
        :return: True/False depending on the user's answer to our disclaimer.
                 Please note that in w3af_gui we'll stop if the user does
                 not accept the disclaimer.
        '''
        startup_cfg = StartUpConfig()

        if startup_cfg.accepted_disclaimer:
            return True

        QUESTION = 'Do you accept the terms and conditions?'
        msg = DISCLAIMER + '\n\n' + QUESTION
        user_response = ask(msg)

        if user_response:
            startup_cfg.accepted_disclaimer = True
            startup_cfg.save()
            return True

        return False
コード例 #20
0
ファイル: test_startup_cfg.py プロジェクト: Adastra-thw/w3af
    def test_save(self):
        scfg = StartUpConfig(self.CFG_FILE)

        scfg.last_upd = date.today()
        scfg.accepted_disclaimer = True
        scfg.last_commit_id = '3f4808082c1943f964669af1a1c94245bab09c61'
        scfg.save()
コード例 #21
0
    def test_load_file_exists(self):
        '''This is a test to verify that the things we saved were persited in
        the actual file.
        '''
        # Save
        scfg = StartUpConfig(self.CFG_FILE)
        scfg.last_upd = date.today()
        scfg.accepted_disclaimer = True
        scfg.last_commit_id = '3f4808082c1943f964669af1a1c94245bab09c61'
        scfg.save()

        # Load
        scfg = StartUpConfig(self.CFG_FILE)
        self.assertEqual(scfg.last_upd, date.today())
        self.assertEqual(scfg.accepted_disclaimer, True)
        self.assertEqual(scfg.last_commit_id,
                         '3f4808082c1943f964669af1a1c94245bab09c61')
        self.assertEqual(scfg.freq, 'D')
コード例 #22
0
ファイル: disclaimer.py プロジェクト: Adastra-thw/w3af
    def accept_disclaimer(self):
        '''
        :return: True/False depending on the user's answer to our disclaimer.
                 Please note that in w3af_gui we'll stop if the user does
                 not accept the disclaimer.
        '''
        startup_cfg = StartUpConfig()

        if startup_cfg.accepted_disclaimer:
            return True


        QUESTION = 'Do you accept the terms and conditions?'
        msg = DISCLAIMER + '\n\n' + QUESTION
        user_response = ask(msg)

        if user_response:
            startup_cfg.accepted_disclaimer = True
            startup_cfg.save()
            return True

        return False
コード例 #23
0
ファイル: test_version_manager.py プロジェクト: weisst/w3af
    def test_update_required_outdated_not_forced(self):
        '''
        Test that we check if we're on the latest version if the latest
        local installation update was 3 days ago and the frequency is set to
        daily.
        
        The local repository is NOT in the latest version. A 'git reset --hard'
        is run at the beginning of this test to reset the repo to a revision
        before the latest one.
        '''
        try:
            git_client = GitClient('.')
            head_id = git_client.get_local_head_id()
            one_before_head = git_client.get_parent_for_revision(head_id)
            git_client.reset_to_previous_state(one_before_head)

            self.vmgr._start_cfg = start_cfg = StartUpConfig()
            start_cfg._autoupd = True
            start_cfg._freq = StartUpConfig.FREQ_DAILY

            last_upd = datetime.date.today() - datetime.timedelta(days=3)
            start_cfg._lastupd = last_upd

            on_update_check_mock = MagicMock()
            on_already_latest_mock = MagicMock()
            on_update_mock = MagicMock()

            self.vmgr.register(VersionMgr.ON_UPDATE_CHECK,
                               on_update_check_mock, None)
            self.vmgr.register(VersionMgr.ON_ALREADY_LATEST,
                               on_already_latest_mock, None)
            self.vmgr.register(VersionMgr.ON_UPDATE, on_update_mock, None)

            self.vmgr.callback_onupdate_confirm = MagicMock(side_effect=[
                True,
            ])

            self.vmgr.update()

            self.assertEqual(on_update_check_mock.call_count, 1)
            self.assertEqual(on_already_latest_mock.call_count, 0)
            self.assertEqual(on_update_mock.call_count, 1)
        finally:
            git_client.pull()
コード例 #24
0
ファイル: test_startup_cfg.py プロジェクト: Adastra-thw/w3af
    def test_load_file_exists(self):
        '''This is a test to verify that the things we saved were persited in
        the actual file.
        '''
        # Save
        scfg = StartUpConfig(self.CFG_FILE)
        scfg.last_upd = date.today()
        scfg.accepted_disclaimer = True
        scfg.last_commit_id = '3f4808082c1943f964669af1a1c94245bab09c61'
        scfg.save()

        # Load
        scfg = StartUpConfig(self.CFG_FILE)
        self.assertEqual(scfg.last_upd, date.today())
        self.assertEqual(scfg.accepted_disclaimer, True)
        self.assertEqual(scfg.last_commit_id, '3f4808082c1943f964669af1a1c94245bab09c61')
        self.assertEqual(scfg.freq, 'D')
コード例 #25
0
ファイル: test_version_manager.py プロジェクト: weisst/w3af
    def test_has_to_update(self):
        '''
        Test [D]aily, [W]eekly and [M]onthly auto-update
        '''
        SC = StartUpConfig
        vmgr = self.vmgr

        for freq, diffdays in ((SC.FREQ_DAILY, 1), (SC.FREQ_WEEKLY, 8),
                               (SC.FREQ_MONTHLY, 34)):

            vmgr._start_cfg = start_cfg = StartUpConfig()
            start_cfg._autoupd = True
            start_cfg._freq = freq

            last_upd = datetime.date.today() - datetime.timedelta(
                days=diffdays)
            start_cfg._lastupd = last_upd

            self.assertTrue(vmgr._has_to_update())
コード例 #26
0
ファイル: version_manager.py プロジェクト: Adastra-thw/w3af
    def __init__(self, localpath=W3AF_LOCAL_PATH, log=None):
        '''
        w3af version manager class. Handles the logic concerning the
        automatic update/commit process of the code.

        :param localpath: Working directory
        :param log: Default output function
        '''
        self._localpath = localpath
        self._client = GitClient(localpath)
        self._client.add_observer(self._client_progress)
        
        log = log if log is not None else om.out.console
        self._log = log
        
        # Set default events
        self.register_default_events(log)
        # Startup configuration
        self._start_cfg = StartUpConfig()
コード例 #27
0
ファイル: version_manager.py プロジェクト: Adastra-thw/w3af
class VersionMgr(object):
    '''
    Perform SVN w3af code update and commit. When an instance is created loads
    data from a .conf file that will be used when actions are executed.
    Also provides some callbacks as well as events to register to.

    Callbacks on:
        UPDATE:
            * callback_onupdate_confirm(msg)
                Return True/False

            * callback_onupdate_show_log(msg, log_func)
                Displays 'msg' to the user and depending on user's answer
                call 'log_func()' which returns a string with the summary of
                the commit logs from the from local revision to repo's.

            * callback_onupdate_error
                If an SVNError occurs this callback is called in order to the
                client class handles the error. Probably notify the user.
        COMMIT:
            {implementation pending}
    Events:
        ON_UPDATE
        ON_UPDATE_ADDED_DEP
        ON_UPDATE_CHECK
        ON_ACTION_ERROR
    '''

    # Events constants
    ON_UPDATE = 1
    ON_UPDATE_ADDED_DEP = 2
    ON_UPDATE_CHECK = 3
    ON_ALREADY_LATEST = 4
    ON_ACTION_ERROR = 5
    ON_COMMIT = 6
    ON_PROGRESS = 7

    # Callbacks
    callback_onupdate_confirm = None
    callback_onupdate_show_log = None
    callback_onupdate_error = None

    # Revision constants
    HEAD = 'HEAD'
    BACK = 'BACK'

    def __init__(self, localpath=W3AF_LOCAL_PATH, log=None):
        '''
        w3af version manager class. Handles the logic concerning the
        automatic update/commit process of the code.

        :param localpath: Working directory
        :param log: Default output function
        '''
        self._localpath = localpath
        self._client = GitClient(localpath)
        self._client.add_observer(self._client_progress)
        
        log = log if log is not None else om.out.console
        self._log = log
        
        # Set default events
        self.register_default_events(log)
        # Startup configuration
        self._start_cfg = StartUpConfig()
    
    def _client_progress(self, op_code, cur_count, max_count, message):
        '''
        The GitClient will call this method when it has progress to show
        for fetch() and pull().
        
        Please note that because I don't need it at this moment, I'm simply
        ignoring all parameters and just letting the observers know that this
        event was triggered.
        '''
        self._notify(VersionMgr.ON_PROGRESS)
        
    def register_default_events(self, log):
        '''
        Default events registration
        
        :param log: Log function to call for events
        :return: None, all saved in self._reg_funcs
        '''
        # Registered functions
        self._reg_funcs = {}
        
        msg = ('Checking if a new version is available in our git repository.'
               ' Please wait...')
        self.register(VersionMgr.ON_UPDATE_CHECK, log, msg)
        
        msg = ('Your installation is already on the latest available version.')
        self.register(VersionMgr.ON_ALREADY_LATEST, log, msg)
        
        msg = 'w3af is updating from github.com ...'
        self.register(VersionMgr.ON_UPDATE, log, msg)
        
        msg = ('The third-party dependencies for w3af have changed, please'
               ' exit the framework and run it again to load all changes'
               ' and install any missing modules.')
        self.register(VersionMgr.ON_UPDATE_ADDED_DEP, log, msg)

    def update(self, force=False):
        '''
        Perform code update if necessary. Return three elems tuple with the
        ChangeLog of the changed files, the local and the final commit id.

        :param force: Force update ignoring the startup config.
        :return: (changelog: A ChangeLog instance,
                  local_head_id: The local id before the update,
                  commit_id: The commit id after the update)
                  
        '''
        if not force and not self._has_to_update():
            # No need to update based on user preferences
            return
        
        # Save the latest update date, always, even when the update had errors
        # or there was no update available
        self._start_cfg.last_upd = date.today()
        self._start_cfg.save()
        
        local_head_id = self._client.get_local_head_id()
        short_local_head_id = to_short_id(local_head_id)
        
        # Lets update!
        self._notify(VersionMgr.ON_UPDATE_CHECK)
        
        # This performs a fetch() which takes time
        remote_head_id = self._client.get_remote_head_id()
        short_remote_head_id = to_short_id(remote_head_id)
        
        if local_head_id == remote_head_id:
            # If local and repo's rev are the same => Nothing to do.
            self._notify(VersionMgr.ON_ALREADY_LATEST)
            return
        
        if self._user_confirmed_update(short_local_head_id, local_head_id,
                                       short_remote_head_id, remote_head_id):
            return self.__update_impl()

    def _user_confirmed_update(self, short_local_head_id, local_head_id,
                                short_remote_head_id, remote_head_id):
        '''
        Ask the user if he wants to update or not.
        
        :return: True if the user wants to update.
        ''' 
        # Call callback function
        if self.callback_onupdate_confirm is not None:
            
            callback = self.callback_onupdate_confirm
            
            # pylint: disable=E1102
            # pylint: disable=E1103
            msg = 'Your current w3af installation is %s (%s). Do you want '\
                  'to update to %s (%s)?'
            proceed_upd = callback(msg % (short_local_head_id,
                                          get_commit_id_date(local_head_id),
                                          short_remote_head_id,
                                          get_commit_id_date(remote_head_id)))
            
            return proceed_upd
    
    def __update_impl(self):
        '''
        Finally call the Git client's pull!
        
        :return: (changelog, local_head_id, target_commit)
        '''
        self._notify(VersionMgr.ON_UPDATE)
        
        try:
            changelog = self._client.pull()
        except GitClientError, exc:
            msg = '%s' % exc
            self._notify(VersionMgr.ON_ACTION_ERROR, msg)
            return
        else:
コード例 #28
0
 def test_disclaimer_not_shown(self):
     startup_cfg = StartUpConfig()
     startup_cfg.accepted_disclaimer = True
     startup_cfg.save()
     
     self.not_find('accept_terms_conditions')
コード例 #29
0
ファイル: test_disclaimer_accept.py プロジェクト: weisst/w3af
    def test_disclaimer_not_shown(self):
        startup_cfg = StartUpConfig()
        startup_cfg.accepted_disclaimer = True
        startup_cfg.save()

        self.not_find('accept_terms_conditions')
コード例 #30
0
ファイル: version_manager.py プロジェクト: weisst/w3af
class VersionMgr(object):
    '''
    Perform SVN w3af code update and commit. When an instance is created loads
    data from a .conf file that will be used when actions are executed.
    Also provides some callbacks as well as events to register to.

    Callbacks on:
        UPDATE:
            * callback_onupdate_confirm(msg)
                Return True/False

            * callback_onupdate_show_log(msg, log_func)
                Displays 'msg' to the user and depending on user's answer
                call 'log_func()' which returns a string with the summary of
                the commit logs from the from local revision to repo's.

            * callback_onupdate_error
                If an SVNError occurs this callback is called in order to the
                client class handles the error. Probably notify the user.
        COMMIT:
            {implementation pending}
    Events:
        ON_UPDATE
        ON_UPDATE_ADDED_DEP
        ON_UPDATE_CHECK
        ON_ACTION_ERROR
    '''

    # Events constants
    ON_UPDATE = 1
    ON_UPDATE_ADDED_DEP = 2
    ON_UPDATE_CHECK = 3
    ON_ALREADY_LATEST = 4
    ON_ACTION_ERROR = 5
    ON_COMMIT = 6
    ON_PROGRESS = 7

    # Callbacks
    callback_onupdate_confirm = None
    callback_onupdate_show_log = None
    callback_onupdate_error = None

    # Revision constants
    HEAD = 'HEAD'
    BACK = 'BACK'

    def __init__(self, localpath=W3AF_LOCAL_PATH, log=None):
        '''
        w3af version manager class. Handles the logic concerning the
        automatic update/commit process of the code.

        :param localpath: Working directory
        :param log: Default output function
        '''
        self._localpath = localpath
        self._client = GitClient(localpath)
        self._client.add_observer(self._client_progress)

        log = log if log is not None else om.out.console
        self._log = log

        # Set default events
        self.register_default_events(log)
        # Startup configuration
        self._start_cfg = StartUpConfig()

    def _client_progress(self, op_code, cur_count, max_count, message):
        '''
        The GitClient will call this method when it has progress to show
        for fetch() and pull().
        
        Please note that because I don't need it at this moment, I'm simply
        ignoring all parameters and just letting the observers know that this
        event was triggered.
        '''
        self._notify(VersionMgr.ON_PROGRESS)

    def register_default_events(self, log):
        '''
        Default events registration
        
        :param log: Log function to call for events
        :return: None, all saved in self._reg_funcs
        '''
        # Registered functions
        self._reg_funcs = {}

        msg = ('Checking if a new version is available in our git repository.'
               ' Please wait...')
        self.register(VersionMgr.ON_UPDATE_CHECK, log, msg)

        msg = ('Your installation is already on the latest available version.')
        self.register(VersionMgr.ON_ALREADY_LATEST, log, msg)

        msg = 'w3af is updating from github.com ...'
        self.register(VersionMgr.ON_UPDATE, log, msg)

        msg = ('The third-party dependencies for w3af have changed, please'
               ' exit the framework and run it again to load all changes'
               ' and install any missing modules.')
        self.register(VersionMgr.ON_UPDATE_ADDED_DEP, log, msg)

    def update(self, force=False):
        '''
        Perform code update if necessary. Return three elems tuple with the
        ChangeLog of the changed files, the local and the final commit id.

        :param force: Force update ignoring the startup config.
        :return: (changelog: A ChangeLog instance,
                  local_head_id: The local id before the update,
                  commit_id: The commit id after the update)
                  
        '''
        if not force and not self._has_to_update():
            # No need to update based on user preferences
            return

        # Save the latest update date, always, even when the update had errors
        # or there was no update available
        self._start_cfg.last_upd = date.today()
        self._start_cfg.save()

        local_head_id = self._client.get_local_head_id()
        short_local_head_id = to_short_id(local_head_id)

        # Lets update!
        self._notify(VersionMgr.ON_UPDATE_CHECK)

        # This performs a fetch() which takes time
        remote_head_id = self._client.get_remote_head_id()
        short_remote_head_id = to_short_id(remote_head_id)

        if local_head_id == remote_head_id:
            # If local and repo's rev are the same => Nothing to do.
            self._notify(VersionMgr.ON_ALREADY_LATEST)
            return

        if self._user_confirmed_update(short_local_head_id, local_head_id,
                                       short_remote_head_id, remote_head_id):
            return self.__update_impl()

    def _user_confirmed_update(self, short_local_head_id, local_head_id,
                               short_remote_head_id, remote_head_id):
        '''
        Ask the user if he wants to update or not.
        
        :return: True if the user wants to update.
        '''
        # Call callback function
        if self.callback_onupdate_confirm is not None:

            callback = self.callback_onupdate_confirm

            # pylint: disable=E1102
            # pylint: disable=E1103
            msg = 'Your current w3af installation is %s (%s). Do you want '\
                  'to update to %s (%s)?'
            proceed_upd = callback(
                msg %
                (short_local_head_id, get_commit_id_date(local_head_id),
                 short_remote_head_id, get_commit_id_date(remote_head_id)))

            return proceed_upd

    def __update_impl(self):
        '''
        Finally call the Git client's pull!
        
        :return: (changelog, local_head_id, target_commit)
        '''
        self._notify(VersionMgr.ON_UPDATE)

        try:
            changelog = self._client.pull()
        except GitClientError, exc:
            msg = '%s' % exc
            self._notify(VersionMgr.ON_ACTION_ERROR, msg)
            return
        else: