示例#1
0
    def __init__(self,
                 cpath=None,
                 solpath=None,
                 precpath=None,
                 presolpath=None,
                 preindexpath=None,
                 watch_filepattern='pre',
                 watch_delay=60,
                 watch_minthreshold=20,
                 watch_maxthreshold=50,
                 *args,
                 **kwargs):
        if preindexpath:
            self.preindexpath = preindexpath
        if cpath:
            self.cpath = cpath
        if solpath:
            self.solpath = solpath
        if precpath:
            self.precpath = precpath
        if presolpath:
            self.presolpath = presolpath

        self.watch_filepattern = watch_filepattern
        self.watch_delay = watch_delay
        self.watch_minthreshold = watch_minthreshold
        self.watch_maxthreshold = watch_maxthreshold

        self.watching = False  # flag to false to say that the coroutine is not yet running

        self.captchagen = CaptchaGenerator(*args, **kwargs)
        self.captchachecker = CaptchaChecker()
        return
示例#2
0
    def __init__(self, cpath=None, solpath=None, precpath=None, presolpath=None, preindexpath=None, watch_filepattern='pre', watch_delay=60, watch_minthreshold=20, watch_maxthreshold=50, *args, **kwargs):
        if preindexpath:
            self.preindexpath = preindexpath
        if cpath:
            self.cpath = cpath
        if solpath:
            self.solpath = solpath
        if precpath:
            self.precpath = precpath
        if presolpath:
            self.presolpath = presolpath

        self.watch_filepattern = watch_filepattern
        self.watch_delay = watch_delay
        self.watch_minthreshold = watch_minthreshold
        self.watch_maxthreshold = watch_maxthreshold

        self.watching = False # flag to false to say that the coroutine is not yet running

        self.captchagen = CaptchaGenerator(*args, **kwargs)
        self.captchachecker = CaptchaChecker()
        return
示例#3
0
class CaptchaManager:
    '''
    A wrapper class to manage the safe handling of Captcha images (optimization using pregeneration of images, deleting captchas after each access, etc.)
    '''
    def __init__(self,
                 cpath=None,
                 solpath=None,
                 precpath=None,
                 presolpath=None,
                 preindexpath=None,
                 watch_filepattern='pre',
                 watch_delay=60,
                 watch_minthreshold=20,
                 watch_maxthreshold=50,
                 *args,
                 **kwargs):
        if preindexpath:
            self.preindexpath = preindexpath
        if cpath:
            self.cpath = cpath
        if solpath:
            self.solpath = solpath
        if precpath:
            self.precpath = precpath
        if presolpath:
            self.presolpath = presolpath

        self.watch_filepattern = watch_filepattern
        self.watch_delay = watch_delay
        self.watch_minthreshold = watch_minthreshold
        self.watch_maxthreshold = watch_maxthreshold

        self.watching = False  # flag to false to say that the coroutine is not yet running

        self.captchagen = CaptchaGenerator(*args, **kwargs)
        self.captchachecker = CaptchaChecker()
        return

    def makeCaptcha(self, startid, filepattern):
        '''
        Make a batch of captcha images given a filename pattern and a starting id (will generate as many captchas as the difference between starting id and maximum threshold)
        '''
        for i in xrange(self.watch_maxthreshold):
            self.captchagen.renderCaptcha(self.precpath, self.presolpath,
                                          "%s%s" % (filepattern, startid + i))

        return startid + self.watch_maxthreshold

    def watchCaptcha(self):
        '''
        Coroutine to pregenerate captchas images and solutions in the background, and also manage the number of available pregenerated captchas between a minimum and maximum threshold
        '''
        self.watching = True  # Notify that the coroutine is running

        while self.watching:  # Stop when the watching flag is set to false (or when the application closes)

            lastid = None
            try:
                with open(
                        self.preindexpath, 'rb'
                ) as f:  # at first we only read the file in a non blocking way to check how many captchas are left
                    (pattern, currentid, lastid) = f.read().strip().split(' ')
                    lastid = int(lastid)
                    currentid = int(currentid)
            except:
                pass

            # Generate a set of captcha if either the file is not yet set or either the number of pregenerated captchas are below the minimum threshold
            newlastid = None
            if not lastid:
                pattern = self.watch_filepattern
                newlastid = self.makeCaptcha(1, pattern)

                with open(self.preindexpath, 'wb') as f:
                    f.write("%s 1 %s" % (pattern, newlastid))
            elif lastid - currentid <= self.watch_minthreshold:  # continue from the last id
                newlastid = self.makeCaptcha(lastid, pattern)

                # Update the new last id into the index file
                with open(self.preindexpath, 'r+b') as f:
                    (pattern, currentid, lastid) = f.read().strip().split(' ')
                    f.seek(
                        0
                    )  # place the cursor at the beginning of the file to overwrite everything
                    f.write("%s %s %s" % (pattern, currentid, newlastid))

            # Sleep a bit until next iteration
            time.sleep(self.watch_delay)

    def spawnCoroutine(self):
        '''
        Spawn the captcha watcher coroutine
        '''
        process = Process(target=call_it, args=(self, 'watchCaptcha'))
        process.start()
        return True

    def getCaptcha(self):
        '''
        Get a captcha image and returns the captcha id (either pick in pregenerated captchas or generate on-the-fly)
        '''

        # Get a pregenerated captcha image if available
        try:
            if not hasattr(self, 'preindexpath'):
                raise Exception("Pregeneration of captcha images disabled")

            with open(self.preindexpath, 'r+b') as f:

                # Read the parameters
                (pattern, currentid, lastid) = f.read().strip().split(' ')
                lastid = int(lastid)
                currentid = int(currentid)

                # Check that we are not out of range
                if lastid - currentid < 0:
                    raise Exception('Pregenerated image index out of range')

                # Save the new data as soon as possible to avoid race conditions
                # Note about race conditions: if the image was already taken, no problem: we generate a new image on the fly, and since we still incremented the counter, next time the currentid should be OK (if not it will be increased another time, etc..)
                nextid = int(currentid) + 1
                f.seek(
                    0
                )  # place the cursor at the beginning of the file to overwrite everything
                f.write(
                    "%s %s %s" % (pattern, nextid, lastid)
                )  # increment the current id cursor and save it in the index file

                # Get the captcha
                cid = self.captchagen.randomID()  # we generate a captcha id
                shutil.move(
                    os.path.join(self.precpath,
                                 "%s%s.jpg" % (pattern, currentid)),
                    os.path.join(self.cpath, "%s.jpg" % cid))
                shutil.move(
                    os.path.join(self.presolpath,
                                 "%s%s.rle" % (pattern, currentid)),
                    os.path.join(self.solpath, "%s.rle" % cid))
                try:  # try to also move the png files if debugPng is enabled
                    shutil.move(
                        os.path.join(self.presolpath,
                                     "%s%s.png" % (pattern, currentid)),
                        os.path.join(self.solpath, "%s.png" % cid))
                except:
                    pass

                if lastid - currentid < self.watch_minthreshold and not self.watching:
                    self.watching = True
                    self.spawnCoroutine()

        # Else we create a new captcha image on-the-fly
        except:
            # List files in pre folders: if at least one is available in both folders with same name then OK
            cid = self.captchagen.renderCaptcha(self.cpath, self.solpath)

        return cid

    def checkCaptcha(self, cid, x, y):
        '''
        Check a captcha response and delete the captcha
        '''
        result = captchachecker.checkSolution(self.solpath, cid, x, y)
        self.delCaptcha(cid)
        return result

    def delCaptcha(self, cid):
        '''
        Delete a captcha (client image and solution mask)
        '''
        os.remove(os.path.join(self.cpath, "%s.jpg" % cid))
        os.remove(os.path.join(self.solpath, "%s.rle" % cid))
        return True
示例#4
0
class CaptchaManager:
    '''
    A wrapper class to manage the safe handling of Captcha images (optimization using pregeneration of images, deleting captchas after each access, etc.)
    '''

    def __init__(self, cpath=None, solpath=None, precpath=None, presolpath=None, preindexpath=None, watch_filepattern='pre', watch_delay=60, watch_minthreshold=20, watch_maxthreshold=50, *args, **kwargs):
        if preindexpath:
            self.preindexpath = preindexpath
        if cpath:
            self.cpath = cpath
        if solpath:
            self.solpath = solpath
        if precpath:
            self.precpath = precpath
        if presolpath:
            self.presolpath = presolpath

        self.watch_filepattern = watch_filepattern
        self.watch_delay = watch_delay
        self.watch_minthreshold = watch_minthreshold
        self.watch_maxthreshold = watch_maxthreshold

        self.watching = False # flag to false to say that the coroutine is not yet running

        self.captchagen = CaptchaGenerator(*args, **kwargs)
        self.captchachecker = CaptchaChecker()
        return

    def makeCaptcha(self, startid, filepattern):
        '''
        Make a batch of captcha images given a filename pattern and a starting id (will generate as many captchas as the difference between starting id and maximum threshold)
        '''
        for i in xrange(self.watch_maxthreshold):
            self.captchagen.renderCaptcha(self.precpath, self.presolpath, "%s%s" % (filepattern, startid+i))

        return startid + self.watch_maxthreshold

    def watchCaptcha(self):
        '''
        Coroutine to pregenerate captchas images and solutions in the background, and also manage the number of available pregenerated captchas between a minimum and maximum threshold
        '''
        self.watching = True # Notify that the coroutine is running

        while self.watching: # Stop when the watching flag is set to false (or when the application closes)

            lastid = None
            try:
                with open(self.preindexpath, 'rb') as f: # at first we only read the file in a non blocking way to check how many captchas are left
                    (pattern, currentid, lastid) = f.read().strip().split(' ')
                    lastid = int(lastid)
                    currentid = int(currentid)
            except:
                pass

            # Generate a set of captcha if either the file is not yet set or either the number of pregenerated captchas are below the minimum threshold
            newlastid = None
            if not lastid:
                pattern = self.watch_filepattern
                newlastid = self.makeCaptcha(1, pattern)

                with open(self.preindexpath, 'wb') as f:
                    f.write("%s 1 %s" % (pattern, newlastid))
            elif lastid - currentid <= self.watch_minthreshold: # continue from the last id
                newlastid = self.makeCaptcha(lastid, pattern)

                # Update the new last id into the index file
                with open(self.preindexpath, 'r+b') as f:
                    (pattern, currentid, lastid) = f.read().strip().split(' ')
                    f.seek(0) # place the cursor at the beginning of the file to overwrite everything
                    f.write("%s %s %s" % (pattern, currentid, newlastid))

            # Sleep a bit until next iteration
            time.sleep(self.watch_delay)


    def spawnCoroutine(self):
        '''
        Spawn the captcha watcher coroutine
        '''
        process = Process(target=call_it, args=(self, 'watchCaptcha'))
        process.start()
        return True


    def getCaptcha(self):
        '''
        Get a captcha image and returns the captcha id (either pick in pregenerated captchas or generate on-the-fly)
        '''

        # Get a pregenerated captcha image if available
        try:
            if not hasattr(self, 'preindexpath'):
                raise Exception("Pregeneration of captcha images disabled")

            with open(self.preindexpath, 'r+b') as f:

                # Read the parameters
                (pattern, currentid, lastid) = f.read().strip().split(' ')
                lastid = int(lastid)
                currentid = int(currentid)

                # Check that we are not out of range
                if lastid - currentid < 0:
                    raise Exception('Pregenerated image index out of range')

                # Save the new data as soon as possible to avoid race conditions
                # Note about race conditions: if the image was already taken, no problem: we generate a new image on the fly, and since we still incremented the counter, next time the currentid should be OK (if not it will be increased another time, etc..)
                nextid = int(currentid) + 1
                f.seek(0) # place the cursor at the beginning of the file to overwrite everything
                f.write("%s %s %s" % (pattern, nextid, lastid)) # increment the current id cursor and save it in the index file

                # Get the captcha
                cid = self.captchagen.randomID() # we generate a captcha id
                shutil.move(os.path.join(self.precpath, "%s%s.jpg" % (pattern, currentid)), os.path.join(self.cpath, "%s.jpg" % cid))
                shutil.move(os.path.join(self.presolpath, "%s%s.rle" % (pattern, currentid)), os.path.join(self.solpath, "%s.rle" % cid))
                try: # try to also move the png files if debugPng is enabled
                    shutil.move(os.path.join(self.presolpath, "%s%s.png" % (pattern, currentid)), os.path.join(self.solpath, "%s.png" % cid))
                except:
                    pass

                if lastid - currentid < self.watch_minthreshold and not self.watching:
                    self.watching = True
                    self.spawnCoroutine()

        # Else we create a new captcha image on-the-fly
        except:
            # List files in pre folders: if at least one is available in both folders with same name then OK
            cid = self.captchagen.renderCaptcha(self.cpath, self.solpath)

        return cid

    def checkCaptcha(self, cid, x, y):
        '''
        Check a captcha response and delete the captcha
        '''
        result = captchachecker.checkSolution(self.solpath, cid, x, y)
        self.delCaptcha(cid)
        return result

    def delCaptcha(self, cid):
        '''
        Delete a captcha (client image and solution mask)
        '''
        os.remove(os.path.join(self.cpath, "%s.jpg" % cid))
        os.remove(os.path.join(self.solpath, "%s.rle" % cid))
        return True